EVOLUTION-MANAGER
Edit File: gc_reader.cpp
/****************************************************************************** * Project: PROJ.4 * Purpose: Code to read a grid catalog from a .cvs file. * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** * Copyright (c) 2012, Frank Warmerdam <warmerdam@pobox.com> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *****************************************************************************/ #define PJ_LIB__ #include <ctype.h> #include <errno.h> #include <stdlib.h> #include <string.h> #include "proj.h" #include "proj_internal.h" static int gc_readentry(projCtx ctx, PAFile fid, PJ_GridCatalogEntry *entry); /************************************************************************/ /* pj_gc_readcatalog() */ /* */ /* Read a grid catalog from a .csv file. */ /************************************************************************/ PJ_GridCatalog *pj_gc_readcatalog( projCtx ctx, const char *catalog_name ) { PAFile fid; PJ_GridCatalog *catalog; int entry_max; char line[302]; fid = pj_open_lib( ctx, catalog_name, "r" ); if (fid == nullptr) return nullptr; /* discard title line */ pj_ctx_fgets(ctx, line, sizeof(line)-1, fid); catalog = (PJ_GridCatalog *) calloc(1,sizeof(PJ_GridCatalog)); if( !catalog ) { pj_ctx_set_errno(ctx, ENOMEM); pj_ctx_fclose(ctx, fid); return nullptr; } catalog->catalog_name = pj_strdup(catalog_name); if (!catalog->catalog_name) { pj_ctx_set_errno(ctx, ENOMEM); free(catalog); pj_ctx_fclose(ctx, fid); return nullptr; } entry_max = 10; catalog->entries = (PJ_GridCatalogEntry *) malloc(entry_max * sizeof(PJ_GridCatalogEntry)); if (!catalog->entries) { pj_ctx_set_errno(ctx, ENOMEM); free(catalog->catalog_name); free(catalog); pj_ctx_fclose(ctx, fid); return nullptr; } while( gc_readentry( ctx, fid, catalog->entries+catalog->entry_count) == 0) { catalog->entry_count++; if( catalog->entry_count == entry_max ) { PJ_GridCatalogEntry* new_entries; entry_max = entry_max * 2; new_entries = (PJ_GridCatalogEntry *) realloc(catalog->entries, entry_max * sizeof(PJ_GridCatalogEntry)); if (new_entries == nullptr ) { int i; for( i = 0; i < catalog->entry_count; i++ ) free( catalog->entries[i].definition ); free( catalog->entries ); free( catalog->catalog_name ); free( catalog ); pj_ctx_fclose(ctx, fid); return nullptr; } catalog->entries = new_entries; } } pj_ctx_fclose(ctx, fid); return catalog; } /************************************************************************/ /* gc_read_csv_line() */ /* */ /* Simple csv line splitter with fixed maximum line size and */ /* token count. */ /************************************************************************/ static int gc_read_csv_line( projCtx ctx, PAFile fid, char **tokens, int max_tokens ) { char line[302]; while( pj_ctx_fgets(ctx, line, sizeof(line)-1, fid) != nullptr ) { char *next = line; int token_count = 0; while( isspace(*next) ) next++; /* skip blank and comment lines */ if( next[0] == '#' || next[0] == '\0' ) continue; while( token_count < max_tokens && *next != '\0' ) { const char *start = next; char* token; while( *next != '\0' && *next != ',' ) next++; if( *next == ',' ) { *next = '\0'; next++; } token = pj_strdup(start); if (!token) { while (token_count > 0) free(tokens[--token_count]); pj_ctx_set_errno(ctx, ENOMEM); return 0; } tokens[token_count++] = token; } return token_count; } return 0; } /************************************************************************/ /* pj_gc_parsedate() */ /* */ /* Parse a date into a floating point year value. Acceptable */ /* values are "yyyy.fraction" and "yyyy-mm-dd". Anything else */ /* returns 0.0. */ /************************************************************************/ double pj_gc_parsedate( projCtx ctx, const char *date_string ) { (void) ctx; if( strlen(date_string) == 10 && date_string[4] == '-' && date_string[7] == '-' ) { int year = atoi(date_string); int month = atoi(date_string+5); int day = atoi(date_string+8); /* simplified calculation so we don't need to know all about months */ return year + ((month-1) * 31 + (day-1)) / 372.0; } else { return pj_atof(date_string); } } /************************************************************************/ /* gc_readentry() */ /* */ /* Read one catalog entry from the file */ /* */ /* Format: */ /* gridname,ll_long,ll_lat,ur_long,ur_lat,priority,date */ /************************************************************************/ static int gc_readentry(projCtx ctx, PAFile fid, PJ_GridCatalogEntry *entry) { #define MAX_TOKENS 30 char *tokens[MAX_TOKENS]; int token_count, i; int error = 0; memset( entry, 0, sizeof(PJ_GridCatalogEntry) ); token_count = gc_read_csv_line( ctx, fid, tokens, MAX_TOKENS ); if( token_count < 5 ) { error = 1; /* TODO: need real error codes */ if( token_count != 0 ) pj_log( ctx, PJ_LOG_ERROR, "Short line in grid catalog." ); } else { entry->definition = tokens[0]; tokens[0] = nullptr; /* We take ownership of tokens[0] */ entry->region.ll_long = dmstor_ctx( ctx, tokens[1], nullptr ); entry->region.ll_lat = dmstor_ctx( ctx, tokens[2], nullptr ); entry->region.ur_long = dmstor_ctx( ctx, tokens[3], nullptr ); entry->region.ur_lat = dmstor_ctx( ctx, tokens[4], nullptr ); if( token_count > 5 ) entry->priority = atoi( tokens[5] ); /* defaults to zero */ if( token_count > 6 ) entry->date = pj_gc_parsedate( ctx, tokens[6] ); } for( i = 0; i < token_count; i++ ) free( tokens[i] ); return error; }