]> granicus.if.org Git - postgis/commitdiff
Update shplib to the latest release (1.3.0b3) and stitch in our special date and...
authorPaul Ramsey <pramsey@cleverelephant.ca>
Tue, 24 Jan 2012 21:57:06 +0000 (21:57 +0000)
committerPaul Ramsey <pramsey@cleverelephant.ca>
Tue, 24 Jan 2012 21:57:06 +0000 (21:57 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@8919 b70326c6-7e19-0410-871a-916f4a2858ee

loader/dbfopen.c
loader/pgsql2shp-core.c
loader/safileio.c
loader/shapefil.h
loader/shp2pgsql-core.c
loader/shpopen.c

index 6f6438d357dc21e1eb66830274b3a515706bc22e..aa50879d60645e5a758e4788355f8c5dfb63c8f8 100644 (file)
  ******************************************************************************
  *
  * $Log: dbfopen.c,v $
+ * Revision 1.89  2011-07-24 05:59:25  fwarmerdam
+ * minimize use of CPLError in favor of SAHooks.Error()
+ *
+ * Revision 1.88  2011-05-13 17:35:17  fwarmerdam
+ * added DBFReorderFields() and DBFAlterFields() functions (from Even)
+ *
+ * Revision 1.87  2011-05-07 22:41:02  fwarmerdam
+ * ensure pending record is flushed when adding a native field (GDAL #4073)
+ *
+ * Revision 1.86  2011-04-17 15:15:29  fwarmerdam
+ * Removed unused variable.
+ *
+ * Revision 1.85  2010-12-06 16:09:34  fwarmerdam
+ * fix buffer read overrun fetching code page (bug 2276)
+ *
  * Revision 1.84  2009-10-29 19:59:48  fwarmerdam
  * avoid crash on truncated header (gdal #3093)
  *
@@ -259,14 +274,10 @@ static int DBFFlushRecord( DBFHandle psDBF )
                                      psDBF->nRecordLength, 
                                      1, psDBF->fp ) != 1 )
         {
-#ifdef USE_CPL
-            CPLError( CE_Failure, CPLE_FileIO, 
-                      "Failure writing DBF record %d.", 
-                      psDBF->nCurrentRecord );
-#else           
-            fprintf( stderr, "Failure writing DBF record %d.", 
+            char szMessage[128];
+            sprintf( szMessage, "Failure writing DBF record %d.", 
                      psDBF->nCurrentRecord );
-#endif
+            psDBF->sHooks.Error( szMessage );
             return FALSE;
         }
     }
@@ -293,28 +304,20 @@ static int DBFLoadRecord( DBFHandle psDBF, int iRecord )
 
        if( psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, SEEK_SET ) != 0 )
         {
-#ifdef USE_CPL
-            CPLError( CE_Failure, CPLE_FileIO,
-                      "fseek(%ld) failed on DBF file.\n",
-                      (long) nRecordOffset );
-#else
-            fprintf( stderr, "fseek(%ld) failed on DBF file.\n",
+            char szMessage[128];
+            sprintf( szMessage, "fseek(%ld) failed on DBF file.\n",
                      (long) nRecordOffset );
-#endif
+            psDBF->sHooks.Error( szMessage );
             return FALSE;
         }
 
        if( psDBF->sHooks.FRead( psDBF->pszCurrentRecord, 
                                  psDBF->nRecordLength, 1, psDBF->fp ) != 1 )
         {
-#ifdef USE_CPL
-            CPLError( CE_Failure, CPLE_FileIO, 
-                      "fread(%d) failed on DBF file.\n",
-                      psDBF->nRecordLength );
-#else
-            fprintf( stderr, "fread(%d) failed on DBF file.\n",
+            char szMessage[128];
+            sprintf( szMessage, "fread(%d) failed on DBF file.\n",
                      psDBF->nRecordLength );
-#endif
+            psDBF->sHooks.Error( szMessage );
             return FALSE;
         }
 
@@ -491,8 +494,7 @@ DBFOpenLL( const char * pszFilename, const char * pszAccess, SAHooks *psHooks )
     if( pfCPG )
     {
         size_t n;
-        char *buffer = (char *) pabyBuf;
-        buffer[0] = '\0';
+        memset( pabyBuf, 0, nBufSize);
         psDBF->sHooks.FRead( pabyBuf, nBufSize - 1, 1, pfCPG );
         n = strcspn( (char *) pabyBuf, "\n\r" );
         if( n > 0 )
@@ -576,9 +578,6 @@ DBFOpenLL( const char * pszFilename, const char * pszAccess, SAHooks *psHooks )
 void SHPAPI_CALL
 DBFClose(DBFHandle psDBF)
 {
-    static char eof = 0x1a;
-    char eof_test;
-
     if( psDBF == NULL )
         return;
 
@@ -597,19 +596,6 @@ DBFClose(DBFHandle psDBF)
     if( psDBF->bUpdated )
         DBFUpdateHeader( psDBF );
 
-/* -------------------------------------------------------------------- */ 
-/*  Add the DBF end-of-file marker after the last record.               */ 
-/* -------------------------------------------------------------------- */ 
-
-    psDBF->sHooks.FSeek(psDBF->fp, -1, SEEK_END);
-    psDBF->sHooks.FRead(&eof_test, 1, 1, psDBF->fp); 
-    if( eof_test != 0x1a ) /* no EOF exists, so write one */ 
-    { 
-        psDBF->sHooks.FSeek(psDBF->fp, 0, SEEK_END); 
-        psDBF->sHooks.FWrite(&eof, 1, 1, psDBF->fp); 
-    } 
-
 /* -------------------------------------------------------------------- */
 /*      Close, and free resources.                                      */
 /* -------------------------------------------------------------------- */
@@ -787,7 +773,7 @@ DBFAddField(DBFHandle psDBF, const char * pszFieldName,
         chNativeType = 'L';
     else if( eType == FTString )
         chNativeType = 'C';
-    else if ( eType == FTDate )
+    else if( eType == FTDate )
         chNativeType = 'D';
     else
         chNativeType = 'N';
@@ -796,6 +782,26 @@ DBFAddField(DBFHandle psDBF, const char * pszFieldName,
                                   nWidth, nDecimals );
 }
 
+/************************************************************************/
+/*                        DBFGetNullCharacter()                         */
+/************************************************************************/
+
+static char DBFGetNullCharacter(char chType)
+{
+    switch (chType)
+    {
+      case 'N':
+      case 'F':
+        return '*';
+      case 'D':
+        return '0';
+      case 'L':
+       return '?';
+      default:
+       return ' ';
+    }
+}
+
 /************************************************************************/
 /*                            DBFAddField()                             */
 /*                                                                      */
@@ -815,6 +821,10 @@ DBFAddNativeFieldType(DBFHandle psDBF, const char * pszFieldName,
     char        chFieldFill;
     SAOffset    nRecordOffset;
 
+    /* make sure that everything is written in .dbf */
+    if( !DBFFlushRecord( psDBF ) )
+        return -1;
+
 /* -------------------------------------------------------------------- */
 /*      Do some checking to ensure we can add records to this file.     */
 /* -------------------------------------------------------------------- */
@@ -902,22 +912,7 @@ DBFAddNativeFieldType(DBFHandle psDBF, const char * pszFieldName,
     /* alloc record */
     pszRecord = (char *) malloc(sizeof(char) * psDBF->nRecordLength);
 
-    switch (chType)
-    {
-      case 'N':
-      case 'F':
-        chFieldFill = '*';
-        break;
-      case 'D':
-        chFieldFill = '0';
-        break;
-      case 'L':
-       chFieldFill = '?';
-       break;
-      default:
-       chFieldFill = ' ';
-       break;
-    }
+    chFieldFill = DBFGetNullCharacter(chType);
 
     for (i = psDBF->nRecords-1; i >= 0; --i)
     {
@@ -944,76 +939,10 @@ DBFAddNativeFieldType(DBFHandle psDBF, const char * pszFieldName,
     psDBF->bNoHeader = TRUE;
     DBFUpdateHeader( psDBF );
 
-    return( psDBF->nFields-1 );
-}
-
-/************************************************************************/
-/*                        DBFReadSetup()                                */
-/*                                                                      */
-/*      Prep a record for reading.                                      */
-/************************************************************************/
-
-int DBFReadSetup(DBFHandle psDBF, int hEntity)
-{
-        int             nRecordOffset;
-
-        /* -------------------------------------------------------------------- */
-        /*      Verify selection.                                               */
-        /* -------------------------------------------------------------------- */
-        if ( hEntity < 0 || hEntity >= psDBF->nRecords )
-                return( 0 );
-
-        /* -------------------------------------------------------------------- */
-        /*      Have we read the record?                                        */
-        /* -------------------------------------------------------------------- */
-        if ( psDBF->nCurrentRecord != hEntity )
-        {
-                DBFFlushRecord( psDBF );
-
-                nRecordOffset = psDBF->nRecordLength * hEntity + psDBF->nHeaderLength;
-
-                if ( psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 ) != 0 )
-                {
-                        fprintf( stderr, "fseek(%d) failed on DBF file.\n",
-                                 nRecordOffset );
-                        return 0;
-                }
-
-                if ( psDBF->sHooks.FRead( psDBF->pszCurrentRecord, psDBF->nRecordLength,
-                            1, psDBF->fp ) != 1 )
-                {
-                        fprintf( stderr, "fread(%d) failed on DBF file.\n",
-                                 psDBF->nRecordLength );
-                        return 0;
-                }
-
-                psDBF->nCurrentRecord = hEntity;
-        }
-
-        return 1;
-
-}
-
-
-/************************************************************************/
-/*                        DBFReadDeleted()                              */
-/*                                                                      */
-/*      Read whether a record is deleted.                               */
-/************************************************************************/
-
-int DBFReadDeleted(DBFHandle psDBF, int hEntity)
-{
-        unsigned char   *pabyRec;
-
-        if ( ! DBFReadSetup( psDBF, hEntity) )
-                return 0;
-
-        /* get reference to current record */
-        pabyRec = (unsigned char *) psDBF->pszCurrentRecord;
-
-        /* 0x20 => not deleted, 0x24 => deleted */
-        return *pabyRec == 0x20 ? 0 : 1;
+    psDBF->nCurrentRecord = -1;
+    psDBF->bCurrentRecordModified = FALSE;
 
+    return( psDBF->nFields-1 );
 }
 
 /************************************************************************/
@@ -1169,34 +1098,28 @@ DBFReadLogicalAttribute( DBFHandle psDBF, int iRecord, int iField )
     return( (const char *) DBFReadAttribute( psDBF, iRecord, iField, 'L' ) );
 }
 
+
 /************************************************************************/
-/*                         DBFIsAttributeNULL()                         */
+/*                         DBFIsValueNULL()                             */
 /*                                                                      */
-/*      Return TRUE if value for field is NULL.                         */
-/*                                                                      */
-/*      Contributed by Jim Matthews.                                    */
+/*      Return TRUE if the passed string is NULL.                       */
 /************************************************************************/
 
-int SHPAPI_CALL
-DBFIsAttributeNULL( DBFHandle psDBF, int iRecord, int iField )
-
+static int DBFIsValueNULL( char chType, const char* pszValue )
 {
-    const char *pszValue;
     int i;
 
-    pszValue = DBFReadStringAttribute( psDBF, iRecord, iField );
-
     if( pszValue == NULL )
         return TRUE;
 
-    switch(psDBF->pachFieldType[iField])
+    switch(chType)
     {
       case 'N':
       case 'F':
         /*
-        ** We accept all asterisks or all blanks as NULL 
-        ** though according to the spec I think it should be all 
-        ** asterisks. 
+        ** We accept all asterisks or all blanks as NULL
+        ** though according to the spec I think it should be all
+        ** asterisks.
         */
         if( pszValue[0] == '*' )
             return TRUE;
@@ -1209,7 +1132,7 @@ DBFIsAttributeNULL( DBFHandle psDBF, int iRecord, int iField )
         return TRUE;
 
       case 'D':
-        /* NULL date fields have value "00000000" */
+        /* NULL date fields have value "00000000" or blank or empty */
         if (pszValue[0] == '\0' ||                  // emtpy string
             strncmp(pszValue,"00000000",8) == 0 || 
             strncmp(pszValue,"        ",8) == 0) {
@@ -1220,14 +1143,12 @@ DBFIsAttributeNULL( DBFHandle psDBF, int iRecord, int iField )
         // return strncmp(pszValue,"00000000",8) == 0;
 
       case 'L':
-        // printf("Is [%s] NULL?", pszValue);
-        /* NULL boolean fields have value "?" */ 
-       if (pszValue[0] == '\0' || pszValue[0] == '?') {
-               return 1;
-       } else {
-               return 0;
-       }
-        // return pszValue[0] == '?';
+        /* NULL boolean fields have value "?" or empty */
+        if (pszValue[0] == '\0' || pszValue[0] == '?') {
+                return 1;
+        } else {
+                return 0;
+        }
 
       default:
         /* empty string fields are considered NULL */
@@ -1235,6 +1156,28 @@ DBFIsAttributeNULL( DBFHandle psDBF, int iRecord, int iField )
     }
 }
 
+/************************************************************************/
+/*                         DBFIsAttributeNULL()                         */
+/*                                                                      */
+/*      Return TRUE if value for field is NULL.                         */
+/*                                                                      */
+/*      Contributed by Jim Matthews.                                    */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFIsAttributeNULL( DBFHandle psDBF, int iRecord, int iField )
+
+{
+    const char *pszValue;
+
+    pszValue = DBFReadStringAttribute( psDBF, iRecord, iField );
+
+    if( pszValue == NULL )
+        return TRUE;
+
+    return DBFIsValueNULL( psDBF->pachFieldType[iField], pszValue );
+}
+
 /************************************************************************/
 /*                          DBFGetFieldCount()                          */
 /*                                                                      */
@@ -1295,8 +1238,7 @@ DBFGetFieldInfo( DBFHandle psDBF, int iField, char * pszFieldName,
        return( FTLogical);
 
     else if ( psDBF->pachFieldType[iField] == 'D' )
-       return ( FTDate );
+        return ( FTDate );
 
     else if( psDBF->pachFieldType[iField] == 'N' 
              || psDBF->pachFieldType[iField] == 'F' )
@@ -1370,33 +1312,9 @@ static int DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField,
 /* -------------------------------------------------------------------- */
     if( pValue == NULL )
     {
-        switch(psDBF->pachFieldType[iField])
-        {
-          case 'N':
-          case 'F':
-           /* NULL numeric fields have value "****************" */
-            memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), '*', 
-                    psDBF->panFieldSize[iField] );
-            break;
-
-          case 'D':
-           /* NULL date fields have value "00000000" */
-            memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), '0', 
-                    psDBF->panFieldSize[iField] );
-            break;
-
-          case 'L':
-           /* NULL boolean fields have value "?" */ 
-            memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), '?', 
-                    psDBF->panFieldSize[iField] );
-            break;
-
-          default:
-            /* empty string fields are considered NULL */
-            memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]), ' ', 
-                    psDBF->panFieldSize[iField] );
-            break;
-        }
+        memset( (char *) (pabyRec+psDBF->panFieldOffset[iField]),
+                DBFGetNullCharacter(psDBF->pachFieldType[iField]),
+                psDBF->panFieldSize[iField] );
         return TRUE;
     }
 
