Beispiel #1
0
static void CPLQuadTreeNodeAddFeatureAlg1( CPLQuadTree* hQuadTree,
                                           QuadTreeNode *psNode,
                                           void* hFeature,
                                           const CPLRectObj* pRect)
{
    int i;
    if (psNode->nNumSubNodes == 0)
    {
        /* If we have reached the max bucket capacity, try to insert */
        /* in a subnode if possible */
        if (psNode->nFeatures >= hQuadTree->nBucketCapacity)
        {
            CPLRectObj half1, half2, quad1, quad2, quad3, quad4;

            CPLQuadTreeSplitBounds(hQuadTree->dfSplitRatio, &psNode->rect, &half1, &half2);
            CPLQuadTreeSplitBounds(hQuadTree->dfSplitRatio, &half1, &quad1, &quad2);
            CPLQuadTreeSplitBounds(hQuadTree->dfSplitRatio, &half2, &quad3, &quad4);

            if (memcmp(&psNode->rect, &quad1, sizeof(CPLRectObj)) != 0 &&
                memcmp(&psNode->rect, &quad2, sizeof(CPLRectObj)) != 0 &&
                memcmp(&psNode->rect, &quad3, sizeof(CPLRectObj)) != 0 &&
                memcmp(&psNode->rect, &quad4, sizeof(CPLRectObj)) != 0 &&
                (CPL_RectContained(pRect, &quad1) ||
                CPL_RectContained(pRect, &quad2) ||
                CPL_RectContained(pRect, &quad3) ||
                CPL_RectContained(pRect, &quad4)))
            {
                psNode->nNumSubNodes = 4;
                psNode->apSubNode[0] = CPLQuadTreeNodeCreate(&quad1);
                psNode->apSubNode[1] = CPLQuadTreeNodeCreate(&quad2);
                psNode->apSubNode[2] = CPLQuadTreeNodeCreate(&quad3);
                psNode->apSubNode[3] = CPLQuadTreeNodeCreate(&quad4);

                int oldNumFeatures = psNode->nFeatures;
                void** oldFeatures = psNode->pahFeatures;
                CPLRectObj* pasOldBounds = psNode->pasBounds;
                psNode->nFeatures = 0;
                psNode->pahFeatures = NULL;
                psNode->pasBounds = NULL;

                /* redispatch existing pahFeatures in apSubNodes */
                int i;
                for(i=0;i<oldNumFeatures;i++)
                {
                    if( hQuadTree->pfnGetBounds == NULL )
                        CPLQuadTreeNodeAddFeatureAlg1(hQuadTree, psNode, oldFeatures[i], &pasOldBounds[i]);
                    else
                    {
                        CPLRectObj bounds;
                        hQuadTree->pfnGetBounds(oldFeatures[i], &bounds);
                        CPLQuadTreeNodeAddFeatureAlg1(hQuadTree, psNode, oldFeatures[i], &bounds);
                    }
                }

                CPLFree(oldFeatures);
                CPLFree(pasOldBounds);

                /* recurse back on this psNode now that it has apSubNodes */
                CPLQuadTreeNodeAddFeatureAlg1(hQuadTree, psNode, hFeature, pRect);
                return;
            }
        }
    }
    else
    {
    /* -------------------------------------------------------------------- */
    /*      If there are apSubNodes, then consider whether this object        */
    /*      will fit in them.                                               */
    /* -------------------------------------------------------------------- */
        for(i=0; i<psNode->nNumSubNodes; i++ )
        {
            if( CPL_RectContained(pRect, &psNode->apSubNode[i]->rect))
            {
                CPLQuadTreeNodeAddFeatureAlg1( hQuadTree, psNode->apSubNode[i], hFeature, pRect);
                return;
            }
        }
    }

/* -------------------------------------------------------------------- */
/*      If none of that worked, just add it to this psNodes list.         */
/* -------------------------------------------------------------------- */
    psNode->nFeatures++;

    if( psNode->nFeatures == 1 )
    {
        CPLAssert( psNode->pahFeatures == NULL );
        psNode->pahFeatures = (void**) CPLMalloc( hQuadTree->nBucketCapacity * sizeof(void*) );
        if( hQuadTree->pfnGetBounds == NULL )
            psNode->pasBounds = (CPLRectObj*) CPLMalloc( hQuadTree->nBucketCapacity * sizeof(CPLRectObj) );
    }
    else if( psNode->nFeatures > hQuadTree->nBucketCapacity )
    {
        psNode->pahFeatures = (void**) CPLRealloc( psNode->pahFeatures, sizeof(void*) * psNode->nFeatures );
        if( hQuadTree->pfnGetBounds == NULL )
            psNode->pasBounds = (CPLRectObj*) CPLRealloc( psNode->pasBounds, sizeof(CPLRectObj) * psNode->nFeatures );
    }
    psNode->pahFeatures[psNode->nFeatures-1] = hFeature;
    if( hQuadTree->pfnGetBounds == NULL )
        psNode->pasBounds[psNode->nFeatures-1] = *pRect;

    return ;
}
OGRLayer *OGRSelafinDataSource::ICreateLayer( const char *pszLayerName, OGRSpatialReference *poSpatialRefP, OGRwkbGeometryType eGType, char ** papszOptions  ) {
    CPLDebug("Selafin","CreateLayer(%s,%s)",pszLayerName,(eGType==wkbPoint)?"wkbPoint":"wkbPolygon");
    // Verify we are in update mode.
    if ( !bUpdate )
    {
        CPLError( CE_Failure, CPLE_NoWriteAccess,
                  "Data source %s opened read-only.  "
                  "New layer %s cannot be created.",
                  pszName, pszLayerName );
        return NULL;
    }
    // Check that new layer is a point or polygon layer
    if( eGType != wkbPoint )
    {
        CPLError( CE_Failure, CPLE_NoWriteAccess, "Selafin format can only handle %s layers whereas input is %s\n.", OGRGeometryTypeToName(wkbPoint),OGRGeometryTypeToName(eGType));
        return NULL;
    }
    // Parse options
    const char *pszTemp=CSLFetchNameValue(papszOptions,"DATE");
    const double dfDate = pszTemp != NULL ? CPLAtof(pszTemp) : 0.0;
    // Set the SRS of the datasource if this is the first layer
    if (nLayers==0 && poSpatialRefP!=NULL) {
        poSpatialRef=poSpatialRefP;
        poSpatialRef->Reference();
        const char* szEpsg=poSpatialRef->GetAttrValue("GEOGCS|AUTHORITY",1);
        int nEpsg=0;
        if (szEpsg!=NULL) nEpsg=(int)strtol(szEpsg,NULL,10);
        if (nEpsg==0) {
            CPLError(CE_Warning,CPLE_AppDefined,"Could not find EPSG code for SRS. The SRS won't be saved in the datasource.");
        } else {
            poHeader->nEpsg=nEpsg;
        }
    }
    // Create the new layer in the Selafin file by adding a "time step" at the end
    // Beware, as the new layer shares the same header, it automatically contains the same number of features and fields as the existing ones. This may not be intuitive for the user.
    if (VSIFSeekL(poHeader->fp,0,SEEK_END)!=0) return NULL;
    if (Selafin::write_integer(poHeader->fp,4)==0 ||
        Selafin::write_float(poHeader->fp,dfDate)==0 ||
        Selafin::write_integer(poHeader->fp,4)==0) {
        CPLError( CE_Failure, CPLE_FileIO, "Could not write to Selafin file %s.\n",pszName);
        return NULL;
    }
    double *pdfValues=NULL;
    if (poHeader->nPoints>0)
    {
        pdfValues=(double*)VSI_MALLOC2_VERBOSE(sizeof(double),poHeader->nPoints);
        if( pdfValues == NULL )
            return NULL;
    }
    for (int i=0;i<poHeader->nVar;++i) {
        if (Selafin::write_floatarray(poHeader->fp,pdfValues,poHeader->nPoints)==0) {
            CPLError( CE_Failure, CPLE_FileIO, "Could not write to Selafin file %s.\n",pszName);
            CPLFree(pdfValues);
            return NULL;
        }
    }
    CPLFree(pdfValues);
    VSIFFlushL(poHeader->fp);
    poHeader->nSteps++;
    // Create two layers as usual, one for points and one for elements
    nLayers+=2;
    papoLayers = (OGRSelafinLayer **) CPLRealloc(papoLayers, sizeof(void*) * nLayers);
    CPLString szName=pszLayerName;
    CPLString szNewLayerName=szName+"_p";
    papoLayers[nLayers-2] =
        new OGRSelafinLayer( szNewLayerName, bUpdate, poSpatialRef, poHeader,
                             poHeader->nSteps-1, POINTS );
    szNewLayerName=szName+"_e";
    papoLayers[nLayers-1] =
        new OGRSelafinLayer( szNewLayerName, bUpdate, poSpatialRef, poHeader,
                             poHeader->nSteps-1, ELEMENTS );
    return papoLayers[nLayers-2];
}
Beispiel #3
0
int OGRMDBDataSource::OpenGDB(OGRMDBTable* poGDB_GeomColumns)
{
    int iTableName = poGDB_GeomColumns->GetColumnIndex("TableName", TRUE);
    int iFieldName = poGDB_GeomColumns->GetColumnIndex("FieldName", TRUE);
    int iShapeType = poGDB_GeomColumns->GetColumnIndex("ShapeType", TRUE);
    int iExtentLeft = poGDB_GeomColumns->GetColumnIndex("ExtentLeft", TRUE);
    int iExtentRight = poGDB_GeomColumns->GetColumnIndex("ExtentRight", TRUE);
    int iExtentBottom = poGDB_GeomColumns->GetColumnIndex("ExtentBottom", TRUE);
    int iExtentTop = poGDB_GeomColumns->GetColumnIndex("ExtentTop", TRUE);
    int iSRID = poGDB_GeomColumns->GetColumnIndex("SRID", TRUE);
    int iHasZ = poGDB_GeomColumns->GetColumnIndex("HasZ", TRUE);

    if (iTableName < 0 || iFieldName < 0 || iShapeType < 0 ||
        iExtentLeft < 0 || iExtentRight < 0 || iExtentBottom < 0 ||
        iExtentTop < 0 || iSRID < 0 || iHasZ < 0)
        return FALSE;

    while(poGDB_GeomColumns->GetNextRow())
    {
        OGRMDBLayer  *poLayer;

        char* pszTableName = poGDB_GeomColumns->GetColumnAsString(iTableName);
        char* pszFieldName = poGDB_GeomColumns->GetColumnAsString(iFieldName);
        if (pszTableName == NULL || pszFieldName == NULL)
        {
            CPLFree(pszTableName);
            CPLFree(pszFieldName);
            continue;
        }

        OGRMDBTable* poTable = poDB->GetTable(pszTableName);
        if (poTable == NULL)
        {
            CPLFree(pszTableName);
            CPLFree(pszFieldName);
            continue;
        }

        poLayer = new OGRMDBLayer( this, poTable );

        if( poLayer->Initialize( pszTableName,
                                 pszFieldName,
                                 poGDB_GeomColumns->GetColumnAsInt(iShapeType),
                                 poGDB_GeomColumns->GetColumnAsDouble(iExtentLeft),
                                 poGDB_GeomColumns->GetColumnAsDouble(iExtentRight),
                                 poGDB_GeomColumns->GetColumnAsDouble(iExtentBottom),
                                 poGDB_GeomColumns->GetColumnAsDouble(iExtentTop),
                                 poGDB_GeomColumns->GetColumnAsInt(iSRID),
                                 poGDB_GeomColumns->GetColumnAsInt(iHasZ) )
            != CE_None )
        {
            delete poLayer;
        }
        else
        {
            papoLayers = (OGRMDBLayer**)CPLRealloc(papoLayers, (nLayers+1) * sizeof(OGRMDBLayer*));
            papoLayers[nLayers++] = poLayer;
        }

        CPLFree(pszTableName);
        CPLFree(pszFieldName);
    }

    return TRUE;
}
OGRLayer *
OGROCIDataSource::ICreateLayer( const char * pszLayerName,
                               OGRSpatialReference *poSRS,
                               OGRwkbGeometryType eType,
                               char ** papszOptions )

{
    char                szCommand[1024];
    char               *pszSafeLayerName = CPLStrdup(pszLayerName);

    poSession->CleanName( pszSafeLayerName );
    CPLDebug( "OCI", "In Create Layer ..." );

    bNoLogging = CSLFetchBoolean( papszOptions, "NO_LOGGING", false );

/* -------------------------------------------------------------------- */
/*      Do we already have this layer?  If so, should we blow it        */
/*      away?                                                           */
/* -------------------------------------------------------------------- */
    int iLayer;

    if( CSLFetchBoolean( papszOptions, "TRUNCATE", false ) )
    {
        CPLDebug( "OCI", "Calling TruncateLayer for %s", pszLayerName );
        TruncateLayer( pszSafeLayerName );
    }
    else
    {
        for( iLayer = 0; iLayer < nLayers; iLayer++ )
        {
            if( EQUAL(pszSafeLayerName,
                      papoLayers[iLayer]->GetLayerDefn()->GetName()) )
            {
                if( CSLFetchNameValue( papszOptions, "OVERWRITE" ) != NULL
                    && !EQUAL(CSLFetchNameValue(papszOptions,"OVERWRITE"),"NO") )
                {
                    DeleteLayer( pszSafeLayerName );
                }
                else
                {
                    CPLError( CE_Failure, CPLE_AppDefined,
                              "Layer %s already exists, CreateLayer failed.\n"
                              "Use the layer creation option OVERWRITE=YES to "
                              "replace it.",
                              pszSafeLayerName );
                    CPLFree( pszSafeLayerName );
                    return NULL;
                }
            }
        }
    }

/* -------------------------------------------------------------------- */
/*      Try to get the SRS Id of this spatial reference system,         */
/*      adding tot the srs table if needed.                             */
/* -------------------------------------------------------------------- */
    char szSRSId[100];

    if( CSLFetchNameValue( papszOptions, "SRID" ) != NULL )
        strcpy( szSRSId, CSLFetchNameValue( papszOptions, "SRID" ) );
    else if( poSRS != NULL )
        snprintf( szSRSId, sizeof(szSRSId), "%d", FetchSRSId( poSRS ) );
    else
        strcpy( szSRSId, "NULL" );

/* -------------------------------------------------------------------- */
/*      Determine name of geometry column to use.                       */
/* -------------------------------------------------------------------- */
    const char *pszGeometryName =
        CSLFetchNameValue( papszOptions, "GEOMETRY_NAME" );
    if( pszGeometryName == NULL )
        pszGeometryName = "ORA_GEOMETRY";
    const bool bGeomNullable =
        CPLFetchBool(const_cast<const char**>(papszOptions), "GEOMETRY_NULLABLE", true);

/* -------------------------------------------------------------------- */
/*      Create a basic table with the FID.  Also include the            */
/*      geometry if this is not a PostGIS enabled table.                */
/* -------------------------------------------------------------------- */
    const char *pszExpectedFIDName =
        CPLGetConfigOption( "OCI_FID", "OGR_FID" );

    OGROCIStatement oStatement( poSession );

/* -------------------------------------------------------------------- */
/*      If geometry type is wkbNone, do not create a geometry column.   */
/* -------------------------------------------------------------------- */

    if ( CSLFetchNameValue( papszOptions, "TRUNCATE" ) == NULL  )
    {
        if (eType == wkbNone)
        {
            snprintf( szCommand, sizeof(szCommand),
                     "CREATE TABLE \"%s\" ( "
                     "%s INTEGER PRIMARY KEY)",
                     pszSafeLayerName, pszExpectedFIDName);
        }
        else
        {
            snprintf( szCommand, sizeof(szCommand),
                     "CREATE TABLE \"%s\" ( "
                     "%s INTEGER PRIMARY KEY, "
                     "%s %s%s )",
                     pszSafeLayerName, pszExpectedFIDName,
                     pszGeometryName, SDO_GEOMETRY,
                     (!bGeomNullable) ? " NOT NULL":"");
        }

        if (bNoLogging)
        {
            char     szCommand2[1024];

            strncpy( szCommand2, szCommand, sizeof(szCommand) );

            snprintf( szCommand, sizeof(szCommand), "%s NOLOGGING "
              "VARRAY %s.SDO_ELEM_INFO STORE AS SECUREFILE LOB (NOCACHE NOLOGGING) "
              "VARRAY %s.SDO_ORDINATES STORE AS SECUREFILE LOB (NOCACHE NOLOGGING) ",
              szCommand2, pszGeometryName, pszGeometryName);
        }

        if( oStatement.Execute( szCommand ) != CE_None )
        {
            CPLFree( pszSafeLayerName );
            return NULL;
        }
    }

/* -------------------------------------------------------------------- */
/*      Create the layer object.                                        */
/* -------------------------------------------------------------------- */
    const char *pszLoaderFile = CSLFetchNameValue(papszOptions,"LOADER_FILE");
    OGROCIWritableLayer *poLayer;

    if( pszLoaderFile == NULL )
        poLayer = new OGROCITableLayer( this, pszSafeLayerName, eType,
                                        EQUAL(szSRSId,"NULL") ? -1 : atoi(szSRSId),
                                        TRUE, TRUE );
    else
        poLayer =
            new OGROCILoaderLayer( this, pszSafeLayerName,
                                   pszGeometryName,
                                   EQUAL(szSRSId,"NULL") ? -1 : atoi(szSRSId),
                                   pszLoaderFile );

/* -------------------------------------------------------------------- */
/*      Set various options on the layer.                               */
/* -------------------------------------------------------------------- */
    poLayer->SetLaunderFlag( CSLFetchBoolean(papszOptions, "LAUNDER", false) );
    poLayer->SetPrecisionFlag( CSLFetchBoolean(papszOptions, "PRECISION", true));

    if( CSLFetchNameValue(papszOptions,"DIM") != NULL )
        poLayer->SetDimension( atoi(CSLFetchNameValue(papszOptions,"DIM")) );

    poLayer->SetOptions( papszOptions );
    if( eType != wkbNone && !bGeomNullable )
        poLayer->GetLayerDefn()->GetGeomFieldDefn(0)->SetNullable(FALSE);

/* -------------------------------------------------------------------- */
/*      Add layer to data source layer list.                            */
/* -------------------------------------------------------------------- */
    papoLayers = (OGROCILayer **)
        CPLRealloc( papoLayers,  sizeof(OGROCILayer *) * (nLayers+1) );

    papoLayers[nLayers++] = poLayer;

    CPLFree( pszSafeLayerName );

    return poLayer;
}
Beispiel #5
0
void    CPLErrorV(CPLErr eErrClass, int err_no, const char *fmt, va_list args )
{
    CPLErrorContext *psCtx = CPLGetErrorContext();

    if (psCtx->nFailureIntoWarning > 0 && eErrClass == CE_Failure)
        eErrClass = CE_Warning;

/* -------------------------------------------------------------------- */
/*      Expand the error message                                        */
/* -------------------------------------------------------------------- */
#if defined(HAVE_VSNPRINTF)
    {
        int nPR;
        va_list wrk_args;

#ifdef va_copy
        va_copy( wrk_args, args );
#else
        wrk_args = args;
#endif

/* -------------------------------------------------------------------- */
/*      If CPL_ACCUM_ERROR_MSG=ON accumulate the error messages,        */
/*      rather than just replacing the last error message.              */
/* -------------------------------------------------------------------- */
        int nPreviousSize = 0;
        if ( psCtx->psHandlerStack != NULL &&
             EQUAL(CPLGetConfigOption( "CPL_ACCUM_ERROR_MSG", "" ), "ON"))
        {
            nPreviousSize = strlen(psCtx->szLastErrMsg);
            if (nPreviousSize)
            {
                if (nPreviousSize + 1 + 1 >= psCtx->nLastErrMsgMax)
                {
                    psCtx->nLastErrMsgMax *= 3;
                    psCtx = (CPLErrorContext *) 
                        CPLRealloc(psCtx, sizeof(CPLErrorContext) - DEFAULT_LAST_ERR_MSG_SIZE + psCtx->nLastErrMsgMax + 1);
                    CPLSetTLS( CTLS_ERRORCONTEXT, psCtx, TRUE );
                }
                psCtx->szLastErrMsg[nPreviousSize] = '\n';
                psCtx->szLastErrMsg[nPreviousSize+1] = '0';
                nPreviousSize ++;
            }
        }

        while( ((nPR = CPLvsnprintf( psCtx->szLastErrMsg+nPreviousSize, 
                                 psCtx->nLastErrMsgMax-nPreviousSize, fmt, wrk_args )) == -1
                || nPR >= psCtx->nLastErrMsgMax-nPreviousSize-1)
               && psCtx->nLastErrMsgMax < 1000000 )
        {
#ifdef va_copy
            va_end( wrk_args );
            va_copy( wrk_args, args );
#else
            wrk_args = args;
#endif
            psCtx->nLastErrMsgMax *= 3;
            psCtx = (CPLErrorContext *) 
                CPLRealloc(psCtx, sizeof(CPLErrorContext) - DEFAULT_LAST_ERR_MSG_SIZE + psCtx->nLastErrMsgMax + 1);
            CPLSetTLS( CTLS_ERRORCONTEXT, psCtx, TRUE );
        }

        va_end( wrk_args );
    }
#else
    // !HAVE_VSNPRINTF
    CPLvsnprintf( psCtx->szLastErrMsg, psCtx->nLastErrMsgMax, fmt, args);
#endif

/* -------------------------------------------------------------------- */
/*      Obfuscate any password in error message                         */
/* -------------------------------------------------------------------- */

    char* pszPassword = strstr(psCtx->szLastErrMsg, "password="******"password="******"CPL_LOG_ERRORS",NULL) != NULL )
        CPLDebug( "CPLError", "%s", psCtx->szLastErrMsg );

