<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html><head><meta name="robots" content="noindex"> <meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1"> <title>cpl_csv.cpp Source File</title> <link href="doxygen.css" rel="stylesheet" type="text/css"> </head><body bgcolor="#ffffff"> <!-- Generated by Doxygen 1.2.3-20001105 on Thu Mar 28 09:47:27 2002 --> <center> <a class="qindex" href="index.html">Main Page</a> <a class="qindex" href="hierarchy.html">Class Hierarchy</a> <a class="qindex" href="annotated.html">Compound List</a> <a class="qindex" href="files.html">File List</a> <a class="qindex" href="functions.html">Compound Members</a> <a class="qindex" href="globals.html">File Members</a> <a class="qindex" href="pages.html">Related Pages</a> </center> <hr><h1>cpl_csv.cpp</h1><div class="fragment"><pre>00001 <font class="comment">/******************************************************************************</font> 00002 <font class="comment"> * $Id: cpl_csv_cpp-source.html,v 1.8 2002/04/16 13:11:47 warmerda Exp $</font> 00003 <font class="comment"> *</font> 00004 <font class="comment"> * Project: CPL - Common Portability Library</font> 00005 <font class="comment"> * Purpose: CSV (comma separated value) file access.</font> 00006 <font class="comment"> * Author: Frank Warmerdam, warmerda@home.com</font> 00007 <font class="comment"> *</font> 00008 <font class="comment"> ******************************************************************************</font> 00009 <font class="comment"> * Copyright (c) 1999, Frank Warmerdam</font> 00010 <font class="comment"> *</font> 00011 <font class="comment"> * Permission is hereby granted, free of charge, to any person obtaining a</font> 00012 <font class="comment"> * copy of this software and associated documentation files (the "Software"),</font> 00013 <font class="comment"> * to deal in the Software without restriction, including without limitation</font> 00014 <font class="comment"> * the rights to use, copy, modify, merge, publish, distribute, sublicense,</font> 00015 <font class="comment"> * and/or sell copies of the Software, and to permit persons to whom the</font> 00016 <font class="comment"> * Software is furnished to do so, subject to the following conditions:</font> 00017 <font class="comment"> *</font> 00018 <font class="comment"> * The above copyright notice and this permission notice shall be included</font> 00019 <font class="comment"> * in all copies or substantial portions of the Software.</font> 00020 <font class="comment"> *</font> 00021 <font class="comment"> * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS</font> 00022 <font class="comment"> * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,</font> 00023 <font class="comment"> * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL</font> 00024 <font class="comment"> * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER</font> 00025 <font class="comment"> * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING</font> 00026 <font class="comment"> * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER</font> 00027 <font class="comment"> * DEALINGS IN THE SOFTWARE.</font> 00028 <font class="comment"> ******************************************************************************</font> 00029 <font class="comment"> *</font> 00030 <font class="comment"> * $Log: cpl_csv_cpp-source.html,v $ 00030 <font class="comment"> * Revision 1.8 2002/04/16 13:11:47 warmerda 00030 <font class="comment"> * updated 00030 <font class="comment"> *</font> 00031 <font class="comment"> * Revision 1.3 2001/07/18 04:00:49 warmerda</font> 00032 <font class="comment"> * added CPL_CVSID</font> 00033 <font class="comment"> *</font> 00034 <font class="comment"> * Revision 1.2 2001/01/19 21:16:41 warmerda</font> 00035 <font class="comment"> * expanded tabs</font> 00036 <font class="comment"> *</font> 00037 <font class="comment"> * Revision 1.1 2000/10/06 15:20:45 warmerda</font> 00038 <font class="comment"> * New</font> 00039 <font class="comment"> *</font> 00040 <font class="comment"> * Revision 1.2 2000/08/29 21:08:08 warmerda</font> 00041 <font class="comment"> * fallback to use CPLFindFile()</font> 00042 <font class="comment"> *</font> 00043 <font class="comment"> * Revision 1.1 2000/04/05 21:55:59 warmerda</font> 00044 <font class="comment"> * New</font> 00045 <font class="comment"> *</font> 00046 <font class="comment"> */</font> 00047 00048 <font class="preprocessor">#include "cpl_csv.h"</font> 00049 <font class="preprocessor">#include "<a class="code" href="cpl_conv_h.html">cpl_conv.h</a>"</font> 00050 00051 CPL_CVSID(<font class="stringliteral">"$Id: cpl_csv_cpp-source.html,v 1.8 2002/04/16 13:11:47 warmerda Exp $"</font>); 00052 00053 <font class="comment">/* ==================================================================== */</font> 00054 <font class="comment">/* The CSVTable is a persistant set of info about an open CSV */</font> 00055 <font class="comment">/* table. While it doesn't currently maintain a record index, */</font> 00056 <font class="comment">/* or in-memory copy of the table, it could be changed to do so */</font> 00057 <font class="comment">/* in the future. */</font> 00058 <font class="comment">/* ==================================================================== */</font> 00059 <font class="keyword">typedef</font> <font class="keyword">struct </font>ctb { 00060 FILE *fp; 00061 00062 <font class="keyword">struct </font>ctb *psNext; 00063 00064 <font class="keywordtype">char</font> *pszFilename; 00065 00066 <font class="keywordtype">char</font> **papszFieldNames; 00067 00068 <font class="keywordtype">char</font> **papszRecFields; 00069 } CSVTable; 00070 00071 <font class="keyword">static</font> CSVTable *psCSVTableList = NULL; 00072 00073 <font class="comment">/************************************************************************/</font> 00074 <font class="comment">/* CSVAccess() */</font> 00075 <font class="comment">/* */</font> 00076 <font class="comment">/* This function will fetch a handle to the requested table. */</font> 00077 <font class="comment">/* If not found in the ``open table list'' the table will be */</font> 00078 <font class="comment">/* opened and added to the list. Eventually this function may */</font> 00079 <font class="comment">/* become public with an abstracted return type so that */</font> 00080 <font class="comment">/* applications can set options about the table. For now this */</font> 00081 <font class="comment">/* isn't done. */</font> 00082 <font class="comment">/************************************************************************/</font> 00083 00084 <font class="keyword">static</font> CSVTable *CSVAccess( <font class="keyword">const</font> <font class="keywordtype">char</font> * pszFilename )<font class="keyword"></font> 00085 <font class="keyword"></font> 00086 <font class="keyword"></font>{ 00087 CSVTable *psTable; 00088 FILE *fp; 00089 00090 <font class="comment">/* -------------------------------------------------------------------- */</font> 00091 <font class="comment">/* Is the table already in the list. */</font> 00092 <font class="comment">/* -------------------------------------------------------------------- */</font> 00093 <font class="keywordflow">for</font>( psTable = psCSVTableList; psTable != NULL; psTable = psTable->psNext ) 00094 { 00095 <font class="keywordflow">if</font>( EQUAL(psTable->pszFilename,pszFilename) ) 00096 { 00097 <font class="comment">/*</font> 00098 <font class="comment"> * Eventually we should consider promoting to the front of</font> 00099 <font class="comment"> * the list to accelerate frequently accessed tables.</font> 00100 <font class="comment"> */</font> 00101 00102 <font class="keywordflow">return</font>( psTable ); 00103 } 00104 } 00105 00106 <font class="comment">/* -------------------------------------------------------------------- */</font> 00107 <font class="comment">/* If not, try to open it. */</font> 00108 <font class="comment">/* -------------------------------------------------------------------- */</font> 00109 fp = VSIFOpen( pszFilename, <font class="stringliteral">"r"</font> ); 00110 <font class="keywordflow">if</font>( fp == NULL ) 00111 <font class="keywordflow">return</font> NULL; 00112 00113 <font class="comment">/* -------------------------------------------------------------------- */</font> 00114 <font class="comment">/* Create an information structure about this table, and add to */</font> 00115 <font class="comment">/* the front of the list. */</font> 00116 <font class="comment">/* -------------------------------------------------------------------- */</font> 00117 psTable = (CSVTable *) <a class="code" href="cpl_conv_h.html#a4">CPLCalloc</a>(<font class="keyword">sizeof</font>(CSVTable),1); 00118 00119 psTable->fp = fp; 00120 psTable->pszFilename = <a class="code" href="cpl_conv_h.html#a6">CPLStrdup</a>( pszFilename ); 00121 psTable->psNext = psCSVTableList; 00122 00123 psCSVTableList = psTable; 00124 00125 <font class="comment">/* -------------------------------------------------------------------- */</font> 00126 <font class="comment">/* Read the table header record containing the field names. */</font> 00127 <font class="comment">/* -------------------------------------------------------------------- */</font> 00128 psTable->papszFieldNames = CSVReadParseLine( fp ); 00129 00130 <font class="keywordflow">return</font>( psTable ); 00131 } 00132 00133 <font class="comment">/************************************************************************/</font> 00134 <font class="comment">/* CSVDeaccess() */</font> 00135 <font class="comment">/************************************************************************/</font> 00136 00137 <font class="keywordtype">void</font> CSVDeaccess( <font class="keyword">const</font> <font class="keywordtype">char</font> * pszFilename )<font class="keyword"></font> 00138 <font class="keyword"></font> 00139 <font class="keyword"></font>{ 00140 CSVTable *psLast, *psTable; 00141 00142 <font class="comment">/* -------------------------------------------------------------------- */</font> 00143 <font class="comment">/* A NULL means deaccess all tables. */</font> 00144 <font class="comment">/* -------------------------------------------------------------------- */</font> 00145 <font class="keywordflow">if</font>( pszFilename == NULL ) 00146 { 00147 <font class="keywordflow">while</font>( psCSVTableList != NULL ) 00148 CSVDeaccess( psCSVTableList->pszFilename ); 00149 00150 <font class="keywordflow">return</font>; 00151 } 00152 00153 <font class="comment">/* -------------------------------------------------------------------- */</font> 00154 <font class="comment">/* Find this table. */</font> 00155 <font class="comment">/* -------------------------------------------------------------------- */</font> 00156 psLast = NULL; 00157 <font class="keywordflow">for</font>( psTable = psCSVTableList; 00158 psTable != NULL && !EQUAL(psTable->pszFilename,pszFilename); 00159 psTable = psTable->psNext ) 00160 { 00161 psLast = psTable; 00162 } 00163 00164 <font class="keywordflow">if</font>( psTable == NULL ) 00165 <font class="keywordflow">return</font>; 00166 00167 <font class="comment">/* -------------------------------------------------------------------- */</font> 00168 <font class="comment">/* Remove the link from the list. */</font> 00169 <font class="comment">/* -------------------------------------------------------------------- */</font> 00170 <font class="keywordflow">if</font>( psLast != NULL ) 00171 psLast->psNext = psTable->psNext; 00172 <font class="keywordflow">else</font> 00173 psCSVTableList = psTable->psNext; 00174 00175 <font class="comment">/* -------------------------------------------------------------------- */</font> 00176 <font class="comment">/* Free the table. */</font> 00177 <font class="comment">/* -------------------------------------------------------------------- */</font> 00178 VSIFClose( psTable->fp ); 00179 00180 CSLDestroy( psTable->papszFieldNames ); 00181 CSLDestroy( psTable->papszRecFields ); 00182 CPLFree( psTable->pszFilename ); 00183 00184 CPLFree( psTable ); 00185 } 00186 00187 <font class="comment">/************************************************************************/</font> 00188 <font class="comment">/* CSVReadParseLine() */</font> 00189 <font class="comment">/* */</font> 00190 <font class="comment">/* Read one line, and return split into fields. The return */</font> 00191 <font class="comment">/* result is a stringlist, in the sense of the CSL functions. */</font> 00192 <font class="comment">/************************************************************************/</font> 00193 00194 <font class="keywordtype">char</font> **CSVReadParseLine( FILE * fp )<font class="keyword"></font> 00195 <font class="keyword"></font> 00196 <font class="keyword"></font>{ 00197 <font class="keyword">const</font> <font class="keywordtype">char</font> *pszLine; 00198 <font class="keywordtype">char</font> *pszWorkLine; 00199 <font class="keywordtype">char</font> **papszReturn; 00200 00201 CPLAssert( fp != NULL ); 00202 <font class="keywordflow">if</font>( fp == NULL ) 00203 <font class="keywordflow">return</font>( NULL ); 00204 00205 pszLine = <a class="code" href="cpl_conv_h.html#a7">CPLReadLine</a>( fp ); 00206 <font class="keywordflow">if</font>( pszLine == NULL ) 00207 <font class="keywordflow">return</font>( NULL ); 00208 00209 <font class="comment">/* -------------------------------------------------------------------- */</font> 00210 <font class="comment">/* If there are no quotes, then this is the simple case. */</font> 00211 <font class="comment">/* Parse, and return tokens. */</font> 00212 <font class="comment">/* -------------------------------------------------------------------- */</font> 00213 <font class="keywordflow">if</font>( strchr(pszLine,<font class="charliteral">'\"'</font>) == NULL ) 00214 <font class="keywordflow">return</font> CSLTokenizeStringComplex( pszLine, <font class="stringliteral">","</font>, TRUE, TRUE ); 00215 00216 <font class="comment">/* -------------------------------------------------------------------- */</font> 00217 <font class="comment">/* We must now count the quotes in our working string, and as */</font> 00218 <font class="comment">/* long as it is odd, keep adding new lines. */</font> 00219 <font class="comment">/* -------------------------------------------------------------------- */</font> 00220 pszWorkLine = <a class="code" href="cpl_conv_h.html#a6">CPLStrdup</a>( pszLine ); 00221 00222 <font class="keywordflow">while</font>( TRUE ) 00223 { 00224 <font class="keywordtype">int</font> i, nCount = 0; 00225 00226 <font class="keywordflow">for</font>( i = 0; pszWorkLine[i] != <font class="charliteral">'\0'</font>; i++ ) 00227 { 00228 <font class="keywordflow">if</font>( pszWorkLine[i] == <font class="charliteral">'\"'</font> 00229 && (i == 0 || pszWorkLine[i-1] != <font class="charliteral">'\\'</font>) ) 00230 nCount++; 00231 } 00232 00233 <font class="keywordflow">if</font>( nCount % 2 == 0 ) 00234 <font class="keywordflow">break</font>; 00235 00236 pszLine = <a class="code" href="cpl_conv_h.html#a7">CPLReadLine</a>( fp ); 00237 <font class="keywordflow">if</font>( pszLine == NULL ) 00238 <font class="keywordflow">break</font>; 00239 00240 pszWorkLine = (<font class="keywordtype">char</font> *) 00241 <a class="code" href="cpl_conv_h.html#a5">CPLRealloc</a>(pszWorkLine, 00242 strlen(pszWorkLine) + strlen(pszLine) + 1); 00243 strcat( pszWorkLine, pszLine ); 00244 } 00245 00246 papszReturn = CSLTokenizeStringComplex( pszWorkLine, <font class="stringliteral">","</font>, TRUE, TRUE ); 00247 00248 CPLFree( pszWorkLine ); 00249 00250 <font class="keywordflow">return</font> papszReturn; 00251 } 00252 00253 <font class="comment">/************************************************************************/</font> 00254 <font class="comment">/* CSVCompare() */</font> 00255 <font class="comment">/* */</font> 00256 <font class="comment">/* Compare a field to a search value using a particular */</font> 00257 <font class="comment">/* criteria. */</font> 00258 <font class="comment">/************************************************************************/</font> 00259 00260 <font class="keyword">static</font> <font class="keywordtype">int</font> CSVCompare( <font class="keyword">const</font> <font class="keywordtype">char</font> * pszFieldValue, <font class="keyword">const</font> <font class="keywordtype">char</font> * pszTarget, 00261 CSVCompareCriteria eCriteria )<font class="keyword"></font> 00262 <font class="keyword"></font> 00263 <font class="keyword"></font>{ 00264 <font class="keywordflow">if</font>( eCriteria == CC_ExactString ) 00265 { 00266 <font class="keywordflow">return</font>( strcmp( pszFieldValue, pszTarget ) == 0 ); 00267 } 00268 <font class="keywordflow">else</font> <font class="keywordflow">if</font>( eCriteria == CC_ApproxString ) 00269 { 00270 <font class="keywordflow">return</font>( EQUAL( pszFieldValue, pszTarget ) ); 00271 } 00272 <font class="keywordflow">else</font> <font class="keywordflow">if</font>( eCriteria == CC_Integer ) 00273 { 00274 <font class="keywordflow">return</font>( atoi(pszFieldValue) == atoi(pszTarget) ); 00275 } 00276 00277 <font class="keywordflow">return</font> FALSE; 00278 } 00279 00280 <font class="comment">/************************************************************************/</font> 00281 <font class="comment">/* CSVScanLines() */</font> 00282 <font class="comment">/* */</font> 00283 <font class="comment">/* Read the file scanline for lines where the key field equals */</font> 00284 <font class="comment">/* the indicated value with the suggested comparison criteria. */</font> 00285 <font class="comment">/* Return the first matching line split into fields. */</font> 00286 <font class="comment">/************************************************************************/</font> 00287 00288 <font class="keywordtype">char</font> **CSVScanLines( FILE *fp, <font class="keywordtype">int</font> iKeyField, <font class="keyword">const</font> <font class="keywordtype">char</font> * pszValue, 00289 CSVCompareCriteria eCriteria )<font class="keyword"></font> 00290 <font class="keyword"></font> 00291 <font class="keyword"></font>{ 00292 <font class="keywordtype">char</font> **papszFields = NULL; 00293 <font class="keywordtype">int</font> bSelected = FALSE, nTestValue; 00294 00295 CPLAssert( pszValue != NULL ); 00296 CPLAssert( iKeyField >= 0 ); 00297 CPLAssert( fp != NULL ); 00298 00299 nTestValue = atoi(pszValue); 00300 00301 <font class="keywordflow">while</font>( !bSelected ) { 00302 papszFields = CSVReadParseLine( fp ); 00303 <font class="keywordflow">if</font>( papszFields == NULL ) 00304 <font class="keywordflow">return</font>( NULL ); 00305 00306 <font class="keywordflow">if</font>( CSLCount( papszFields ) < iKeyField+1 ) 00307 { 00308 <font class="comment">/* not selected */</font> 00309 } 00310 <font class="keywordflow">else</font> <font class="keywordflow">if</font>( eCriteria == CC_Integer 00311 && atoi(papszFields[iKeyField]) == nTestValue ) 00312 { 00313 bSelected = TRUE; 00314 } 00315 <font class="keywordflow">else</font> 00316 { 00317 bSelected = CSVCompare( papszFields[iKeyField], pszValue, 00318 eCriteria ); 00319 } 00320 00321 <font class="keywordflow">if</font>( !bSelected ) 00322 { 00323 CSLDestroy( papszFields ); 00324 papszFields = NULL; 00325 } 00326 } 00327 00328 <font class="keywordflow">return</font>( papszFields ); 00329 } 00330 00331 <font class="comment">/************************************************************************/</font> 00332 <font class="comment">/* CSVScanFile() */</font> 00333 <font class="comment">/* */</font> 00334 <font class="comment">/* Scan a whole file using criteria similar to above, but also */</font> 00335 <font class="comment">/* taking care of file opening and closing. */</font> 00336 <font class="comment">/************************************************************************/</font> 00337 00338 <font class="keywordtype">char</font> **CSVScanFile( <font class="keyword">const</font> <font class="keywordtype">char</font> * pszFilename, <font class="keywordtype">int</font> iKeyField, 00339 <font class="keyword">const</font> <font class="keywordtype">char</font> * pszValue, CSVCompareCriteria eCriteria )<font class="keyword"></font> 00340 <font class="keyword"></font> 00341 <font class="keyword"></font>{ 00342 CSVTable *psTable; 00343 00344 <font class="comment">/* -------------------------------------------------------------------- */</font> 00345 <font class="comment">/* Get access to the table. */</font> 00346 <font class="comment">/* -------------------------------------------------------------------- */</font> 00347 CPLAssert( pszFilename != NULL ); 00348 00349 <font class="keywordflow">if</font>( iKeyField < 0 ) 00350 <font class="keywordflow">return</font> NULL; 00351 00352 psTable = CSVAccess( pszFilename ); 00353 <font class="keywordflow">if</font>( psTable == NULL ) 00354 <font class="keywordflow">return</font> NULL; 00355 00356 <font class="comment">/* -------------------------------------------------------------------- */</font> 00357 <font class="comment">/* Does the current record match the criteria? If so, just */</font> 00358 <font class="comment">/* return it again. */</font> 00359 <font class="comment">/* -------------------------------------------------------------------- */</font> 00360 <font class="keywordflow">if</font>( iKeyField >= 0 00361 && iKeyField < CSLCount(psTable->papszRecFields) 00362 && CSVCompare(pszValue,psTable->papszRecFields[iKeyField],eCriteria) ) 00363 { 00364 <font class="keywordflow">return</font> psTable->papszRecFields; 00365 } 00366 00367 <font class="comment">/* -------------------------------------------------------------------- */</font> 00368 <font class="comment">/* Scan the file from the beginning, replacing the ``current */</font> 00369 <font class="comment">/* record'' in our structure with the one that is found. */</font> 00370 <font class="comment">/* -------------------------------------------------------------------- */</font> 00371 VSIRewind( psTable->fp ); 00372 <a class="code" href="cpl_conv_h.html#a7">CPLReadLine</a>( psTable->fp ); <font class="comment">/* throw away the header line */</font> 00373 00374 CSLDestroy( psTable->papszRecFields ); 00375 psTable->papszRecFields = 00376 CSVScanLines( psTable->fp, iKeyField, pszValue, eCriteria ); 00377 00378 <font class="keywordflow">return</font>( psTable->papszRecFields ); 00379 } 00380 00381 <font class="comment">/************************************************************************/</font> 00382 <font class="comment">/* CPLGetFieldId() */</font> 00383 <font class="comment">/* */</font> 00384 <font class="comment">/* Read the first record of a CSV file (rewinding to be sure), */</font> 00385 <font class="comment">/* and find the field with the indicated name. Returns -1 if */</font> 00386 <font class="comment">/* it fails to find the field name. Comparison is case */</font> 00387 <font class="comment">/* insensitive, but otherwise exact. After this function has */</font> 00388 <font class="comment">/* been called the file pointer will be positioned just after */</font> 00389 <font class="comment">/* the first record. */</font> 00390 <font class="comment">/************************************************************************/</font> 00391 00392 <font class="keywordtype">int</font> CSVGetFieldId( FILE * fp, <font class="keyword">const</font> <font class="keywordtype">char</font> * pszFieldName )<font class="keyword"></font> 00393 <font class="keyword"></font> 00394 <font class="keyword"></font>{ 00395 <font class="keywordtype">char</font> **papszFields; 00396 <font class="keywordtype">int</font> i; 00397 00398 CPLAssert( fp != NULL && pszFieldName != NULL ); 00399 00400 VSIRewind( fp ); 00401 00402 papszFields = CSVReadParseLine( fp ); 00403 <font class="keywordflow">for</font>( i = 0; papszFields != NULL && papszFields[i] != NULL; i++ ) 00404 { 00405 <font class="keywordflow">if</font>( EQUAL(papszFields[i],pszFieldName) ) 00406 { 00407 CSLDestroy( papszFields ); 00408 <font class="keywordflow">return</font> i; 00409 } 00410 } 00411 00412 CSLDestroy( papszFields ); 00413 00414 <font class="keywordflow">return</font> -1; 00415 } 00416 00417 <font class="comment">/************************************************************************/</font> 00418 <font class="comment">/* CSVGetFileFieldId() */</font> 00419 <font class="comment">/* */</font> 00420 <font class="comment">/* Same as CPLGetFieldId(), except that we get the file based */</font> 00421 <font class="comment">/* on filename, rather than having an existing handle. */</font> 00422 <font class="comment">/************************************************************************/</font> 00423 00424 <font class="keywordtype">int</font> CSVGetFileFieldId( <font class="keyword">const</font> <font class="keywordtype">char</font> * pszFilename, <font class="keyword">const</font> <font class="keywordtype">char</font> * pszFieldName )<font class="keyword"></font> 00425 <font class="keyword"></font> 00426 <font class="keyword"></font>{ 00427 CSVTable *psTable; 00428 <font class="keywordtype">int</font> i; 00429 00430 <font class="comment">/* -------------------------------------------------------------------- */</font> 00431 <font class="comment">/* Get access to the table. */</font> 00432 <font class="comment">/* -------------------------------------------------------------------- */</font> 00433 CPLAssert( pszFilename != NULL ); 00434 00435 psTable = CSVAccess( pszFilename ); 00436 <font class="keywordflow">if</font>( psTable == NULL ) 00437 <font class="keywordflow">return</font> -1; 00438 00439 <font class="comment">/* -------------------------------------------------------------------- */</font> 00440 <font class="comment">/* Find the requested field. */</font> 00441 <font class="comment">/* -------------------------------------------------------------------- */</font> 00442 <font class="keywordflow">for</font>( i = 0; 00443 psTable->papszFieldNames != NULL 00444 && psTable->papszFieldNames[i] != NULL; 00445 i++ ) 00446 { 00447 <font class="keywordflow">if</font>( EQUAL(psTable->papszFieldNames[i],pszFieldName) ) 00448 { 00449 <font class="keywordflow">return</font> i; 00450 } 00451 } 00452 00453 <font class="keywordflow">return</font> -1; 00454 } 00455 00456 00457 <font class="comment">/************************************************************************/</font> 00458 <font class="comment">/* CSVScanFileByName() */</font> 00459 <font class="comment">/* */</font> 00460 <font class="comment">/* Same as CSVScanFile(), but using a field name instead of a */</font> 00461 <font class="comment">/* field number. */</font> 00462 <font class="comment">/************************************************************************/</font> 00463 00464 <font class="keywordtype">char</font> **CSVScanFileByName( <font class="keyword">const</font> <font class="keywordtype">char</font> * pszFilename, 00465 <font class="keyword">const</font> <font class="keywordtype">char</font> * pszKeyFieldName, 00466 <font class="keyword">const</font> <font class="keywordtype">char</font> * pszValue, CSVCompareCriteria eCriteria )<font class="keyword"></font> 00467 <font class="keyword"></font> 00468 <font class="keyword"></font>{ 00469 <font class="keywordtype">int</font> iKeyField; 00470 00471 iKeyField = CSVGetFileFieldId( pszFilename, pszKeyFieldName ); 00472 <font class="keywordflow">if</font>( iKeyField == -1 ) 00473 <font class="keywordflow">return</font> NULL; 00474 00475 <font class="keywordflow">return</font>( CSVScanFile( pszFilename, iKeyField, pszValue, eCriteria ) ); 00476 } 00477 00478 <font class="comment">/************************************************************************/</font> 00479 <font class="comment">/* CSVGetField() */</font> 00480 <font class="comment">/* */</font> 00481 <font class="comment">/* The all-in-one function to fetch a particular field value */</font> 00482 <font class="comment">/* from a CSV file. Note this function will return an empty */</font> 00483 <font class="comment">/* string, rather than NULL if it fails to find the desired */</font> 00484 <font class="comment">/* value for some reason. The caller can't establish that the */</font> 00485 <font class="comment">/* fetch failed. */</font> 00486 <font class="comment">/************************************************************************/</font> 00487 00488 <font class="keyword">const</font> <font class="keywordtype">char</font> *CSVGetField( <font class="keyword">const</font> <font class="keywordtype">char</font> * pszFilename, 00489 <font class="keyword">const</font> <font class="keywordtype">char</font> * pszKeyFieldName, 00490 <font class="keyword">const</font> <font class="keywordtype">char</font> * pszKeyFieldValue, 00491 CSVCompareCriteria eCriteria, 00492 <font class="keyword">const</font> <font class="keywordtype">char</font> * pszTargetField )<font class="keyword"></font> 00493 <font class="keyword"></font> 00494 <font class="keyword"></font>{ 00495 CSVTable *psTable; 00496 <font class="keywordtype">char</font> **papszRecord; 00497 <font class="keywordtype">int</font> iTargetField; 00498 00499 <font class="comment">/* -------------------------------------------------------------------- */</font> 00500 <font class="comment">/* Find the table. */</font> 00501 <font class="comment">/* -------------------------------------------------------------------- */</font> 00502 psTable = CSVAccess( pszFilename ); 00503 <font class="keywordflow">if</font>( psTable == NULL ) 00504 <font class="keywordflow">return</font> <font class="stringliteral">""</font>; 00505 00506 <font class="comment">/* -------------------------------------------------------------------- */</font> 00507 <font class="comment">/* Find the correct record. */</font> 00508 <font class="comment">/* -------------------------------------------------------------------- */</font> 00509 papszRecord = CSVScanFileByName( pszFilename, pszKeyFieldName, 00510 pszKeyFieldValue, eCriteria ); 00511 00512 <font class="keywordflow">if</font>( papszRecord == NULL ) 00513 <font class="keywordflow">return</font> <font class="stringliteral">""</font>; 00514 00515 <font class="comment">/* -------------------------------------------------------------------- */</font> 00516 <font class="comment">/* Figure out which field we want out of this. */</font> 00517 <font class="comment">/* -------------------------------------------------------------------- */</font> 00518 iTargetField = CSVGetFileFieldId( pszFilename, pszTargetField ); 00519 <font class="keywordflow">if</font>( iTargetField < 0 ) 00520 <font class="keywordflow">return</font> <font class="stringliteral">""</font>; 00521 00522 <font class="keywordflow">if</font>( iTargetField >= CSLCount( papszRecord ) ) 00523 <font class="keywordflow">return</font> <font class="stringliteral">""</font>; 00524 00525 <font class="keywordflow">return</font>( papszRecord[iTargetField] ); 00526 } 00527 00528 <font class="comment">/************************************************************************/</font> 00529 <font class="comment">/* CSVFilename() */</font> 00530 <font class="comment">/* */</font> 00531 <font class="comment">/* Return the full path to a particular CSV file. This will */</font> 00532 <font class="comment">/* eventually be something the application can override. */</font> 00533 <font class="comment">/************************************************************************/</font> 00534 00535 <font class="keyword">static</font> <font class="keyword">const</font> <font class="keywordtype">char</font> *(*pfnCSVFilenameHook)(<font class="keyword">const</font> <font class="keywordtype">char</font> *) = NULL; 00536 00537 <font class="keyword">const</font> <font class="keywordtype">char</font> * CSVFilename( <font class="keyword">const</font> <font class="keywordtype">char</font> *pszBasename )<font class="keyword"></font> 00538 <font class="keyword"></font> 00539 <font class="keyword"></font>{ 00540 <font class="keyword">static</font> <font class="keywordtype">char</font> szPath[512]; 00541 00542 <font class="keywordflow">if</font>( pfnCSVFilenameHook == NULL ) 00543 { 00544 FILE *fp = NULL; 00545 <font class="keyword">const</font> <font class="keywordtype">char</font> *pszResult = CPLFindFile( <font class="stringliteral">"epsg_csv"</font>, pszBasename ); 00546 00547 <font class="keywordflow">if</font>( pszResult != NULL ) 00548 <font class="keywordflow">return</font> pszResult; 00549 00550 <font class="keywordflow">if</font>( getenv(<font class="stringliteral">"GEOTIFF_CSV"</font>) != NULL ) 00551 { 00552 sprintf( szPath, <font class="stringliteral">"%s/%s"</font>, getenv(<font class="stringliteral">"GEOTIFF_CSV"</font>), pszBasename ); 00553 } 00554 <font class="keywordflow">else</font> <font class="keywordflow">if</font>( (fp = fopen( <font class="stringliteral">"csv/horiz_cs.csv"</font>, <font class="stringliteral">"rt"</font> )) != NULL ) 00555 { 00556 sprintf( szPath, <font class="stringliteral">"csv/%s"</font>, pszBasename ); 00557 } 00558 <font class="keywordflow">else</font> 00559 { 00560 sprintf( szPath, <font class="stringliteral">"/usr/local/share/epsg_csv/%s"</font>, pszBasename ); 00561 } 00562 00563 <font class="keywordflow">if</font>( fp != NULL ) 00564 fclose( fp ); 00565 00566 <font class="keywordflow">return</font>( szPath ); 00567 } 00568 <font class="keywordflow">else</font> 00569 <font class="keywordflow">return</font>( pfnCSVFilenameHook( pszBasename ) ); 00570 } 00571 00572 <font class="comment">/************************************************************************/</font> 00573 <font class="comment">/* SetCSVFilenameHook() */</font> 00574 <font class="comment">/* */</font> 00575 <font class="comment">/* Applications can use this to set a function that will */</font> 00576 <font class="comment">/* massage CSV filenames. */</font> 00577 <font class="comment">/************************************************************************/</font> 00578 00623 <font class="keywordtype">void</font> SetCSVFilenameHook( <font class="keyword">const</font> <font class="keywordtype">char</font> *(*pfnNewHook)( <font class="keyword">const</font> <font class="keywordtype">char</font> * ) ) 00624 00625 { 00626 pfnCSVFilenameHook = pfnNewHook; 00627 } </div></pre><hr><address><small>Generated at Thu Mar 28 09:47:27 2002 for GDAL by <a href="http://www.stack.nl/~dimitri/doxygen/index.html"> <img src="doxygen.gif" alt="doxygen" align="middle" border=0 width=110 height=53></a>1.2.3-20001105 written by <a href="mailto:dimitri@stack.nl">Dimitri van Heesch</a>, © 1997-2000</small></address> </body> </html>