@@ -1483,7 +1401,7 @@ static int DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField,
 
 int SHPAPI_CALL
 DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity, int iField,
-                              const void * pValue )
+                              void * pValue )
 
 {
     int                        i, j;
@@ -1935,7 +1853,7 @@ DBFDeleteField(DBFHandle psDBF, int iField)
     psDBF->nRecordLength -= nDeletedFieldSize;
 
     /* overwrite field information in header */
-    memcpy(psDBF->pszHeader + iField*32,
+    memmove(psDBF->pszHeader + iField*32,
            psDBF->pszHeader + (iField+1)*32,
            sizeof(char) * (psDBF->nFields - iField)*32);
 
@@ -1983,5 +1901,337 @@ DBFDeleteField(DBFHandle psDBF, int iField)
     /* free record */
     free(pszRecord);
 
+    psDBF->nCurrentRecord = -1;
+    psDBF->bCurrentRecordModified = FALSE;
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                          DBFReorderFields()                          */
+/*                                                                      */
+/*      Reorder the fields of a .dbf file                               */
+/*                                                                      */
+/* panMap must be exactly psDBF->nFields long and be a permutation      */
+/* of [0, psDBF->nFields-1]. This assumption will not be asserted in the*/
+/* code of DBFReorderFields.                                            */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFReorderFields( DBFHandle psDBF, int* panMap )
+{
+    SAOffset nRecordOffset;
+    int      i, iRecord;
+    int     *panFieldOffsetNew;
+    int     *panFieldSizeNew;
+    int     *panFieldDecimalsNew;
+    char    *pachFieldTypeNew;
+    char    *pszHeaderNew;
+    char    *pszRecord;
+    char    *pszRecordNew;
+
+    if ( psDBF->nFields == 0 )
+        return TRUE;
+
+    /* make sure that everything is written in .dbf */
+    if( !DBFFlushRecord( psDBF ) )
+        return FALSE;
+
+    panFieldOffsetNew = (int *) malloc(sizeof(int) * psDBF->nFields);
+    panFieldSizeNew = (int *) malloc(sizeof(int) *  psDBF->nFields);
+    panFieldDecimalsNew = (int *) malloc(sizeof(int) *  psDBF->nFields);
+    pachFieldTypeNew = (char *) malloc(sizeof(char) *  psDBF->nFields);
+    pszHeaderNew = (char*) malloc(sizeof(char) * 32 *  psDBF->nFields);
+
+    /* shuffle fields definitions */
+    for(i=0; i < psDBF->nFields; i++)
+    {
+        panFieldSizeNew[i] = psDBF->panFieldSize[panMap[i]];
+        panFieldDecimalsNew[i] = psDBF->panFieldDecimals[panMap[i]];
+        pachFieldTypeNew[i] = psDBF->pachFieldType[panMap[i]];
+        memcpy(pszHeaderNew + i * 32,
+               psDBF->pszHeader + panMap[i] * 32, 32);
+    }
+    panFieldOffsetNew[0] = 1;
+    for(i=1; i < psDBF->nFields; i++)
+    {
+        panFieldOffsetNew[i] = panFieldOffsetNew[i - 1] + panFieldSizeNew[i - 1];
+    }
+
+    free(psDBF->pszHeader);
+    psDBF->pszHeader = pszHeaderNew;
+
+    /* we're done if we're dealing with not yet created .dbf */
+    if ( !(psDBF->bNoHeader && psDBF->nRecords == 0) )
+    {
+        /* force update of header with new header and record length */
+        psDBF->bNoHeader = TRUE;
+        DBFUpdateHeader( psDBF );
+
+        /* alloc record */
+        pszRecord = (char *) malloc(sizeof(char) * psDBF->nRecordLength);
+        pszRecordNew = (char *) malloc(sizeof(char) * psDBF->nRecordLength);
+
+        /* shuffle fields in records */
+        for (iRecord = 0; iRecord < psDBF->nRecords; iRecord++)
+        {
+            nRecordOffset =
+                psDBF->nRecordLength * (SAOffset) iRecord + psDBF->nHeaderLength;
+
+            /* load record */
+            psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
+            psDBF->sHooks.FRead( pszRecord, psDBF->nRecordLength, 1, psDBF->fp );
+
+            pszRecordNew[0] = pszRecord[0];
+
+            for(i=0; i < psDBF->nFields; i++)
+            {
+                memcpy(pszRecordNew + panFieldOffsetNew[i],
+                       pszRecord + psDBF->panFieldOffset[panMap[i]],
+                       psDBF->panFieldSize[panMap[i]]);
+            }
+
+            /* write record */
+            psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
+            psDBF->sHooks.FWrite( pszRecordNew, psDBF->nRecordLength, 1, psDBF->fp );
+        }
+
+        /* free record */
+        free(pszRecord);
+        free(pszRecordNew);
+    }
+
+    free(psDBF->panFieldOffset);
+    free(psDBF->panFieldSize);
+    free(psDBF->panFieldDecimals);
+    free(psDBF->pachFieldType);
+
+    psDBF->panFieldOffset = panFieldOffsetNew;
+    psDBF->panFieldSize = panFieldSizeNew;
+    psDBF->panFieldDecimals =panFieldDecimalsNew;
+    psDBF->pachFieldType = pachFieldTypeNew;
+
+    psDBF->nCurrentRecord = -1;
+    psDBF->bCurrentRecordModified = FALSE;
+
+    return TRUE;
+}
+
+
+/************************************************************************/
+/*                          DBFAlterFieldDefn()                         */
+/*                                                                      */
+/*      Alter a field definition in a .dbf file                         */
+/************************************************************************/
+
+int SHPAPI_CALL
+DBFAlterFieldDefn( DBFHandle psDBF, int iField, const char * pszFieldName,
+                    char chType, int nWidth, int nDecimals )
+{
+    int   i;
+    int   iRecord;
+    int   nOffset;
+    int   nOldWidth;
+    int   nOldRecordLength;
+    int   nRecordOffset;
+    char* pszFInfo;
+    char  chOldType;
+    int   bIsNULL;
+    char chFieldFill;
+
+    if (iField < 0 || iField >= psDBF->nFields)
+        return FALSE;
+
+    /* make sure that everything is written in .dbf */
+    if( !DBFFlushRecord( psDBF ) )
+        return FALSE;
+
+    chFieldFill = DBFGetNullCharacter(chType);
+
+    chOldType = psDBF->pachFieldType[iField];
+    nOffset = psDBF->panFieldOffset[iField];
+    nOldWidth = psDBF->panFieldSize[iField];
+    nOldRecordLength = psDBF->nRecordLength;
+
+/* -------------------------------------------------------------------- */
+/*      Do some checking to ensure we can add records to this file.     */
+/* -------------------------------------------------------------------- */
+    if( nWidth < 1 )
+        return -1;
+
+    if( nWidth > 255 )
+        nWidth = 255;
+
+/* -------------------------------------------------------------------- */
+/*      Assign the new field information fields.                        */
+/* -------------------------------------------------------------------- */
+    psDBF->panFieldSize[iField] = nWidth;
+    psDBF->panFieldDecimals[iField] = nDecimals;
+    psDBF->pachFieldType[iField] = chType;
+
+/* -------------------------------------------------------------------- */
+/*      Update the header information.                                  */
+/* -------------------------------------------------------------------- */
+    pszFInfo = psDBF->pszHeader + 32 * iField;
+
+    for( i = 0; i < 32; i++ )
+        pszFInfo[i] = '\0';
+
+    if( (int) strlen(pszFieldName) < 10 )
+        strncpy( pszFInfo, pszFieldName, strlen(pszFieldName));
+    else
+        strncpy( pszFInfo, pszFieldName, 10);
+
+    pszFInfo[11] = psDBF->pachFieldType[iField];
+
+    if( chType == 'C' )
+    {
+        pszFInfo[16] = (unsigned char) (nWidth % 256);
+        pszFInfo[17] = (unsigned char) (nWidth / 256);
+    }
+    else
+    {
+        pszFInfo[16] = (unsigned char) nWidth;
+        pszFInfo[17] = (unsigned char) nDecimals;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Update offsets                                                  */
+/* -------------------------------------------------------------------- */
+    if (nWidth != nOldWidth)
+    {
+        for (i = iField + 1; i < psDBF->nFields; i++)
+             psDBF->panFieldOffset[i] += nWidth - nOldWidth;
+        psDBF->nRecordLength += nWidth - nOldWidth;
+
+        psDBF->pszCurrentRecord = (char *) SfRealloc(psDBF->pszCurrentRecord,
+                                                     psDBF->nRecordLength);
+    }
+
+    /* we're done if we're dealing with not yet created .dbf */
+    if ( psDBF->bNoHeader && psDBF->nRecords == 0 )
+        return TRUE;
+
+    /* force update of header with new header and record length */
+    psDBF->bNoHeader = TRUE;
+    DBFUpdateHeader( psDBF );
+
+    if (nWidth < nOldWidth || (nWidth == nOldWidth && chType != chOldType))
+    {
+        char* pszRecord = (char *) malloc(sizeof(char) * nOldRecordLength);
+        char* pszOldField = (char *) malloc(sizeof(char) * (nOldWidth + 1));
+
+        pszOldField[nOldWidth] = 0;
+
+        /* move records to their new positions */
+        for (iRecord = 0; iRecord < psDBF->nRecords; iRecord++)
+        {
+            nRecordOffset =
+                nOldRecordLength * (SAOffset) iRecord + psDBF->nHeaderLength;
+
+            /* load record */
+            psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
+            psDBF->sHooks.FRead( pszRecord, nOldRecordLength, 1, psDBF->fp );
+
+            memcpy(pszOldField, pszRecord + nOffset, nOldWidth);
+            bIsNULL = DBFIsValueNULL( chOldType, pszOldField );
+
+            if (nWidth != nOldWidth)
+            {
+                if ((chOldType == 'N' || chOldType == 'F') && pszOldField[0] == ' ')
+                {
+                    /* Strip leading spaces when truncating a numeric field */
+                    memmove( pszRecord + nOffset,
+                            pszRecord + nOffset + nOldWidth - nWidth,
+                            nWidth );
+                }
+                if (nOffset + nOldWidth < nOldRecordLength)
+                {
+                    memmove( pszRecord + nOffset + nWidth,
+                            pszRecord + nOffset + nOldWidth,
+                            nOldRecordLength - (nOffset + nOldWidth));
+                }
+            }
+
+            /* Convert null value to the appropriate value of the new type */
+            if (bIsNULL)
+            {
+                memset( pszRecord + nOffset, chFieldFill, nWidth);
+            }
+
+            nRecordOffset =
+                psDBF->nRecordLength * (SAOffset) iRecord + psDBF->nHeaderLength;
+
+            /* write record */
+            psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
+            psDBF->sHooks.FWrite( pszRecord, psDBF->nRecordLength, 1, psDBF->fp );
+        }
+
+        free(pszRecord);
+        free(pszOldField);
+    }
+    else if (nWidth > nOldWidth)
+    {
+        char* pszRecord = (char *) malloc(sizeof(char) * psDBF->nRecordLength);
+        char* pszOldField = (char *) malloc(sizeof(char) * (nOldWidth + 1));
+
+        pszOldField[nOldWidth] = 0;
+
+        /* move records to their new positions */
+        for (iRecord = psDBF->nRecords - 1; iRecord >= 0; iRecord--)
+        {
+            nRecordOffset =
+                nOldRecordLength * (SAOffset) iRecord + psDBF->nHeaderLength;
+
+            /* load record */
+            psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
+            psDBF->sHooks.FRead( pszRecord, nOldRecordLength, 1, psDBF->fp );
+
+            memcpy(pszOldField, pszRecord + nOffset, nOldWidth);
+            bIsNULL = DBFIsValueNULL( chOldType, pszOldField );
+
+            if (nOffset + nOldWidth < nOldRecordLength)
+            {
+                memmove( pszRecord + nOffset + nWidth,
+                         pszRecord + nOffset + nOldWidth,
+                         nOldRecordLength - (nOffset + nOldWidth));
+            }
+
+            /* Convert null value to the appropriate value of the new type */
+            if (bIsNULL)
+            {
+                memset( pszRecord + nOffset, chFieldFill, nWidth);
+            }
+            else
+            {
+                if ((chOldType == 'N' || chOldType == 'F'))
+                {
+                    /* Add leading spaces when expanding a numeric field */
+                    memmove( pszRecord + nOffset + nWidth - nOldWidth,
+                             pszRecord + nOffset, nOldWidth );
+                    memset( pszRecord + nOffset, ' ', nWidth - nOldWidth );
+                }
+                else
+                {
+                    /* Add trailing spaces */
+                    memset(pszRecord + nOffset + nOldWidth, ' ', nWidth - nOldWidth);
+                }
+            }
+
+            nRecordOffset =
+                psDBF->nRecordLength * (SAOffset) iRecord + psDBF->nHeaderLength;
+
+            /* write record */
+            psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
+            psDBF->sHooks.FWrite( pszRecord, psDBF->nRecordLength, 1, psDBF->fp );
+        }
+
+        free(pszRecord);
+        free(pszOldField);
+    }
+
+    psDBF->nCurrentRecord = -1;
+    psDBF->bCurrentRecordModified = FALSE;
+
     return TRUE;
 }
index c3075e879f6b70070ca88b866a0e2e878832d7b1..d2abacf5595cdce2cd38ce36186c308af0dcfed0 100644 (file)
@@ -64,7 +64,7 @@ static SHPObject *create_polygon(SHPDUMPERSTATE *state, LWPOLY *lwpolygon);
 static SHPObject *create_multipolygon(SHPDUMPERSTATE *state, LWMPOLY *lwmultipolygon);
 static SHPObject *create_linestring(SHPDUMPERSTATE *state, LWLINE *lwlinestring);
 static SHPObject *create_multilinestring(SHPDUMPERSTATE *state, LWMLINE *lwmultilinestring);
-static const char *nullDBFValue(char fieldType);
+static char *nullDBFValue(char fieldType);
 static int getMaxFieldSize(PGconn *conn, char *schema, char *table, char *fname);
 static int getTableInfo(SHPDUMPERSTATE *state);
 static int projFileCreate(SHPDUMPERSTATE *state);
@@ -74,7 +74,7 @@ static int projFileCreate(SHPDUMPERSTATE *state);
  * Might return untouched input or pointer to static private
  * buffer: use return value right away.
  */
-static const char * goodDBFValue(const char *in, char fieldType);
+static char * goodDBFValue(char *in, char fieldType);
 
 /** @brief Binary to hexewkb conversion function */
 char *convert_bytes_to_hex(uint8_t *ewkb, size_t size);
@@ -633,7 +633,7 @@ shapetypename(int num)
 
 
 /* This is taken and adapted from dbfopen.c of shapelib */
-static const char *
+static char *
 nullDBFValue(char fieldType)
 {
        switch (fieldType)
@@ -662,8 +662,8 @@ nullDBFValue(char fieldType)
  *             Might return untouched input or pointer to static private
  *             buffer: use return value right away.
  */
-static const char *
-goodDBFValue(const char *in, char fieldType)
+static char *
+goodDBFValue(char *in, char fieldType)
 {
        /*
         * We only work on FTLogical and FTDate.
@@ -2026,7 +2026,7 @@ int ShpLoaderGenerateShapeRow(SHPDUMPERSTATE *state)
        char *hexewkb = NULL;
        unsigned char *hexewkb_binary = NULL;
        size_t hexewkb_len;
-       const char *val;
+       char *val;
        SHPObject *obj = NULL;
        LWGEOM *lwgeom;
 
index 43b1e3106550d0509ab8f5bc291aa6fab3dfc762..f3affe2ea504fb8d559d878544765120dd140dcb 100644 (file)
@@ -76,18 +76,6 @@ SHP_CVSID("$Id: safileio.c,v 1.4 2008-01-16 20:05:14 bram Exp $");
 #   endif
 #endif
 
-/* Local Prototypes */
-SAFile SADFOpen( const char *pszFilename, const char *pszAccess );
-SAOffset SADFRead( void *p, SAOffset size, SAOffset nmemb, SAFile file );
-SAOffset SADFWrite( void *p, SAOffset size, SAOffset nmemb, SAFile file );
-SAOffset SADFSeek( SAFile file, SAOffset offset, int whence );
-SAOffset SADFTell( SAFile file );
-int SADFFlush( SAFile file );
-int SADFClose( SAFile file );
-int SADRemove( const char *filename );
-void SADError( const char *message );
-
-
 /************************************************************************/
 /*                              SADFOpen()                              */
 /************************************************************************/
index 535c880fae0ddca2892d6c4cfcd70b404d07b3b4..b6ca718ed288cbecf9ca1c167c541d494ff53319 100644 (file)
  ******************************************************************************
  *
  * $Log: shapefil.h,v $
+ * Revision 1.51  2011-07-24 05:59:25  fwarmerdam
+ * minimize use of CPLError in favor of SAHooks.Error()
+ *
+ * Revision 1.50  2011-05-13 17:35:17  fwarmerdam
+ * added DBFReorderFields() and DBFAlterFields() functions (from Even)
+ *
+ * Revision 1.49  2011-04-16 14:38:21  fwarmerdam
+ * avoid warnings with gcc on SHP_CVSID
+ *
+ * Revision 1.48  2010-08-27 23:42:52  fwarmerdam
+ * add SHPAPI_CALL attribute in code
+ *
  * Revision 1.47  2010-01-28 11:34:34  fwarmerdam
  * handle the shape file length limits more gracefully (#3236)
  *
 #include <dbmalloc.h>
 #endif
 
-#ifdef USE_CPL
-#include "cpl_error.h"
-#include "cpl_vsi.h"
-#endif
-
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -209,8 +216,12 @@ extern "C" {
 /*      as unreferenced variables resulting in lots of warnings.        */
 /* -------------------------------------------------------------------- */
 #ifndef DISABLE_CVSID
-#  define SHP_CVSID(string)     static char cpl_cvsid[] = string; \
+#  if defined(__GNUC__) && __GNUC__ >= 4
+#    define SHP_CVSID(string)     static char cpl_cvsid[] __attribute__((used)) = string;
+#  else
+#    define SHP_CVSID(string)     static char cpl_cvsid[] = string; \
 static char *cvsid_aw() { return( cvsid_aw() ? ((char *) NULL) : cpl_cvsid ); }
+#  endif
 #else
 #  define SHP_CVSID(string)
 #endif
@@ -444,8 +455,6 @@ void    SHPAPI_CALL
 
 int    SHPAPI_CALL
       SHPWriteTree( SHPTree *hTree, const char * pszFilename );
-SHPTree SHPAPI_CALL
-      SHPReadTree( const char * pszFilename );
 
 int    SHPAPI_CALL
       SHPTreeAddObject( SHPTree * hTree, SHPObject * psObject );
@@ -548,6 +557,13 @@ int        SHPAPI_CALL
 int    SHPAPI_CALL
       DBFDeleteField( DBFHandle hDBF, int iField );
 
+int SHPAPI_CALL
+      DBFReorderFields( DBFHandle psDBF, int* panMap );
+
+int SHPAPI_CALL
+      DBFAlterFieldDefn( DBFHandle psDBF, int iField, const char * pszFieldName,
+                         char chType, int nWidth, int nDecimals );
+
 DBFFieldType SHPAPI_CALL
       DBFGetFieldInfo( DBFHandle psDBF, int iField, 
                        char * pszFieldName, int * pnWidth, int * pnDecimals );
@@ -566,11 +582,6 @@ const char SHPAPI_CALL1(*)
 int     SHPAPI_CALL
       DBFIsAttributeNULL( DBFHandle hDBF, int iShape, int iField );
 
-int SHPAPI_CALL
-      DBFReadSetup ( DBFHandle psDBF, int hEntity );
-int SHPAPI_CALL
-      DBFReadDeleted ( DBFHandle psDBF, int hEntity );
-
 int SHPAPI_CALL
       DBFWriteIntegerAttribute( DBFHandle hDBF, int iShape, int iField, 
                                 int nFieldValue );
@@ -588,7 +599,7 @@ int SHPAPI_CALL
                               const char lFieldValue);
 int SHPAPI_CALL
      DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity, int iField,
-                               const void * pValue );
+                               void * pValue );
 const char SHPAPI_CALL1(*)
       DBFReadTuple(DBFHandle psDBF, int hEntity );
 int SHPAPI_CALL
index 31704c5581baed4f9ee1362119f4f5908b159e05..e66bcb6995def370048a6ce4a00f29874c3d1816 100644 (file)
@@ -1453,7 +1453,7 @@ ShpLoaderGenerateSQLRowStatement(SHPLOADERSTATE *state, int item, char **strreco
        stringbuffer_clear(sb);
 
        /* If we are reading the DBF only and the record has been marked deleted, return deleted record status */
-       if (state->config->readshape == 0 && DBFReadDeleted(state->hDBFHandle, item))
+       if (state->config->readshape == 0 && DBFIsRecordDeleted(state->hDBFHandle, item))
        {
                *strrecord = NULL;
                return SHPLOADERRECDELETED;
index 689a2ddc92e230df444eb194d6c554e2eacc2d1a..197071f31d0b1fbf3338fbe551aec413305298a7 100644 (file)
  ******************************************************************************
  *
  * $Log: shpopen.c,v $
+ * Revision 1.70  2011-07-24 05:59:25  fwarmerdam
+ * minimize use of CPLError in favor of SAHooks.Error()
+ *
+ * Revision 1.69  2011-07-24 03:24:22  fwarmerdam
+ * fix memory leaks in error cases creating shapefiles (#2061)
+ *
+ * Revision 1.68  2010-08-27 23:42:52  fwarmerdam
+ * add SHPAPI_CALL attribute in code
+ *
  * Revision 1.67  2010-07-01 08:15:48  fwarmerdam
  * do not error out on an object with zero vertices
  *
 
 SHP_CVSID("$Id$")
 
-typedef unsigned char uint8_t;
+typedef unsigned char uchar;
 
 #if UINT_MAX == 65535
 typedef unsigned long        int32;
@@ -295,13 +304,13 @@ static void       SwapWord( int length, void * wordP )
 
 {
     int                i;
-    uint8_t    temp;
+    uchar      temp;
 
     for( i=0; i < length/2; i++ )
     {
-       temp = ((uint8_t *) wordP)[i];
-       ((uint8_t *)wordP)[i] = ((uint8_t *) wordP)[length-i-1];
-       ((uint8_t *) wordP)[length-i-1] = temp;
+       temp = ((uchar *) wordP)[i];
+       ((uchar *)wordP)[i] = ((uchar *) wordP)[length-i-1];
+       ((uchar *) wordP)[length-i-1] = temp;
     }
 }
 
@@ -328,10 +337,10 @@ static void * SfRealloc( void * pMem, int nNewSize )
 /*     contents of the index (.shx) file.                              */
 /************************************************************************/
 
-void SHPWriteHeader( SHPHandle psSHP )
+void SHPAPI_CALL SHPWriteHeader( SHPHandle psSHP )
 
 {
-    uint8_t            abyHeader[100];
+    uchar      abyHeader[100];
     int                i;
     int32      i32;
     double     dValue;
@@ -477,10 +486,9 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
     char               *pszFullname, *pszBasename;
     SHPHandle          psSHP;
     
-    uint8_t            *pabyBuf;
+    uchar              *pabyBuf;
     int                        i;
     double             dValue;
-    int                 recordsInSHP;
     
 /* -------------------------------------------------------------------- */
 /*      Ensure the access string is one of the legal ones.  We          */
@@ -497,7 +505,7 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
 /*     Establish the byte order on this machine.                       */
 /* -------------------------------------------------------------------- */
     i = 1;
-    if( *((uint8_t *) &i) == 1 )
+    if( *((uchar *) &i) == 1 )
         bBigEndian = FALSE;
     else
         bBigEndian = TRUE;
@@ -539,15 +547,11 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
     
     if( psSHP->fpSHP == NULL )
     {
-#ifdef USE_CPL
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Unable to open %s.shp or %s.SHP.", 
+        char *pszMessage = (char *) malloc(strlen(pszBasename)*2+256);
+        sprintf( pszMessage, "Unable to open %s.shp or %s.SHP.", 
                   pszBasename, pszBasename );
-#endif
-        free( psSHP );
-        free( pszBasename );
-        free( pszFullname );
-        return( NULL );
+        psHooks->Error( pszMessage );
+        free( pszMessage );
     }
 
     sprintf( pszFullname, "%s.shx", pszBasename );
@@ -560,11 +564,12 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
     
     if( psSHP->fpSHX == NULL )
     {
-#ifdef USE_CPL
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Unable to open %s.shx or %s.SHX.", 
+        char *pszMessage = (char *) malloc(strlen(pszBasename)*2+256);
+        sprintf( pszMessage, "Unable to open %s.shx or %s.SHX.", 
                   pszBasename, pszBasename );
-#endif
+        psHooks->Error( pszMessage );
+        free( pszMessage );
+
         psSHP->sHooks.FClose( psSHP->fpSHP );
         free( psSHP );
         free( pszBasename );
@@ -578,7 +583,7 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
 /* -------------------------------------------------------------------- */
 /*  Read the file size from the SHP file.                              */
 /* -------------------------------------------------------------------- */
-    pabyBuf = (uint8_t *) malloc(100);
+    pabyBuf = (uchar *) malloc(100);
     psSHP->sHooks.FRead( pabyBuf, 100, 1, psSHP->fpSHP );
 
     psSHP->nFileSize = ((unsigned int)pabyBuf[24] * 256 * 256 * 256
@@ -673,7 +678,7 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
         malloc(sizeof(unsigned int) * MAX(1,psSHP->nMaxRecords) );
     psSHP->panRecSize = (unsigned int *)
         malloc(sizeof(unsigned int) * MAX(1,psSHP->nMaxRecords) );
-    pabyBuf = (uint8_t *) malloc(8 * MAX(1,psSHP->nRecords) );
+    pabyBuf = (uchar *) malloc(8 * MAX(1,psSHP->nRecords) );
 
     if (psSHP->panRecOffset == NULL ||
         psSHP->panRecSize == NULL ||
@@ -695,15 +700,14 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
         return( NULL );
     }
 
-    recordsInSHP = (int) psSHP->sHooks.FRead( pabyBuf, 8, psSHP->nRecords, psSHP->fpSHX );
-    if( recordsInSHP 
+    if( (int) psSHP->sHooks.FRead( pabyBuf, 8, psSHP->nRecords, psSHP->fpSHX ) 
         != psSHP->nRecords )
     {
         char szError[200];
 
         sprintf( szError, 
-                 "Failed to read all values for %d records in .shx file, %d expected.",
-                 psSHP->nRecords, recordsInSHP );
+                 "Failed to read all values for %d records in .shx file.",
+                 psSHP->nRecords );
         psSHP->sHooks.Error( szError );
 
         /* SHX is short or unreadable for some reason. */
@@ -839,10 +843,10 @@ SHPHandle SHPAPI_CALL
 SHPCreateLL( const char * pszLayer, int nShapeType, SAHooks *psHooks )
 
 {
-    char       *pszBasename, *pszFullname;
+    char       *pszBasename = NULL, *pszFullname = NULL;
     int                i;
-    SAFile     fpSHP, fpSHX;
-    uint8_t            abyHeader[100];
+    SAFile     fpSHP = NULL, fpSHX = NULL;
+    uchar      abyHeader[100];
     int32      i32;
     double     dValue;
     
@@ -850,7 +854,7 @@ SHPCreateLL( const char * pszLayer, int nShapeType, SAHooks *psHooks )
 /*      Establish the byte order on this system.                        */
 /* -------------------------------------------------------------------- */
     i = 1;
-    if( *((uint8_t *) &i) == 1 )
+    if( *((uchar *) &i) == 1 )
         bBigEndian = FALSE;
     else
         bBigEndian = TRUE;
@@ -878,7 +882,7 @@ SHPCreateLL( const char * pszLayer, int nShapeType, SAHooks *psHooks )
     if( fpSHP == NULL )
     {
         psHooks->Error( "Failed to create file .shp file." );
-        return( NULL );
+        goto error;
     }
 
     sprintf( pszFullname, "%s.shx", pszBasename );
@@ -886,11 +890,11 @@ SHPCreateLL( const char * pszLayer, int nShapeType, SAHooks *psHooks )
     if( fpSHX == NULL )
     {
         psHooks->Error( "Failed to create file .shx file." );
-        return( NULL );
+        goto error;
     }
 
-    free( pszFullname );
-    free( pszBasename );
+    free( pszFullname ); pszFullname = NULL;
+    free( pszBasename ); pszBasename = NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Prepare header block for .shp file.                             */
@@ -925,7 +929,7 @@ SHPCreateLL( const char * pszLayer, int nShapeType, SAHooks *psHooks )
     if( psHooks->FWrite( abyHeader, 100, 1, fpSHP ) != 1 )
     {
         psHooks->Error( "Failed to write .shp header." );
-        return NULL;
+        goto error;
     }
 
 /* -------------------------------------------------------------------- */
@@ -938,7 +942,7 @@ SHPCreateLL( const char * pszLayer, int nShapeType, SAHooks *psHooks )
     if( psHooks->FWrite( abyHeader, 100, 1, fpSHX ) != 1 )
     {
         psHooks->Error( "Failed to write .shx header." );
-        return NULL;
+        goto error;
     }
 
 /* -------------------------------------------------------------------- */
@@ -948,6 +952,13 @@ SHPCreateLL( const char * pszLayer, int nShapeType, SAHooks *psHooks )
     psHooks->FClose( fpSHX );
 
     return( SHPOpenLL( pszLayer, "r+b", psHooks ) );
+
+error:
+    if (pszFullname) free(pszFullname);
+    if (pszBasename) free(pszBasename);
+    if (fpSHP) psHooks->FClose( fpSHP );
+    if (fpSHX) psHooks->FClose( fpSHX );
+    return NULL;
 }
 
 /************************************************************************/
@@ -957,7 +968,7 @@ SHPCreateLL( const char * pszLayer, int nShapeType, SAHooks *psHooks )
 /*      indicated location in the record.                               */
 /************************************************************************/
 
-static void    _SHPSetBounds( uint8_t * pabyRec, SHPObject * psShape )
+static void    _SHPSetBounds( uchar * pabyRec, SHPObject * psShape )
 
 {
     ByteCopy( &(psShape->dfXMin), pabyRec +  0, 8 );
@@ -1158,7 +1169,7 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
 {
     unsigned int               nRecordOffset, nRecordSize=0;
     int i;
-    uint8_t    *pabyRec;
+    uchar      *pabyRec;
     int32      i32;
 
     psSHP->bUpdated = TRUE;
@@ -1197,7 +1208,7 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
 /* -------------------------------------------------------------------- */
 /*      Initialize record.                                              */
 /* -------------------------------------------------------------------- */
-    pabyRec = (uint8_t *) malloc(psObject->nVertices * 4 * sizeof(double) 
+    pabyRec = (uchar *) malloc(psObject->nVertices * 4 * sizeof(double) 
                                + psObject->nParts * 8 + 128);
     
 /* -------------------------------------------------------------------- */
@@ -1565,7 +1576,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
     nEntitySize = psSHP->panRecSize[hEntity]+8;
     if( nEntitySize > psSHP->nBufSize )
     {
-        psSHP->pabyRec = (uint8_t *) SfRealloc(psSHP->pabyRec,nEntitySize);
+        psSHP->pabyRec = (uchar *) SfRealloc(psSHP->pabyRec,nEntitySize);
         if (psSHP->pabyRec == NULL)
         {
             char szError[200];