/* -------------------------------------------------------------------- */
/*      Invoke the current error handler.                               */
/* -------------------------------------------------------------------- */
    if( psCtx->psHandlerStack != NULL )
    {
        psCtx->psHandlerStack->pfnHandler(eErrClass, err_no, 
                                          psCtx->szLastErrMsg);
    }
    else
    {
        CPLMutexHolderD( &hErrorMutex );
        if( pfnErrorHandler != NULL )
            pfnErrorHandler(eErrClass, err_no, psCtx->szLastErrMsg);
    }

    if( eErrClass == CE_Fatal )
        abort();
}
Beispiel #6
0
MAIN_START(argc, argv)

{
    // Check that we are running against at least GDAL 1.5.
    // Note to developers: if we use newer API, please change the requirement.
    if (atoi(GDALVersionInfo("VERSION_NUM")) < 1500)
    {
        fprintf(stderr,
                "At least, GDAL >= 1.5.0 is required for this version of %s, "
                "which was compiled against GDAL %s\n",
                argv[0], GDAL_RELEASE_NAME);
        exit(1);
    }

    GDALAllRegister();
    argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
    if( argc < 1 )
        exit( -argc );

    const char         *pszSrcFilename = nullptr;
    const char         *pszDstFilename = nullptr;
    int                 nOrder = 0;
    void               *hTransformArg;
    GDALTransformerFunc pfnTransformer = nullptr;
    int                 nGCPCount = 0;
    GDAL_GCP            *pasGCPs = nullptr;
    int                 bInverse = FALSE;
    CPLStringList       aosTO;
    int                 bOutputXY = FALSE;
    double              dfX = 0.0;
    double              dfY = 0.0;
    double              dfZ = 0.0;
    double              dfT = 0.0;
    bool                bCoordOnCommandLine = false;

/* -------------------------------------------------------------------- */
/*      Parse arguments.                                                */
/* -------------------------------------------------------------------- */
    for( int i = 1; i < argc && argv[i] != nullptr; i++ )
    {
        if( EQUAL(argv[i], "--utility_version") )
        {
            printf("%s was compiled against GDAL %s and "
                   "is running against GDAL %s\n",
                   argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
            CSLDestroy(argv);
            return 0;
        }
        else if( EQUAL(argv[i],"--help") )
        {
            Usage();
        }
        else if( EQUAL(argv[i],"-t_srs") )
        {
            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
            const char *pszSRS = argv[++i];
            if( !IsValidSRS(pszSRS) )
                exit(1);
            aosTO.SetNameValue("DST_SRS", pszSRS );
        }
        else if( EQUAL(argv[i],"-s_srs") )
        {
            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
            const char *pszSRS = argv[++i];
            if( !IsValidSRS(pszSRS) )
                exit(1);
            aosTO.SetNameValue("SRC_SRS", pszSRS );
        }
        else if( EQUAL(argv[i],"-ct") )
        {
            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
            const char *pszCT = argv[++i];
            aosTO.SetNameValue("COORDINATE_OPERATION", pszCT );
        }
        else if( EQUAL(argv[i],"-order") )
        {
            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
            nOrder = atoi(argv[++i]);
            aosTO.SetNameValue("MAX_GCP_ORDER", argv[i] );
        }
        else if( EQUAL(argv[i],"-tps") )
        {
            aosTO.SetNameValue("METHOD", "GCP_TPS" );
            nOrder = -1;
        }
        else if( EQUAL(argv[i],"-rpc") )
        {
            aosTO.SetNameValue("METHOD", "RPC" );
        }
        else if( EQUAL(argv[i],"-geoloc") )
        {
            aosTO.SetNameValue("METHOD", "GEOLOC_ARRAY" );
        }
        else if( EQUAL(argv[i],"-i") )
        {
            bInverse = TRUE;
        }
        else if( EQUAL(argv[i],"-to")  )
        {
            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
            aosTO.AddString( argv[++i] );
        }
        else if( EQUAL(argv[i],"-gcp") )
        {
            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(4);
            char* endptr = nullptr;
            /* -gcp pixel line easting northing [elev] */

            nGCPCount++;
            pasGCPs = static_cast<GDAL_GCP *>(
                CPLRealloc(pasGCPs, sizeof(GDAL_GCP) * nGCPCount));
            GDALInitGCPs( 1, pasGCPs + nGCPCount - 1 );

            pasGCPs[nGCPCount-1].dfGCPPixel = CPLAtof(argv[++i]);
            pasGCPs[nGCPCount-1].dfGCPLine = CPLAtof(argv[++i]);
            pasGCPs[nGCPCount-1].dfGCPX = CPLAtof(argv[++i]);
            pasGCPs[nGCPCount-1].dfGCPY = CPLAtof(argv[++i]);
            if( argv[i+1] != nullptr &&
                (CPLStrtod(argv[i+1], &endptr) != 0.0 || argv[i+1][0] == '0') )
            {
                // Check that last argument is really a number and not a
                // filename looking like a number (see ticket #863).
                if (endptr && *endptr == 0)
                    pasGCPs[nGCPCount-1].dfGCPZ = CPLAtof(argv[++i]);
            }

            /* should set id and info? */
        }
        else if( EQUAL(argv[i],"-output_xy") )
        {
            bOutputXY = TRUE;
        }
        else if( EQUAL(argv[i],"-coord")  && i + 2 < argc)
        {
            bCoordOnCommandLine = true;
            dfX = CPLAtof(argv[++i]);
            dfY = CPLAtof(argv[++i]);
            if( i + 1 < argc && CPLGetValueType(argv[i+1]) != CPL_VALUE_STRING )
                dfZ = CPLAtof(argv[++i]);
            if( i + 1 < argc && CPLGetValueType(argv[i+1]) != CPL_VALUE_STRING )
                dfT = CPLAtof(argv[++i]);
        }
        else if( argv[i][0] == '-' )
        {
            Usage(CPLSPrintf("Unknown option name '%s'", argv[i]));
        }
        else if( pszSrcFilename == nullptr )
        {
            pszSrcFilename = argv[i];
        }
        else if( pszDstFilename == nullptr )
        {
            pszDstFilename = argv[i];
        }
        else
        {
            Usage("Too many command options.");
        }
    }

/* -------------------------------------------------------------------- */
/*      Open src and destination file, if appropriate.                  */
/* -------------------------------------------------------------------- */
    GDALDatasetH hSrcDS = nullptr;
    if( pszSrcFilename != nullptr )
    {
        hSrcDS = GDALOpen( pszSrcFilename, GA_ReadOnly );
        if( hSrcDS == nullptr )
            exit( 1 );
    }

    GDALDatasetH hDstDS = nullptr;
    if( pszDstFilename != nullptr )
    {
        hDstDS = GDALOpen( pszDstFilename, GA_ReadOnly );
        if( hDstDS == nullptr )
            exit( 1 );
    }

    if( hSrcDS != nullptr && nGCPCount > 0 )
    {
        fprintf(stderr,
                "Command line GCPs and input file specified, "
                "specify one or the other.\n");
        exit( 1 );
    }

/* -------------------------------------------------------------------- */
/*      Create a transformation object from the source to               */
/*      destination coordinate system.                                  */
/* -------------------------------------------------------------------- */
    if( nGCPCount != 0 && nOrder == -1 )
    {
        pfnTransformer = GDALTPSTransform;
        hTransformArg =
            GDALCreateTPSTransformer( nGCPCount, pasGCPs, FALSE );
    }
    else if( nGCPCount != 0 )
    {
        pfnTransformer = GDALGCPTransform;
        hTransformArg =
            GDALCreateGCPTransformer( nGCPCount, pasGCPs, nOrder, FALSE );
    }
    else
    {
        pfnTransformer = GDALGenImgProjTransform;
        hTransformArg =
            GDALCreateGenImgProjTransformer2( hSrcDS, hDstDS, aosTO.List() );
    }

    if( hTransformArg == nullptr )
    {
        exit( 1 );
    }

/* -------------------------------------------------------------------- */
/*      Read points from stdin, transform and write to stdout.          */
/* -------------------------------------------------------------------- */
    double dfLastT = 0.0;

    while( bCoordOnCommandLine || !feof(stdin) )
    {
        if( !bCoordOnCommandLine )
        {
            char szLine[1024];

            if( fgets( szLine, sizeof(szLine)-1, stdin ) == nullptr )
                break;

            char **papszTokens = CSLTokenizeString(szLine);
            const int nCount = CSLCount(papszTokens);

            if( nCount < 2 )
            {
                CSLDestroy(papszTokens);
                continue;
            }

            dfX = CPLAtof(papszTokens[0]);
            dfY = CPLAtof(papszTokens[1]);
            if( nCount >= 3 )
                dfZ = CPLAtof(papszTokens[2]);
            else
                dfZ = 0.0;
            if( nCount == 4 )
                dfT = CPLAtof(papszTokens[3]);
            else 
                dfT = 0.0;
            CSLDestroy(papszTokens);
        }
        if( dfT != dfLastT && nGCPCount == 0 )
        {
            if( dfT != 0.0 )
            {
                aosTO.SetNameValue("COORDINATE_EPOCH", CPLSPrintf("%g", dfT));
            }
            else
            {
                aosTO.SetNameValue("COORDINATE_EPOCH", nullptr);
            }
            GDALDestroyGenImgProjTransformer(hTransformArg);
            hTransformArg =
                GDALCreateGenImgProjTransformer2( hSrcDS, hDstDS, aosTO.List() );
        }

        int bSuccess = TRUE;
        if( pfnTransformer( hTransformArg, bInverse, 1,
                            &dfX, &dfY, &dfZ, &bSuccess )
            && bSuccess )
        {
            if( bOutputXY )
                CPLprintf( "%.15g %.15g\n", dfX, dfY );
            else
                CPLprintf( "%.15g %.15g %.15g\n", dfX, dfY, dfZ );
        }
        else
        {
            printf( "transformation failed.\n" );
        }

        if( bCoordOnCommandLine )
            break;
        dfLastT = dfT;
    }

    if( nGCPCount != 0 && nOrder == -1 )
    {
        GDALDestroyTPSTransformer(hTransformArg);
    }
    else if( nGCPCount != 0 )
    {
        GDALDestroyGCPTransformer(hTransformArg);
    }
    else
    {
        GDALDestroyGenImgProjTransformer(hTransformArg);
    }

    if (nGCPCount)
    {
        GDALDeinitGCPs( nGCPCount, pasGCPs );
        CPLFree( pasGCPs );
    }

    if (hSrcDS)
        GDALClose(hSrcDS);

    if (hDstDS)
        GDALClose(hDstDS);

    GDALDumpOpenDatasets( stderr );
    GDALDestroyDriverManager();

    CSLDestroy( argv );

    return 0;
}
char *CPLRecodeFromWCharIconv( const wchar_t *pwszSource, 
                               const char *pszSrcEncoding, 
                               const char *pszDstEncoding )

{
/* -------------------------------------------------------------------- */
/*      What is the source length.                                      */
/* -------------------------------------------------------------------- */
    size_t  nSrcLen = 0;

    while ( pwszSource[nSrcLen] != 0 )
        nSrcLen++;

/* -------------------------------------------------------------------- */
/*      iconv() does not support wchar_t so we need to repack the       */
/*      characters according to the width of a character in the         */
/*      source encoding.  For instance if wchar_t is 4 bytes but our    */
/*      source is UTF16 then we need to pack down into 2 byte           */
/*      characters before passing to iconv().                           */
/* -------------------------------------------------------------------- */
    int nTargetCharWidth = CPLEncodingCharSize( pszSrcEncoding );

    if( nTargetCharWidth < 1 )
    {
        CPLError( CE_Warning, CPLE_AppDefined,
                  "Recode from %s with CPLRecodeFromWChar() failed because"
                  " the width of characters in the encoding are not known.",
                  pszSrcEncoding );
        return CPLStrdup("");
    }

    GByte *pszIconvSrcBuf = (GByte*) CPLCalloc((nSrcLen+1),nTargetCharWidth);
    unsigned int iSrc;

    for( iSrc = 0; iSrc <= nSrcLen; iSrc++ )
    {
        if( nTargetCharWidth == 1 )
            pszIconvSrcBuf[iSrc] = (GByte) pwszSource[iSrc];
        else if( nTargetCharWidth == 2 )
            ((short *)pszIconvSrcBuf)[iSrc] = (short) pwszSource[iSrc];
        else if( nTargetCharWidth == 4 )
            ((GInt32 *)pszIconvSrcBuf)[iSrc] = pwszSource[iSrc];
    }

/* -------------------------------------------------------------------- */
/*      Create the iconv() translation object.                          */
/* -------------------------------------------------------------------- */
    iconv_t sConv;

    sConv = iconv_open( pszDstEncoding, pszSrcEncoding );

    if ( sConv == (iconv_t)-1 )
    {
        CPLFree( pszIconvSrcBuf );
        CPLError( CE_Warning, CPLE_AppDefined, 
                  "Recode from %s to %s failed with the error: \"%s\".", 
                  pszSrcEncoding, pszDstEncoding, strerror(errno) );

        return CPLStrdup( "" );
    }

/* -------------------------------------------------------------------- */
/*      XXX: There is a portability issue: iconv() function could be    */
/*      declared differently on different platforms. The second         */
/*      argument could be declared as char** (as POSIX defines) or      */
/*      as a const char**. Handle it with the ICONV_CONST macro here.   */
/* -------------------------------------------------------------------- */
    ICONV_CONST char *pszSrcBuf = (ICONV_CONST char *) pszIconvSrcBuf;

    /* iconv expects a number of bytes, not characters */
    nSrcLen *= sizeof(wchar_t);

/* -------------------------------------------------------------------- */
/*      Allocate destination buffer.                                    */
/* -------------------------------------------------------------------- */
    size_t  nDstCurLen = MAX(CPL_RECODE_DSTBUF_SIZE, nSrcLen + 1);
    size_t  nDstLen = nDstCurLen;
    char    *pszDestination = (char *)CPLCalloc( nDstCurLen, sizeof(char) );
    char    *pszDstBuf = pszDestination;

    while ( nSrcLen > 0 )
    {
        size_t  nConverted =
            iconv( sConv, &pszSrcBuf, &nSrcLen, &pszDstBuf, &nDstLen );

        if ( nConverted == (size_t)-1 )
        {
            if ( errno == EILSEQ )
            {
                // Skip the invalid sequence in the input string.
                nSrcLen--;
                pszSrcBuf += sizeof(wchar_t);
                static int bHasWarned = FALSE;
                if (!bHasWarned)
                {
                    bHasWarned = TRUE;
                    CPLError(CE_Warning, CPLE_AppDefined,
                            "One or several characters couldn't be converted correctly from %s to %s.\n"
                            "This warning will not be emitted anymore",
                             pszSrcEncoding, pszDstEncoding);
                }
                continue;
            }

            else if ( errno == E2BIG )
            {
                // We are running out of the output buffer.
                // Dynamically increase the buffer size.
                size_t nTmp = nDstCurLen;
                nDstCurLen *= 2;
                pszDestination =
                    (char *)CPLRealloc( pszDestination, nDstCurLen );
                pszDstBuf = pszDestination + nTmp - nDstLen;
                nDstLen += nDstCurLen - nTmp;
                continue;
            }

            else
                break;
        }
    }

    pszDestination[nDstCurLen - nDstLen] = '\0';

    iconv_close( sConv );

    CPLFree( pszIconvSrcBuf );

    return pszDestination;
}
OGRLayer *
OGRIngresDataSource::CreateLayer( const char * pszLayerNameIn,
                              OGRSpatialReference *poSRS,
                              OGRwkbGeometryType eType,
                              char ** papszOptions )

{
    const char          *pszGeometryType = NULL;
    const char		*pszGeomColumnName;
    const char 		*pszExpectedFIDName; 
	
    char                *pszLayerName;
    int                 nDimension = 3; // Ingres only supports 2d currently


    if( CSLFetchBoolean(papszOptions,"LAUNDER",TRUE) )
        pszLayerName = LaunderName( pszLayerNameIn );
    else
        pszLayerName = CPLStrdup( pszLayerNameIn );

    if( wkbFlatten(eType) == eType )
        nDimension = 2;

    CPLDebug("INGRES","Creating layer %s.", pszLayerName);

/* -------------------------------------------------------------------- */
/*      Do we already have this layer?  If so, should we blow it        */
/*      away?                                                           */
/* -------------------------------------------------------------------- */

    int iLayer;
    for( iLayer = 0; iLayer < nLayers; iLayer++ )
    {
        if( EQUAL(pszLayerName,papoLayers[iLayer]->GetLayerDefn()->GetName()) )
        {
			
            if( CSLFetchNameValue( papszOptions, "OVERWRITE" ) != NULL
                && !EQUAL(CSLFetchNameValue(papszOptions,"OVERWRITE"),"NO") )
            {
                DeleteLayer( iLayer );
            }
            else
            {
                CPLFree( pszLayerName );
                CPLError( CE_Failure, CPLE_AppDefined,
                          "Layer %s already exists, CreateLayer failed.\n"
                          "Use the layer creation option OVERWRITE=YES to "
                          "replace it.",
                          pszLayerName );
                return NULL;
            }
        }
    }

/* -------------------------------------------------------------------- */
/*      What do we want to use for geometry and FID columns?            */
/* -------------------------------------------------------------------- */
    pszGeomColumnName = CSLFetchNameValue( papszOptions, "GEOMETRY_NAME" );
    if (!pszGeomColumnName)
        pszGeomColumnName="SHAPE";

    pszExpectedFIDName = CSLFetchNameValue( papszOptions, "INGRES_FID" );
    if (!pszExpectedFIDName)
        pszExpectedFIDName="OGR_FID";

    CPLDebug("INGRES","Geometry Column Name %s.", pszGeomColumnName);
    CPLDebug("INGRES","FID Column Name %s.", pszExpectedFIDName);

/* -------------------------------------------------------------------- */
/*      What sort of geometry column do we want to create?              */
/* -------------------------------------------------------------------- */
    pszGeometryType = CSLFetchNameValue( papszOptions, "GEOMETRY_TYPE" );

    if( pszGeometryType != NULL )
        /* user selected type */;
    
    else if( wkbFlatten(eType) == wkbPoint )
        pszGeometryType = "POINT";

    else if( wkbFlatten(eType) == wkbLineString)
    {
    	if( IsNewIngres() )
    	{
            pszGeometryType = "LINESTRING";
    	}
    	else
    	{
            pszGeometryType = "LONG LINE";
    	}
    }

    else if( wkbFlatten(eType) == wkbPolygon )
    {
    	if( IsNewIngres() )
    	{
            pszGeometryType = "POLYGON";
    	}
    	else
    	{
            pszGeometryType = "LONG POLYGON";
    	}
    }

    else if( wkbFlatten(eType) == wkbMultiPolygon )
    {
    	if( IsNewIngres() )
            pszGeometryType = "MULTIPOLYGON";
    }

    else if( wkbFlatten(eType) == wkbMultiLineString )
    {
    	if( IsNewIngres() )
            pszGeometryType = "MULTILINESTRING";
    }

    else if( wkbFlatten(eType) == wkbMultiPoint )
    {
    	if( IsNewIngres() )
            pszGeometryType = "MULTIPOINT";
    }

    else if( wkbFlatten(eType) == wkbGeometryCollection )
    {
    	if( IsNewIngres() )
            pszGeometryType = "GEOMETRYCOLLECTION";
    }

    else if( wkbFlatten(eType) == wkbUnknown )
    {
    	if( IsNewIngres() )
            // this is also used as the generic geometry type.
            pszGeometryType = "GEOMETRYCOLLECTION";
    }

    /* -------------------------------------------------------------------- */
    /*      Try to get the SRS Id of this spatial reference system,         */
    /*      adding tot the srs table if needed.                             */
    /* -------------------------------------------------------------------- */
    int nSRSId = -1;
    
    if( poSRS != NULL && IsNewIngres() == TRUE )
        nSRSId = FetchSRSId( poSRS );

/* -------------------------------------------------------------------- */
/*      Form table creation command.                                    */
/* -------------------------------------------------------------------- */
    CPLString osCommand;

    if( pszGeometryType == NULL )
    {
        osCommand.Printf( "CREATE TABLE %s ( "
                          "   %s INTEGER )",
                          pszLayerName, pszExpectedFIDName );
    }
    else
    {
        if(nSRSId != -1)
        {
            osCommand.Printf( "CREATE TABLE %s ("
                              " %s INTEGER NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS seq_%s IDENTITY (START WITH 1 INCREMENT BY 1),"  
                              " %s %s SRID %d ) ",
                              pszLayerName,                              
                              pszExpectedFIDName,
                              pszLayerName,
                              pszGeomColumnName,
                              pszGeometryType,
                              nSRSId);
        }
        else
        {
            osCommand.Printf( "CREATE TABLE %s ("
                              " %s INTEGER NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS seq_%s IDENTITY (START WITH 1 INCREMENT BY 1),"
                              " %s %s )",
                              pszLayerName,                              
                              pszExpectedFIDName,
                              pszLayerName,
                              pszGeomColumnName,
                              pszGeometryType);
        }
    }

/* -------------------------------------------------------------------- */
/*      Execute the create table command.                               */
/* -------------------------------------------------------------------- */
    {
        OGRIngresStatement  oStmt( hConn );

        if( !oStmt.ExecuteSQL( osCommand ) )
            return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Create the layer object.                                        */
/* -------------------------------------------------------------------- */
    OGRIngresTableLayer     *poLayer;
    OGRErr                  eErr;

    poLayer = new OGRIngresTableLayer( this, pszLayerName, TRUE, nSRSId );
    eErr = poLayer->Initialize(pszLayerName);
    if (eErr == OGRERR_FAILURE)
    {
        delete poLayer;
        return NULL;
    }

    poLayer->SetLaunderFlag( CSLFetchBoolean(papszOptions,"LAUNDER",TRUE) );
    poLayer->SetPrecisionFlag( CSLFetchBoolean(papszOptions,"PRECISION",TRUE));

/* -------------------------------------------------------------------- */
/*      Add layer to data source layer list.                            */
/* -------------------------------------------------------------------- */
    papoLayers = (OGRIngresLayer **)
        CPLRealloc( papoLayers,  sizeof(OGRIngresLayer *) * (nLayers+1) );

    papoLayers[nLayers++] = poLayer;

    CPLFree( pszLayerName );

    return poLayer;
}
int OGRSDTSDataSource::Open( const char * pszFilename, int bTestOpen )

{
    pszName = CPLStrdup( pszFilename );

/* -------------------------------------------------------------------- */
/*      Verify that the extension is DDF if we are testopening.         */
/* -------------------------------------------------------------------- */
    if( bTestOpen && !(strlen(pszFilename) > 4 &&
        EQUAL(pszFilename+strlen(pszFilename)-4,".ddf")) )
        return FALSE;

/* -------------------------------------------------------------------- */
/*      Check a few bits of the header to see if it looks like an       */
/*      SDTS file (really, if it looks like an ISO8211 file).           */
/* -------------------------------------------------------------------- */
    if( bTestOpen )
    {
        FILE    *fp;
        char    pachLeader[10];

        fp = VSIFOpen( pszFilename, "rb" );
        if( fp == NULL )
            return FALSE;

        if( VSIFRead( pachLeader, 1, 10, fp ) != 10
            || (pachLeader[5] != '1' && pachLeader[5] != '2'
                && pachLeader[5] != '3' )
            || pachLeader[6] != 'L'
            || (pachLeader[8] != '1' && pachLeader[8] != ' ') )
        {
            VSIFClose( fp );
            return FALSE;
        }

        VSIFClose( fp );
    }

/* -------------------------------------------------------------------- */
/*      Create a transfer, and open it.                                 */
/* -------------------------------------------------------------------- */
    poTransfer = new SDTSTransfer();

    if( !poTransfer->Open( pszFilename ) )
    {
        delete poTransfer;
        poTransfer = NULL;

        return FALSE;
    }

/* -------------------------------------------------------------------- */
/*      Initialize the projection.                                      */
/* -------------------------------------------------------------------- */
    SDTS_XREF   *poXREF = poTransfer->GetXREF();

    poSRS = new OGRSpatialReference();

    if( EQUAL(poXREF->pszSystemName,"UTM") )
    {
        poSRS->SetUTM( poXREF->nZone, TRUE );
    }

    if( EQUAL(poXREF->pszDatum,"NAS") )
        poSRS->SetGeogCS("NAD27", "North_American_Datum_1927",
                         "Clarke 1866", 6378206.4, 294.978698213901 );

    else if( EQUAL(poXREF->pszDatum,"NAX") )
        poSRS->SetGeogCS("NAD83", "North_American_Datum_1983",
                         "GRS 1980", 6378137, 298.257222101 );

    else if( EQUAL(poXREF->pszDatum,"WGC") )
        poSRS->SetGeogCS("WGS 72", "WGS_1972", "NWL 10D", 6378135, 298.26 );

    else if( EQUAL(poXREF->pszDatum,"WGE") )
        poSRS->SetGeogCS("WGS 84", "WGS_1984",
                         "WGS 84", 6378137, 298.257223563 );

    else
        poSRS->SetGeogCS("WGS 84", "WGS_1984",
                         "WGS 84", 6378137, 298.257223563 );

    poSRS->Fixup();

/* -------------------------------------------------------------------- */
/*      Initialize a layer for each source dataset layer.               */
/* -------------------------------------------------------------------- */
    for( int iLayer = 0; iLayer < poTransfer->GetLayerCount(); iLayer++ )
    {
        SDTSIndexedReader       *poReader;

        if( poTransfer->GetLayerType( iLayer ) == SLTRaster )
            continue;

        poReader = poTransfer->GetLayerIndexedReader( iLayer );
        if( poReader == NULL )
            continue;

        papoLayers = (OGRSDTSLayer **)
            CPLRealloc( papoLayers, sizeof(void*) * ++nLayers );
        papoLayers[nLayers-1] = new OGRSDTSLayer( poTransfer, iLayer, this );
    }

    return TRUE;
}
OGRLayer *
OGRTABDataSource::ICreateLayer( const char * pszLayerName,
                               OGRSpatialReference *poSRSIn,
                               OGRwkbGeometryType /* eGeomTypeIn */,
                               char ** papszOptions )

{
    IMapInfoFile        *poFile;
    char                *pszFullFilename;
    const char          *pszOpt = NULL;

    if( !m_bUpdate )
    {
        CPLError( CE_Failure, CPLE_AppDefined, 
                    "Cannot create layer on read-only dataset.");
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      If it's a single file mode file, then we may have already       */
/*      instantiated the low level layer.   We would just need to       */
/*      reset the coordinate system and (potentially) bounds.           */
/* -------------------------------------------------------------------- */
    if( m_bSingleFile )
    {
        if( m_bSingleLayerAlreadyCreated )
        {
            CPLError( CE_Failure, CPLE_AppDefined, 
                      "Unable to create new layers in this single file dataset.");
            return NULL;
        }

        m_bSingleLayerAlreadyCreated = TRUE;

        poFile = (IMapInfoFile *) m_papoLayers[0];
    }

    else
    {
        if( m_bCreateMIF )
        {
            pszFullFilename = CPLStrdup( CPLFormFilename( m_pszDirectory,
                                                          pszLayerName, "mif" ) );
            
            poFile = new MIFFile;
        }
        else
        {
            pszFullFilename = CPLStrdup( CPLFormFilename( m_pszDirectory,
                                                          pszLayerName, "tab" ) );
            
            poFile = new TABFile;
        }
        
        if( poFile->Open( pszFullFilename, TABWrite, FALSE ) != 0 )
        {
            CPLFree( pszFullFilename );
            delete poFile;
            return FALSE;
        }

        m_nLayerCount++;
        m_papoLayers = (IMapInfoFile **)
            CPLRealloc(m_papoLayers,sizeof(void*)*m_nLayerCount);
        m_papoLayers[m_nLayerCount-1] = poFile;

        CPLFree( pszFullFilename );
    }

    poFile->SetDescription( poFile->GetName() );

/* -------------------------------------------------------------------- */
/*      Assign the coordinate system (if provided) and set              */
/*      reasonable bounds.                                              */
/* -------------------------------------------------------------------- */
    if( poSRSIn != NULL )
    {
        poFile->SetSpatialRef( poSRSIn );
        // SetSpatialRef() has cloned the passed geometry
        poFile->GetLayerDefn()->GetGeomFieldDefn(0)->SetSpatialRef(poFile->GetSpatialRef());
    }

    // Pull out the bounds if supplied
    if( (pszOpt=CSLFetchNameValue(papszOptions, "BOUNDS")) != NULL ) {
        double dfBounds[4];
        if( CPLsscanf(pszOpt, "%lf,%lf,%lf,%lf", &dfBounds[0], 
                                          &dfBounds[1], 
                                          &dfBounds[2], 
                                          &dfBounds[3]) != 4 )
        {
            CPLError( CE_Failure, CPLE_IllegalArg,
                        "Invalid BOUNDS parameter, expected min_x,min_y,max_x,max_y\n" );
        }
        else
        {
            poFile->SetBounds( dfBounds[0], dfBounds[1], dfBounds[2], dfBounds[3] );
        }
    }

    if( !poFile->IsBoundsSet() && !m_bCreateMIF )
    {
        if( poSRSIn != NULL && poSRSIn->GetRoot() != NULL
            && EQUAL(poSRSIn->GetRoot()->GetValue(),"GEOGCS") )
            poFile->SetBounds( -1000, -1000, 1000, 1000 );
        else
            poFile->SetBounds( -30000000, -15000000, 30000000, 15000000 );
    }

    if (m_bQuickSpatialIndexMode == TRUE && poFile->SetQuickSpatialIndexMode(TRUE) != 0)
    {
        CPLError( CE_Warning, CPLE_AppDefined, 
                  "Setting Quick Spatial Index Mode failed.");
    }
    else if (m_bQuickSpatialIndexMode == FALSE && poFile->SetQuickSpatialIndexMode(FALSE) != 0)
    {
        CPLError( CE_Warning, CPLE_AppDefined, 
                  "Setting Normal Spatial Index Mode failed.");
    }

    return poFile;
}
Beispiel #11
0
OGRSpatialReference *OGRIngresDataSource::FetchSRS( int nId )
{
    char         szCommand[1024];
    char           **papszRow;
    OGRIngresStatement oStatement(GetConn());
            
    if( nId < 0 )
        return NULL;

    /*
     * Only the new Ingres Geospatial library
     */
    if(IsNewIngres() == FALSE)
        return NULL;

/* -------------------------------------------------------------------- */
/*      First, we look through our SRID cache, is it there?             */
/* -------------------------------------------------------------------- */
    int  i;

    for( i = 0; i < nKnownSRID; i++ )
    {
        if( panSRID[i] == nId )
            return papoSRS[i];
    }

    OGRSpatialReference *poSRS = NULL;

    sprintf( szCommand,
         "SELECT srtext FROM spatial_ref_sys WHERE srid = %d",
         nId );

    oStatement.ExecuteSQL(szCommand);
        
    char    *pszWKT = NULL;
    papszRow = NULL;
    

    papszRow = oStatement.GetRow();

    if( papszRow != NULL)
    {
        if(papszRow[0] != NULL )
        {
            //VARCHAR uses the first two bytes for length
            pszWKT = &papszRow[0][2];
        }
    }

     poSRS = new OGRSpatialReference();
     if( pszWKT == NULL || poSRS->importFromWkt( &pszWKT ) != OGRERR_NONE )
     {
         delete poSRS;
         poSRS = NULL;
     }

/* -------------------------------------------------------------------- */
/*      Add to the cache.                                               */
/* -------------------------------------------------------------------- */
    panSRID = (int *) CPLRealloc(panSRID,sizeof(int) * (nKnownSRID+1) );
    papoSRS = (OGRSpatialReference **) 
        CPLRealloc(papoSRS, sizeof(void*) * (nKnownSRID + 1) );
    panSRID[nKnownSRID] = nId;
    papoSRS[nKnownSRID] = poSRS;

    return poSRS;
}
int OGRTABDataSource::Open( GDALOpenInfo* poOpenInfo, int bTestOpen )

{
    CPLAssert( m_pszName == NULL );

    m_pszName = CPLStrdup( poOpenInfo->pszFilename );
    m_bUpdate = (poOpenInfo->eAccess == GA_Update );

/* -------------------------------------------------------------------- */
/*      If it is a file, try to open as a Mapinfo file.                 */
/* -------------------------------------------------------------------- */
    if( !poOpenInfo->bIsDirectory )
    {
        IMapInfoFile    *poFile;

        poFile = IMapInfoFile::SmartOpen( m_pszName, m_bUpdate, bTestOpen );
        if( poFile == NULL )
            return FALSE;

        poFile->SetDescription( poFile->GetName() );

        m_nLayerCount = 1;
        m_papoLayers = (IMapInfoFile **) CPLMalloc(sizeof(void*));
        m_papoLayers[0] = poFile;

        m_pszDirectory = CPLStrdup( CPLGetPath(m_pszName) );

        m_bSingleFile = TRUE;
        m_bSingleLayerAlreadyCreated = TRUE;
    }

/* -------------------------------------------------------------------- */
/*      Otherwise, we need to scan the whole directory for files        */
/*      ending in .tab or .mif.                                         */
/* -------------------------------------------------------------------- */
    else
    {
        char    **papszFileList = CPLReadDir( m_pszName );
        
        m_pszDirectory = CPLStrdup( m_pszName );

        for( int iFile = 0;
             papszFileList != NULL && papszFileList[iFile] != NULL;
             iFile++ )
        {
            IMapInfoFile *poFile;
            const char  *pszExtension = CPLGetExtension(papszFileList[iFile]);
            char        *pszSubFilename;

            if( !EQUAL(pszExtension,"tab") && !EQUAL(pszExtension,"mif") )
                continue;

            pszSubFilename = CPLStrdup(
                CPLFormFilename( m_pszDirectory, papszFileList[iFile], NULL ));

            poFile = IMapInfoFile::SmartOpen( pszSubFilename, m_bUpdate, bTestOpen );
            CPLFree( pszSubFilename );
            
            if( poFile == NULL )
            {
                CSLDestroy( papszFileList );
                return FALSE;
            }
            poFile->SetDescription( poFile->GetName() );

            m_nLayerCount++;
            m_papoLayers = (IMapInfoFile **)
                CPLRealloc(m_papoLayers,sizeof(void*)*m_nLayerCount);
            m_papoLayers[m_nLayerCount-1] = poFile;
        }

        CSLDestroy( papszFileList );

        if( m_nLayerCount == 0 )
        {
            if( !bTestOpen )
                CPLError( CE_Failure, CPLE_OpenFailed,
                          "No mapinfo files found in directory %s.\n",
                          m_pszDirectory );
            
            return FALSE;
        }
    }

    return TRUE;
}
Beispiel #13
0
CPLString &CPLString::vPrintf( const char *pszFormat, va_list args )

{
/* -------------------------------------------------------------------- */
/*      This implementation for platforms without vsnprintf() will      */
/*      just plain fail if the formatted contents are too large.        */
/* -------------------------------------------------------------------- */

#if !defined(HAVE_VSNPRINTF)
    char *pszBuffer = (char *) CPLMalloc(30000);
    if( vsprintf( pszBuffer, pszFormat, args) > 29998 )
    {
        CPLError( CE_Fatal, CPLE_AppDefined, 
                  "CPLString::vPrintf() ... buffer overrun." );
    }
    *this = pszBuffer;
    CPLFree( pszBuffer );

/* -------------------------------------------------------------------- */
/*      This should grow a big enough buffer to hold any formatted      */
/*      result.                                                         */
/* -------------------------------------------------------------------- */
#else
    char szModestBuffer[500];
    int nPR;
    va_list wrk_args;

#ifdef va_copy
    va_copy( wrk_args, args );
#else
    wrk_args = args;
#endif
    
    nPR = vsnprintf( szModestBuffer, sizeof(szModestBuffer), pszFormat, 
                     wrk_args );
    if( nPR == -1 || nPR >= (int) sizeof(szModestBuffer)-1 )
    {
        int nWorkBufferSize = 2000;
        char *pszWorkBuffer = (char *) CPLMalloc(nWorkBufferSize);

#ifdef va_copy
        va_end( wrk_args );
        va_copy( wrk_args, args );
#else
        wrk_args = args;
#endif
        while( (nPR=vsnprintf( pszWorkBuffer, nWorkBufferSize, pszFormat,wrk_args))
               >= nWorkBufferSize-1 
               || nPR == -1 )
        {
            nWorkBufferSize *= 4;
            pszWorkBuffer = (char *) CPLRealloc(pszWorkBuffer, 
                                                nWorkBufferSize );
#ifdef va_copy
            va_end( wrk_args );
            va_copy( wrk_args, args );
#else
            wrk_args = args;
#endif
        }
        *this = pszWorkBuffer;
        CPLFree( pszWorkBuffer );
    }
    else
    {
        *this = szModestBuffer;
    }
    va_end( wrk_args );
#endif

    return *this;
}
Beispiel #14
0
static void CPLQuadTreeNodeAddFeatureAlg2( CPLQuadTree *hQuadTree,
                                           QuadTreeNode *psNode,
                                           void* hFeature,
                                           const CPLRectObj* pRect,
                                           int nMaxDepth)
{
    int i;

  /* -------------------------------------------------------------------- */
  /*      If there are apSubNodes, then consider whether this object        */
  /*      will fit in them.                                               */
  /* -------------------------------------------------------------------- */
    if( nMaxDepth > 1 && psNode->nNumSubNodes > 0 )
    {
        for(i=0; i<psNode->nNumSubNodes; i++ )
        {
            if( CPL_RectContained(pRect, &psNode->apSubNode[i]->rect))
            {
                CPLQuadTreeNodeAddFeatureAlg2( hQuadTree, psNode->apSubNode[i],
                                               hFeature, pRect, nMaxDepth-1);
                return;
            }
        }
    }

  /* -------------------------------------------------------------------- */
  /*      Otherwise, consider creating four apSubNodes if could fit into    */
  /*      them, and adding to the appropriate apSubNode.                    */
  /* -------------------------------------------------------------------- */
    else if( nMaxDepth > 1 && psNode->nNumSubNodes == 0 )
    {
        CPLRectObj half1, half2, quad1, quad2, quad3, quad4;

        CPLQuadTreeSplitBounds(hQuadTree->dfSplitRatio, &psNode->rect, &half1, &half2);
        CPLQuadTreeSplitBounds(hQuadTree->dfSplitRatio, &half1, &quad1, &quad2);
        CPLQuadTreeSplitBounds(hQuadTree->dfSplitRatio, &half2, &quad3, &quad4);

        if( memcmp(&psNode->rect, &quad1, sizeof(CPLRectObj)) != 0 &&
            memcmp(&psNode->rect, &quad2, sizeof(CPLRectObj)) != 0 &&
            memcmp(&psNode->rect, &quad3, sizeof(CPLRectObj)) != 0 &&
            memcmp(&psNode->rect, &quad4, sizeof(CPLRectObj)) != 0 &&
            (CPL_RectContained(pRect, &quad1) ||
             CPL_RectContained(pRect, &quad2) ||
             CPL_RectContained(pRect, &quad3) ||
             CPL_RectContained(pRect, &quad4)) )
        {
            psNode->nNumSubNodes = 4;
            psNode->apSubNode[0] = CPLQuadTreeNodeCreate(&quad1);
            psNode->apSubNode[1] = CPLQuadTreeNodeCreate(&quad2);
            psNode->apSubNode[2] = CPLQuadTreeNodeCreate(&quad3);
            psNode->apSubNode[3] = CPLQuadTreeNodeCreate(&quad4);

            /* recurse back on this psNode now that it has apSubNodes */
            CPLQuadTreeNodeAddFeatureAlg2(hQuadTree, psNode, hFeature, pRect, nMaxDepth);
            return;
        }
    }

/* -------------------------------------------------------------------- */
/*      If none of that worked, just add it to this psNodes list.         */
/* -------------------------------------------------------------------- */
    psNode->nFeatures++;

    psNode->pahFeatures =
            (void**) CPLRealloc( psNode->pahFeatures,
                                 sizeof(void*) * psNode->nFeatures );
    if( hQuadTree->pfnGetBounds == NULL )
    {
        psNode->pasBounds =
            (CPLRectObj*) CPLRealloc( psNode->pasBounds,
                                 sizeof(CPLRectObj) * psNode->nFeatures );
    }
    psNode->pahFeatures[psNode->nFeatures-1] = hFeature;
    if( hQuadTree->pfnGetBounds == NULL )
    {
        psNode->pasBounds[psNode->nFeatures-1] = *pRect;
    }
}
Beispiel #15
0
int OGRODBCDataSource::Open( const char * pszNewName, int bUpdate,
                             CPL_UNUSED int bTestOpen )
{
    CPLAssert( nLayers == 0 );

    if( !STARTS_WITH_CI(pszNewName, "ODBC:") && EQUAL(CPLGetExtension(pszNewName), "MDB") )
        return OpenMDB(pszNewName, bUpdate);

/* -------------------------------------------------------------------- */
/*      Start parsing dataset name from the end of string, fetching     */
/*      the name of spatial reference table and names for SRID and      */
/*      SRTEXT columns first.                                           */
/* -------------------------------------------------------------------- */
    char *pszWrkName = CPLStrdup( pszNewName + 5 ); // Skip the 'ODBC:' part
    char **papszTables = nullptr;
    char **papszGeomCol = nullptr;
    char *pszSRSTableName = nullptr;
    char *pszSRIDCol = nullptr;
    char *pszSRTextCol = nullptr;
    char *pszDelimiter = nullptr;

    if ( (pszDelimiter = strrchr( pszWrkName, ':' )) != nullptr )
    {
        char *pszOBracket = strchr( pszDelimiter + 1, '(' );

        if( strchr(pszDelimiter,'\\') != nullptr
            || strchr(pszDelimiter,'/') != nullptr )
        {
            /*
            ** if there are special tokens then this isn't really
            ** the srs table name, so avoid further processing.
            */
        }
        else if( pszOBracket == nullptr )
        {
            pszSRSTableName = CPLStrdup( pszDelimiter + 1 );
            *pszDelimiter = '\0';
        }
        else
        {
            char *pszCBracket = strchr( pszOBracket, ')' );
            if( pszCBracket != nullptr )
                *pszCBracket = '\0';

            char *pszComma = strchr( pszOBracket, ',' );
            if( pszComma != nullptr )
            {
                *pszComma = '\0';
                pszSRIDCol = CPLStrdup( pszComma + 1 );
            }

            *pszOBracket = '\0';
            pszSRSTableName = CPLStrdup( pszDelimiter + 1 );
            pszSRTextCol = CPLStrdup( pszOBracket + 1 );

            *pszDelimiter = '\0';
        }
    }

/* -------------------------------------------------------------------- */
/*      Strip off any comma delimited set of tables names to access     */
/*      from the end of the string first.  Also allow an optional       */
/*      bracketed geometry column name after the table name.            */
/* -------------------------------------------------------------------- */
    while( (pszDelimiter = strrchr( pszWrkName, ',' )) != nullptr )
    {
        char *pszOBracket = strstr( pszDelimiter + 1, "(" );
        if( pszOBracket == nullptr )
        {
            papszTables = CSLAddString( papszTables, pszDelimiter + 1 );
            papszGeomCol = CSLAddString( papszGeomCol, "" );
        }
        else
        {
            char *pszCBracket = strstr(pszOBracket,")");

            if( pszCBracket != nullptr )
                *pszCBracket = '\0';

            *pszOBracket = '\0';
            papszTables = CSLAddString( papszTables, pszDelimiter + 1 );
            papszGeomCol = CSLAddString( papszGeomCol, pszOBracket+1 );
        }
        *pszDelimiter = '\0';
    }

/* -------------------------------------------------------------------- */
/*      Split out userid, password and DSN.  The general form is        */
/*      user/password@dsn.  But if there are no @ characters the        */
/*      whole thing is assumed to be a DSN.                             */
/* -------------------------------------------------------------------- */
    char *pszUserid = nullptr;
    char *pszPassword = nullptr;
    char *pszDSN = nullptr;

    if( strstr(pszWrkName,"@") == nullptr )
    {
        pszDSN = CPLStrdup( pszWrkName );
    }
    else
    {

        pszDSN = CPLStrdup(strstr(pszWrkName, "@") + 1);
        if( *pszWrkName == '/' )
        {
            pszPassword = CPLStrdup(pszWrkName + 1);
            char *pszTarget = strstr(pszPassword,"@");
            *pszTarget = '\0';
        }
        else
        {
            pszUserid = CPLStrdup(pszWrkName);
            char *pszTarget = strstr(pszUserid,"@");
            *pszTarget = '\0';

            pszTarget = strstr(pszUserid,"/");
            if( pszTarget != nullptr )
            {
                *pszTarget = '\0';
                pszPassword = CPLStrdup(pszTarget+1);
            }
        }
    }

    CPLFree( pszWrkName );

/* -------------------------------------------------------------------- */
/*      Initialize based on the DSN.                                    */
/* -------------------------------------------------------------------- */
    CPLDebug( "OGR_ODBC",
              "EstablishSession(DSN:\"%s\", userid:\"%s\", password:\"%s\")",
              pszDSN, pszUserid ? pszUserid : "",
              pszPassword ? pszPassword : "" );

    if( !oSession.EstablishSession( pszDSN, pszUserid, pszPassword ) )
    {
        CPLError( CE_Failure, CPLE_AppDefined,
                  "Unable to initialize ODBC connection to DSN for %s,\n"
                  "%s",
                  pszNewName+5, oSession.GetLastError() );
        CSLDestroy( papszTables );
        CSLDestroy( papszGeomCol );
        CPLFree( pszDSN );
        CPLFree( pszUserid );
        CPLFree( pszPassword );
        CPLFree( pszSRIDCol );
        CPLFree( pszSRTextCol );
        CPLFree( pszSRSTableName );
        return FALSE;
    }

    CPLFree( pszDSN );
    CPLFree( pszUserid );
    CPLFree( pszPassword );

    pszName = CPLStrdup( pszNewName );

    bDSUpdate = bUpdate;

/* -------------------------------------------------------------------- */
/*      If no explicit list of tables was given, check for a list in    */
/*      a geometry_columns table.                                       */
/* -------------------------------------------------------------------- */
    if( papszTables == nullptr )
    {
        CPLODBCStatement oStmt( &oSession );

        oStmt.Append( "SELECT f_table_name, f_geometry_column, geometry_type"
                      " FROM geometry_columns" );
        if( oStmt.ExecuteSQL() )
        {
            while( oStmt.Fetch() )
            {
                papszTables =
                    CSLAddString( papszTables, oStmt.GetColData(0) );
                papszGeomCol =
                    CSLAddString( papszGeomCol, oStmt.GetColData(1) );
            }
        }
    }

/* -------------------------------------------------------------------- */
/*      Otherwise our final resort is to return all tables as           */
/*      non-spatial tables.                                             */
/* -------------------------------------------------------------------- */
    if( papszTables == nullptr )
    {
        CPLODBCStatement oTableList( &oSession );

        if( oTableList.GetTables() )
        {
            while( oTableList.Fetch() )
            {
                const char *pszSchema = oTableList.GetColData(1);
                CPLString osLayerName;

                if( pszSchema != nullptr && strlen(pszSchema) > 0 )
                {
                    osLayerName = pszSchema;
                    osLayerName += ".";
                }

                osLayerName += oTableList.GetColData(2);

                papszTables = CSLAddString( papszTables, osLayerName );

                papszGeomCol = CSLAddString(papszGeomCol,"");
            }
        }
    }

/* -------------------------------------------------------------------- */
/*      If we have an explicit list of requested tables, use them       */
/*      (non-spatial).                                                  */
/* -------------------------------------------------------------------- */
    for( int iTable = 0;
         papszTables != nullptr && papszTables[iTable] != nullptr;
         iTable++ )
    {
        if( strlen(papszGeomCol[iTable]) > 0 )
            OpenTable( papszTables[iTable], papszGeomCol[iTable], bUpdate );
        else
            OpenTable( papszTables[iTable], nullptr, bUpdate );
    }

    CSLDestroy( papszTables );
    CSLDestroy( papszGeomCol );

/* -------------------------------------------------------------------- */
/*      If no explicit list of tables was given, check for a list in    */
/*      a geometry_columns table.                                       */
/* -------------------------------------------------------------------- */
    if ( pszSRSTableName )
    {
        CPLODBCStatement oSRSList( &oSession );

        if ( !pszSRTextCol )
            pszSRTextCol = CPLStrdup( "srtext" );
        if ( !pszSRIDCol )
            pszSRIDCol = CPLStrdup( "srid" );

        oSRSList.Append( "SELECT " );
        oSRSList.Append( pszSRIDCol );
        oSRSList.Append( "," );
        oSRSList.Append( pszSRTextCol );
        oSRSList.Append( " FROM " );
        oSRSList.Append( pszSRSTableName );

        CPLDebug( "OGR_ODBC", "ExecuteSQL(%s) to read SRS table",
                  oSRSList.GetCommand() );
        if ( oSRSList.ExecuteSQL() )
        {
            int nRows = 256;     // A reasonable number of SRIDs to start from
            panSRID = (int *)CPLMalloc( nRows * sizeof(int) );
            papoSRS = (OGRSpatialReference **)
                CPLMalloc( nRows * sizeof(OGRSpatialReference*) );

            while ( oSRSList.Fetch() )
            {
                const char *pszSRID = oSRSList.GetColData( pszSRIDCol );
                if ( !pszSRID )
                    continue;

                const char *pszSRText = oSRSList.GetColData( pszSRTextCol );

                if ( pszSRText )
                {
                    if ( nKnownSRID > nRows )
                    {
                        nRows *= 2;
                        panSRID = (int *)CPLRealloc( panSRID,
                                                     nRows * sizeof(int) );
                        papoSRS = (OGRSpatialReference **)
                            CPLRealloc( papoSRS,
                            nRows * sizeof(OGRSpatialReference*) );
                    }
                    panSRID[nKnownSRID] = atoi( pszSRID );
                    papoSRS[nKnownSRID] = new OGRSpatialReference();
                    if ( papoSRS[nKnownSRID]->importFromWkt( pszSRText )
                         != OGRERR_NONE )
                    {
                        delete papoSRS[nKnownSRID];
                        continue;
                    }
                    nKnownSRID++;
                }
            }
        }
    }

    if ( pszSRIDCol )
        CPLFree( pszSRIDCol );
    if ( pszSRTextCol )
        CPLFree( pszSRTextCol );
    if ( pszSRSTableName )
        CPLFree( pszSRSTableName );

    return TRUE;
}
int OGRCARTODataSource::Open( const char * pszFilename,
                                char** papszOpenOptionsIn,
                                int bUpdateIn )

{
    bReadWrite = bUpdateIn;
    bBatchInsert = CPLTestBool(CSLFetchNameValueDef(papszOpenOptionsIn, "BATCH_INSERT", "YES"));

    pszName = CPLStrdup( pszFilename );
    if( CSLFetchNameValue(papszOpenOptionsIn, "ACCOUNT") )
        pszAccount = CPLStrdup(CSLFetchNameValue(papszOpenOptionsIn, "ACCOUNT"));
    else
    {
        if( STARTS_WITH_CI(pszFilename, "CARTODB:") )
            pszAccount = CPLStrdup(pszFilename + strlen("CARTODB:"));
        else
            pszAccount = CPLStrdup(pszFilename + strlen("CARTO:"));
        char* pchSpace = strchr(pszAccount, ' ');
        if( pchSpace )
            *pchSpace = '\0';
        if( pszAccount[0] == 0 )
        {
            CPLError(CE_Failure, CPLE_AppDefined, "Missing account name");
            return FALSE;
        }
    }

    osAPIKey = CSLFetchNameValueDef(papszOpenOptionsIn, "API_KEY",
                            CPLGetConfigOption("CARTO_API_KEY", 
                                CPLGetConfigOption("CARTODB_API_KEY", "")));

    CPLString osTables = OGRCARTOGetOptionValue(pszFilename, "tables");

    /*if( osTables.size() == 0 && osAPIKey.size() == 0 )
    {
        CPLError(CE_Failure, CPLE_AppDefined,
                 "When not specifying tables option, CARTO_API_KEY must be defined");
        return FALSE;
    }*/

    bUseHTTPS = CPLTestBool(CPLGetConfigOption("CARTO_HTTPS",
                                CPLGetConfigOption("CARTODB_HTTPS", "YES")));

    OGRLayer* poSchemaLayer = ExecuteSQLInternal("SELECT current_schema()");
    if( poSchemaLayer )
    {
        OGRFeature* poFeat = poSchemaLayer->GetNextFeature();
        if( poFeat )
        {
            if( poFeat->GetFieldCount() == 1 )
            {
                osCurrentSchema = poFeat->GetFieldAsString(0);
            }
            delete poFeat;
        }
        ReleaseResultSet(poSchemaLayer);
    }
    if( osCurrentSchema.size() == 0 )
        return FALSE;

/* -------------------------------------------------------------------- */
/*      Find out PostGIS version                                        */
/* -------------------------------------------------------------------- */
    if( bReadWrite )
    {
        OGRLayer* poPostGISVersionLayer = ExecuteSQLInternal("SELECT postgis_version()");
        if( poPostGISVersionLayer )
        {
            OGRFeature* poFeat = poPostGISVersionLayer->GetNextFeature();
            if( poFeat )
            {
                if( poFeat->GetFieldCount() == 1 )
                {
                    const char* pszVersion = poFeat->GetFieldAsString(0);
                    nPostGISMajor = atoi(pszVersion);
                    const char* pszDot = strchr(pszVersion, '.');
                    nPostGISMinor = 0;
                    if( pszDot )
                        nPostGISMinor = atoi(pszDot + 1);
                }
                delete poFeat;
            }
            ReleaseResultSet(poPostGISVersionLayer);
        }
    }

    if( osAPIKey.size() && bUpdateIn )
    {
        ExecuteSQLInternal(
                "DROP FUNCTION IF EXISTS ogr_table_metadata(TEXT,TEXT); "
                "CREATE OR REPLACE FUNCTION ogr_table_metadata(schema_name TEXT, table_name TEXT) RETURNS TABLE "
                "(attname TEXT, typname TEXT, attlen INT, format_type TEXT, "
                "attnum INT, attnotnull BOOLEAN, indisprimary BOOLEAN, "
                "defaultexpr TEXT, dim INT, srid INT, geomtyp TEXT, srtext TEXT) AS $$ "
                "SELECT a.attname::text, t.typname::text, a.attlen::int, "
                        "format_type(a.atttypid,a.atttypmod)::text, "
                        "a.attnum::int, "
                        "a.attnotnull::boolean, "
                        "i.indisprimary::boolean, "
                        "pg_get_expr(def.adbin, c.oid)::text AS defaultexpr, "
                        "(CASE WHEN t.typname = 'geometry' THEN postgis_typmod_dims(a.atttypmod) ELSE NULL END)::int dim, "
                        "(CASE WHEN t.typname = 'geometry' THEN postgis_typmod_srid(a.atttypmod) ELSE NULL END)::int srid, "
                        "(CASE WHEN t.typname = 'geometry' THEN postgis_typmod_type(a.atttypmod) ELSE NULL END)::text geomtyp, "
                        "srtext "
                "FROM pg_class c "
                "JOIN pg_attribute a ON a.attnum > 0 AND "
                                        "a.attrelid = c.oid AND c.relname = $2 "
                                        "AND c.relname IN (SELECT CDB_UserTables())"
                "JOIN pg_type t ON a.atttypid = t.oid "
                "JOIN pg_namespace n ON c.relnamespace=n.oid AND n.nspname = $1 "
                "LEFT JOIN pg_index i ON c.oid = i.indrelid AND "
                                        "i.indisprimary = 't' AND a.attnum = ANY(i.indkey) "
                "LEFT JOIN pg_attrdef def ON def.adrelid = c.oid AND "
                                            "def.adnum = a.attnum "
                "LEFT JOIN spatial_ref_sys srs ON srs.srid = postgis_typmod_srid(a.atttypmod) "
                "ORDER BY a.attnum "
                "$$ LANGUAGE SQL");
    }

    if (osTables.size() != 0)
    {
        char** papszTables = CSLTokenizeString2(osTables, ",", 0);
        for(int i=0;papszTables && papszTables[i];i++)
        {
            papoLayers = (OGRCARTOTableLayer**) CPLRealloc(
                papoLayers, (nLayers + 1) * sizeof(OGRCARTOTableLayer*));
            papoLayers[nLayers ++] = new OGRCARTOTableLayer(this, papszTables[i]);
        }
        CSLDestroy(papszTables);
        return TRUE;
    }

    OGRLayer* poTableListLayer = ExecuteSQLInternal("SELECT CDB_UserTables()");
    if( poTableListLayer )
    {
        OGRFeature* poFeat;
        while( (poFeat = poTableListLayer->GetNextFeature()) != NULL )
        {
            if( poFeat->GetFieldCount() == 1 )
            {
                papoLayers = (OGRCARTOTableLayer**) CPLRealloc(
                    papoLayers, (nLayers + 1) * sizeof(OGRCARTOTableLayer*));
                papoLayers[nLayers ++] = new OGRCARTOTableLayer(
                            this, poFeat->GetFieldAsString(0));
            }
            delete poFeat;
        }
        ReleaseResultSet(poTableListLayer);
    }
    else if( osCurrentSchema == "public" )
        return FALSE;

    /* There's currently a bug with CDB_UserTables() on multi-user accounts */
    if( nLayers == 0 && osCurrentSchema != "public" )
    {
        CPLString osSQL;
        osSQL.Printf("SELECT c.relname FROM pg_class c, pg_namespace n "
                     "WHERE c.relkind in ('r', 'v') AND c.relname !~ '^pg_' AND c.relnamespace=n.oid AND n.nspname = '%s'",
                     OGRCARTOEscapeLiteral(osCurrentSchema).c_str());
        poTableListLayer = ExecuteSQLInternal(osSQL);
        if( poTableListLayer )
        {
            OGRFeature* poFeat;
            while( (poFeat = poTableListLayer->GetNextFeature()) != NULL )
            {
                if( poFeat->GetFieldCount() == 1 )
                {
                    papoLayers = (OGRCARTOTableLayer**) CPLRealloc(
                        papoLayers, (nLayers + 1) * sizeof(OGRCARTOTableLayer*));
                    papoLayers[nLayers ++] = new OGRCARTOTableLayer(
                                this, poFeat->GetFieldAsString(0));
                }
                delete poFeat;
            }
            ReleaseResultSet(poTableListLayer);
        }
        else
            return FALSE;
    }

    return TRUE;
}
OGRLayer *
OGRPGDumpDataSource::ICreateLayer( const char * pszLayerName,
                                  OGRSpatialReference *poSRS,
                                  OGRwkbGeometryType eType,
                                  char ** papszOptions )

{
    CPLString            osCommand;
    const char          *pszGeomType = NULL;
    char                *pszTableName = NULL;
    char                *pszSchemaName = NULL;
    int                  nDimension = 3;
    int                  bHavePostGIS = TRUE;

    const char* pszFIDColumnNameIn = CSLFetchNameValue(papszOptions, "FID");
    CPLString osFIDColumnName, osFIDColumnNameEscaped;
    if (pszFIDColumnNameIn == NULL)
        osFIDColumnName = "ogc_fid";
    else
    {
        if( CSLFetchBoolean(papszOptions,"LAUNDER", TRUE) )
        {
            char* pszLaunderedFid = OGRPGCommonLaunderName(pszFIDColumnNameIn, "PGDump");
            osFIDColumnName = pszLaunderedFid;
            CPLFree(pszLaunderedFid);
        }
        else
        {
            osFIDColumnName = pszFIDColumnNameIn;
        }
    }
    osFIDColumnNameEscaped = OGRPGDumpEscapeColumnName(osFIDColumnName);

    if (strncmp(pszLayerName, "pg", 2) == 0)
    {
        CPLError(CE_Warning, CPLE_AppDefined,
                 "The layer name should not begin by 'pg' as it is a reserved prefix");
    }
    
    //bHavePostGIS = CSLFetchBoolean(papszOptions,"POSTGIS", TRUE);

    int bCreateTable = CSLFetchBoolean(papszOptions,"CREATE_TABLE", TRUE);
    int bCreateSchema = CSLFetchBoolean(papszOptions,"CREATE_SCHEMA", TRUE);
    const char* pszDropTable = CSLFetchNameValueDef(papszOptions,"DROP_TABLE", "IF_EXISTS");

    if( wkbFlatten(eType) == eType )
        nDimension = 2;

    if( CSLFetchNameValue( papszOptions, "DIM") != NULL )
        nDimension = atoi(CSLFetchNameValue( papszOptions, "DIM"));

    /* Should we turn layers with None geometry type as Unknown/GEOMETRY */
    /* so they are still recorded in geometry_columns table ? (#4012) */
    int bNoneAsUnknown = CSLTestBoolean(CSLFetchNameValueDef(
                                    papszOptions, "NONE_AS_UNKNOWN", "NO"));
    if (bNoneAsUnknown && eType == wkbNone)
        eType = wkbUnknown;
    else if (eType == wkbNone)
        bHavePostGIS = FALSE;

    int bExtractSchemaFromLayerName = CSLTestBoolean(CSLFetchNameValueDef(
                                    papszOptions, "EXTRACT_SCHEMA_FROM_LAYER_NAME", "YES"));

    /* Postgres Schema handling:
       Extract schema name from input layer name or passed with -lco SCHEMA.
       Set layer name to "schema.table" or to "table" if schema == current_schema()
       Usage without schema name is backwards compatible
    */
    const char* pszDotPos = strstr(pszLayerName,".");
    if ( pszDotPos != NULL && bExtractSchemaFromLayerName )
    {
      int length = pszDotPos - pszLayerName;
      pszSchemaName = (char*)CPLMalloc(length+1);
      strncpy(pszSchemaName, pszLayerName, length);
      pszSchemaName[length] = '\0';

      if( CSLFetchBoolean(papszOptions,"LAUNDER", TRUE) )
          pszTableName = OGRPGCommonLaunderName( pszDotPos + 1, "PGDump" ); //skip "."
      else
          pszTableName = CPLStrdup( pszDotPos + 1 ); //skip "."
    }
    else
    {
      pszSchemaName = NULL;
      if( CSLFetchBoolean(papszOptions,"LAUNDER", TRUE) )
          pszTableName = OGRPGCommonLaunderName( pszLayerName, "PGDump" ); //skip "."
      else
          pszTableName = CPLStrdup( pszLayerName ); //skip "."
    }

    LogCommit();

/* -------------------------------------------------------------------- */
/*      Set the default schema for the layers.                          */
/* -------------------------------------------------------------------- */
    if( CSLFetchNameValue( papszOptions, "SCHEMA" ) != NULL )
    {
        CPLFree(pszSchemaName);
        pszSchemaName = CPLStrdup(CSLFetchNameValue( papszOptions, "SCHEMA" ));
        if (bCreateSchema)
        {
            osCommand.Printf("CREATE SCHEMA \"%s\"", pszSchemaName);
            Log(osCommand);
        }
    }

    if ( pszSchemaName == NULL)
    {
        pszSchemaName = CPLStrdup("public");
    }

/* -------------------------------------------------------------------- */
/*      Do we already have this layer?                                  */
/* -------------------------------------------------------------------- */
    int iLayer;

    for( iLayer = 0; iLayer < nLayers; iLayer++ )
    {
        if( EQUAL(pszLayerName,papoLayers[iLayer]->GetLayerDefn()->GetName()) )
        {
            CPLError( CE_Failure, CPLE_AppDefined,
                      "Layer %s already exists, CreateLayer failed.\n", 
                      pszLayerName );
            CPLFree( pszTableName );
            CPLFree( pszSchemaName );
            return NULL;
        }
    }


    if (bCreateTable && (EQUAL(pszDropTable, "YES") ||
                         EQUAL(pszDropTable, "ON") ||
                         EQUAL(pszDropTable, "TRUE") ||
                         EQUAL(pszDropTable, "IF_EXISTS")))
    {
        if (EQUAL(pszDropTable, "IF_EXISTS"))
            osCommand.Printf("DROP TABLE IF EXISTS \"%s\".\"%s\" CASCADE", pszSchemaName, pszTableName );
        else
            osCommand.Printf("DROP TABLE \"%s\".\"%s\" CASCADE", pszSchemaName, pszTableName );
        Log(osCommand);
    }
    
/* -------------------------------------------------------------------- */
/*      Handle the GEOM_TYPE option.                                    */
/* -------------------------------------------------------------------- */
    pszGeomType = CSLFetchNameValue( papszOptions, "GEOM_TYPE" );
    if( pszGeomType == NULL )
    {
        pszGeomType = "geometry";
    }

    if( !EQUAL(pszGeomType,"geometry") && !EQUAL(pszGeomType, "geography"))
    {
        CPLError( CE_Failure, CPLE_AppDefined,
                    "GEOM_TYPE in PostGIS enabled databases must be 'geometry' or 'geography'.\n"
                    "Creation of layer %s with GEOM_TYPE %s has failed.",
                    pszLayerName, pszGeomType );
        CPLFree( pszTableName );
        CPLFree( pszSchemaName );
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Try to get the SRS Id of this spatial reference system,         */
/*      adding tot the srs table if needed.                             */
/* -------------------------------------------------------------------- */
    int nUnknownSRSId = -1;
    const char* pszPostgisVersion = CSLFetchNameValue( papszOptions, "POSTGIS_VERSION" );
    int bPostGIS2 = FALSE;
    if( pszPostgisVersion != NULL && atoi(pszPostgisVersion) >= 2 )
    {
        bPostGIS2 = TRUE;
        nUnknownSRSId = 0;
    }

    int nSRSId = nUnknownSRSId;
    int nForcedSRSId = -2;
    if( CSLFetchNameValue( papszOptions, "SRID") != NULL )
    {
        nSRSId = atoi(CSLFetchNameValue( papszOptions, "SRID"));
        nForcedSRSId = nSRSId;
    }
    else
    {
        if (poSRS)
        {
            const char* pszAuthorityName = poSRS->GetAuthorityName(NULL);
            if( pszAuthorityName != NULL && EQUAL( pszAuthorityName, "EPSG" ) )
            {
                /* Assume the EPSG Id is the SRS ID. Might be a wrong guess ! */
                nSRSId = atoi( poSRS->GetAuthorityCode(NULL) );
            }
            else
            {
                const char* pszGeogCSName = poSRS->GetAttrValue("GEOGCS");
                if (pszGeogCSName != NULL && EQUAL(pszGeogCSName, "GCS_WGS_1984"))
                    nSRSId = 4326;
            }
        }
    }

    CPLString osEscapedTableNameSingleQuote = OGRPGDumpEscapeString(pszTableName);
    const char* pszEscapedTableNameSingleQuote = osEscapedTableNameSingleQuote.c_str();

    const char *pszGeometryType = OGRToOGCGeomType(eType);

    const char *pszGFldName = NULL;
    if( bHavePostGIS && !EQUAL(pszGeomType, "geography"))
    {
        if( CSLFetchNameValue( papszOptions, "GEOMETRY_NAME") != NULL )
            pszGFldName = CSLFetchNameValue( papszOptions, "GEOMETRY_NAME");
        else
            pszGFldName = "wkb_geometry";

        if( pszPostgisVersion == NULL || atoi(pszPostgisVersion) < 2 )
        {
            /* Sometimes there is an old cruft entry in the geometry_columns
            * table if things were not properly cleaned up before.  We make
            * an effort to clean out such cruft.
            * Note: PostGIS 2.0 defines geometry_columns as a view (no clean up is needed)
            */
            osCommand.Printf(
                    "DELETE FROM geometry_columns WHERE f_table_name = %s AND f_table_schema = '%s'",
                    pszEscapedTableNameSingleQuote, pszSchemaName );
            if (bCreateTable)
                Log(osCommand);
        }
    }


    LogStartTransaction();

/* -------------------------------------------------------------------- */
/*      Create a basic table with the FID.  Also include the            */
/*      geometry if this is not a PostGIS enabled table.                */
/* -------------------------------------------------------------------- */
    int bFID64 = CSLFetchBoolean(papszOptions, "FID64", FALSE);
    const char* pszSerialType = bFID64 ? "BIGSERIAL": "SERIAL";
    
    CPLString osCreateTable;
    int bTemporary = CSLFetchBoolean( papszOptions, "TEMPORARY", FALSE );
    if (bTemporary)
    {
        CPLFree(pszSchemaName);
        pszSchemaName = CPLStrdup("pg_temp_1");
        osCreateTable.Printf("CREATE TEMPORARY TABLE \"%s\"", pszTableName);
    }
    else
        osCreateTable.Printf("CREATE TABLE%s \"%s\".\"%s\"",
                             CSLFetchBoolean( papszOptions, "UNLOGGED", FALSE ) ? " UNLOGGED": "",
                             pszSchemaName, pszTableName);

    if( !bHavePostGIS )
    {
        if (eType == wkbNone)
            osCommand.Printf(
                    "%s ( "
                    "   %s %s, "
                    "   CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )",
                    osCreateTable.c_str(), osFIDColumnNameEscaped.c_str(), pszSerialType, pszTableName, osFIDColumnNameEscaped.c_str() );
        else
            osCommand.Printf(
                    "%s ( "
                    "   %s %s, "
                    "   WKB_GEOMETRY %s, "
                    "   CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )",
                    osCreateTable.c_str(), osFIDColumnNameEscaped.c_str(), pszSerialType, pszGeomType, pszTableName, osFIDColumnNameEscaped.c_str() );
    }
    else if ( EQUAL(pszGeomType, "geography") )
    {
        if( CSLFetchNameValue( papszOptions, "GEOMETRY_NAME") != NULL )
            pszGFldName = CSLFetchNameValue( papszOptions, "GEOMETRY_NAME");
        else
            pszGFldName = "the_geog";

        if (nSRSId)
            osCommand.Printf(
                     "%s ( %s %s, \"%s\" geography(%s%s,%d), CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )",
                     osCreateTable.c_str(), osFIDColumnNameEscaped.c_str(), pszSerialType, pszGFldName, pszGeometryType, nDimension == 2 ? "" : "Z", nSRSId, pszTableName, osFIDColumnNameEscaped.c_str() );
        else
            osCommand.Printf(
                     "%s ( %s %s, \"%s\" geography(%s%s), CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )",
                     osCreateTable.c_str(), osFIDColumnNameEscaped.c_str(), pszSerialType, pszGFldName, pszGeometryType, nDimension == 2 ? "" : "Z", pszTableName, osFIDColumnNameEscaped.c_str() );
    }
    else
    {
        osCommand.Printf(
                 "%s ( %s %s, CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )",
                 osCreateTable.c_str(), osFIDColumnNameEscaped.c_str(), pszSerialType, pszTableName, osFIDColumnNameEscaped.c_str() );
    }

    if (bCreateTable)
        Log(osCommand);

/* -------------------------------------------------------------------- */
/*      Eventually we should be adding this table to a table of         */
/*      "geometric layers", capturing the WKT projection, and           */
/*      perhaps some other housekeeping.                                */
/* -------------------------------------------------------------------- */
    if( bCreateTable && bHavePostGIS && !EQUAL(pszGeomType, "geography"))
    {
        osCommand.Printf(
                "SELECT AddGeometryColumn('%s',%s,'%s',%d,'%s',%d)",
                pszSchemaName, pszEscapedTableNameSingleQuote, pszGFldName,
                nSRSId, pszGeometryType, nDimension );
        Log(osCommand);
    }

    const char *pszSI = CSLFetchNameValue( papszOptions, "SPATIAL_INDEX" );
    int bCreateSpatialIndex = ( pszSI == NULL || CSLTestBoolean(pszSI) );
    if( bCreateTable && bHavePostGIS && bCreateSpatialIndex )
    {
/* -------------------------------------------------------------------- */
/*      Create the spatial index.                                       */
/*                                                                      */
/*      We're doing this before we add geometry and record to the table */
/*      so this may not be exactly the best way to do it.               */
/* -------------------------------------------------------------------- */
        osCommand.Printf("CREATE INDEX \"%s_%s_geom_idx\" "
                        "ON \"%s\".\"%s\" "
                        "USING GIST (\"%s\")",
                pszTableName, pszGFldName, pszSchemaName, pszTableName, pszGFldName);

        Log(osCommand);
    }

/* -------------------------------------------------------------------- */
/*      Create the layer object.                                        */
/* -------------------------------------------------------------------- */
    OGRPGDumpLayer     *poLayer;

    int bWriteAsHex = !CSLFetchBoolean(papszOptions,"WRITE_EWKT_GEOM",FALSE);

    poLayer = new OGRPGDumpLayer( this, pszSchemaName, pszTableName,
                                  osFIDColumnName, bWriteAsHex, bCreateTable );
    poLayer->SetLaunderFlag( CSLFetchBoolean(papszOptions,"LAUNDER",TRUE) );
    poLayer->SetPrecisionFlag( CSLFetchBoolean(papszOptions,"PRECISION",TRUE));

    const char* pszOverrideColumnTypes = CSLFetchNameValue( papszOptions, "COLUMN_TYPES" );
    poLayer->SetOverrideColumnTypes(pszOverrideColumnTypes);
    poLayer->SetUnknownSRSId(nUnknownSRSId);
    poLayer->SetForcedSRSId(nForcedSRSId);
    poLayer->SetCreateSpatialIndexFlag(bCreateSpatialIndex);
    poLayer->SetPostGIS2(bPostGIS2);

    if( bHavePostGIS )
    {
        OGRGeomFieldDefn oTmp( pszGFldName, eType );
        OGRPGDumpGeomFieldDefn *poGeomField =
            new OGRPGDumpGeomFieldDefn(&oTmp);
        poGeomField->nSRSId = nSRSId;
        poGeomField->nCoordDimension = nDimension;
        poLayer->GetLayerDefn()->AddGeomFieldDefn(poGeomField, FALSE);
    }

/* -------------------------------------------------------------------- */
/*      Add layer to data source layer list.                            */
/* -------------------------------------------------------------------- */
    papoLayers = (OGRPGDumpLayer **)
        CPLRealloc( papoLayers,  sizeof(OGRPGDumpLayer *) * (nLayers+1) );

    papoLayers[nLayers++] = poLayer;

    CPLFree( pszTableName );
    CPLFree( pszSchemaName );

    return poLayer;
}
OGRLayer   *OGRCARTODataSource::ICreateLayer( const char *pszNameIn,
                                           OGRSpatialReference *poSpatialRef,
                                           OGRwkbGeometryType eGType,
                                           char ** papszOptions )
{
    if (!bReadWrite)
    {
        CPLError(CE_Failure, CPLE_AppDefined, "Operation not available in read-only mode");
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Do we already have this layer?  If so, should we blow it        */
/*      away?                                                           */
/* -------------------------------------------------------------------- */
    int iLayer;

    for( iLayer = 0; iLayer < nLayers; iLayer++ )
    {
        if( EQUAL(pszNameIn,papoLayers[iLayer]->GetName()) )
        {
            if( CSLFetchNameValue( papszOptions, "OVERWRITE" ) != NULL
                && !EQUAL(CSLFetchNameValue(papszOptions,"OVERWRITE"),"NO") )
            {
                DeleteLayer( iLayer );
            }
            else
            {
                CPLError( CE_Failure, CPLE_AppDefined,
                          "Layer %s already exists, CreateLayer failed.\n"
                          "Use the layer creation option OVERWRITE=YES to "
                          "replace it.",
                          pszNameIn );
                return NULL;
            }
        }
    }

    CPLString osName(pszNameIn);
    if( CPLFetchBool(const_cast<const char**>(papszOptions), "LAUNDER", true) )
    {
        char* pszTmp = OGRPGCommonLaunderName(pszNameIn);
        osName = pszTmp;
        CPLFree(pszTmp);
    }


    OGRCARTOTableLayer* poLayer = new OGRCARTOTableLayer(this, osName);
    const bool bGeomNullable = CPLFetchBool(const_cast<const char**>(papszOptions), "GEOMETRY_NULLABLE", true);
    int nSRID = (poSpatialRef && eGType != wkbNone) ? FetchSRSId( poSpatialRef ) : 0;
    bool bCartoify = CPLFetchBool(const_cast<const char**>(papszOptions), "CARTODBFY",
                                    CPLFetchBool(const_cast<const char**>(papszOptions), "CARTODBIFY",
                                                 true));
    if( bCartoify )
    {
        if( nSRID != 4326 )
        {
            if( eGType != wkbNone )
            {
                CPLError(CE_Warning, CPLE_AppDefined,
                        "Cannot register table in dashboard with "
                        "cdb_cartodbfytable() since its SRS is not EPSG:4326");
            }
            bCartoify = false;
        }
    }

    poLayer->SetLaunderFlag( CPLFetchBool(const_cast<const char**>(papszOptions), "LAUNDER", true) );
    poLayer->SetDeferredCreation(eGType, poSpatialRef, bGeomNullable, bCartoify);
    papoLayers = (OGRCARTOTableLayer**) CPLRealloc(
                    papoLayers, (nLayers + 1) * sizeof(OGRCARTOTableLayer*));
    papoLayers[nLayers ++] = poLayer;

    return poLayer;
}
int OGRBNADataSource::Open( const char * pszFilename, int bUpdateIn)

{
    int ok = FALSE;

    pszName = CPLStrdup( pszFilename );
    bUpdate = bUpdateIn;
    
    VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
    if (fp)
    {
        BNARecord* record;
        int curLine = 0;
        const char* layerRadixName[] = { "points", "polygons", "lines", "ellipses"};
        OGRwkbGeometryType wkbGeomTypes[] = { wkbPoint, wkbMultiPolygon, wkbLineString, wkbPolygon };
        int i;
#if defined(BNA_FAST_DS_OPEN)
        record = BNA_GetNextRecord(fp, &ok, &curLine, FALSE, BNA_READ_NONE);
        BNA_FreeRecord(record);

        if (ok)
        {
            nLayers = 4;

            papoLayers = (OGRBNALayer **) CPLMalloc(nLayers * sizeof(OGRBNALayer*));
            for(i=0;i<4;i++)
                papoLayers[i] = new OGRBNALayer( pszFilename,
                                                 layerRadixName[i],
                                                 (BNAFeatureType)i, wkbGeomTypes[i], FALSE, this );
        }
#else
        int nFeatures[4] = { 0, 0, 0, 0 };
        OffsetAndLine* offsetAndLineFeaturesTable[4] = { NULL, NULL, NULL, NULL };
        int nIDs[4] = {0, 0, 0, 0};
        int partialIndexTable = TRUE;

        while(1)
        {
            int offset = (int) VSIFTellL(fp);
            int line = curLine;
            record =  BNA_GetNextRecord(fp, &ok, &curLine, FALSE, BNA_READ_NONE);
            if (ok == FALSE)
            {
                BNA_FreeRecord(record);
                if (line != 0)
                    ok = TRUE;
                break;
            }
            if (record == NULL)
            {
                /* end of file */
                ok = TRUE;

                /* and we have finally build the whole index table */
                partialIndexTable = FALSE;
                break;
            }

            if (record->nIDs > nIDs[record->featureType])
                nIDs[record->featureType] = record->nIDs;

            nFeatures[record->featureType]++;
            offsetAndLineFeaturesTable[record->featureType] =
                (OffsetAndLine*)CPLRealloc(offsetAndLineFeaturesTable[record->featureType],
                                           nFeatures[record->featureType] * sizeof(OffsetAndLine));
            offsetAndLineFeaturesTable[record->featureType][nFeatures[record->featureType]-1].offset = offset;
            offsetAndLineFeaturesTable[record->featureType][nFeatures[record->featureType]-1].line = line;

            BNA_FreeRecord(record);
        }

        nLayers = (nFeatures[0] != 0) + (nFeatures[1] != 0) + (nFeatures[2] != 0) + (nFeatures[3] != 0);
        papoLayers = (OGRBNALayer **) CPLMalloc(nLayers * sizeof(OGRBNALayer*));
        int iLayer = 0;
        for(i=0;i<4;i++)
        {
            if (nFeatures[i])
            {
                papoLayers[iLayer] = new OGRBNALayer( pszFilename,
                                                      layerRadixName[i],
                                                      (BNAFeatureType)i,
                                                      wkbGeomTypes[i],
                                                      FALSE,
                                                      this,
                                                      nIDs[i]);
                papoLayers[iLayer]->SetFeatureIndexTable(nFeatures[i],
                                                        offsetAndLineFeaturesTable[i],
                                                        partialIndexTable);
                iLayer++;
            }
        }
#endif
        VSIFCloseL(fp);
    }

    return ok;
}
Beispiel #20
0
/*
 * ICreateLayer
 */
OGRLayer *OGRNGWDataset::ICreateLayer( const char *pszNameIn,
                                           OGRSpatialReference *poSpatialRef,
                                           OGRwkbGeometryType eGType,
                                           char **papszOptions )
{
    if( !bReadWrite )
    {
        CPLError(CE_Failure, CPLE_AppDefined,
            "Operation not available in read-only mode");
        return nullptr;
    }

    // Check permissions as we create new layer in memory and will create in during SyncToDisk.
    FetchPermissions();

    if( !stPermissions.bResourceCanCreate )
    {
        CPLError(CE_Failure, CPLE_AppDefined, "Operation not permitted.");
        return nullptr;
    }

    // Check input parameters.
    if( eGType < wkbPoint || eGType > wkbMultiPolygon )
    {
        CPLError(CE_Failure, CPLE_AppDefined,
            "Unsupported geometry type: %s", OGRGeometryTypeToName(eGType));
        return nullptr;
    }

    if( !poSpatialRef )
    {
        CPLError(CE_Failure, CPLE_AppDefined, "Undefined spatial reference");
        return nullptr;
    }

    poSpatialRef->AutoIdentifyEPSG();
    const char *pszEPSG = poSpatialRef->GetAuthorityCode( nullptr );
    int nEPSG = -1;
    if( pszEPSG != nullptr )
    {
        nEPSG = atoi( pszEPSG );
    }

    if( nEPSG != 3857 ) // TODO: Check NextGIS Web supported SRS.
    {
        CPLError(CE_Failure, CPLE_AppDefined,
            "Unsupported spatial reference EPSG code: %d", nEPSG);
        return nullptr;
    }

    // Do we already have this layer?  If so, should we blow it away?
    bool bOverwrite = CPLFetchBool(papszOptions, "OVERWRITE", "NO");
    for( int iLayer = 0; iLayer < nLayers; ++iLayer )
    {
        if( EQUAL(pszNameIn, papoLayers[iLayer]->GetName()) )
        {
            if( bOverwrite )
            {
                DeleteLayer( iLayer );
                break;
            }
            else
            {
                CPLError( CE_Failure, CPLE_AppDefined,
                          "Layer %s already exists, CreateLayer failed.\n"
                          "Use the layer creation option OVERWRITE=YES to "
                          "replace it.",
                          pszNameIn );
                return nullptr;
            }
        }
    }

    // Create layer.
    std::string osKey = CSLFetchNameValueDef( papszOptions, "KEY", "");
    std::string osDesc = CSLFetchNameValueDef( papszOptions, "DESCRIPTION", "");
    OGRNGWLayer *poLayer = new OGRNGWLayer( this, pszNameIn, poSpatialRef, eGType,
        osKey, osDesc );
    papoLayers = (OGRNGWLayer**) CPLRealloc(papoLayers, (nLayers + 1) *
        sizeof(OGRNGWLayer*));
    papoLayers[nLayers++] = poLayer;
    return poLayer;
}
char *CPLRecodeIconv( const char *pszSource, 
                      const char *pszSrcEncoding, 
                      const char *pszDstEncoding )

{
    iconv_t sConv;

    sConv = iconv_open( pszDstEncoding, pszSrcEncoding );

    if ( sConv == (iconv_t)-1 )
    {
        CPLError( CE_Warning, CPLE_AppDefined, 
                  "Recode from %s to %s failed with the error: \"%s\".", 
                  pszSrcEncoding, pszDstEncoding, strerror(errno) );

        return CPLStrdup(pszSource);
    }

/* -------------------------------------------------------------------- */
/*      XXX: There is a portability issue: iconv() function could be    */
/*      declared differently on different platforms. The second         */
/*      argument could be declared as char** (as POSIX defines) or      */
/*      as a const char**. Handle it with the ICONV_CONST macro here.   */
/* -------------------------------------------------------------------- */
    ICONV_CONST char *pszSrcBuf = (ICONV_CONST char *)pszSource;
    size_t  nSrcLen = strlen( pszSource );
    size_t  nDstCurLen = MAX(CPL_RECODE_DSTBUF_SIZE, nSrcLen + 1);
    size_t  nDstLen = nDstCurLen;
    char    *pszDestination = (char *)CPLCalloc( nDstCurLen, sizeof(char) );
    char    *pszDstBuf = pszDestination;

    while ( nSrcLen > 0 )
    {
        size_t  nConverted =
            iconv( sConv, &pszSrcBuf, &nSrcLen, &pszDstBuf, &nDstLen );

        if ( nConverted == (size_t)-1 )
        {
            if ( errno == EILSEQ )
            {
                // Skip the invalid sequence in the input string.
                static int bHasWarned = FALSE;
                if (!bHasWarned)
                {
                    bHasWarned = TRUE;
                    CPLError(CE_Warning, CPLE_AppDefined,
                            "One or several characters couldn't be converted correctly from %s to %s.\n"
                            "This warning will not be emitted anymore",
                             pszSrcEncoding, pszDstEncoding);
                }
                nSrcLen--, pszSrcBuf++;
                continue;
            }

            else if ( errno == E2BIG )
            {
                // We are running out of the output buffer.
                // Dynamically increase the buffer size.
                size_t nTmp = nDstCurLen;
                nDstCurLen *= 2;
                pszDestination =
                    (char *)CPLRealloc( pszDestination, nDstCurLen );
                pszDstBuf = pszDestination + nTmp - nDstLen;
                nDstLen += nDstCurLen - nTmp;
                continue;
            }

            else
                break;
        }
    }

    pszDestination[nDstCurLen - nDstLen] = '\0';

    iconv_close( sConv );

    return pszDestination;
}
OGRLayer* OGRGeoPackageDataSource::CreateLayer( const char * pszLayerName,
                                      OGRSpatialReference * poSpatialRef,
                                      OGRwkbGeometryType eGType,
                                      char **papszOptions )
{
    int iLayer;
    OGRErr err;
    
    if( !m_bUpdate )
        return NULL;

    /* Read GEOMETRY_COLUMN option */
    const char* pszGeomColumnName = CSLFetchNameValue(papszOptions, "GEOMETRY_COLUMN");
    if (pszGeomColumnName == NULL)
        pszGeomColumnName = "geom";
    
    /* Read FID option */
    const char* pszFIDColumnName = CSLFetchNameValue(papszOptions, "FID");
    if (pszFIDColumnName == NULL)
        pszFIDColumnName = "fid";

    if ( strspn(pszFIDColumnName, "`~!@#$%^&*()+-={}|[]\\:\";'<>?,./") > 0 )
    {
        CPLError(CE_Failure, CPLE_AppDefined,
                 "The primary key (%s) name may not contain special characters or spaces", 
                 pszFIDColumnName);
        return NULL;
    }

    /* Avoiding gpkg prefixes is not an official requirement, but seems wise */
    if (strncmp(pszLayerName, "gpkg", 4) == 0)
    {
        CPLError(CE_Failure, CPLE_AppDefined,
                 "The layer name may not begin with 'gpkg' as it is a reserved geopackage prefix");
        return NULL;
    }

    /* Pre-emptively try and avoid sqlite3 syntax errors due to  */
    /* illegal characters */
    if ( strspn(pszLayerName, "`~!@#$%^&*()+-={}|[]\\:\";'<>?,./") > 0 )
    {
        CPLError(CE_Failure, CPLE_AppDefined,
                 "The layer name may not contain special characters or spaces");
        return NULL;
    }

    /* Check for any existing layers that already use this name */
    for( iLayer = 0; iLayer < m_nLayers; iLayer++ )
    {
        if( EQUAL(pszLayerName, m_papoLayers[iLayer]->GetName()) )
        {
            const char *pszOverwrite = CSLFetchNameValue(papszOptions,"OVERWRITE");
            if( pszOverwrite != NULL && CSLTestBoolean(pszOverwrite) )
            {
                DeleteLayer( iLayer );
            }
            else
            {
                CPLError( CE_Failure, CPLE_AppDefined,
                          "Layer %s already exists, CreateLayer failed.\n"
                          "Use the layer creation option OVERWRITE=YES to "
                          "replace it.",
                          pszLayerName );
                return NULL;
            }
        }
    }

    /* Read our SRS_ID from the OGRSpatialReference */
    int nSRSId = UNDEFINED_SRID;
    if( poSpatialRef != NULL )
        nSRSId = GetSrsId( poSpatialRef );
        
    /* Requirement 25: The geometry_type_name value in a gpkg_geometry_columns */
    /* row SHALL be one of the uppercase geometry type names specified in */
    /* Geometry Types (Normative). */
    const char *pszGeometryType = OGRToOGCGeomType(eGType);
    
    /* Create the table! */
    char *pszSQL = NULL;
    if ( eGType != wkbNone )
    {
        pszSQL = sqlite3_mprintf(
            "CREATE TABLE %s ( "
            "%s INTEGER PRIMARY KEY AUTOINCREMENT, "
            "%s %s )",
             pszLayerName, pszFIDColumnName, pszGeomColumnName, pszGeometryType);
    }
    else
    {
        pszSQL = sqlite3_mprintf(
            "CREATE TABLE %s ( "
            "%s INTEGER PRIMARY KEY AUTOINCREMENT )",
             pszLayerName, pszFIDColumnName);
    }
    
    err = SQLCommand(m_poDb, pszSQL);
    sqlite3_free(pszSQL);
    if ( OGRERR_NONE != err )
        return NULL;

    /* Only spatial tables need to be registered in the metadata (hmmm) */
    if ( eGType != wkbNone )
    {
        /* Requirement 27: The z value in a gpkg_geometry_columns table row */
        /* SHALL be one of 0 (none), 1 (mandatory), or 2 (optional) */
        int bGeometryTypeHasZ = (wkb25DBit & eGType) != 0;

        /* Update gpkg_geometry_columns with the table info */
        pszSQL = sqlite3_mprintf(
            "INSERT INTO gpkg_geometry_columns "
            "(table_name,column_name,geometry_type_name,srs_id,z,m)"
            " VALUES "
            "('%q','%q','%q',%d,%d,%d)",
            pszLayerName,pszGeomColumnName,pszGeometryType,
            nSRSId,bGeometryTypeHasZ,0);
    
        err = SQLCommand(m_poDb, pszSQL);
        sqlite3_free(pszSQL);
        if ( err != OGRERR_NONE )
            return NULL;

        /* Update gpkg_contents with the table info */
        pszSQL = sqlite3_mprintf(
            "INSERT INTO gpkg_contents "
            "(table_name,data_type,identifier,last_change,srs_id)"
            " VALUES "
            "('%q','features','%q',strftime('%%Y-%%m-%%dT%%H:%%M:%%fZ',CURRENT_TIMESTAMP),%d)",
            pszLayerName, pszLayerName, nSRSId);
    
        err = SQLCommand(m_poDb, pszSQL);
        sqlite3_free(pszSQL);
        if ( err != OGRERR_NONE )
            return NULL;

    }

    /* This is where spatial index logic will go in the future */
    const char *pszSI = CSLFetchNameValue( papszOptions, "SPATIAL_INDEX" );
    int bCreateSpatialIndex = ( pszSI == NULL || CSLTestBoolean(pszSI) );
    if( eGType != wkbNone && bCreateSpatialIndex )
    {
        /* This is where spatial index logic will go in the future */
    }
    
    /* The database is now all set up, so create a blank layer and read in the */
    /* info from the database. */
    OGRGeoPackageLayer *poLayer = new OGRGeoPackageLayer(this, pszLayerName);
    
    if( OGRERR_NONE != poLayer->ReadTableDefinition() )
    {
        delete poLayer;
        return NULL;
    }

    m_papoLayers = (OGRLayer**)CPLRealloc(m_papoLayers,  sizeof(OGRGeoPackageLayer*) * (m_nLayers+1));
    m_papoLayers[m_nLayers++] = poLayer;
    return poLayer;
}
OGRSpatialReference *OGROCIDataSource::FetchSRS( int nId )

{
    if( nId < 0 )
        return NULL;

/* -------------------------------------------------------------------- */
/*      First, we look through our SRID cache, is it there?             */
/* -------------------------------------------------------------------- */
    int  i;

    for( i = 0; i < nKnownSRID; i++ )
    {
        if( panSRID[i] == nId )
            return papoSRS[i];
    }

/* -------------------------------------------------------------------- */
/*      Try looking up in MDSYS.CS_SRS table.                           */
/* -------------------------------------------------------------------- */
    OGROCIStatement oStatement( GetSession() );
    char            szSelect[200], **papszResult;

    snprintf( szSelect, sizeof(szSelect),
             "SELECT WKTEXT, AUTH_SRID, AUTH_NAME FROM MDSYS.CS_SRS "
             "WHERE SRID = %d AND WKTEXT IS NOT NULL", nId );

    if( oStatement.Execute( szSelect ) != CE_None )
        return NULL;

    papszResult = oStatement.SimpleFetchRow();
    if( CSLCount(papszResult) < 1 )
        return NULL;

/* -------------------------------------------------------------------- */
/*      Turn into a spatial reference.                                  */
/* -------------------------------------------------------------------- */
    char *pszWKT = papszResult[0];
    OGRSpatialReference *poSRS = NULL;

    poSRS = new OGRSpatialReference();
    if( poSRS->importFromWkt( &pszWKT ) != OGRERR_NONE )
    {
        delete poSRS;
        poSRS = NULL;
    }

/* -------------------------------------------------------------------- */
/*      If we have a corresponding EPSG code for this SRID, use that    */
/*      authority.                                                      */
/* -------------------------------------------------------------------- */
    int bGotEPSGMapping = FALSE;
    for( i = 0; anEPSGOracleMapping[i] != 0; i += 2 )
    {
        if( anEPSGOracleMapping[i] == nId )
        {
            poSRS->SetAuthority( poSRS->GetRoot()->GetValue(), "EPSG",
                                 anEPSGOracleMapping[i+1] );
            bGotEPSGMapping = TRUE;
            break;
        }
    }

/* -------------------------------------------------------------------- */
/*      Insert authority information, if it is available.               */
/* -------------------------------------------------------------------- */
    if( papszResult[1] != NULL && atoi(papszResult[1]) != 0
        && papszResult[2] != NULL && strlen(papszResult[1]) != 0
        && poSRS->GetRoot() != NULL
        && !bGotEPSGMapping )
    {
        poSRS->SetAuthority( poSRS->GetRoot()->GetValue(),
                             papszResult[2], atoi(papszResult[1]) );
    }

/* -------------------------------------------------------------------- */
/*      Add to the cache.                                               */
/* -------------------------------------------------------------------- */
    panSRID = (int *) CPLRealloc(panSRID,sizeof(int) * (nKnownSRID+1) );
    papoSRS = (OGRSpatialReference **)
        CPLRealloc(papoSRS, sizeof(void*) * (nKnownSRID + 1) );
    panSRID[nKnownSRID] = nId;
    papoSRS[nKnownSRID] = poSRS;

    nKnownSRID++;

    return poSRS;
}
Beispiel #24
0
OGRErr OGRPolygon::importFromWkt( char ** ppszInput )

{
    char        szToken[OGR_WKT_TOKEN_MAX];
    const char  *pszInput = *ppszInput;

/* -------------------------------------------------------------------- */
/*      Clear existing rings.                                           */
/* -------------------------------------------------------------------- */
    empty();

/* -------------------------------------------------------------------- */
/*      Read and verify the ``POLYGON'' keyword token.                  */
/* -------------------------------------------------------------------- */
    pszInput = OGRWktReadToken( pszInput, szToken );

    if( !EQUAL(szToken,"POLYGON") )
        return OGRERR_CORRUPT_DATA;

/* -------------------------------------------------------------------- */
/*      Check for EMPTY ...                                             */
/* -------------------------------------------------------------------- */
    const char *pszPreScan;
    int bHasZ = FALSE, bHasM = FALSE;

    pszPreScan = OGRWktReadToken( pszInput, szToken );
    if( EQUAL(szToken,"EMPTY") )
    {
        *ppszInput = (char *) pszPreScan;
        empty();
        return OGRERR_NONE;
    }

/* -------------------------------------------------------------------- */
/*      Check for Z, M or ZM. Will ignore the Measure                   */
/* -------------------------------------------------------------------- */
    else if( EQUAL(szToken,"Z") )
    {
        bHasZ = TRUE;
    }
    else if( EQUAL(szToken,"M") )
    {
        bHasM = TRUE;
    }
    else if( EQUAL(szToken,"ZM") )
    {
        bHasZ = TRUE;
        bHasM = TRUE;
    }

    if (bHasZ || bHasM)
    {
        pszInput = pszPreScan;
        pszPreScan = OGRWktReadToken( pszInput, szToken );
        if( EQUAL(szToken,"EMPTY") )
        {
            *ppszInput = (char *) pszPreScan;
            empty();
            /* FIXME?: In theory we should store the dimension and M presence */
            /* if we want to allow round-trip with ExportToWKT v1.2 */
            return OGRERR_NONE;
        }
    }

    if( !EQUAL(szToken,"(") )
        return OGRERR_CORRUPT_DATA;

    if ( !bHasZ && !bHasM )
    {
        /* Test for old-style POLYGON(EMPTY) */
        pszPreScan = OGRWktReadToken( pszPreScan, szToken );
        if( EQUAL(szToken,"EMPTY") )
        {
            pszPreScan = OGRWktReadToken( pszPreScan, szToken );

            if( EQUAL(szToken,",") )
            {
                /* This is OK according to SFSQL SPEC. */
            }
            else if( !EQUAL(szToken,")") )
                return OGRERR_CORRUPT_DATA;
            else
            {
                *ppszInput = (char *) pszPreScan;
                empty();
                return OGRERR_NONE;
            }
        }
    }

    /* Skip first '(' */
    pszInput = OGRWktReadToken( pszInput, szToken );

/* ==================================================================== */
/*      Read each ring in turn.  Note that we try to reuse the same     */
/*      point list buffer from ring to ring to cut down on              */
/*      allocate/deallocate overhead.                                   */
/* ==================================================================== */
    OGRRawPoint *paoPoints = NULL;
    int         nMaxPoints = 0, nMaxRings = 0;
    double      *padfZ = NULL;

    nCoordDimension = 2;
    
    do
    {
        int     nPoints = 0;

        const char* pszNext = OGRWktReadToken( pszInput, szToken );
        if (EQUAL(szToken,"EMPTY"))
        {
/* -------------------------------------------------------------------- */
/*      Do we need to grow the ring array?                              */
/* -------------------------------------------------------------------- */
            if( nRingCount == nMaxRings )
            {
                nMaxRings = nMaxRings * 2 + 1;
                papoRings = (OGRLinearRing **)
                    CPLRealloc(papoRings, nMaxRings * sizeof(OGRLinearRing*));
            }
            papoRings[nRingCount] = new OGRLinearRing();
            nRingCount++;

            pszInput = OGRWktReadToken( pszNext, szToken );
            if ( !EQUAL(szToken, ",") )
                break;

            continue;
        }

/* -------------------------------------------------------------------- */
/*      Read points for one ring from input.                            */
/* -------------------------------------------------------------------- */
        pszInput = OGRWktReadPoints( pszInput, &paoPoints, &padfZ, &nMaxPoints,
                                     &nPoints );

        if( pszInput == NULL || nPoints == 0 )
        {
            CPLFree( paoPoints );
            return OGRERR_CORRUPT_DATA;
        }
        
/* -------------------------------------------------------------------- */
/*      Do we need to grow the ring array?                              */
/* -------------------------------------------------------------------- */
        if( nRingCount == nMaxRings )
        {
            nMaxRings = nMaxRings * 2 + 1;
            papoRings = (OGRLinearRing **)
                CPLRealloc(papoRings, nMaxRings * sizeof(OGRLinearRing*));
        }

/* -------------------------------------------------------------------- */
/*      Create the new ring, and assign to ring list.                   */
/* -------------------------------------------------------------------- */
        papoRings[nRingCount] = new OGRLinearRing();
        /* Ignore Z array when we have a POLYGON M */
        if (bHasM && !bHasZ)
            papoRings[nRingCount]->setPoints( nPoints, paoPoints, NULL );
        else
            papoRings[nRingCount]->setPoints( nPoints, paoPoints, padfZ );

        nRingCount++;

        if( padfZ && !(bHasM && !bHasZ) )
            nCoordDimension = 3;

/* -------------------------------------------------------------------- */
/*      Read the delimeter following the ring.                          */
/* -------------------------------------------------------------------- */
        
        pszInput = OGRWktReadToken( pszInput, szToken );
    } while( szToken[0] == ',' );

/* -------------------------------------------------------------------- */
/*      freak if we don't get a closing bracket.                        */
/* -------------------------------------------------------------------- */
    CPLFree( paoPoints );
    CPLFree( padfZ );

    if( szToken[0] != ')' )
        return OGRERR_CORRUPT_DATA;
    
    *ppszInput = (char *) pszInput;
    return OGRERR_NONE;
}
int OGRSelafinDataSource::OpenTable(const char * pszFilename) {
#ifdef DEBUG_VERBOSE
    CPLDebug("Selafin", "OpenTable(%s,%i)",
             pszFilename, static_cast<int>(bUpdate));
#endif
    // Open the file
    VSILFILE *fp = NULL;
    if( bUpdate )
    {
        // We have to implement this locking feature for write access because
        // the same file may hold several layers, and some programs (like QGIS)
        // open each layer in a single datasource, so the same file might be
        // opened several times for write access.
        if (TakeLock(pszFilename)==0) {
            CPLError(CE_Failure, CPLE_OpenFailed,
                     "Failed to open %s for write access, "
                     "lock file found %s.",
                     pszFilename, pszLockName);
            return FALSE;
        }
        fp = VSIFOpenL( pszFilename, "rb+" );
    }
    else
    {
        fp = VSIFOpenL( pszFilename, "rb" );
    }

    if( fp == NULL ) {
        CPLError( CE_Warning, CPLE_OpenFailed, "Failed to open %s, %s.", pszFilename, VSIStrerror( errno ) );
        return FALSE;
    }
    if( !bUpdate && strstr(pszFilename, "/vsigzip/") == NULL && strstr(pszFilename, "/vsizip/") == NULL ) fp = (VSILFILE*) VSICreateBufferedReaderHandle((VSIVirtualHandle*)fp);

    // Quickly check if the file is in Selafin format, before actually starting to read to make it faster
    char szBuf[9];
    VSIFReadL(szBuf,1,4,fp);
    if (szBuf[0]!=0 || szBuf[1]!=0 || szBuf[2]!=0 || szBuf[3]!=0x50) {
        VSIFCloseL(fp);
        return FALSE;
    }
    VSIFSeekL(fp,84,SEEK_SET);
    VSIFReadL(szBuf,1,8,fp);
    if (szBuf[0]!=0 || szBuf[1]!=0 || szBuf[2]!=0 || szBuf[3]!=0x50 || szBuf[4]!=0 || szBuf[5]!=0 || szBuf[6]!=0 || szBuf[7]!=8) {
        VSIFCloseL(fp);
        return FALSE;
    }
    /* VSIFSeekL(fp,76,SEEK_SET);
    VSIFReadL(szBuf,1,8,fp);
    if (STRNCASECMP(szBuf,"Seraphin",8)!=0 && STRNCASECMP(szBuf,"Serafin",7)!=0) {
        VSIFCloseL(fp);
        return FALSE;
    } */

    // Get layer base name
    CPLString osBaseLayerName = CPLGetBasename(pszFilename);
    CPLString osExt = CPLGetExtension(pszFilename);
    if( STARTS_WITH(pszFilename, "/vsigzip/") && EQUAL(osExt, "gz") ) {
        size_t nPos=std::string::npos;
        if (strlen(pszFilename)>3) nPos=osExt.find_last_of('.',strlen(pszFilename)-4);
        if (nPos!=std::string::npos) {
            osExt=osExt.substr(nPos+1,strlen(pszFilename)-4-nPos);
            osBaseLayerName=osBaseLayerName.substr(0,nPos);
        } else {
            osExt="";
        }
    }

    // Read header of file to get common information for all layers
    poHeader=Selafin::read_header(fp,pszFilename);
    if (poHeader==NULL) {
        VSIFCloseL(fp);
        CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open %s, wrong format.\n", pszFilename);
        return FALSE;
    }
    if (poHeader->nEpsg!=0) {
        poSpatialRef=new OGRSpatialReference();
        if (poSpatialRef->importFromEPSG(poHeader->nEpsg)!=OGRERR_NONE) {
            CPLError( CE_Warning, CPLE_AppDefined, "EPSG %d not found. Could not set datasource SRS.\n", poHeader->nEpsg);
            delete poSpatialRef;
            poSpatialRef=NULL;
        }
    }

    // Create two layers for each selected time step: one for points, the other for elements
    poRange.setMaxValue(poHeader->nSteps);
    const int nNewLayers = static_cast<int>(poRange.getSize());
    if (EQUAL(pszFilename, "/vsistdin/")) osBaseLayerName = "layer";
    CPLString osLayerName;
    papoLayers = (OGRSelafinLayer **) CPLRealloc(papoLayers, sizeof(void*) * (nLayers+nNewLayers));
    for (size_t j=0;j<2;++j) {
        SelafinTypeDef eType=(j==0)?POINTS:ELEMENTS;
        for (int i=0;i<poHeader->nSteps;++i) {
            if (poRange.contains(eType,i)) {
                char szTemp[30];
                double dfTime = 0.0;
                if( VSIFSeekL(fp, poHeader->getPosition(i)+4, SEEK_SET)!=0 ||
                    Selafin::read_float(fp, dfTime)==0 )
                {
                    VSIFCloseL(fp);
                    CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open %s, wrong format.\n", pszFilename);
                    return FALSE;
                }
                if (poHeader->panStartDate==NULL) snprintf(szTemp,29,"%d",i); else {
                    struct tm sDate;
                    memset(&sDate, 0, sizeof(sDate));
                    sDate.tm_year=poHeader->panStartDate[0]-1900;
                    sDate.tm_mon=poHeader->panStartDate[1]-1;
                    sDate.tm_mday=poHeader->panStartDate[2];
                    sDate.tm_hour=poHeader->panStartDate[3];
                    sDate.tm_min=poHeader->panStartDate[4];
                    sDate.tm_sec=poHeader->panStartDate[5]+(int)dfTime;
                    mktime(&sDate);
                    strftime(szTemp,29,"%Y_%m_%d_%H_%M_%S",&sDate);
                }
                if (eType==POINTS) osLayerName=osBaseLayerName+"_p"+szTemp; else osLayerName=osBaseLayerName+"_e"+szTemp;
                papoLayers[nLayers++] =
                    new OGRSelafinLayer( osLayerName, bUpdate, poSpatialRef,
                                         poHeader, i, eType);
                //poHeader->nRefCount++;
            }
        }
    }

    // Free allocated variables and exit
    return TRUE;
}
Beispiel #26
0
void NASHandler::startElement( const XMLCh* const /* uri */,
                               const XMLCh* const localname,
                               const XMLCh* const /* qname */,
                               const Attributes& attrs )

{
    char        szElementName[MAX_TOKEN_SIZE];
    GMLReadState *poState = m_poReader->GetState();

    tr_strcpy( szElementName, localname );

    if ( ( m_bIgnoreFeature && m_nDepth >= m_nDepthFeature ) ||
         ( m_osIgnoredElement != "" && m_nDepth >= m_nDepthElement ) )
    {
        m_nDepth ++;
        return;
    }

    // ignore attributes of external references and "objektkoordinaten"
    // (see PostNAS #3 and #15)
    if ( EQUAL( szElementName, "zeigtAufExternes" ) ||
         EQUAL( szElementName, "objektkoordinaten" ) )
    {
        m_osIgnoredElement = szElementName;
        m_nDepthElement    = m_nDepth;
        m_nDepth ++;

        return;
    }

#ifdef DEBUG_VERBOSE
    CPLDebug( "NAS",
              "%*sstartElement %s m_bIgnoreFeature:%d depth:%d "
              "depthFeature:%d featureClass:%s",
              m_nDepth, "", szElementName,
              m_bIgnoreFeature, m_nDepth, m_nDepthFeature,
              poState->m_poFeature ? poState->m_poFeature->
                  GetClass()->GetElementName() : "(no feature)"
            );
#endif

/* -------------------------------------------------------------------- */
/*      If we are in the midst of collecting a feature attribute        */
/*      value, then this must be a complex attribute which we don't     */
/*      try to collect for now, so just terminate the field             */
/*      collection.                                                     */
/* -------------------------------------------------------------------- */
    if( m_pszCurField != NULL )
    {
        CPLFree( m_pszCurField );
        m_pszCurField = NULL;
    }

/* -------------------------------------------------------------------- */
/*      If we are collecting geometry, or if we determine this is a     */
/*      geometry element then append to the geometry info.              */
/* -------------------------------------------------------------------- */
    const char *pszLast = NULL;

    if( m_pszGeometry != NULL
        || IsGeometryElement( szElementName ) )
    {
        const int nLNLen = tr_strlen( localname );
        CPLString osAttributes = GetAttributes( &attrs );

        /* should save attributes too! */

        if( m_pszGeometry == NULL )
            m_nGeometryDepth = poState->m_nPathLength;

        if( m_pszGeometry == NULL ||
            m_nGeomLen + nLNLen + 4 + (int)osAttributes.size() > m_nGeomAlloc )
        {
            m_nGeomAlloc = (int) (m_nGeomAlloc * 1.3 + nLNLen + osAttributes.size() + 1000);
            m_pszGeometry = (char *)
                CPLRealloc( m_pszGeometry, m_nGeomAlloc);
        }

        strcpy( m_pszGeometry+m_nGeomLen, "<" );
        tr_strcpy( m_pszGeometry+m_nGeomLen+1, localname );

        if( osAttributes.size() > 0 )
        {
            strcat( m_pszGeometry+m_nGeomLen, " " );
            strcat( m_pszGeometry+m_nGeomLen, osAttributes );
        }

        strcat( m_pszGeometry+m_nGeomLen, ">" );
        m_nGeomLen += static_cast<int>(strlen(m_pszGeometry+m_nGeomLen));
    }

/* -------------------------------------------------------------------- */
/*      Is this the ogc:Filter element in a update operation            */
/*      (wfs:Delete, wfsext:Replace or wfs:Update)?                     */
/*      specialized sort of feature.                                    */
/* -------------------------------------------------------------------- */
    else if( EQUAL(szElementName,"Filter")
             && (pszLast = m_poReader->GetState()->GetLastComponent()) != NULL
             && (EQUAL(pszLast,"Delete") || EQUAL(pszLast,"Replace") ||
                 EQUAL(pszLast,"Update")) )
    {
        const char* pszFilteredClassName = m_poReader->GetFilteredClassName();
        if ( pszFilteredClassName != NULL &&
             strcmp("Delete", pszFilteredClassName) != 0 )
        {
            m_bIgnoreFeature = true;
            m_nDepthFeature = m_nDepth;
            m_nDepth ++;

            return;
        }

        if( m_osLastTypeName == "" )
        {
            CPLError( CE_Failure, CPLE_AssertionFailed,
                      "m_osLastTypeName == \"\"");

            m_bIgnoreFeature = true;
            m_nDepthFeature = m_nDepth;
            m_nDepth ++;
            return;
        }

        if( EQUAL( pszLast, "Replace" )  &&
            ( m_osLastReplacingFID == "" || m_osLastSafeToIgnore == "" ) )
        {
            CPLError( CE_Failure, CPLE_AssertionFailed,
                      "m_osLastReplacingFID == \"\" || "
                      "m_osLastSafeToIgnore == \"\"" );

            m_bIgnoreFeature = true;
            m_nDepthFeature = m_nDepth;
            m_nDepth ++;
            return;
        }

        if( EQUAL( pszLast, "Update" )  &&
            ( m_osLastEnded == "" || m_osLastOccasion == "" ) )
        {
            CPLError( CE_Failure, CPLE_AssertionFailed,
                      "m_osLastEnded == \"\" || m_osLastOccasion == \"\"" );

            m_bIgnoreFeature = true;
            m_nDepthFeature = m_nDepth;
            m_nDepth ++;
            return;
        }

        m_bIgnoreFeature = false;

        m_poReader->PushFeature( "Delete", attrs );

        m_nDepthFeature = m_nDepth;
        m_nDepth ++;

        m_poReader->SetFeaturePropertyDirectly(
            "typeName", CPLStrdup(m_osLastTypeName) );
        m_poReader->SetFeaturePropertyDirectly( "context", CPLStrdup(pszLast) );

        if( EQUAL( pszLast, "Replace" ) )
        {
            //CPLAssert( m_osLastReplacingFID != "" );
            //CPLAssert( m_osLastSafeToIgnore != "" );
            m_poReader->SetFeaturePropertyDirectly(
                "replacedBy", CPLStrdup(m_osLastReplacingFID) );
            m_poReader->SetFeaturePropertyDirectly(
                "safeToIgnore", CPLStrdup(m_osLastSafeToIgnore) );
        }
        else if( EQUAL( pszLast, "Update" ) )
        {
            //CPLAssert( m_osLastEnded != "" );
            //CPLAssert( m_osLastOccasion != "" );
            m_poReader->SetFeaturePropertyDirectly(
                "endet", CPLStrdup(m_osLastEnded) );
            m_poReader->SetFeaturePropertyDirectly(
                "anlass", CPLStrdup(m_osLastOccasion) );
            m_osLastEnded = "";
            m_osLastOccasion = "";
        }

        return;
    }

/* -------------------------------------------------------------------- */
/*      Is it a feature?  If so push a whole new state, and return.     */
/* -------------------------------------------------------------------- */
    else if( m_poReader->IsFeatureElement( szElementName ) )
    {
        m_osLastTypeName = szElementName;

        const char* pszFilteredClassName = m_poReader->GetFilteredClassName();

        pszLast = m_poReader->GetState()->GetLastComponent();
        if( pszLast != NULL && EQUAL(pszLast,"Replace") )
        {
            XMLCh  Name[100];

            tr_strcpy( Name, "gml:id" );
            int nIndex = attrs.getIndex( Name );

            if( nIndex == -1 || m_osLastReplacingFID !="" )
            {
                CPLError( CE_Failure, CPLE_AssertionFailed,
                          "nIndex == -1 || m_osLastReplacingFID !=\"\"" );

                m_bIgnoreFeature = true;
                m_nDepthFeature = m_nDepth;
                m_nDepth ++;

                return;
            }

            // Capture "gml:id" attribute as part of the property value -
            // primarily this is for the wfsext:Replace operation's attribute.
            char *pszReplacingFID = tr_strdup( attrs.getValue( nIndex ) );
            m_osLastReplacingFID = pszReplacingFID;
            CPLFree( pszReplacingFID );

#ifdef DEBUG_VERBOSE
            CPLDebug( "NAS", "%*s### Replace typeName=%s replacedBy=%s",
                      m_nDepth, "", m_osLastTypeName.c_str(),
                      m_osLastReplacingFID.c_str() );
#endif
        }

        if ( pszFilteredClassName != NULL &&
             strcmp(szElementName, pszFilteredClassName) != 0 )
        {
            m_bIgnoreFeature = true;
            m_nDepthFeature = m_nDepth;
            m_nDepth ++;

            return;
        }

        m_bIgnoreFeature = false;

        m_poReader->PushFeature( szElementName, attrs );

        m_nDepthFeature = m_nDepth;
        m_nDepth ++;

        return;
    }

/* -------------------------------------------------------------------- */
/*      If it is the wfs:Delete or wfs:Update element, then remember    */
/*      the typeName attribute so we can assign it to the feature that  */
/*      will be produced when we process the Filter element.            */
/* -------------------------------------------------------------------- */
    else if( EQUAL(szElementName,"Delete") || EQUAL(szElementName,"Update") )
    {
        XMLCh  Name[100];

        tr_strcpy( Name, "typeName" );
        int nIndex = attrs.getIndex( Name );

        if( nIndex != -1 )
        {
            char *pszTypeName = tr_strdup( attrs.getValue( nIndex ) );
            m_osLastTypeName = pszTypeName;
            CPLFree( pszTypeName );
        }

        m_osLastSafeToIgnore = "";
        m_osLastReplacingFID = "";

        if( EQUAL(szElementName,"Update") )
        {
            m_bInUpdate = true;
        }
    }

    else if ( m_bInUpdate && EQUAL(szElementName, "Property") )
    {
        m_bInUpdateProperty = true;
    }

    else if ( m_bInUpdateProperty && ( EQUAL(szElementName, "Name" ) ||
                                       EQUAL(szElementName, "Value" ) ) )
    {
        // collect attribute name or value
        CPLFree( m_pszCurField );
        m_pszCurField = CPLStrdup("");
    }

/* -------------------------------------------------------------------- */
/*      If it is the wfsext:Replace element, then remember the          */
/*      safeToIgnore attribute so we can assign it to the feature       */
/*      that will be produced when we process the Filter element.       */
/* -------------------------------------------------------------------- */
    else if( EQUAL(szElementName,"Replace") )
    {
        XMLCh  Name[100];

        tr_strcpy( Name, "safeToIgnore" );
        int nIndex = attrs.getIndex( Name );

        if( nIndex != -1 )
        {
            char *pszSafeToIgnore = tr_strdup( attrs.getValue( nIndex ) );
            m_osLastSafeToIgnore = pszSafeToIgnore;
            CPLFree( pszSafeToIgnore );
        }
        else
        {
            CPLError( CE_Warning, CPLE_AppDefined,
                      "NAS: safeToIgnore attribute missing" );
            m_osLastSafeToIgnore = "false";
        }

        m_osLastReplacingFID = "";
    }

/* -------------------------------------------------------------------- */
/*      If it is (or at least potentially is) a simple attribute,       */
/*      then start collecting it.                                       */
/* -------------------------------------------------------------------- */
    else if( m_poReader->IsAttributeElement( szElementName ) )
    {
        CPLFree( m_pszCurField );
        m_pszCurField = CPLStrdup("");

        // Capture href as OB property.
        m_poReader->CheckForRelations( szElementName, attrs, &m_pszCurField );

        // Capture "fid" attribute as part of the property value -
        // primarily this is for wfs:Delete operation's FeatureId attribute.
        if( EQUAL(szElementName,"FeatureId") )
            m_poReader->CheckForFID( attrs, &m_pszCurField );
    }

/* -------------------------------------------------------------------- */
/*      Push the element onto the current state's path.                 */
/* -------------------------------------------------------------------- */
    poState->PushPath( szElementName );

    m_nDepth ++;
}
Beispiel #27
0
int OGRMDBDataSource::OpenGeomediaWarehouse(OGRMDBTable* poGAliasTable)
{
    int iTableName = poGAliasTable->GetColumnIndex("TableName", TRUE);
    int iTableType = poGAliasTable->GetColumnIndex("TableType", TRUE);

    if (iTableName < 0 || iTableType < 0)
        return FALSE;

    char* pszFeatureTableName = NULL;
    char* pszGeometryProperties = NULL;
    char* pszGCoordSystemTable = NULL;
    while(poGAliasTable->GetNextRow())
    {
        char* pszTableType = poGAliasTable->GetColumnAsString(iTableType);
        if (pszTableType == NULL)
            continue;

        if (strcmp(pszTableType, "INGRFeatures") == 0)
        {
            pszFeatureTableName = poGAliasTable->GetColumnAsString(iTableName);
        }
        else if (strcmp(pszTableType, "INGRGeometryProperties") == 0)
        {
            pszGeometryProperties = poGAliasTable->GetColumnAsString(iTableName);
        }
        else if (strcmp(pszTableType, "GCoordSystemTable") == 0)
        {
            pszGCoordSystemTable = poGAliasTable->GetColumnAsString(iTableName);
        }

        CPLFree(pszTableType);
    }

    if (pszFeatureTableName == NULL)
    {
        CPLFree(pszGeometryProperties);
        CPLFree(pszGCoordSystemTable);
        return FALSE;
    }

    OGRMDBTable* poGFeaturesTable = poDB->GetTable(pszFeatureTableName);
    CPLFree(pszFeatureTableName);
    pszFeatureTableName = NULL;

    OGRMDBTable* poGeometryPropertiesTable;
    if (pszGeometryProperties)
        poGeometryPropertiesTable = poDB->GetTable(pszGeometryProperties);
    else
        poGeometryPropertiesTable = NULL;
    CPLFree(pszGeometryProperties);
    pszGeometryProperties = NULL;

    if (poGFeaturesTable == NULL)
    {
        delete poGeometryPropertiesTable;
        CPLFree(pszGCoordSystemTable);
        return FALSE;
    }

    int iFeatureName = poGFeaturesTable->GetColumnIndex("FeatureName", TRUE);
    int iGeometryType = poGFeaturesTable->GetColumnIndex("GeometryType", TRUE);
    int iPrimaryGeometryFieldName = poGFeaturesTable->GetColumnIndex("PrimaryGeometryFieldName", TRUE);

    if (iFeatureName < 0 || iGeometryType < 0 || iPrimaryGeometryFieldName < 0)
    {
        delete poGeometryPropertiesTable;
        delete poGFeaturesTable;
        CPLFree(pszGCoordSystemTable);
        return FALSE;
    }

    if (poGeometryPropertiesTable != NULL && poGeometryPropertiesTable->GetRowCount() != poGFeaturesTable->GetRowCount())
    {
        delete poGeometryPropertiesTable;
        poGeometryPropertiesTable = NULL;
    }

    int iGCoordSystemGUID = -1;
    if (poGeometryPropertiesTable)
    {
        iGCoordSystemGUID = poGeometryPropertiesTable->GetColumnIndex("GCoordSystemGUID", TRUE);
        if (iGCoordSystemGUID < 0)
        {
            delete poGeometryPropertiesTable;
            delete poGFeaturesTable;
            CPLFree(pszGCoordSystemTable);
            return FALSE;
        }
    }

    while(poGFeaturesTable->GetNextRow() &&
          (poGeometryPropertiesTable == NULL || poGeometryPropertiesTable->GetNextRow()))
    {
        char* pszFeatureName = poGFeaturesTable->GetColumnAsString(iFeatureName);
        //int nGeometryType = poGFeaturesTable->GetColumnAsInt(iGeometryType);
        char* pszGeometryFieldName = poGFeaturesTable->GetColumnAsString(iPrimaryGeometryFieldName);
        char* pszGCoordSystemGUID;
        if (poGeometryPropertiesTable)
            pszGCoordSystemGUID = poGeometryPropertiesTable->GetColumnAsString(iGCoordSystemGUID);
        else
            pszGCoordSystemGUID = NULL;
        if (pszFeatureName && pszGeometryFieldName)
        {
            OGRMDBTable* poTable = poDB->GetTable(pszFeatureName);
            if (poTable)
            {
                OGRMDBLayer* poLayer = new OGRMDBLayer( this, poTable );

                if( poLayer->Initialize( pszFeatureName,
                                         pszGeometryFieldName,
                                         GetGeomediaSRS(pszGCoordSystemTable, pszGCoordSystemGUID) )
                    != CE_None )
                {
                    delete poLayer;
                }
                else
                {
                    papoLayers = (OGRMDBLayer**)CPLRealloc(papoLayers, (nLayers+1) * sizeof(OGRMDBLayer*));
                    papoLayers[nLayers++] = poLayer;
                }
            }
        }
        CPLFree(pszFeatureName);
        CPLFree(pszGeometryFieldName);
        CPLFree(pszGCoordSystemGUID);
    }

    delete poGeometryPropertiesTable;
    delete poGFeaturesTable;
    CPLFree(pszGCoordSystemTable);

    return TRUE;
}
Beispiel #28
0
void NASHandler::endElement( const XMLCh* const /* uri */ ,
                             const XMLCh* const localname,
                             const XMLCh* const /* qname */)

{
    char        szElementName[MAX_TOKEN_SIZE];
    GMLReadState *poState = m_poReader->GetState();

    tr_strcpy( szElementName, localname );

    m_nDepth --;

    if (m_bIgnoreFeature && m_nDepth >= m_nDepthFeature)
    {
        if (m_nDepth == m_nDepthFeature)
        {
            m_bIgnoreFeature = false;
            m_nDepthFeature = 0;
        }
        return;
    }

    if ( m_osIgnoredElement != "" && m_nDepth >= m_nDepthElement )
    {
        if ( m_nDepth == m_nDepthElement )
        {
            m_osIgnoredElement = "";
            m_nDepthElement    = 0;
        }
        return;
    }

#ifdef DEBUG_VERBOSE
    CPLDebug("NAS",
              "%*sendElement %s m_bIgnoreFeature:%d depth:%d depthFeature:%d featureClass:%s",
              m_nDepth, "", szElementName,
              m_bIgnoreFeature, m_nDepth, m_nDepthFeature,
              poState->m_poFeature ? poState->m_poFeature->GetClass()->GetElementName() : "(no feature)"
            );
#endif

   if( m_bInUpdateProperty )
   {
       if( EQUAL( szElementName, "Name" ) )
       {
           CPLAssert( m_osLastPropertyName == "" );
           m_osLastPropertyName = m_pszCurField;
           m_pszCurField = NULL;
       }
       else if( EQUAL( szElementName, "Value" ) )
       {
           CPLAssert( m_osLastPropertyValue == "" );
           m_osLastPropertyValue = m_pszCurField;
           m_pszCurField = NULL;
       }
       else if( EQUAL( szElementName, "Property" ) )
       {
           if( EQUAL( m_osLastPropertyName, "adv:lebenszeitintervall/adv:AA_Lebenszeitintervall/adv:endet" ) )
           {
               CPLAssert( m_osLastPropertyValue != "" );
               m_osLastEnded = m_osLastPropertyValue;
           }
           else if( EQUAL( m_osLastPropertyName, "adv:anlass" ) )
           {
               CPLAssert( m_osLastPropertyValue != "" );
               m_osLastOccasion = m_osLastPropertyValue;
           }
           else
           {
               CPLError( CE_Warning, CPLE_AppDefined,
                         "NAS: Expected property name or value instead of %s",
                         m_osLastPropertyName.c_str() );
           }

           m_osLastPropertyName = "";
           m_osLastPropertyValue = "";
           m_bInUpdateProperty = false;
       }

       poState->PopPath();

       return;
   }

   if ( m_bInUpdate && EQUAL( szElementName, "Update" ) )
   {
       m_bInUpdate = false;
   }

/* -------------------------------------------------------------------- */
/*      Is this closing off an attribute value?  We assume so if        */
/*      we are collecting an attribute value and got to this point.     */
/*      We don't bother validating that the closing tag matches the     */
/*      opening tag.                                                    */
/* -------------------------------------------------------------------- */
    if( m_pszCurField != NULL )
    {
        CPLAssert( poState->m_poFeature != NULL );

        m_poReader->SetFeaturePropertyDirectly( poState->osPath.c_str(), m_pszCurField );
        m_pszCurField = NULL;
    }

/* -------------------------------------------------------------------- */
/*      If we are collecting Geometry than store it, and consider if    */
/*      this is the end of the geometry.                                */
/* -------------------------------------------------------------------- */
    if( m_pszGeometry != NULL )
    {
        int nLNLen = tr_strlen( localname );

        /* should save attributes too! */

        if( m_nGeomLen + nLNLen + 4 > m_nGeomAlloc )
        {
            m_nGeomAlloc = (int) (m_nGeomAlloc * 1.3 + nLNLen + 1000);
            m_pszGeometry = (char *)
                CPLRealloc( m_pszGeometry, m_nGeomAlloc);
        }

        strcat( m_pszGeometry+m_nGeomLen, "</" );
        tr_strcpy( m_pszGeometry+m_nGeomLen+2, localname );
        strcat( m_pszGeometry+m_nGeomLen+nLNLen+2, ">" );
        m_nGeomLen += static_cast<int>(strlen(m_pszGeometry+m_nGeomLen));

        if( poState->m_nPathLength == m_nGeometryDepth+1 )
        {
            if( poState->m_poFeature != NULL )
            {
                CPLXMLNode* psNode = CPLParseXMLString(m_pszGeometry);
                if (psNode)
                {
                    /* workaround for common malformed gml:pos with just a
                     * elevation value instead of a full 3D coordinate:
                     *
                     * <gml:Point gml:id="BII2H">
                     *    <gml:pos srsName="urn:adv:crs:ETRS89_h">41.394</gml:pos>
                     * </gml:Point>
                     *
                     */
                    const char *pszPos;
                    if( (pszPos = CPLGetXMLValue( psNode, "=Point.pos", NULL ) ) != NULL
                        && strstr(pszPos, " ") == NULL )
                    {
                        CPLSetXMLValue( psNode, "pos", CPLSPrintf("0 0 %s", pszPos) );
                    }

                    if ( poState->m_poFeature->GetGeometryList() &&
                         poState->m_poFeature->GetGeometryList()[0] )
                    {
                        int iId = poState->m_poFeature->GetClass()->GetPropertyIndex( "gml_id" );
                        const GMLProperty *poIdProp = poState->m_poFeature->GetProperty(iId);
#ifdef DEBUG_VERBOSE
                        char *pszOldGeom = CPLSerializeXMLTree( poState->m_poFeature->GetGeometryList()[0] );

                        CPLDebug("NAS", "Overwriting other geometry (%s; replace:%s; with:%s)",
                                 poIdProp && poIdProp->nSubProperties>0 && poIdProp->papszSubProperties[0] ? poIdProp->papszSubProperties[0] : "(null)",
                                 m_pszGeometry,
                                 pszOldGeom
                                );

                        CPLFree( pszOldGeom );
#else
                        CPLError( CE_Warning, CPLE_AppDefined, "NAS: Overwriting other geometry (%s)",
                                 poIdProp && poIdProp->nSubProperties>0 && poIdProp->papszSubProperties[0] ? poIdProp->papszSubProperties[0] : "(null)" );
#endif
                    }

                    poState->m_poFeature->SetGeometryDirectly( psNode );
                }
                else
                    CPLError( CE_Warning, CPLE_AppDefined, "NAS: Invalid geometry skipped" );
            }
            else
                CPLError( CE_Warning, CPLE_AppDefined, "NAS: Skipping geometry without feature" );

            CPLFree( m_pszGeometry );
            m_pszGeometry = NULL;
            m_nGeomAlloc = m_nGeomLen = 0;
        }
    }

/* -------------------------------------------------------------------- */
/*      If we are collecting a feature, and this element tag matches    */
/*      element name for the class, then we have finished the           */
/*      feature, and we pop the feature read state.                     */
/* -------------------------------------------------------------------- */
    const char *pszLast = NULL;

    if( m_nDepth == m_nDepthFeature && poState->m_poFeature != NULL
        && EQUAL(szElementName,
                 poState->m_poFeature->GetClass()->GetElementName()) )
    {
        m_nDepthFeature = 0;
        m_poReader->PopState();
    }

/* -------------------------------------------------------------------- */
/*      Ends of a wfs:Delete or wfs:Update should be triggered on the   */
/*      close of the <Filter> element.                                  */
/* -------------------------------------------------------------------- */
    else if( m_nDepth == m_nDepthFeature
             && poState->m_poFeature != NULL
             && EQUAL(szElementName,"Filter")
             && (pszLast=poState->m_poFeature->GetClass()->GetElementName())
                != NULL
             && ( EQUAL(pszLast, "Delete") || EQUAL(pszLast, "Update") ) )
    {
        m_nDepthFeature = 0;
        m_poReader->PopState();
    }

/* -------------------------------------------------------------------- */
/*      Otherwise, we just pop the element off the local read states    */
/*      element stack.                                                  */
/* -------------------------------------------------------------------- */
    else
    {
        if( EQUAL(szElementName,poState->GetLastComponent()) )
            poState->PopPath();
        else
        {
            CPLAssert( false );
        }
    }
}
Beispiel #29
0
OGRGeometry *OGRIngresLayer::TranslateGeometry( const char *pszGeom )

{
    OGRGeometry *poGeom = NULL;

/* -------------------------------------------------------------------- */
/*      Parse the tuple list into an array of x/y vertices.  The        */
/*      input may look like "(2,3)" or "((2,3),(4,5),...)".  Extra      */
/*      spaces may occur between tokens.                                */
/* -------------------------------------------------------------------- */
    double *padfXY = NULL;
    int    nVertMax = 0, nVertCount = 0;
    int    nDepth = 0;
    const char *pszNext = pszGeom;

    while( *pszNext != '\0' )
    {
        while( *pszNext == ' ' )
            pszNext++;

        if( *pszNext == '(' )
        {
            pszNext++;
            nDepth++;
            continue;
        }

        if( *pszNext == ')' )
        {
            pszNext++;
            CPLAssert( nDepth == 1 );
            nDepth--;
            break;
        }

        if( *pszNext == ',' )
        {
            pszNext++;
            CPLAssert( nDepth == 1 );
            continue;
        }

        if( nVertCount == nVertMax )
        {
            nVertMax = nVertMax * 2 + 1;
            padfXY = (double *) 
                CPLRealloc(padfXY, sizeof(double) * nVertMax * 2 );
        }

        if( !ParseXY( &pszNext, padfXY + nVertCount*2 ) )
        {
            CPLDebug( "INGRES", "Error parsing geometry: %s", 
                      pszGeom );
            CPLFree( padfXY );
            return NULL;
        }
        
        CPLAssert( *pszNext == ')' );
        nVertCount++;
        pszNext++;
        nDepth--;

        while( *pszNext == ' ' )
            pszNext++;
    }

    CPLAssert( nDepth == 0 );

/* -------------------------------------------------------------------- */
/*      Handle Box/IBox.                                                */
/* -------------------------------------------------------------------- */
    if( EQUAL(osIngresGeomType,"BOX")
        || EQUAL(osIngresGeomType,"IBOX") )
    {
        CPLAssert( nVertCount == 2 );

        OGRLinearRing *poRing = new OGRLinearRing();
        poRing->addPoint( padfXY[0], padfXY[1] );
        poRing->addPoint( padfXY[2], padfXY[1] );
        poRing->addPoint( padfXY[2], padfXY[3] );
        poRing->addPoint( padfXY[0], padfXY[3] );
        poRing->addPoint( padfXY[0], padfXY[1] );

        OGRPolygon *poPolygon = new OGRPolygon();
        poPolygon->addRingDirectly( poRing );

        poGeom = poPolygon;
    }

/* -------------------------------------------------------------------- */
/*      Handle Point/IPoint                                             */
/* -------------------------------------------------------------------- */
    else if( EQUAL(osIngresGeomType,"POINT")
             || EQUAL(osIngresGeomType,"IPOINT") )
    {
        CPLAssert( nVertCount == 1 );

        poGeom = new OGRPoint( padfXY[0], padfXY[1] );
    }

/* -------------------------------------------------------------------- */
/*      Handle various linestring types.                                */
/* -------------------------------------------------------------------- */
    else if( EQUAL(osIngresGeomType,"LSEG")
             || EQUAL(osIngresGeomType,"ILSEG")
             || EQUAL(osIngresGeomType,"LINE")
             || EQUAL(osIngresGeomType,"LONG LINE")
             || EQUAL(osIngresGeomType,"ILINE") )
    {
        OGRLineString *poLine = new OGRLineString();
        int iVert;

        poLine->setNumPoints( nVertCount );
        for( iVert = 0; iVert < nVertCount; iVert++ )
            poLine->setPoint( iVert, padfXY[iVert*2+0], padfXY[iVert*2+1] );

        poGeom = poLine;
    }

/* -------------------------------------------------------------------- */
/*      Handle Polygon/IPolygon/LongPolygon.                            */
/* -------------------------------------------------------------------- */
    else if( EQUAL(osIngresGeomType,"POLYGON")
             || EQUAL(osIngresGeomType,"IPOLYGON")
             || EQUAL(osIngresGeomType,"LONG POLYGON") )
    {
        OGRLinearRing *poLine = new OGRLinearRing();
        int iVert;

        poLine->setNumPoints( nVertCount );
        for( iVert = 0; iVert < nVertCount; iVert++ )
            poLine->setPoint( iVert, padfXY[iVert*2+0], padfXY[iVert*2+1] );

        // INGRES polygons are implicitly closed, but OGR expects explicit
        if( poLine->getX(nVertCount-1) != poLine->getX(0)
            || poLine->getY(nVertCount-1) != poLine->getY(0) )
            poLine->addPoint( poLine->getX(0), poLine->getY(0) );

        OGRPolygon *poPolygon = new OGRPolygon();
        poPolygon->addRingDirectly( poLine );
        poGeom = poPolygon;
    }

    return poGeom;
}
int OGRAmigoCloudDataSource::Open( const char * pszFilename,
                                   char** papszOpenOptionsIn,
                                   int bUpdateIn )

{

    bReadWrite = CPL_TO_BOOL(bUpdateIn);

    pszName = CPLStrdup( pszFilename );
    pszProjectId = CPLStrdup(pszFilename + strlen("AMIGOCLOUD:"));
    char* pchSpace = strchr(pszProjectId, ' ');
    if( pchSpace )
        *pchSpace = '\0';
    if( pszProjectId[0] == 0 )
    {
        CPLError(CE_Failure, CPLE_AppDefined, "Missing project id");
        return FALSE;
    }

    osAPIKey = CSLFetchNameValueDef(papszOpenOptionsIn, "AMIGOCLOUD_API_KEY",
                                    CPLGetConfigOption("AMIGOCLOUD_API_KEY", ""));

    if (osAPIKey.empty())
    {
        osAPIKey = OGRAMIGOCLOUDGetOptionValue(pszFilename, "AMIGOCLOUD_API_KEY");
    }
    if (osAPIKey.empty())
    {
        CPLError(CE_Failure, CPLE_AppDefined, "AMIGOCLOUD_API_KEY is not defined.\n");
        return FALSE;
    }

    OGRLayer* poSchemaLayer = ExecuteSQLInternal("SELECT current_schema()");
    if( poSchemaLayer )
    {
        OGRFeature* poFeat = poSchemaLayer->GetNextFeature();
        if( poFeat )
        {
            if( poFeat->GetFieldCount() == 1 )
            {
                osCurrentSchema = poFeat->GetFieldAsString(0);
            }
            delete poFeat;
        }
        ReleaseResultSet(poSchemaLayer);
    }
    if( osCurrentSchema.empty() )
        return FALSE;

    CPLString osDatasets = OGRAMIGOCLOUDGetOptionValue(pszFilename, "datasets");
    if (!osDatasets.empty())
    {
        char** papszTables = CSLTokenizeString2(osDatasets, ",", 0);
        for(int i=0;papszTables && papszTables[i];i++)
        {

            papoLayers = (OGRAmigoCloudTableLayer**) CPLRealloc(
                papoLayers, (nLayers + 1) * sizeof(OGRAmigoCloudTableLayer*));

            papoLayers[nLayers ++] = new OGRAmigoCloudTableLayer(this, papszTables[i]);
        }
        CSLDestroy(papszTables);

        // If OVERWRITE: YES, truncate the layer.
        if( nLayers==1 &&
            CPLFetchBool(papszOpenOptionsIn, "OVERWRITE", false) )
        {
           TruncateDataset(papoLayers[0]->GetTableName());
        }
        return TRUE;
    } else {
        // If 'datasets' word is in the filename, but no dataset id specified,
        // print the list of available datasets
        if(std::string(pszFilename).find("datasets") != std::string::npos)
            ListDatasets();
    }

    return TRUE;
}