void GDALGMLJP2Expr::ReportError( const char* pszOriStr, const char* pszStr, const char* pszIntroMessage ) { size_t nDist = static_cast<size_t>(pszStr - pszOriStr); if( nDist > 40 ) nDist = 40; CPLString osErrMsg(pszIntroMessage); CPLString osInvalidExpr = CPLString(pszStr - nDist).substr(0, nDist + 20); for( int i = static_cast<int>(nDist) - 1; i >= 0; --i ) { if( osInvalidExpr[i] == '\n' ) { osInvalidExpr = osInvalidExpr.substr(i+1); nDist -= i + 1; break; } } for( size_t i = nDist; i < osInvalidExpr.size(); ++i ) { if( osInvalidExpr[i] == '\n' ) { osInvalidExpr.resize(i); break; } } osErrMsg += osInvalidExpr; osErrMsg += "\n"; for( size_t i = 0; i < nDist; ++i ) osErrMsg += " "; osErrMsg += "^"; CPLError(CE_Failure, CPLE_AppDefined, "%s", osErrMsg.c_str()); }
OGRErr OGRSQLiteSelectLayerCommonBehaviour::GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) { if( iGeomField < 0 || iGeomField >= poLayer->GetLayerDefn()->GetGeomFieldCount() || poLayer->GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetType() == wkbNone ) { if( iGeomField != 0 ) { CPLError(CE_Failure, CPLE_AppDefined, "Invalid geometry field index : %d", iGeomField); } return OGRERR_FAILURE; } /* Caching of extent by SQL string is interesting to speed-up the */ /* establishment of the WFS GetCapabilities document for a MapServer mapfile */ /* which has several layers, only differing by scale rules */ if( iGeomField == 0 ) { const OGREnvelope* psCachedExtent = poDS->GetEnvelopeFromSQL(osSQLBase); if (psCachedExtent) { memcpy(psExtent, psCachedExtent, sizeof(*psCachedExtent)); return OGRERR_NONE; } } CPLString osSQLCommand = osSQLBase; /* ORDER BY are costly to evaluate and are not necessary to establish */ /* the layer extent. */ size_t nOrderByPos = osSQLCommand.ifind(" ORDER BY "); if( osSQLCommand.ifind("SELECT ") == 0 && osSQLCommand.ifind("SELECT ", 1) == std::string::npos && /* Ensure there's no sub SELECT that could confuse our heuristics */ nOrderByPos != std::string::npos && osSQLCommand.ifind(" LIMIT ") == std::string::npos && osSQLCommand.ifind(" UNION ") == std::string::npos && osSQLCommand.ifind(" INTERSECT ") == std::string::npos && osSQLCommand.ifind(" EXCEPT ") == std::string::npos) { osSQLCommand.resize(nOrderByPos); OGRLayer* poTmpLayer = poDS->ExecuteSQL(osSQLCommand.c_str(), NULL, NULL); if (poTmpLayer) { OGRErr eErr = poTmpLayer->GetExtent(iGeomField, psExtent, bForce); poDS->ReleaseResultSet(poTmpLayer); return eErr; } } OGRErr eErr; if( iGeomField == 0 ) eErr = poLayer->BaseGetExtent(psExtent, bForce); else eErr = poLayer->BaseGetExtent(iGeomField, psExtent, bForce); if (iGeomField == 0 && eErr == OGRERR_NONE && poDS->GetUpdate() == FALSE) poDS->SetEnvelopeForSQL(osSQLBase, *psExtent); return eErr; }
const char *RDataset::ASCIIFGets() { char chNextChar; osLastStringRead.resize(0); do { chNextChar = '\n'; VSIFReadL( &chNextChar, 1, 1, fp ); if( chNextChar != '\n' ) osLastStringRead += chNextChar; } while( chNextChar != '\n' && chNextChar != '\0' ); return osLastStringRead; }
OGRErr OGRSQLiteSelectLayer::GetExtent(OGREnvelope *psExtent, int bForce) { if (GetGeomType() == wkbNone) return OGRERR_FAILURE; /* Caching of extent by SQL string is interesting to speed-up the */ /* establishment of the WFS GetCapabilities document for a MapServer mapfile */ /* which has several layers, only differing by scale rules */ const OGREnvelope* psCachedExtent = poDS->GetEnvelopeFromSQL(osSQLBase); if (psCachedExtent) { memcpy(psExtent, psCachedExtent, sizeof(*psCachedExtent)); return OGRERR_NONE; } CPLString osSQLCommand = osSQLBase; /* ORDER BY are costly to evaluate and are not necessary to establish */ /* the layer extent. */ size_t nOrderByPos = osSQLCommand.ifind(" ORDER BY "); if( osSQLCommand.ifind("SELECT ") == 0 && nOrderByPos != std::string::npos && osSQLCommand.ifind(" LIMIT ") == std::string::npos && osSQLCommand.ifind(" UNION ") == std::string::npos && osSQLCommand.ifind(" INTERSECT ") == std::string::npos && osSQLCommand.ifind(" EXCEPT ") == std::string::npos) { osSQLCommand.resize(nOrderByPos); OGRLayer* poTmpLayer = poDS->ExecuteSQL(osSQLCommand.c_str(), NULL, NULL); if (poTmpLayer) { OGRErr eErr = poTmpLayer->GetExtent(psExtent, bForce); poDS->ReleaseResultSet(poTmpLayer); return eErr; } } OGRErr eErr = OGRSQLiteLayer::GetExtent(psExtent, bForce); if (eErr == OGRERR_NONE && poDS->GetUpdate() == FALSE) poDS->SetEnvelopeForSQL(osSQLBase, *psExtent); return eErr; }
swq_expr_node *SWQCastEvaluator( swq_expr_node *node, swq_expr_node **sub_node_values ) { swq_expr_node *poRetNode = NULL; swq_expr_node *poSrcNode = sub_node_values[0]; switch( node->field_type ) { case SWQ_INTEGER: { poRetNode = new swq_expr_node( 0 ); switch( poSrcNode->field_type ) { case SWQ_INTEGER: case SWQ_BOOLEAN: poRetNode->int_value = poSrcNode->int_value; break; case SWQ_FLOAT: poRetNode->int_value = (int) poSrcNode->float_value; break; default: poRetNode->int_value = atoi(poSrcNode->string_value); break; } } break; case SWQ_FLOAT: { poRetNode = new swq_expr_node( 0.0 ); switch( poSrcNode->field_type ) { case SWQ_INTEGER: case SWQ_BOOLEAN: poRetNode->float_value = poSrcNode->int_value; break; case SWQ_FLOAT: poRetNode->float_value = poSrcNode->float_value; break; default: poRetNode->float_value = atof(poSrcNode->string_value); break; } } break; // everything else is a string. default: { CPLString osRet; switch( poSrcNode->field_type ) { case SWQ_INTEGER: case SWQ_BOOLEAN: osRet.Printf( "%d", poSrcNode->int_value ); break; case SWQ_FLOAT: osRet.Printf( "%.15g", poSrcNode->float_value ); break; default: osRet = poSrcNode->string_value; break; } if( node->nSubExprCount > 2 ) { int nWidth; nWidth = sub_node_values[2]->int_value; if( nWidth > 0 && (int) strlen(osRet) > nWidth ) osRet.resize(nWidth); } poRetNode = new swq_expr_node( osRet.c_str() ); } } return poRetNode; }
swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node, swq_expr_node **sub_node_values ) { swq_expr_node *poRet = NULL; /* -------------------------------------------------------------------- */ /* Floating point operations. */ /* -------------------------------------------------------------------- */ if( sub_node_values[0]->field_type == SWQ_FLOAT || (node->nSubExprCount > 1 && sub_node_values[1]->field_type == SWQ_FLOAT) ) { poRet = new swq_expr_node(0); poRet->field_type = node->field_type; if( SWQ_IS_INTEGER(sub_node_values[0]->field_type) ) sub_node_values[0]->float_value = (double) sub_node_values[0]->int_value; if( node->nSubExprCount > 1 && SWQ_IS_INTEGER(sub_node_values[1]->field_type) ) sub_node_values[1]->float_value = (double)sub_node_values[1]->int_value; if( node->nOperation != SWQ_ISNULL ) { for( int i = 0; i < node->nSubExprCount; i++ ) { if( sub_node_values[i]->is_null ) { if( poRet->field_type == SWQ_BOOLEAN ) { poRet->int_value = FALSE; return poRet; } else if( poRet->field_type == SWQ_FLOAT ) { poRet->float_value = 0; poRet->is_null = 1; return poRet; } else if( SWQ_IS_INTEGER(poRet->field_type) || node->nOperation == SWQ_MODULUS ) { poRet->field_type = SWQ_INTEGER; poRet->int_value = 0; poRet->is_null = 1; return poRet; } } } } switch( (swq_op) node->nOperation ) { case SWQ_EQ: poRet->int_value = sub_node_values[0]->float_value == sub_node_values[1]->float_value; break; case SWQ_NE: poRet->int_value = sub_node_values[0]->float_value != sub_node_values[1]->float_value; break; case SWQ_GT: poRet->int_value = sub_node_values[0]->float_value > sub_node_values[1]->float_value; break; case SWQ_LT: poRet->int_value = sub_node_values[0]->float_value < sub_node_values[1]->float_value; break; case SWQ_GE: poRet->int_value = sub_node_values[0]->float_value >= sub_node_values[1]->float_value; break; case SWQ_LE: poRet->int_value = sub_node_values[0]->float_value <= sub_node_values[1]->float_value; break; case SWQ_IN: { poRet->int_value = 0; for( int i = 1; i < node->nSubExprCount; i++ ) { if( sub_node_values[0]->float_value == sub_node_values[i]->float_value ) { poRet->int_value = 1; break; } } } break; case SWQ_BETWEEN: poRet->int_value = sub_node_values[0]->float_value >= sub_node_values[1]->float_value && sub_node_values[0]->float_value <= sub_node_values[2]->float_value; break; case SWQ_ISNULL: poRet->int_value = sub_node_values[0]->is_null; break; case SWQ_ADD: poRet->float_value = sub_node_values[0]->float_value + sub_node_values[1]->float_value; break; case SWQ_SUBTRACT: poRet->float_value = sub_node_values[0]->float_value - sub_node_values[1]->float_value; break; case SWQ_MULTIPLY: poRet->float_value = sub_node_values[0]->float_value * sub_node_values[1]->float_value; break; case SWQ_DIVIDE: if( sub_node_values[1]->float_value == 0 ) poRet->float_value = INT_MAX; else poRet->float_value = sub_node_values[0]->float_value / sub_node_values[1]->float_value; break; case SWQ_MODULUS: { GIntBig nRight = (GIntBig) sub_node_values[1]->float_value; poRet->field_type = SWQ_INTEGER; if (nRight == 0) poRet->int_value = INT_MAX; else poRet->int_value = ((GIntBig) sub_node_values[0]->float_value) % nRight; break; } default: CPLAssert( false ); delete poRet; poRet = NULL; break; } } /* -------------------------------------------------------------------- */ /* integer/boolean operations. */ /* -------------------------------------------------------------------- */ else if( SWQ_IS_INTEGER(sub_node_values[0]->field_type) || sub_node_values[0]->field_type == SWQ_BOOLEAN ) { poRet = new swq_expr_node(0); poRet->field_type = node->field_type; if( node->nOperation != SWQ_ISNULL ) { for( int i = 0; i < node->nSubExprCount; i++ ) { if( sub_node_values[i]->is_null ) { if( poRet->field_type == SWQ_BOOLEAN ) { poRet->int_value = FALSE; return poRet; } else if( SWQ_IS_INTEGER(poRet->field_type) ) { poRet->int_value = 0; poRet->is_null = 1; return poRet; } } } } switch( (swq_op) node->nOperation ) { case SWQ_AND: poRet->int_value = sub_node_values[0]->int_value && sub_node_values[1]->int_value; break; case SWQ_OR: poRet->int_value = sub_node_values[0]->int_value || sub_node_values[1]->int_value; break; case SWQ_NOT: poRet->int_value = !sub_node_values[0]->int_value; break; case SWQ_EQ: poRet->int_value = sub_node_values[0]->int_value == sub_node_values[1]->int_value; break; case SWQ_NE: poRet->int_value = sub_node_values[0]->int_value != sub_node_values[1]->int_value; break; case SWQ_GT: poRet->int_value = sub_node_values[0]->int_value > sub_node_values[1]->int_value; break; case SWQ_LT: poRet->int_value = sub_node_values[0]->int_value < sub_node_values[1]->int_value; break; case SWQ_GE: poRet->int_value = sub_node_values[0]->int_value >= sub_node_values[1]->int_value; break; case SWQ_LE: poRet->int_value = sub_node_values[0]->int_value <= sub_node_values[1]->int_value; break; case SWQ_IN: { poRet->int_value = 0; for( int i = 1; i < node->nSubExprCount; i++ ) { if( sub_node_values[0]->int_value == sub_node_values[i]->int_value ) { poRet->int_value = 1; break; } } } break; case SWQ_BETWEEN: poRet->int_value = sub_node_values[0]->int_value >= sub_node_values[1]->int_value && sub_node_values[0]->int_value <= sub_node_values[2]->int_value; break; case SWQ_ISNULL: poRet->int_value = sub_node_values[0]->is_null; break; case SWQ_ADD: poRet->int_value = sub_node_values[0]->int_value + sub_node_values[1]->int_value; break; case SWQ_SUBTRACT: poRet->int_value = sub_node_values[0]->int_value - sub_node_values[1]->int_value; break; case SWQ_MULTIPLY: poRet->int_value = sub_node_values[0]->int_value * sub_node_values[1]->int_value; break; case SWQ_DIVIDE: if( sub_node_values[1]->int_value == 0 ) poRet->int_value = INT_MAX; else poRet->int_value = sub_node_values[0]->int_value / sub_node_values[1]->int_value; break; case SWQ_MODULUS: if( sub_node_values[1]->int_value == 0 ) poRet->int_value = INT_MAX; else poRet->int_value = sub_node_values[0]->int_value % sub_node_values[1]->int_value; break; default: CPLAssert( false ); delete poRet; poRet = NULL; break; } } /* -------------------------------------------------------------------- */ /* String operations. */ /* -------------------------------------------------------------------- */ else { poRet = new swq_expr_node(0); poRet->field_type = node->field_type; if( node->nOperation != SWQ_ISNULL ) { for( int i = 0; i < node->nSubExprCount; i++ ) { if( sub_node_values[i]->is_null ) { if( poRet->field_type == SWQ_BOOLEAN ) { poRet->int_value = FALSE; return poRet; } else if( poRet->field_type == SWQ_STRING ) { poRet->string_value = CPLStrdup(""); poRet->is_null = 1; return poRet; } } } } switch( (swq_op) node->nOperation ) { case SWQ_EQ: { /* When comparing timestamps, the +00 at the end might be discarded */ /* if the other member has no explicit timezone */ if( (sub_node_values[0]->field_type == SWQ_TIMESTAMP || sub_node_values[0]->field_type == SWQ_STRING) && (sub_node_values[1]->field_type == SWQ_TIMESTAMP || sub_node_values[1]->field_type == SWQ_STRING) && strlen(sub_node_values[0]->string_value) > 3 && strlen(sub_node_values[1]->string_value) > 3 && (strcmp(sub_node_values[0]->string_value + strlen(sub_node_values[0]->string_value)-3, "+00") == 0 && sub_node_values[1]->string_value[strlen(sub_node_values[1]->string_value)-3] == ':') ) { poRet->int_value = EQUALN(sub_node_values[0]->string_value, sub_node_values[1]->string_value, strlen(sub_node_values[1]->string_value)); } else if( (sub_node_values[0]->field_type == SWQ_TIMESTAMP || sub_node_values[0]->field_type == SWQ_STRING) && (sub_node_values[1]->field_type == SWQ_TIMESTAMP || sub_node_values[1]->field_type == SWQ_STRING) && strlen(sub_node_values[0]->string_value) > 3 && strlen(sub_node_values[1]->string_value) > 3 && (sub_node_values[0]->string_value[strlen(sub_node_values[0]->string_value)-3] == ':') && strcmp(sub_node_values[1]->string_value + strlen(sub_node_values[1]->string_value)-3, "+00") == 0) { poRet->int_value = EQUALN(sub_node_values[0]->string_value, sub_node_values[1]->string_value, strlen(sub_node_values[0]->string_value)); } else { poRet->int_value = strcasecmp(sub_node_values[0]->string_value, sub_node_values[1]->string_value) == 0; } break; } case SWQ_NE: poRet->int_value = strcasecmp(sub_node_values[0]->string_value, sub_node_values[1]->string_value) != 0; break; case SWQ_GT: poRet->int_value = strcasecmp(sub_node_values[0]->string_value, sub_node_values[1]->string_value) > 0; break; case SWQ_LT: poRet->int_value = strcasecmp(sub_node_values[0]->string_value, sub_node_values[1]->string_value) < 0; break; case SWQ_GE: poRet->int_value = strcasecmp(sub_node_values[0]->string_value, sub_node_values[1]->string_value) >= 0; break; case SWQ_LE: poRet->int_value = strcasecmp(sub_node_values[0]->string_value, sub_node_values[1]->string_value) <= 0; break; case SWQ_IN: { poRet->int_value = 0; for( int i = 1; i < node->nSubExprCount; i++ ) { if( strcasecmp(sub_node_values[0]->string_value, sub_node_values[i]->string_value) == 0 ) { poRet->int_value = 1; break; } } } break; case SWQ_BETWEEN: poRet->int_value = strcasecmp(sub_node_values[0]->string_value, sub_node_values[1]->string_value) >= 0 && strcasecmp(sub_node_values[0]->string_value, sub_node_values[2]->string_value) <= 0; break; case SWQ_LIKE: { char chEscape = '\0'; if( node->nSubExprCount == 3 ) chEscape = sub_node_values[2]->string_value[0]; poRet->int_value = swq_test_like(sub_node_values[0]->string_value, sub_node_values[1]->string_value, chEscape); break; } case SWQ_ISNULL: poRet->int_value = sub_node_values[0]->is_null; break; case SWQ_CONCAT: case SWQ_ADD: { CPLString osResult = sub_node_values[0]->string_value; for( int i = 1; i < node->nSubExprCount; i++ ) osResult += sub_node_values[i]->string_value; poRet->string_value = CPLStrdup(osResult); poRet->is_null = sub_node_values[0]->is_null; break; } case SWQ_SUBSTR: { int nOffset, nSize; const char *pszSrcStr = sub_node_values[0]->string_value; if( SWQ_IS_INTEGER(sub_node_values[1]->field_type) ) nOffset = (int)sub_node_values[1]->int_value; else if( sub_node_values[1]->field_type == SWQ_FLOAT ) nOffset = (int) sub_node_values[1]->float_value; else nOffset = 0; if( node->nSubExprCount < 3 ) nSize = 100000; else if( SWQ_IS_INTEGER(sub_node_values[2]->field_type) ) nSize = (int)sub_node_values[2]->int_value; else if( sub_node_values[2]->field_type == SWQ_FLOAT ) nSize = (int) sub_node_values[2]->float_value; else nSize = 0; int nSrcStrLen = (int)strlen(pszSrcStr); /* In SQL, the first character is at offset 1 */ /* And 0 is considered as 1 */ if (nOffset > 0) nOffset --; /* Some implementations allow negative offsets, to start */ /* from the end of the string */ else if( nOffset < 0 ) { if( nSrcStrLen + nOffset >= 0 ) nOffset = nSrcStrLen + nOffset; else nOffset = 0; } if( nSize < 0 || nOffset > nSrcStrLen ) { nOffset = 0; nSize = 0; } else if( nOffset + nSize > nSrcStrLen ) nSize = nSrcStrLen - nOffset; CPLString osResult = pszSrcStr + nOffset; if( (int)osResult.size() > nSize ) osResult.resize( nSize ); poRet->string_value = CPLStrdup(osResult); poRet->is_null = sub_node_values[0]->is_null; break; } case SWQ_HSTORE_GET_VALUE: { const char *pszHStore = sub_node_values[0]->string_value; const char *pszSearchedKey = sub_node_values[1]->string_value; char* pszRet = OGRHStoreGetValue(pszHStore, pszSearchedKey); poRet->string_value = pszRet ? pszRet : CPLStrdup(""); poRet->is_null = (pszRet == NULL); break; } default: CPLAssert( false ); delete poRet; poRet = NULL; break; } } return poRet; }
swq_expr_node *SWQCastEvaluator( swq_expr_node *node, swq_expr_node **sub_node_values ) { swq_expr_node *poRetNode = NULL; swq_expr_node *poSrcNode = sub_node_values[0]; switch( node->field_type ) { case SWQ_INTEGER: { poRetNode = new swq_expr_node( 0 ); poRetNode->is_null = poSrcNode->is_null; switch( poSrcNode->field_type ) { case SWQ_INTEGER: case SWQ_BOOLEAN: poRetNode->int_value = poSrcNode->int_value; break; case SWQ_INTEGER64: // TODO: warn in case of overflow ? poRetNode->int_value = (int) poSrcNode->int_value; break; case SWQ_FLOAT: poRetNode->int_value = (int) poSrcNode->float_value; break; default: poRetNode->int_value = atoi(poSrcNode->string_value); break; } } break; case SWQ_INTEGER64: { poRetNode = new swq_expr_node( 0 ); poRetNode->is_null = poSrcNode->is_null; poRetNode->field_type = SWQ_INTEGER64; switch( poSrcNode->field_type ) { case SWQ_INTEGER: case SWQ_INTEGER64: case SWQ_BOOLEAN: poRetNode->int_value = poSrcNode->int_value; break; case SWQ_FLOAT: poRetNode->int_value = (GIntBig) poSrcNode->float_value; break; default: poRetNode->int_value = CPLAtoGIntBig(poSrcNode->string_value); break; } } break; case SWQ_FLOAT: { poRetNode = new swq_expr_node( 0.0 ); poRetNode->is_null = poSrcNode->is_null; switch( poSrcNode->field_type ) { case SWQ_INTEGER: case SWQ_INTEGER64: case SWQ_BOOLEAN: poRetNode->float_value = (double) poSrcNode->int_value; break; case SWQ_FLOAT: poRetNode->float_value = poSrcNode->float_value; break; default: poRetNode->float_value = CPLAtof(poSrcNode->string_value); break; } } break; case SWQ_GEOMETRY: { poRetNode = new swq_expr_node( (OGRGeometry*) NULL ); if( !poSrcNode->is_null ) { switch( poSrcNode->field_type ) { case SWQ_GEOMETRY: { poRetNode->geometry_value = poSrcNode->geometry_value->clone(); poRetNode->is_null = FALSE; break; } case SWQ_STRING: { char* pszTmp = poSrcNode->string_value; OGRGeometryFactory::createFromWkt(&pszTmp, NULL, &(poRetNode->geometry_value)); if( poRetNode->geometry_value != NULL ) poRetNode->is_null = FALSE; break; } default: break; } } break; } // everything else is a string. default: { CPLString osRet; switch( poSrcNode->field_type ) { case SWQ_INTEGER: case SWQ_BOOLEAN: case SWQ_INTEGER64: osRet.Printf( CPL_FRMT_GIB, poSrcNode->int_value ); break; case SWQ_FLOAT: osRet.Printf( "%.15g", poSrcNode->float_value ); break; case SWQ_GEOMETRY: { if( poSrcNode->geometry_value != NULL ) { char* pszWKT = NULL; poSrcNode->geometry_value->exportToWkt(&pszWKT); osRet = pszWKT; CPLFree(pszWKT); } else osRet = ""; break; } default: osRet = poSrcNode->string_value; break; } if( node->nSubExprCount > 2 ) { int nWidth; nWidth = (int) sub_node_values[2]->int_value; if( nWidth > 0 && (int) strlen(osRet) > nWidth ) osRet.resize(nWidth); } poRetNode = new swq_expr_node( osRet.c_str() ); poRetNode->is_null = poSrcNode->is_null; } } return poRetNode; }
void OGROSMLayer::AddComputedAttribute(const char* pszName, OGRFieldType eType, const char* pszSQL) { if( poDS->hDBForComputedAttributes == NULL ) { int rc; #ifdef HAVE_SQLITE_VFS rc = sqlite3_open_v2( ":memory:", &(poDS->hDBForComputedAttributes), SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX, NULL ); #else rc = sqlite3_open( ":memory:", &(poDS->hDBForComputedAttributes) ); #endif if( rc != SQLITE_OK ) { CPLError( CE_Failure, CPLE_AppDefined, "Cannot open temporary sqlite DB" ); return; } } if( poFeatureDefn->GetFieldIndex(pszName) >= 0 ) { CPLError( CE_Failure, CPLE_AppDefined, "A field with same name %s already exists", pszName ); return; } CPLString osSQL(pszSQL); std::vector<CPLString> aosAttrToBind; std::vector<int> anIndexToBind; size_t nStartSearch = 0; while(TRUE) { size_t nPos = osSQL.find("[", nStartSearch); if( nPos == std::string::npos ) break; nStartSearch = nPos + 1; if( nPos > 0 && osSQL[nPos-1] != '\\' ) { CPLString osAttr = osSQL.substr(nPos + 1); size_t nPos2 = osAttr.find("]"); if( nPos2 == std::string::npos ) break; osAttr.resize(nPos2); osSQL = osSQL.substr(0, nPos) + "?" + osSQL.substr(nPos + 1 + nPos2+1); aosAttrToBind.push_back(osAttr); anIndexToBind.push_back(poFeatureDefn->GetFieldIndex(osAttr)); } } while(TRUE) { size_t nPos = osSQL.find("\\"); if( nPos == std::string::npos || nPos == osSQL.size() - 1 ) break; osSQL = osSQL.substr(0, nPos) + osSQL.substr(nPos + 1); } CPLDebug("OSM", "SQL : \"%s\"", osSQL.c_str()); sqlite3_stmt *hStmt; int rc = sqlite3_prepare( poDS->hDBForComputedAttributes, osSQL, -1, &hStmt, NULL ); if( rc != SQLITE_OK ) { CPLError( CE_Failure, CPLE_AppDefined, "sqlite3_prepare() failed : %s", sqlite3_errmsg(poDS->hDBForComputedAttributes) ); return; } OGRFieldDefn oField(pszName, eType); poFeatureDefn->AddFieldDefn(&oField); oComputedAttributes.push_back(OGROSMComputedAttribute(pszName)); oComputedAttributes[oComputedAttributes.size()-1].eType = eType; oComputedAttributes[oComputedAttributes.size()-1].nIndex = poFeatureDefn->GetFieldCount() - 1; oComputedAttributes[oComputedAttributes.size()-1].osSQL = pszSQL; oComputedAttributes[oComputedAttributes.size()-1].hStmt = hStmt; oComputedAttributes[oComputedAttributes.size()-1].aosAttrToBind = aosAttrToBind; oComputedAttributes[oComputedAttributes.size()-1].anIndexToBind = anIndexToBind; }
static int WFS_ExprDumpAsOGCFilter(CPLString& osFilter, const Expr* expr, int bExpectBinary, ExprDumpFilterOptions* psOptions) { switch(expr->eType) { case TOKEN_VAR_NAME: { if (bExpectBinary) return FALSE; /* Special fields not understood by server */ if (EQUAL(expr->pszVal, "gml_id") || EQUAL(expr->pszVal, "FID") || EQUAL(expr->pszVal, "OGR_GEOMETRY") || EQUAL(expr->pszVal, "OGR_GEOM_WKT") || EQUAL(expr->pszVal, "OGR_GEOM_AREA") || EQUAL(expr->pszVal, "OGR_STYLE")) { CPLDebug("WFS", "Attribute refers to a OGR special field. Cannot use server-side filtering"); return FALSE; } const char* pszFieldname; CPLString osVal; if (expr->pszVal[0] == '\'' || expr->pszVal[0] == '"') { osVal = expr->pszVal + 1; osVal.resize(osVal.size() - 1); pszFieldname = osVal.c_str(); } else pszFieldname = expr->pszVal; if (psOptions->poFDefn->GetFieldIndex(pszFieldname) == -1) { CPLDebug("WFS", "Field '%s' unknown. Cannot use server-side filtering", pszFieldname); return FALSE; } if (psOptions->nVersion >= 200) osFilter += "<ValueReference>"; else osFilter += "<PropertyName>"; char* pszFieldnameXML = CPLEscapeString(pszFieldname, -1, CPLES_XML); osFilter += pszFieldnameXML; CPLFree(pszFieldnameXML); if (psOptions->nVersion >= 200) osFilter += "</ValueReference>"; else osFilter += "</PropertyName>"; break; } case TOKEN_LITERAL: { if (bExpectBinary) return FALSE; const char* pszLiteral; CPLString osVal; if (expr->pszVal[0] == '\'' || expr->pszVal[0] == '"') { osVal = expr->pszVal + 1; osVal.resize(osVal.size() - 1); pszLiteral = osVal.c_str(); } else pszLiteral = expr->pszVal; osFilter += "<Literal>"; char* pszLiteralXML = CPLEscapeString(pszLiteral, -1, CPLES_XML); osFilter += pszLiteralXML; CPLFree(pszLiteralXML); osFilter += "</Literal>"; break; } case TOKEN_NOT: osFilter += "<Not>"; if (!WFS_ExprDumpAsOGCFilter(osFilter, expr->expr1, TRUE, psOptions)) return FALSE; osFilter += "</Not>"; break; case TOKEN_LIKE: { CPLString osVal; char ch; char firstCh = 0; int i; if (psOptions->nVersion == 100) osFilter += "<PropertyIsLike wildCard='*' singleChar='_' escape='!'>"; else osFilter += "<PropertyIsLike wildCard='*' singleChar='_' escapeChar='!'>"; if (!WFS_ExprDumpAsOGCFilter(osFilter, expr->expr1, FALSE, psOptions)) return FALSE; if (expr->expr2->eType != TOKEN_LITERAL) return FALSE; osFilter += "<Literal>"; /* Escape value according to above special characters */ /* For URL compatibility reason, we remap the OGR SQL '%' wildchard into '*' */ i = 0; ch = expr->expr2->pszVal[i]; if (ch == '\'' || ch == '"') { firstCh = ch; i ++; } for(; (ch = expr->expr2->pszVal[i]) != '\0'; i++) { if (ch == '%') osVal += "*"; else if (ch == '!') osVal += "!!"; else if (ch == '*') osVal += "!*"; else if (ch == firstCh && expr->expr2->pszVal[i + 1] == 0) break; else { char ach[2]; ach[0] = ch; ach[1] = 0; osVal += ach; } } osFilter += osVal; osFilter += "</Literal>"; osFilter += "</PropertyIsLike>"; break; } case TOKEN_EQUAL: case TOKEN_NOT_EQUAL: case TOKEN_LESSER_OR_EQUAL: case TOKEN_LESSER: case TOKEN_GREATER_OR_EQUAL: case TOKEN_GREATER: { if (expr->eType == TOKEN_EQUAL && expr->expr2->eType == TOKEN_LITERAL && EQUAL(expr->expr2->pszVal, "NULL")) { osFilter += "<PropertyIsNull>"; if (!WFS_ExprDumpAsOGCFilter(osFilter, expr->expr1, FALSE, psOptions)) return FALSE; osFilter += "</PropertyIsNull>"; psOptions->bOutNeedsNullCheck = TRUE; break; } if (expr->eType == TOKEN_NOT_EQUAL && expr->expr2->eType == TOKEN_LITERAL && EQUAL(expr->expr2->pszVal, "NULL")) { osFilter += "<Not><PropertyIsNull>"; if (!WFS_ExprDumpAsOGCFilter(osFilter, expr->expr1, FALSE, psOptions)) return FALSE; osFilter += "</PropertyIsNull></Not>"; psOptions->bOutNeedsNullCheck = TRUE; break; } TokenType eType = expr->eType; int bAddClosingNot = FALSE; if (!psOptions->bPropertyIsNotEqualToSupported && eType == TOKEN_NOT_EQUAL) { osFilter += "<Not>"; eType = TOKEN_EQUAL; bAddClosingNot = TRUE; } const char* pszName = NULL; switch(eType) { case TOKEN_EQUAL: pszName = "PropertyIsEqualTo"; break; case TOKEN_NOT_EQUAL: pszName = "PropertyIsNotEqualTo"; break; case TOKEN_LESSER_OR_EQUAL: pszName = "PropertyIsLessThanOrEqualTo"; break; case TOKEN_LESSER: pszName = "PropertyIsLessThan"; break; case TOKEN_GREATER_OR_EQUAL: pszName = "PropertyIsGreaterThanOrEqualTo"; break; case TOKEN_GREATER: pszName = "PropertyIsGreaterThan"; break; default: break; } osFilter += "<"; osFilter += pszName; osFilter += ">"; if (!WFS_ExprDumpAsOGCFilter(osFilter, expr->expr1, FALSE, psOptions)) return FALSE; if (!WFS_ExprDumpAsOGCFilter(osFilter, expr->expr2, FALSE, psOptions)) return FALSE; osFilter += "</"; osFilter += pszName; osFilter += ">"; if (bAddClosingNot) osFilter += "</Not>"; break; } case TOKEN_AND: case TOKEN_OR: { const char* pszName = (expr->eType == TOKEN_AND) ? "And" : "Or"; osFilter += "<"; osFilter += pszName; osFilter += ">"; if (!WFS_ExprDumpAsOGCFilter(osFilter, expr->expr1, TRUE, psOptions)) return FALSE; if (!WFS_ExprDumpAsOGCFilter(osFilter, expr->expr2, TRUE, psOptions)) return FALSE; osFilter += "</"; osFilter += pszName; osFilter += ">"; break; } default: return FALSE; } return TRUE; }
bool VSIDIRAz::AnalyseAzureFileList( const CPLString& osBaseURL, const char* pszXML) { #if DEBUG_VERBOSE CPLDebug("AZURE", "%s", pszXML); #endif CPLXMLNode* psTree = CPLParseXMLString(pszXML); if( psTree == nullptr ) return false; CPLXMLNode* psEnumerationResults = CPLGetXMLNode(psTree, "=EnumerationResults"); bool bNonEmpty = false; if( psEnumerationResults ) { CPLString osPrefix = CPLGetXMLValue(psEnumerationResults, "Prefix", ""); CPLXMLNode* psBlobs = CPLGetXMLNode(psEnumerationResults, "Blobs"); if( psBlobs == nullptr ) { psBlobs = CPLGetXMLNode(psEnumerationResults, "Containers"); if( psBlobs != nullptr ) bNonEmpty = true; } // Count the number of occurrences of a path. Can be 1 or 2. 2 in the case // that both a filename and directory exist std::map<CPLString, int> aoNameCount; for(CPLXMLNode* psIter = psBlobs ? psBlobs->psChild : nullptr; psIter != nullptr; psIter = psIter->psNext ) { if( psIter->eType != CXT_Element ) continue; if( strcmp(psIter->pszValue, "Blob") == 0 ) { const char* pszKey = CPLGetXMLValue(psIter, "Name", nullptr); if( pszKey && strstr(pszKey, GDAL_MARKER_FOR_DIR) != nullptr ) { bNonEmpty = true; } else if( pszKey && strlen(pszKey) > osPrefix.size() ) { bNonEmpty = true; aoNameCount[pszKey + osPrefix.size()] ++; } } else if( strcmp(psIter->pszValue, "BlobPrefix") == 0 || strcmp(psIter->pszValue, "Container") == 0 ) { bNonEmpty = true; const char* pszKey = CPLGetXMLValue(psIter, "Name", nullptr); if( pszKey && strncmp(pszKey, osPrefix, osPrefix.size()) == 0 ) { CPLString osKey = pszKey; if( !osKey.empty() && osKey.back() == '/' ) osKey.resize(osKey.size()-1); if( osKey.size() > osPrefix.size() ) { aoNameCount[osKey.c_str() + osPrefix.size()] ++; } } } } for(CPLXMLNode* psIter = psBlobs ? psBlobs->psChild : nullptr; psIter != nullptr; psIter = psIter->psNext ) { if( psIter->eType != CXT_Element ) continue; if( strcmp(psIter->pszValue, "Blob") == 0 ) { const char* pszKey = CPLGetXMLValue(psIter, "Name", nullptr); if( pszKey && strstr(pszKey, GDAL_MARKER_FOR_DIR) != nullptr ) { if( nRecurseDepth < 0 ) { aoEntries.push_back( std::unique_ptr<VSIDIREntry>(new VSIDIREntry())); auto& entry = aoEntries.back(); entry->pszName = CPLStrdup(pszKey + osPrefix.size()); char* pszMarker = strstr(entry->pszName, GDAL_MARKER_FOR_DIR); if( pszMarker ) *pszMarker = '\0'; entry->nMode = S_IFDIR; entry->bModeKnown = true; } } else if( pszKey && strlen(pszKey) > osPrefix.size() ) { aoEntries.push_back( std::unique_ptr<VSIDIREntry>(new VSIDIREntry())); auto& entry = aoEntries.back(); entry->pszName = CPLStrdup(pszKey + osPrefix.size()); entry->nSize = static_cast<GUIntBig>( CPLAtoGIntBig(CPLGetXMLValue(psIter, "Properties.Content-Length", "0"))); entry->bSizeKnown = true; entry->nMode = S_IFDIR; entry->bModeKnown = true; CPLString ETag = CPLGetXMLValue(psIter, "Etag", ""); if( !ETag.empty() ) { entry->papszExtra = CSLSetNameValue( entry->papszExtra, "ETag", ETag.c_str()); } int nYear, nMonth, nDay, nHour, nMinute, nSecond; if( CPLParseRFC822DateTime( CPLGetXMLValue(psIter, "Properties.Last-Modified", ""), &nYear, &nMonth, &nDay, &nHour, &nMinute, &nSecond, nullptr, nullptr ) ) { struct tm brokendowntime; brokendowntime.tm_year = nYear - 1900; brokendowntime.tm_mon = nMonth - 1; brokendowntime.tm_mday = nDay; brokendowntime.tm_hour = nHour; brokendowntime.tm_min = nMinute; brokendowntime.tm_sec = nSecond < 0 ? 0 : nSecond; entry->nMTime = CPLYMDHMSToUnixTime(&brokendowntime); entry->bMTimeKnown = true; } if( bCacheResults ) { FileProp prop; prop.eExists = EXIST_YES; prop.bHasComputedFileSize = true; prop.fileSize = entry->nSize; prop.bIsDirectory = false; prop.mTime = static_cast<time_t>(entry->nMTime); prop.ETag = ETag; CPLString osCachedFilename = osBaseURL + "/" + osPrefix + entry->pszName; #if DEBUG_VERBOSE CPLDebug("AZURE", "Cache %s", osCachedFilename.c_str()); #endif poFS->SetCachedFileProp(osCachedFilename, prop); } } } else if( strcmp(psIter->pszValue, "BlobPrefix") == 0 || strcmp(psIter->pszValue, "Container") == 0 ) { const char* pszKey = CPLGetXMLValue(psIter, "Name", nullptr); if( pszKey && strncmp(pszKey, osPrefix, osPrefix.size()) == 0 ) { CPLString osKey = pszKey; if( !osKey.empty() && osKey.back() == '/' ) osKey.resize(osKey.size()-1); if( osKey.size() > osPrefix.size() ) { aoEntries.push_back( std::unique_ptr<VSIDIREntry>(new VSIDIREntry())); auto& entry = aoEntries.back(); entry->pszName = CPLStrdup(osKey.c_str() + osPrefix.size()); if( aoNameCount[entry->pszName] == 2 ) { // Add a / suffix to disambiguish the situation // Normally we don't suffix directories with /, but // we have no alternative here CPLString osTemp(entry->pszName); osTemp += '/'; CPLFree(entry->pszName); entry->pszName = CPLStrdup(osTemp); } entry->nMode = S_IFDIR; entry->bModeKnown = true; if( bCacheResults ) { FileProp prop; prop.eExists = EXIST_YES; prop.bIsDirectory = true; prop.bHasComputedFileSize = true; prop.fileSize = 0; prop.mTime = 0; CPLString osCachedFilename = osBaseURL + "/" + osPrefix + entry->pszName; #if DEBUG_VERBOSE CPLDebug("AZURE", "Cache %s", osCachedFilename.c_str()); #endif poFS->SetCachedFileProp(osCachedFilename, prop); } } } } if( nMaxFiles > 0 && aoEntries.size() > static_cast<unsigned>(nMaxFiles) ) break; } osNextMarker = CPLGetXMLValue(psEnumerationResults, "NextMarker", ""); } CPLDestroyXMLNode(psTree); return bNonEmpty; }
static CPLString GetProj4Filename(const char* pszFilename) { CPLString osFilename; /* or fixed path: /name, ./name or ../name */ if ( !CPLIsFilenameRelative(pszFilename) || *pszFilename == '.' ) { return pszFilename; } #if defined(PROJ_STATIC) && PROJ_VERSION >= 5 PJ_GRID_INFO info = proj_grid_info(pszFilename); if( info.filename[0] ) { osFilename = info.filename; } #elif defined(PROJ_STATIC) && PJ_VERSION > 493 osFilename.resize(2048); projCtx ctx = pj_ctx_alloc(); if( pj_find_file(ctx, pszFilename, &osFilename[0], osFilename.size()) ) { osFilename.resize( strlen(osFilename) ); } else { osFilename.clear(); } pj_ctx_free(ctx); #else // Transpose some of the proj.4 pj_open_lib() logic... /* check if ~/name */ char* pszSysname; if (*pszFilename == '~' && (pszFilename[1] == '/' || pszFilename[1] == '\\') ) { if ((pszSysname = getenv("HOME")) != nullptr) { osFilename = CPLFormFilename(pszSysname, pszFilename + 1, nullptr); } return osFilename; } /* or is environment PROJ_LIB defined */ else if ((pszSysname = getenv("PROJ_LIB")) != nullptr) { osFilename = CPLFormFilename(pszSysname, pszFilename, nullptr); VSIStatBufL sStat; if( VSIStatL(osFilename, &sStat) == 0 ) return osFilename; osFilename.clear(); } #if defined(PROJ_STATIC) && PJ_VERSION >= 490 // Super messy. proj.4 up to 4.9.3 had no public API to return the full // path to a resource file, so we rely on the fact that it emits a log // message with it... // Basically this is needed in the case where the file is in the // resource installation directory of proj.4, which we have no way to // know otherwise. CPLString osMsg; projCtx ctx = pj_ctx_alloc(); pj_ctx_set_app_data(ctx, &osMsg); pj_ctx_set_debug(ctx, PJ_LOG_DEBUG_MAJOR); pj_ctx_set_logger(ctx, my_proj4_logger); PAFile f = pj_open_lib(ctx, pszFilename, "rb"); if( f ) { pj_ctx_fclose(ctx, f); size_t nPos = osMsg.find("fopen("); if( nPos != std::string::npos ) { osFilename = osMsg.substr(nPos + strlen("fopen(")); nPos = osFilename.find(")"); if( nPos != std::string::npos ) osFilename = osFilename.substr(0, nPos); } } pj_ctx_free(ctx); #endif #endif return osFilename; }
/*! \brief VFKReaderSQLite constructor */ VFKReaderSQLite::VFKReaderSQLite(const char *pszFilename) : VFKReader(pszFilename) { const char *pszDbNameConf; CPLString osDbName; CPLString osCommand; VSIStatBufL sStatBufDb, sStatBufVfk; /* open tmp SQLite DB (re-use DB file if already exists) */ pszDbNameConf = CPLGetConfigOption("OGR_VFK_DB_NAME", NULL); if (pszDbNameConf) { osDbName = pszDbNameConf; } else { osDbName = CPLResetExtension(m_pszFilename, "db"); } size_t nLen = osDbName.length(); if( nLen > 2048 ) { nLen = 2048; osDbName.resize(nLen); } m_pszDBname = new char [nLen+1]; std::strncpy(m_pszDBname, osDbName.c_str(), nLen); m_pszDBname[nLen] = 0; CPLDebug("OGR-VFK", "Using internal DB: %s", m_pszDBname); if (CPLTestBool(CPLGetConfigOption("OGR_VFK_DB_SPATIAL", "YES"))) m_bSpatial = TRUE; /* build geometry from DB */ else m_bSpatial = FALSE; /* store also geometry in DB */ m_bNewDb = TRUE; if (VSIStatL(osDbName, &sStatBufDb) == 0) { if (CPLTestBool(CPLGetConfigOption("OGR_VFK_DB_OVERWRITE", "NO"))) { m_bNewDb = TRUE; /* overwrite existing DB */ CPLDebug("OGR-VFK", "Internal DB (%s) already exists and will be overwritten", m_pszDBname); VSIUnlink(osDbName); } else { if (VSIStatL(pszFilename, &sStatBufVfk) == 0 && sStatBufVfk.st_mtime > sStatBufDb.st_mtime) { CPLDebug("OGR-VFK", "Found %s but ignoring because it appears\n" "be older than the associated VFK file.", osDbName.c_str()); m_bNewDb = TRUE; VSIUnlink(osDbName); } else { m_bNewDb = FALSE; /* re-use existing DB */ } } } /* if (m_bNewDb) { CPLError(CE_Warning, CPLE_AppDefined, "INFO: No internal SQLite DB found. Reading VFK data may take some time..."); } */ CPLDebug("OGR-VFK", "New DB: %s Spatial: %s", m_bNewDb ? "yes" : "no", m_bSpatial ? "yes" : "no"); if (SQLITE_OK != sqlite3_open(osDbName, &m_poDB)) { CPLError(CE_Failure, CPLE_AppDefined, "Creating SQLite DB failed"); } else { char* pszErrMsg = NULL; CPL_IGNORE_RET_VAL(sqlite3_exec(m_poDB, "PRAGMA synchronous = OFF", NULL, NULL, &pszErrMsg)); sqlite3_free(pszErrMsg); } if (m_bNewDb) { /* new DB, create support metadata tables */ osCommand.Printf("CREATE TABLE %s (file_name text, table_name text, num_records integer, " "num_features integer, num_geometries integer, table_defn text)", VFK_DB_TABLE); ExecuteSQL(osCommand.c_str()); /* header table */ osCommand.Printf("CREATE TABLE %s (key text, value text)", VFK_DB_HEADER); ExecuteSQL(osCommand.c_str()); } }
swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node, swq_expr_node **sub_node_values ) { swq_expr_node *poRet = NULL; /* -------------------------------------------------------------------- */ /* Floating point operations. */ /* -------------------------------------------------------------------- */ if( sub_node_values[0]->field_type == SWQ_FLOAT || (node->nSubExprCount > 1 && sub_node_values[1]->field_type == SWQ_FLOAT) ) { poRet = new swq_expr_node(0); poRet->field_type = node->field_type; if( sub_node_values[0]->field_type == SWQ_INTEGER ) sub_node_values[0]->float_value = sub_node_values[0]->int_value; if( node->nSubExprCount > 1 && sub_node_values[1]->field_type == SWQ_INTEGER ) sub_node_values[1]->float_value = sub_node_values[1]->int_value; switch( (swq_op) node->nOperation ) { case SWQ_EQ: poRet->int_value = sub_node_values[0]->float_value == sub_node_values[1]->float_value; break; case SWQ_NE: poRet->int_value = sub_node_values[0]->float_value != sub_node_values[1]->float_value; break; case SWQ_GT: poRet->int_value = sub_node_values[0]->float_value > sub_node_values[1]->float_value; break; case SWQ_LT: poRet->int_value = sub_node_values[0]->float_value < sub_node_values[1]->float_value; break; case SWQ_GE: poRet->int_value = sub_node_values[0]->float_value >= sub_node_values[1]->float_value; break; case SWQ_LE: poRet->int_value = sub_node_values[0]->float_value <= sub_node_values[1]->float_value; break; case SWQ_IN: { int i; poRet->int_value = 0; for( i = 1; i < node->nSubExprCount; i++ ) { if( sub_node_values[0]->float_value == sub_node_values[i]->float_value ) { poRet->int_value = 1; break; } } } break; case SWQ_BETWEEN: poRet->int_value = sub_node_values[0]->float_value >= sub_node_values[1]->float_value && sub_node_values[0]->float_value <= sub_node_values[2]->float_value; break; case SWQ_ISNULL: poRet->int_value = sub_node_values[0]->is_null; break; case SWQ_ADD: poRet->float_value = sub_node_values[0]->float_value + sub_node_values[1]->float_value; break; case SWQ_SUBTRACT: poRet->float_value = sub_node_values[0]->float_value - sub_node_values[1]->float_value; break; case SWQ_MULTIPLY: poRet->float_value = sub_node_values[0]->float_value * sub_node_values[1]->float_value; break; case SWQ_DIVIDE: if( sub_node_values[1]->float_value == 0 ) poRet->float_value = INT_MAX; else poRet->float_value = sub_node_values[0]->float_value / sub_node_values[1]->float_value; break; case SWQ_MODULUS: { int nRight = (int) sub_node_values[1]->float_value; poRet->field_type = SWQ_INTEGER; if (nRight == 0) poRet->int_value = INT_MAX; else poRet->int_value = ((int) sub_node_values[0]->float_value) % nRight; break; } default: CPLAssert( FALSE ); delete poRet; poRet = NULL; break; } } /* -------------------------------------------------------------------- */ /* integer/boolean operations. */ /* -------------------------------------------------------------------- */ else if( sub_node_values[0]->field_type == SWQ_INTEGER || sub_node_values[0]->field_type == SWQ_BOOLEAN ) { poRet = new swq_expr_node(0); poRet->field_type = node->field_type; switch( (swq_op) node->nOperation ) { case SWQ_AND: poRet->int_value = sub_node_values[0]->int_value && sub_node_values[1]->int_value; break; case SWQ_OR: poRet->int_value = sub_node_values[0]->int_value || sub_node_values[1]->int_value; break; case SWQ_NOT: poRet->int_value = !sub_node_values[0]->int_value; break; case SWQ_EQ: poRet->int_value = sub_node_values[0]->int_value == sub_node_values[1]->int_value; break; case SWQ_NE: poRet->int_value = sub_node_values[0]->int_value != sub_node_values[1]->int_value; break; case SWQ_GT: poRet->int_value = sub_node_values[0]->int_value > sub_node_values[1]->int_value; break; case SWQ_LT: poRet->int_value = sub_node_values[0]->int_value < sub_node_values[1]->int_value; break; case SWQ_GE: poRet->int_value = sub_node_values[0]->int_value >= sub_node_values[1]->int_value; break; case SWQ_LE: poRet->int_value = sub_node_values[0]->int_value <= sub_node_values[1]->int_value; break; case SWQ_IN: { int i; poRet->int_value = 0; for( i = 1; i < node->nSubExprCount; i++ ) { if( sub_node_values[0]->int_value == sub_node_values[i]->int_value ) { poRet->int_value = 1; break; } } } break; case SWQ_BETWEEN: poRet->int_value = sub_node_values[0]->int_value >= sub_node_values[1]->int_value && sub_node_values[0]->int_value <= sub_node_values[2]->int_value; break; case SWQ_ISNULL: poRet->int_value = sub_node_values[0]->is_null; break; case SWQ_ADD: poRet->int_value = sub_node_values[0]->int_value + sub_node_values[1]->int_value; break; case SWQ_SUBTRACT: poRet->int_value = sub_node_values[0]->int_value - sub_node_values[1]->int_value; break; case SWQ_MULTIPLY: poRet->int_value = sub_node_values[0]->int_value * sub_node_values[1]->int_value; break; case SWQ_DIVIDE: if( sub_node_values[1]->int_value == 0 ) poRet->int_value = INT_MAX; else poRet->int_value = sub_node_values[0]->int_value / sub_node_values[1]->int_value; break; case SWQ_MODULUS: if( sub_node_values[1]->int_value == 0 ) poRet->int_value = INT_MAX; else poRet->int_value = sub_node_values[0]->int_value % sub_node_values[1]->int_value; break; default: CPLAssert( FALSE ); delete poRet; poRet = NULL; break; } } /* -------------------------------------------------------------------- */ /* String operations. */ /* -------------------------------------------------------------------- */ else { poRet = new swq_expr_node(0); poRet->field_type = node->field_type; switch( (swq_op) node->nOperation ) { case SWQ_EQ: poRet->int_value = strcasecmp(sub_node_values[0]->string_value, sub_node_values[1]->string_value) == 0; break; case SWQ_NE: poRet->int_value = strcasecmp(sub_node_values[0]->string_value, sub_node_values[1]->string_value) != 0; break; case SWQ_GT: poRet->int_value = strcasecmp(sub_node_values[0]->string_value, sub_node_values[1]->string_value) > 0; break; case SWQ_LT: poRet->int_value = strcasecmp(sub_node_values[0]->string_value, sub_node_values[1]->string_value) < 0; break; case SWQ_GE: poRet->int_value = strcasecmp(sub_node_values[0]->string_value, sub_node_values[1]->string_value) >= 0; break; case SWQ_LE: poRet->int_value = strcasecmp(sub_node_values[0]->string_value, sub_node_values[1]->string_value) <= 0; break; case SWQ_IN: { int i; poRet->int_value = 0; for( i = 1; i < node->nSubExprCount; i++ ) { if( strcasecmp(sub_node_values[0]->string_value, sub_node_values[i]->string_value) == 0 ) { poRet->int_value = 1; break; } } } break; case SWQ_BETWEEN: poRet->int_value = strcasecmp(sub_node_values[0]->string_value, sub_node_values[1]->string_value) >= 0 && strcasecmp(sub_node_values[0]->string_value, sub_node_values[2]->string_value) <= 0; break; case SWQ_LIKE: poRet->int_value = swq_test_like(sub_node_values[0]->string_value, sub_node_values[1]->string_value); break; case SWQ_ISNULL: poRet->int_value = sub_node_values[0]->is_null; break; case SWQ_CONCAT: case SWQ_ADD: { CPLString osResult = sub_node_values[0]->string_value; int i; for( i = 1; i < node->nSubExprCount; i++ ) osResult += sub_node_values[i]->string_value; poRet->string_value = CPLStrdup(osResult); break; } case SWQ_SUBSTR: { int nOffset, nSize; const char *pszSrcStr = sub_node_values[0]->string_value; if( sub_node_values[1]->field_type == SWQ_INTEGER ) nOffset = sub_node_values[1]->int_value; else if( sub_node_values[1]->field_type == SWQ_FLOAT ) nOffset = (int) sub_node_values[1]->float_value; else nOffset = 0; if( node->nSubExprCount < 3 ) nSize = 100000; else if( sub_node_values[2]->field_type == SWQ_INTEGER ) nSize = sub_node_values[2]->int_value; else if( sub_node_values[2]->field_type == SWQ_FLOAT ) nSize = (int) sub_node_values[2]->float_value; else nSize = 0; int nSrcStrLen = (int)strlen(pszSrcStr); if( nOffset < 0 || nSize < 0 || nOffset > nSrcStrLen ) { nOffset = 0; nSize = 0; } else if( nOffset + nSize > nSrcStrLen ) nSize = nSrcStrLen - nOffset; CPLString osResult = pszSrcStr + nOffset; if( (int)osResult.size() > nSize ) osResult.resize( nSize ); poRet->string_value = CPLStrdup(osResult); break; } default: CPLAssert( FALSE ); delete poRet; poRet = NULL; break; } } return poRet; }
static CPLXMLNode * GDALWMSDatasetGetConfigFromURL(GDALOpenInfo *poOpenInfo) { const char* pszBaseURL = poOpenInfo->pszFilename; if (EQUALN(pszBaseURL, "WMS:", 4)) pszBaseURL += 4; CPLString osLayer = CPLURLGetValue(pszBaseURL, "LAYERS"); CPLString osVersion = CPLURLGetValue(pszBaseURL, "VERSION"); CPLString osSRS = CPLURLGetValue(pszBaseURL, "SRS"); CPLString osCRS = CPLURLGetValue(pszBaseURL, "CRS"); CPLString osBBOX = CPLURLGetValue(pszBaseURL, "BBOX"); CPLString osFormat = CPLURLGetValue(pszBaseURL, "FORMAT"); CPLString osTransparent = CPLURLGetValue(pszBaseURL, "TRANSPARENT"); /* GDAL specific extensions to alter the default settings */ CPLString osOverviewCount = CPLURLGetValue(pszBaseURL, "OVERVIEWCOUNT"); CPLString osTileSize = CPLURLGetValue(pszBaseURL, "TILESIZE"); CPLString osMinResolution = CPLURLGetValue(pszBaseURL, "MINRESOLUTION"); CPLString osBBOXOrder = CPLURLGetValue(pszBaseURL, "BBOXORDER"); CPLString osBaseURL = pszBaseURL; /* Remove all keywords to get base URL */ osBaseURL = CPLURLAddKVP(osBaseURL, "VERSION", NULL); osBaseURL = CPLURLAddKVP(osBaseURL, "REQUEST", NULL); osBaseURL = CPLURLAddKVP(osBaseURL, "LAYERS", NULL); osBaseURL = CPLURLAddKVP(osBaseURL, "SRS", NULL); osBaseURL = CPLURLAddKVP(osBaseURL, "CRS", NULL); osBaseURL = CPLURLAddKVP(osBaseURL, "BBOX", NULL); osBaseURL = CPLURLAddKVP(osBaseURL, "FORMAT", NULL); osBaseURL = CPLURLAddKVP(osBaseURL, "TRANSPARENT", NULL); osBaseURL = CPLURLAddKVP(osBaseURL, "STYLES", NULL); osBaseURL = CPLURLAddKVP(osBaseURL, "WIDTH", NULL); osBaseURL = CPLURLAddKVP(osBaseURL, "HEIGHT", NULL); osBaseURL = CPLURLAddKVP(osBaseURL, "OVERVIEWCOUNT", NULL); osBaseURL = CPLURLAddKVP(osBaseURL, "TILESIZE", NULL); osBaseURL = CPLURLAddKVP(osBaseURL, "MINRESOLUTION", NULL); osBaseURL = CPLURLAddKVP(osBaseURL, "BBOXORDER", NULL); if (osBaseURL.size() > 0 && osBaseURL[osBaseURL.size() - 1] == '&') osBaseURL.resize(osBaseURL.size() - 1); if (osVersion.size() == 0) osVersion = "1.1.1"; CPLString osSRSTag; CPLString osSRSValue; if(VersionStringToInt(osVersion.c_str())>= VersionStringToInt("1.3.0")) { if (osSRS.size()) { CPLError(CE_Warning, CPLE_AppDefined, "WMS version 1.3 and above expects CRS however SRS was set instead."); } osSRSValue = osCRS; osSRSTag = "CRS"; } else { if (osCRS.size()) { CPLError(CE_Warning, CPLE_AppDefined, "WMS version 1.1.1 and below expects SRS however CRS was set instead."); } osSRSValue = osSRS; osSRSTag = "SRS"; } if (osSRSValue.size() == 0) osSRSValue = "EPSG:4326"; if (osBBOX.size() == 0) { if (osBBOXOrder.compare("yxYX") == 0) osBBOX = "-90,-180,90,180"; else osBBOX = "-180,-90,180,90"; } char** papszTokens = CSLTokenizeStringComplex(osBBOX, ",", 0, 0); if (CSLCount(papszTokens) != 4) { CSLDestroy(papszTokens); return NULL; } const char* pszMinX = papszTokens[0]; const char* pszMinY = papszTokens[1]; const char* pszMaxX = papszTokens[2]; const char* pszMaxY = papszTokens[3]; if (osBBOXOrder.compare("yxYX") == 0) { std::swap(pszMinX, pszMinY); std::swap(pszMaxX, pszMaxY); } double dfMinX = CPLAtofM(pszMinX); double dfMinY = CPLAtofM(pszMinY); double dfMaxX = CPLAtofM(pszMaxX); double dfMaxY = CPLAtofM(pszMaxY); if (dfMaxY <= dfMinY || dfMaxX <= dfMinX) { CSLDestroy(papszTokens); return NULL; } int nTileSize = atoi(osTileSize); if (nTileSize <= 128 || nTileSize > 2048) nTileSize = 1024; int nXSize, nYSize; int nOverviewCount = (osOverviewCount.size()) ? atoi(osOverviewCount) : 20; if (osMinResolution.size() != 0) { double dfMinResolution = CPLAtofM(osMinResolution); while (nOverviewCount > 20) { nOverviewCount --; dfMinResolution *= 2; } nXSize = (int) ((dfMaxX - dfMinX) / dfMinResolution + 0.5); nYSize = (int) ((dfMaxY - dfMinY) / dfMinResolution + 0.5); } else { double dfRatio = (dfMaxX - dfMinX) / (dfMaxY - dfMinY); if (dfRatio > 1) { nXSize = nTileSize; nYSize = (int) (nXSize / dfRatio); } else { nYSize = nTileSize; nXSize = (int) (nYSize * dfRatio); } if (nOverviewCount < 0 || nOverviewCount > 20) nOverviewCount = 20; nXSize = nXSize * (1 << nOverviewCount); nYSize = nYSize * (1 << nOverviewCount); } int bTransparent = osTransparent.size() ? CSLTestBoolean(osTransparent) : FALSE; if (osFormat.size() == 0) { if (!bTransparent) { osFormat = "image/jpeg"; } else { osFormat = "image/png"; } } char* pszEscapedURL = CPLEscapeString(osBaseURL.c_str(), -1, CPLES_XML); char* pszEscapedLayerURL = CPLEscapeString(osLayer.c_str(), -1, CPLES_URL); char* pszEscapedLayerXML = CPLEscapeString(pszEscapedLayerURL, -1, CPLES_XML); CPLString osXML = CPLSPrintf( "<GDAL_WMS>\n" " <Service name=\"WMS\">\n" " <Version>%s</Version>\n" " <ServerUrl>%s</ServerUrl>\n" " <Layers>%s</Layers>\n" " <%s>%s</%s>\n" " <ImageFormat>%s</ImageFormat>\n" " <Transparent>%s</Transparent>\n" " <BBoxOrder>%s</BBoxOrder>\n" " </Service>\n" " <DataWindow>\n" " <UpperLeftX>%s</UpperLeftX>\n" " <UpperLeftY>%s</UpperLeftY>\n" " <LowerRightX>%s</LowerRightX>\n" " <LowerRightY>%s</LowerRightY>\n" " <SizeX>%d</SizeX>\n" " <SizeY>%d</SizeY>\n" " </DataWindow>\n" " <BandsCount>%d</BandsCount>\n" " <BlockSizeX>%d</BlockSizeX>\n" " <BlockSizeY>%d</BlockSizeY>\n" " <OverviewCount>%d</OverviewCount>\n" "</GDAL_WMS>\n", osVersion.c_str(), pszEscapedURL, pszEscapedLayerXML, osSRSTag.c_str(), osSRSValue.c_str(), osSRSTag.c_str(), osFormat.c_str(), (bTransparent) ? "TRUE" : "FALSE", (osBBOXOrder.size()) ? osBBOXOrder.c_str() : "xyXY", pszMinX, pszMaxY, pszMaxX, pszMinY, nXSize, nYSize, (bTransparent) ? 4 : 3, nTileSize, nTileSize, nOverviewCount); CPLFree(pszEscapedURL); CPLFree(pszEscapedLayerURL); CPLFree(pszEscapedLayerXML); CSLDestroy(papszTokens); CPLDebug("WMS", "Opening WMS :\n%s", osXML.c_str()); return CPLParseXMLString(osXML); }
static CPLXMLNode * GDALWMSDatasetGetConfigFromTileMap(CPLXMLNode* psXML) { CPLXMLNode* psRoot = CPLGetXMLNode( psXML, "=TileMap" ); if (psRoot == NULL) return NULL; CPLXMLNode* psTileSets = CPLGetXMLNode(psRoot, "TileSets"); if (psTileSets == NULL) return NULL; const char* pszURL = CPLGetXMLValue(psRoot, "tilemapservice", NULL); int bCanChangeURL = TRUE; CPLString osURL; if (pszURL) { osURL = pszURL; /* Special hack for http://tilecache.osgeo.org/wms-c/Basic.py/1.0.0/basic/ */ if (strlen(pszURL) > 10 && strncmp(pszURL, "http://tilecache.osgeo.org/wms-c/Basic.py/1.0.0/", strlen("http://tilecache.osgeo.org/wms-c/Basic.py/1.0.0/")) == 0 && strcmp(pszURL + strlen(pszURL) - strlen("1.0.0/"), "1.0.0/") == 0) { osURL.resize(strlen(pszURL) - strlen("1.0.0/")); bCanChangeURL = FALSE; } osURL += "${z}/${x}/${y}.${format}"; } const char* pszSRS = CPLGetXMLValue(psRoot, "SRS", NULL); if (pszSRS == NULL) return NULL; CPLXMLNode* psBoundingBox = CPLGetXMLNode( psRoot, "BoundingBox" ); if (psBoundingBox == NULL) return NULL; const char* pszMinX = CPLGetXMLValue(psBoundingBox, "minx", NULL); const char* pszMinY = CPLGetXMLValue(psBoundingBox, "miny", NULL); const char* pszMaxX = CPLGetXMLValue(psBoundingBox, "maxx", NULL); const char* pszMaxY = CPLGetXMLValue(psBoundingBox, "maxy", NULL); if (pszMinX == NULL || pszMinY == NULL || pszMaxX == NULL || pszMaxY == NULL) return NULL; double dfMinX = CPLAtofM(pszMinX); double dfMinY = CPLAtofM(pszMinY); double dfMaxX = CPLAtofM(pszMaxX); double dfMaxY = CPLAtofM(pszMaxY); if (dfMaxY <= dfMinY || dfMaxX <= dfMinX) return NULL; CPLXMLNode* psTileFormat = CPLGetXMLNode( psRoot, "TileFormat" ); if (psTileFormat == NULL) return NULL; const char* pszTileWidth = CPLGetXMLValue(psTileFormat, "width", NULL); const char* pszTileHeight = CPLGetXMLValue(psTileFormat, "height", NULL); const char* pszTileFormat = CPLGetXMLValue(psTileFormat, "extension", NULL); if (pszTileWidth == NULL || pszTileHeight == NULL || pszTileFormat == NULL) return NULL; int nTileWidth = atoi(pszTileWidth); int nTileHeight = atoi(pszTileHeight); if (nTileWidth < 128 || nTileHeight < 128) return NULL; CPLXMLNode* psIter = psTileSets->psChild; int nLevelCount = 0; double dfPixelSize = 0; for(; psIter != NULL; psIter = psIter->psNext) { if (psIter->eType == CXT_Element && EQUAL(psIter->pszValue, "TileSet")) { const char* pszOrder = CPLGetXMLValue(psIter, "order", NULL); if (pszOrder == NULL) { CPLDebug("WMS", "Cannot find order attribute"); return NULL; } if (atoi(pszOrder) != nLevelCount) { CPLDebug("WMS", "Expected order=%d, got %s", nLevelCount, pszOrder); return NULL; } const char* pszHref = CPLGetXMLValue(psIter, "href", NULL); if (nLevelCount == 0 && pszHref != NULL) { if (bCanChangeURL && strlen(pszHref) > 10 && strcmp(pszHref + strlen(pszHref) - strlen("/0"), "/0") == 0) { osURL = pszHref; osURL.resize(strlen(pszHref) - strlen("/0")); osURL += "/${z}/${x}/${y}.${format}"; } } const char* pszUnitsPerPixel = CPLGetXMLValue(psIter, "units-per-pixel", NULL); if (pszUnitsPerPixel == NULL) return NULL; dfPixelSize = CPLAtofM(pszUnitsPerPixel); nLevelCount++; } } if (nLevelCount == 0 || osURL.size() == 0) return NULL; int nXSize = 0; int nYSize = 0; while(nLevelCount > 0) { GIntBig nXSizeBig = (GIntBig)((dfMaxX - dfMinX) / dfPixelSize + 0.5); GIntBig nYSizeBig = (GIntBig)((dfMaxY - dfMinY) / dfPixelSize + 0.5); if (nXSizeBig < INT_MAX && nYSizeBig < INT_MAX) { nXSize = (int)nXSizeBig; nYSize = (int)nYSizeBig; break; } CPLDebug("WMS", "Dropping one overview level so raster size fits into 32bit..."); dfPixelSize *= 2; nLevelCount --; } char* pszEscapedURL = CPLEscapeString(osURL.c_str(), -1, CPLES_XML); CPLString osXML = CPLSPrintf( "<GDAL_WMS>\n" " <Service name=\"TMS\">\n" " <ServerUrl>%s</ServerUrl>\n" " <Format>%s</Format>\n" " </Service>\n" " <DataWindow>\n" " <UpperLeftX>%s</UpperLeftX>\n" " <UpperLeftY>%s</UpperLeftY>\n" " <LowerRightX>%s</LowerRightX>\n" " <LowerRightY>%s</LowerRightY>\n" " <TileLevel>%d</TileLevel>\n" " <SizeX>%d</SizeX>\n" " <SizeY>%d</SizeY>\n" " </DataWindow>\n" " <Projection>%s</Projection>\n" " <BlockSizeX>%d</BlockSizeX>\n" " <BlockSizeY>%d</BlockSizeY>\n" " <BandsCount>%d</BandsCount>\n" "</GDAL_WMS>\n", pszEscapedURL, pszTileFormat, pszMinX, pszMaxY, pszMaxX, pszMinY, nLevelCount - 1, nXSize, nYSize, pszSRS, nTileWidth, nTileHeight, 3); CPLDebug("WMS", "Opening TMS :\n%s", osXML.c_str()); CPLFree(pszEscapedURL); return CPLParseXMLString(osXML); }
char **CPL_STDCALL GDALLoadRPBFile( const char *pszFilename, char **papszSiblingFiles ) { /* -------------------------------------------------------------------- */ /* Try to identify the RPB file in upper or lower case. */ /* -------------------------------------------------------------------- */ CPLString osTarget = CPLResetExtension( pszFilename, "RPB" ); /* Is this already a RPB file ? */ if (EQUAL(CPLGetExtension(pszFilename), "RPB")) osTarget = pszFilename; else if( papszSiblingFiles == NULL ) { VSIStatBufL sStatBuf; if( VSIStatL( osTarget, &sStatBuf ) != 0 ) { osTarget = CPLResetExtension( pszFilename, "rpb" ); if( VSIStatL( osTarget, &sStatBuf ) != 0 ) return NULL; } } else { int iSibling = CSLFindString( papszSiblingFiles, CPLGetFilename(osTarget) ); if( iSibling < 0 ) return NULL; osTarget.resize(osTarget.size() - strlen(papszSiblingFiles[iSibling])); osTarget += papszSiblingFiles[iSibling]; } /* -------------------------------------------------------------------- */ /* Read file and parse. */ /* -------------------------------------------------------------------- */ CPLKeywordParser oParser; VSILFILE *fp = VSIFOpenL( osTarget, "r" ); if( fp == NULL ) return NULL; if( !oParser.Ingest( fp ) ) { VSIFCloseL( fp ); return NULL; } VSIFCloseL( fp ); /* -------------------------------------------------------------------- */ /* Extract RPC information, in a GDAL "standard" metadata format. */ /* -------------------------------------------------------------------- */ int i; char **papszMD = NULL; for( i = 0; apszRPBMap[i] != NULL; i += 2 ) { const char *pszRPBVal = oParser.GetKeyword( apszRPBMap[i+1] ); CPLString osAdjVal; if( pszRPBVal == NULL ) { CPLError( CE_Failure, CPLE_AppDefined, "%s file found, but missing %s field (and possibly others).", osTarget.c_str(), apszRPBMap[i+1] ); CSLDestroy( papszMD ); return NULL; } if( strchr(pszRPBVal,',') == NULL ) osAdjVal = pszRPBVal; else { // strip out commas and turn newlines into spaces. int j; for( j = 0; pszRPBVal[j] != '\0'; j++ ) { switch( pszRPBVal[j] ) { case ',': case '\n': case '\r': osAdjVal += ' '; break; case '(': case ')': break; default: osAdjVal += pszRPBVal[j]; } } } papszMD = CSLSetNameValue( papszMD, apszRPBMap[i], osAdjVal ); } return papszMD; }
char ** CPL_STDCALL GDALLoadIMDFile( const char *pszFilename, char **papszSiblingFiles ) { /* -------------------------------------------------------------------- */ /* Try to identify the IMD file in upper or lower case. */ /* -------------------------------------------------------------------- */ CPLString osTarget = CPLResetExtension( pszFilename, "IMD" ); /* Is this already a IMD file ? */ if (EQUAL(CPLGetExtension(pszFilename), "IMD")) osTarget = pszFilename; else if( papszSiblingFiles == NULL ) { VSIStatBufL sStatBuf; if( VSIStatL( osTarget, &sStatBuf ) != 0 ) { osTarget = CPLResetExtension( pszFilename, "imd" ); if( VSIStatL( osTarget, &sStatBuf ) != 0 ) return NULL; } } else { int iSibling = CSLFindString( papszSiblingFiles, CPLGetFilename(osTarget) ); if( iSibling < 0 ) return NULL; osTarget.resize(osTarget.size() - strlen(papszSiblingFiles[iSibling])); osTarget += papszSiblingFiles[iSibling]; } /* -------------------------------------------------------------------- */ /* Read file and parse. */ /* -------------------------------------------------------------------- */ CPLKeywordParser oParser; VSILFILE *fp = VSIFOpenL( osTarget, "r" ); if( fp == NULL ) return NULL; if( !oParser.Ingest( fp ) ) { VSIFCloseL( fp ); return NULL; } VSIFCloseL( fp ); /* -------------------------------------------------------------------- */ /* Consider version changing. */ /* -------------------------------------------------------------------- */ char **papszIMD = CSLDuplicate( oParser.GetAllKeywords() ); const char *pszVersion = CSLFetchNameValue( papszIMD, "version" ); if( pszVersion == NULL ) { /* ? */; } else if( EQUAL(pszVersion,"\"AA\"") ) { GDAL_IMD_AA2R( &papszIMD ); } return papszIMD; }
char **CPL_STDCALL GDALLoadRPCFile( const char *pszFilename, char **papszSiblingFiles ) { /* -------------------------------------------------------------------- */ /* Try to identify the RPC file in upper or lower case. */ /* -------------------------------------------------------------------- */ CPLString osTarget; /* Is this already a _RPC.TXT file ? */ if (strlen(pszFilename) > 8 && EQUAL(pszFilename + strlen(pszFilename) - 8, "_RPC.TXT")) osTarget = pszFilename; else { CPLString osSrcPath = pszFilename; CPLString soPt("."); size_t found = osSrcPath.rfind(soPt); if (found == CPLString::npos) return NULL; osSrcPath.replace (found, osSrcPath.size() - found, "_rpc.txt"); CPLString osTarget = osSrcPath; if( papszSiblingFiles == NULL ) { VSIStatBufL sStatBuf; if( VSIStatL( osTarget, &sStatBuf ) != 0 ) { osSrcPath = pszFilename; osSrcPath.replace (found, osSrcPath.size() - found, "_RPC.TXT"); osTarget = osSrcPath; if( VSIStatL( osTarget, &sStatBuf ) != 0 ) { osSrcPath = pszFilename; osSrcPath.replace (found, osSrcPath.size() - found, "_rpc.TXT"); osTarget = osSrcPath; if( VSIStatL( osTarget, &sStatBuf ) != 0 ) { return NULL; } } } } else { int iSibling = CSLFindString( papszSiblingFiles, CPLGetFilename(osTarget) ); if( iSibling < 0 ) return NULL; osTarget.resize(osTarget.size() - strlen(papszSiblingFiles[iSibling])); osTarget += papszSiblingFiles[iSibling]; } } /* -------------------------------------------------------------------- */ /* Read file and parse. */ /* -------------------------------------------------------------------- */ char **papszLines = CSLLoad2( osTarget, 100, 100, NULL ); if(!papszLines) return NULL; char **papszMD = NULL; /* From LINE_OFF to HEIGHT_SCALE */ for(size_t i = 0; i < 19; i += 2 ) { const char *pszRPBVal = CSLFetchNameValue(papszLines, apszRPBMap[i] ); if( pszRPBVal == NULL ) { CPLError( CE_Failure, CPLE_AppDefined, "%s file found, but missing %s field (and possibly others).", osTarget.c_str(), apszRPBMap[i]); CSLDestroy( papszMD ); CSLDestroy( papszLines ); return NULL; } else { papszMD = CSLSetNameValue( papszMD, apszRPBMap[i], pszRPBVal ); } } /* For LINE_NUM_COEFF, LINE_DEN_COEFF, SAMP_NUM_COEFF, SAMP_DEN_COEFF */ /* parameters that have 20 values each */ for(size_t i = 20; apszRPBMap[i] != NULL; i += 2 ) { CPLString soVal; for(int j = 1; j <= 20; j++) { CPLString soRPBMapItem; soRPBMapItem.Printf("%s_%d", apszRPBMap[i], j); const char *pszRPBVal = CSLFetchNameValue(papszLines, soRPBMapItem.c_str() ); if( pszRPBVal == NULL ) { CPLError( CE_Failure, CPLE_AppDefined, "%s file found, but missing %s field (and possibly others).", osTarget.c_str(), soRPBMapItem.c_str() ); CSLDestroy( papszMD ); CSLDestroy( papszLines ); return NULL; } else { soVal += pszRPBVal; soVal += " "; } } papszMD = CSLSetNameValue( papszMD, apszRPBMap[i], soVal.c_str() ); } CSLDestroy( papszLines ); return papszMD; }
GDALDataset *SAFEDataset::Open( GDALOpenInfo * poOpenInfo ) { /* -------------------------------------------------------------------- */ /* Is this a SENTINEL-1 manifest.safe definition? */ /* -------------------------------------------------------------------- */ if ( !SAFEDataset::Identify( poOpenInfo ) ) { return nullptr; } /* -------------------------------------------------------------------- */ /* Get subdataset information, if relevant */ /* -------------------------------------------------------------------- */ CPLString osMDFilename; //Subdataset 1st level selection (ex: for swath selection) CPLString osSelectedSubDS1; //Subdataset 2nd level selection (ex: for polarisation selection) CPLString osSelectedSubDS2; if (STARTS_WITH_CI(poOpenInfo->pszFilename, "SENTINEL1_DS:")) { osMDFilename = poOpenInfo->pszFilename + strlen("SENTINEL1_DS:"); const char* pszSelection1 = strrchr(osMDFilename.c_str(), ':'); if (pszSelection1 == nullptr || pszSelection1 == osMDFilename.c_str() ) { CPLError(CE_Failure, CPLE_AppDefined, "Invalid syntax for SENTINEL1_DS:"); return nullptr; } osMDFilename.resize( pszSelection1 - osMDFilename.c_str() ); osSelectedSubDS1 = pszSelection1 + strlen(":"); const char* pszSelection2 = strchr(osSelectedSubDS1.c_str(), '_'); if (pszSelection2 != nullptr && pszSelection2 != pszSelection1 ) { osSelectedSubDS1.resize( pszSelection2 - osSelectedSubDS1.c_str() ); osSelectedSubDS2 = pszSelection2 + strlen("_"); } //update directory check: VSIStatBufL sStat; if( VSIStatL( osMDFilename.c_str(), &sStat ) == 0 ) poOpenInfo->bIsDirectory = VSI_ISDIR( sStat.st_mode ); } else { osMDFilename = poOpenInfo->pszFilename; } if( poOpenInfo->bIsDirectory ) { osMDFilename = CPLFormCIFilename( osMDFilename.c_str(), "manifest.safe", nullptr ); } /* -------------------------------------------------------------------- */ /* Ingest the manifest.safe file. */ /* -------------------------------------------------------------------- */ //TODO REMOVE CPLXMLNode *psImageAttributes, *psImageGenerationParameters; CPLXMLNode *psManifest = CPLParseXMLFile( osMDFilename ); if( psManifest == nullptr ) return nullptr; CPLString osPath(CPLGetPath( osMDFilename )); /* -------------------------------------------------------------------- */ /* Confirm the requested access is supported. */ /* -------------------------------------------------------------------- */ if( poOpenInfo->eAccess == GA_Update ) { CPLDestroyXMLNode( psManifest ); CPLError( CE_Failure, CPLE_NotSupported, "The SAFE driver does not support update access to existing" " datasets.\n" ); return nullptr; } /* -------------------------------------------------------------------- */ /* Get contentUnit parent element. */ /* -------------------------------------------------------------------- */ CPLXMLNode *psContentUnits = CPLGetXMLNode( psManifest, "=xfdu:XFDU.informationPackageMap.xfdu:contentUnit" ); if( psContentUnits == nullptr ) { CPLDestroyXMLNode( psManifest ); CPLError( CE_Failure, CPLE_OpenFailed, "Failed to find <xfdu:XFDU><informationPackageMap>" "<xfdu:contentUnit> in manifest file." ); return nullptr; } /* -------------------------------------------------------------------- */ /* Get Metadata Objects element. */ /* -------------------------------------------------------------------- */ CPLXMLNode *psMetaDataObjects = CPLGetXMLNode( psManifest, "=xfdu:XFDU.metadataSection" ); if( psMetaDataObjects == nullptr ) { CPLDestroyXMLNode( psManifest ); CPLError( CE_Failure, CPLE_OpenFailed, "Failed to find <xfdu:XFDU><metadataSection>" "in manifest file." ); return nullptr; } /* -------------------------------------------------------------------- */ /* Get Data Objects element. */ /* -------------------------------------------------------------------- */ CPLXMLNode *psDataObjects = CPLGetXMLNode( psManifest, "=xfdu:XFDU.dataObjectSection" ); if( psDataObjects == nullptr ) { CPLDestroyXMLNode( psManifest ); CPLError( CE_Failure, CPLE_OpenFailed, "Failed to find <xfdu:XFDU><dataObjectSection> in document." ); return nullptr; } /* -------------------------------------------------------------------- */ /* Create the dataset. */ /* -------------------------------------------------------------------- */ SAFEDataset *poDS = new SAFEDataset(); poDS->psManifest = psManifest; /* -------------------------------------------------------------------- */ /* Look for "Measurement Data Unit" contentUnit elements. */ /* -------------------------------------------------------------------- */ CPLXMLNode *psAnnotation = nullptr; //Map with all measures aggregated by swath std::map<CPLString, std::set<CPLString> > oMapSwaths2Pols; for( CPLXMLNode *psContentUnit = psContentUnits->psChild; psContentUnit != nullptr; psContentUnit = psContentUnit->psNext ) { if( psContentUnit->eType != CXT_Element || !(EQUAL(psContentUnit->pszValue,"xfdu:contentUnit")) ) { continue; } const char *pszUnitType = CPLGetXMLValue( psContentUnit, "unitType", "" ); const char *pszAnnotation = nullptr; const char *pszCalibration = nullptr; const char *pszMeasurement = nullptr; if ( EQUAL(pszUnitType, "Measurement Data Unit") ) { /* Get dmdID and dataObjectID */ const char *pszDmdID = CPLGetXMLValue(psContentUnit, "dmdID", ""); const char *pszDataObjectID = CPLGetXMLValue( psContentUnit, "dataObjectPointer.dataObjectID", "" ); if( *pszDataObjectID == '\0' || *pszDmdID == '\0' ) { continue; } CPLXMLNode *psDataObject = SAFEDataset::GetDataObject( psDataObjects, pszDataObjectID); const char *pszRepId = CPLGetXMLValue( psDataObject, "repID", "" ); if ( !EQUAL(pszRepId, "s1Level1MeasurementSchema") ) { continue; } pszMeasurement = CPLGetXMLValue( psDataObject, "byteStream.fileLocation.href", ""); if( *pszMeasurement == '\0' ) { continue; } char** papszTokens = CSLTokenizeString2( pszDmdID, " ", CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES ); for( int j = 0; j < CSLCount( papszTokens ); j++ ) { const char* pszId = papszTokens[j]; if( *pszId == '\0' ) { continue; } //Map the metadata ID to the object element CPLXMLNode *psDO = SAFEDataset::GetDataObject( psMetaDataObjects, psDataObjects, pszId); if (psDO == nullptr) { continue; } //check object type pszRepId = CPLGetXMLValue( psDO, "repID", "" ); if( EQUAL(pszRepId, "s1Level1ProductSchema") ) { /* Get annotation filename */ pszAnnotation = CPLGetXMLValue( psDO, "byteStream.fileLocation.href", ""); if( *pszAnnotation == '\0' ) { continue; } } else if( EQUAL(pszRepId, "s1Level1CalibrationSchema") ) { pszCalibration = CPLGetXMLValue( psDO, "byteStream.fileLocation.href", ""); if( *pszCalibration == '\0' ) { continue; } } else { continue; } } CSLDestroy(papszTokens); if (pszAnnotation == nullptr || pszCalibration == nullptr ) { continue; } //open Annotation XML file CPLString osAnnotationFilePath = CPLFormFilename( osPath, pszAnnotation, nullptr ); if( psAnnotation ) CPLDestroyXMLNode(psAnnotation); psAnnotation = CPLParseXMLFile( osAnnotationFilePath ); if( psAnnotation == nullptr ) continue; /* -------------------------------------------------------------------- */ /* Get overall image information. */ /* -------------------------------------------------------------------- */ poDS->nRasterXSize = atoi(CPLGetXMLValue( psAnnotation, "=product.imageAnnotation.imageInformation.numberOfSamples", "-1" )); poDS->nRasterYSize = atoi(CPLGetXMLValue( psAnnotation, "=product.imageAnnotation.imageInformation.numberOfLines", "-1" )); if (poDS->nRasterXSize <= 1 || poDS->nRasterYSize <= 1) { CPLError( CE_Failure, CPLE_OpenFailed, "Non-sane raster dimensions provided in manifest.safe. " "If this is a valid SENTINEL-1 scene, please contact your " "data provider for a corrected dataset." ); delete poDS; CPLDestroyXMLNode(psAnnotation); return nullptr; } CPLString osProductType = CPLGetXMLValue( psAnnotation, "=product.adsHeader.productType", "UNK" ); CPLString osMissionId = CPLGetXMLValue( psAnnotation, "=product.adsHeader.missionId", "UNK" ); CPLString osPolarisation = CPLGetXMLValue( psAnnotation, "=product.adsHeader.polarisation", "UNK" ); CPLString osMode = CPLGetXMLValue( psAnnotation, "=product.adsHeader.mode", "UNK" ); CPLString osSwath = CPLGetXMLValue( psAnnotation, "=product.adsHeader.swath", "UNK" ); oMapSwaths2Pols[osSwath].insert(osPolarisation); if (osSelectedSubDS1.empty()) { // If not subdataset was selected, // open the first one we can find. osSelectedSubDS1 = osSwath; } if (!EQUAL(osSelectedSubDS1.c_str(), osSwath.c_str())) { //do not mix swath, otherwise it does not work for SLC products continue; } if (!osSelectedSubDS2.empty() && (osSelectedSubDS2.find(osPolarisation)== std::string::npos)) { // Add only selected polarisations. continue; } poDS->SetMetadataItem("PRODUCT_TYPE", osProductType.c_str()); poDS->SetMetadataItem("MISSION_ID", osMissionId.c_str()); poDS->SetMetadataItem("MODE", osMode.c_str()); poDS->SetMetadataItem("SWATH", osSwath.c_str()); /* -------------------------------------------------------------------- */ /* Get dataType (so we can recognize complex data), and the */ /* bitsPerSample. */ /* -------------------------------------------------------------------- */ const char *pszDataType = CPLGetXMLValue( psAnnotation, "=product.imageAnnotation.imageInformation.outputPixels", "" ); GDALDataType eDataType; if( EQUAL(pszDataType,"16 bit Signed Integer") ) eDataType = GDT_CInt16; else if( EQUAL(pszDataType,"16 bit Unsigned Integer") ) eDataType = GDT_UInt16; else { delete poDS; CPLError( CE_Failure, CPLE_AppDefined, "dataType=%s: not a supported configuration.", pszDataType ); CPLDestroyXMLNode(psAnnotation); return nullptr; } /* Extract pixel spacing information */ const char *pszPixelSpacing = CPLGetXMLValue( psAnnotation, "=product.imageAnnotation.imageInformation.rangePixelSpacing", "UNK" ); poDS->SetMetadataItem( "PIXEL_SPACING", pszPixelSpacing ); const char *pszLineSpacing = CPLGetXMLValue( psAnnotation, "=product.imageAnnotation.imageInformation.azimuthPixelSpacing", "UNK" ); poDS->SetMetadataItem( "LINE_SPACING", pszLineSpacing ); /* -------------------------------------------------------------------- */ /* Form full filename (path of manifest.safe + measurement file). */ /* -------------------------------------------------------------------- */ char *pszFullname = CPLStrdup(CPLFormFilename( osPath, pszMeasurement, nullptr )); /* -------------------------------------------------------------------- */ /* Try and open the file. */ /* -------------------------------------------------------------------- */ GDALDataset *poBandFile = reinterpret_cast<GDALDataset *>( GDALOpen( pszFullname, GA_ReadOnly ) ); if( poBandFile == nullptr ) { // NOP } else if (poBandFile->GetRasterCount() == 0) { GDALClose( (GDALRasterBandH) poBandFile ); } else { poDS->papszExtraFiles = CSLAddString( poDS->papszExtraFiles, osAnnotationFilePath ); poDS->papszExtraFiles = CSLAddString( poDS->papszExtraFiles, pszFullname ); /* -------------------------------------------------------------------- */ /* Create the band. */ /* -------------------------------------------------------------------- */ SAFERasterBand *poBand = new SAFERasterBand( poDS, eDataType, osSwath.c_str(), osPolarisation.c_str(), poBandFile ); poDS->SetBand( poDS->GetRasterCount() + 1, poBand ); } CPLFree( pszFullname ); } } //loop through all Swath/pols to add subdatasets int iSubDS = 1; for (std::map<CPLString, std::set<CPLString> >::iterator iterSwath=oMapSwaths2Pols.begin(); iterSwath!=oMapSwaths2Pols.end(); ++iterSwath) { CPLString osSubDS1 = iterSwath->first; CPLString osSubDS2; for (std::set<CPLString>::iterator iterPol=iterSwath->second.begin(); iterPol!=iterSwath->second.end(); ++iterPol) { if (!osSubDS2.empty()) { osSubDS2 += "+"; } osSubDS2 += *iterPol; //Create single band SubDataset SAFEDataset::AddSubDataset(poDS, iSubDS, CPLSPrintf("SENTINEL1_DS:%s:%s_%s", osPath.c_str(), osSubDS1.c_str(), (*iterPol).c_str()), CPLSPrintf("Single band with %s swath and %s polarisation", osSubDS1.c_str(), (*iterPol).c_str()) ); iSubDS++; } if (iterSwath->second.size()>1) { //Create single band SubDataset with all polarisations SAFEDataset::AddSubDataset(poDS, iSubDS, CPLSPrintf("SENTINEL1_DS:%s:%s", osPath.c_str(), osSubDS1.c_str()), CPLSPrintf("%s swath with all polarisations as bands", osSubDS1.c_str()) ); iSubDS++; } } if (poDS->GetRasterCount() == 0) { CPLError( CE_Failure, CPLE_OpenFailed, "Measurement bands not found." ); delete poDS; if( psAnnotation ) CPLDestroyXMLNode(psAnnotation); return nullptr; } /* -------------------------------------------------------------------- */ /* Collect more metadata elements */ /* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */ /* Platform information */ /* -------------------------------------------------------------------- */ CPLXMLNode *psPlatformAttrs = SAFEDataset::GetMetaDataObject( psMetaDataObjects, "platform"); if (psPlatformAttrs != nullptr) { const char *pszItem = CPLGetXMLValue( psPlatformAttrs, "metadataWrap.xmlData.safe:platform" ".safe:familyName", "" ); poDS->SetMetadataItem( "SATELLITE_IDENTIFIER", pszItem ); pszItem = CPLGetXMLValue( psPlatformAttrs, "metadataWrap.xmlData.safe:platform" ".safe:instrument.safe:familyName.abbreviation", "" ); poDS->SetMetadataItem( "SENSOR_IDENTIFIER", pszItem ); pszItem = CPLGetXMLValue( psPlatformAttrs, "metadataWrap.xmlData.safe:platform" ".safe:instrument.safe:extension" ".s1sarl1:instrumentMode.s1sarl1:mode", "UNK" ); poDS->SetMetadataItem( "BEAM_MODE", pszItem ); pszItem = CPLGetXMLValue( psPlatformAttrs, "metadataWrap.xmlData.safe:platform" ".safe:instrument.safe:extension" ".s1sarl1:instrumentMode.s1sarl1:swath", "UNK" ); poDS->SetMetadataItem( "BEAM_SWATH", pszItem ); } /* -------------------------------------------------------------------- */ /* Acquisition Period information */ /* -------------------------------------------------------------------- */ CPLXMLNode *psAcquisitionAttrs = SAFEDataset::GetMetaDataObject( psMetaDataObjects, "acquisitionPeriod"); if (psAcquisitionAttrs != nullptr) { const char *pszItem = CPLGetXMLValue( psAcquisitionAttrs, "metadataWrap.xmlData.safe:acquisitionPeriod" ".safe:startTime", "UNK" ); poDS->SetMetadataItem( "ACQUISITION_START_TIME", pszItem ); pszItem = CPLGetXMLValue( psAcquisitionAttrs, "metadataWrap.xmlData.safe:acquisitionPeriod" ".safe:stopTime", "UNK" ); poDS->SetMetadataItem( "ACQUISITION_STOP_TIME", pszItem ); } /* -------------------------------------------------------------------- */ /* Processing information */ /* -------------------------------------------------------------------- */ CPLXMLNode *psProcessingAttrs = SAFEDataset::GetMetaDataObject( psMetaDataObjects, "processing"); if (psProcessingAttrs != nullptr) { const char *pszItem = CPLGetXMLValue( psProcessingAttrs, "metadataWrap.xmlData.safe:processing.safe:facility.name", "UNK" ); poDS->SetMetadataItem( "FACILITY_IDENTIFIER", pszItem ); } /* -------------------------------------------------------------------- */ /* Measurement Orbit Reference information */ /* -------------------------------------------------------------------- */ CPLXMLNode *psOrbitAttrs = SAFEDataset::GetMetaDataObject( psMetaDataObjects, "measurementOrbitReference"); if (psOrbitAttrs != nullptr) { const char *pszItem = CPLGetXMLValue( psOrbitAttrs, "metadataWrap.xmlData.safe:orbitReference" ".safe:orbitNumber", "UNK" ); poDS->SetMetadataItem( "ORBIT_NUMBER", pszItem ); pszItem = CPLGetXMLValue( psOrbitAttrs, "metadataWrap.xmlData.safe:orbitReference" ".safe:extension.s1:orbitProperties.s1:pass", "UNK" ); poDS->SetMetadataItem( "ORBIT_DIRECTION", pszItem ); } /* -------------------------------------------------------------------- */ /* Collect Annotation Processing Information */ /* -------------------------------------------------------------------- */ CPLXMLNode *psProcessingInfo = CPLGetXMLNode( psAnnotation, "=product.imageAnnotation.processingInformation" ); if ( psProcessingInfo != nullptr ) { OGRSpatialReference oLL, oPrj; const char *pszEllipsoidName = CPLGetXMLValue( psProcessingInfo, "ellipsoidName", "" ); const double minor_axis = CPLAtof(CPLGetXMLValue( psProcessingInfo, "ellipsoidSemiMinorAxis", "0.0" )); const double major_axis = CPLAtof(CPLGetXMLValue( psProcessingInfo, "ellipsoidSemiMajorAxis", "0.0" )); if ( EQUAL(pszEllipsoidName, "") || ( minor_axis == 0.0 ) || ( major_axis == 0.0 ) ) { CPLError(CE_Warning,CPLE_AppDefined,"Warning- incomplete" " ellipsoid information. Using wgs-84 parameters.\n"); oLL.SetWellKnownGeogCS( "WGS84" ); oPrj.SetWellKnownGeogCS( "WGS84" ); } else if ( EQUAL( pszEllipsoidName, "WGS84" ) ) { oLL.SetWellKnownGeogCS( "WGS84" ); oPrj.SetWellKnownGeogCS( "WGS84" ); } else { const double inv_flattening = major_axis/(major_axis - minor_axis); oLL.SetGeogCS( "","",pszEllipsoidName, major_axis, inv_flattening); oPrj.SetGeogCS( "","",pszEllipsoidName, major_axis, inv_flattening); } CPLFree( poDS->pszGCPProjection ); poDS->pszGCPProjection = nullptr; oLL.exportToWkt( &(poDS->pszGCPProjection) ); } /* -------------------------------------------------------------------- */ /* Collect GCPs. */ /* -------------------------------------------------------------------- */ CPLXMLNode *psGeoGrid = CPLGetXMLNode( psAnnotation, "=product.geolocationGrid.geolocationGridPointList" ); if( psGeoGrid != nullptr ) { /* count GCPs */ poDS->nGCPCount = 0; for( CPLXMLNode *psNode = psGeoGrid->psChild; psNode != nullptr; psNode = psNode->psNext ) { if( EQUAL(psNode->pszValue,"geolocationGridPoint") ) poDS->nGCPCount++ ; } poDS->pasGCPList = reinterpret_cast<GDAL_GCP *>( CPLCalloc( sizeof(GDAL_GCP), poDS->nGCPCount ) ); poDS->nGCPCount = 0; for( CPLXMLNode *psNode = psGeoGrid->psChild; psNode != nullptr; psNode = psNode->psNext ) { GDAL_GCP *psGCP = poDS->pasGCPList + poDS->nGCPCount; if( !EQUAL(psNode->pszValue,"geolocationGridPoint") ) continue; poDS->nGCPCount++ ; char szID[32]; snprintf( szID, sizeof(szID), "%d", poDS->nGCPCount ); psGCP->pszId = CPLStrdup( szID ); psGCP->pszInfo = CPLStrdup(""); psGCP->dfGCPPixel = CPLAtof(CPLGetXMLValue(psNode,"pixel","0")); psGCP->dfGCPLine = CPLAtof(CPLGetXMLValue(psNode,"line","0")); psGCP->dfGCPX = CPLAtof(CPLGetXMLValue(psNode,"longitude","")); psGCP->dfGCPY = CPLAtof(CPLGetXMLValue(psNode,"latitude","")); psGCP->dfGCPZ = CPLAtof(CPLGetXMLValue(psNode,"height","")); } } CPLDestroyXMLNode(psAnnotation); /* -------------------------------------------------------------------- */ /* Initialize any PAM information. */ /* -------------------------------------------------------------------- */ const CPLString osDescription = osMDFilename; /* -------------------------------------------------------------------- */ /* Initialize any PAM information. */ /* -------------------------------------------------------------------- */ poDS->SetDescription( osDescription ); poDS->SetPhysicalFilename( osMDFilename ); poDS->SetSubdatasetName( osDescription ); poDS->TryLoadXML(); /* -------------------------------------------------------------------- */ /* Check for overviews. */ /* -------------------------------------------------------------------- */ poDS->oOvManager.Initialize( poDS, ":::VIRTUAL:::" ); return poDS; }
OGRLayer * OGRGeoPackageDataSource::ExecuteSQL( const char *pszSQLCommand, OGRGeometry *poSpatialFilter, const char *pszDialect ) { if( EQUALN(pszSQLCommand, "SELECT ", 7) || (pszDialect != NULL && EQUAL(pszDialect,"OGRSQL")) ) return OGRDataSource::ExecuteSQL( pszSQLCommand, poSpatialFilter, pszDialect ); /* -------------------------------------------------------------------- */ /* Prepare statement. */ /* -------------------------------------------------------------------- */ int rc; sqlite3_stmt *hSQLStmt = NULL; CPLString osSQLCommand = pszSQLCommand; #if 0 /* This will speed-up layer creation */ /* ORDER BY are costly to evaluate and are not necessary to establish */ /* the layer definition. */ int bUseStatementForGetNextFeature = TRUE; int bEmptyLayer = FALSE; if( osSQLCommand.ifind("SELECT ") == 0 && osSQLCommand.ifind(" UNION ") == std::string::npos && osSQLCommand.ifind(" INTERSECT ") == std::string::npos && osSQLCommand.ifind(" EXCEPT ") == std::string::npos ) { size_t nOrderByPos = osSQLCommand.ifind(" ORDER BY "); if( nOrderByPos != std::string::npos ) { osSQLCommand.resize(nOrderByPos); bUseStatementForGetNextFeature = FALSE; } } #endif rc = sqlite3_prepare( m_poDb, osSQLCommand.c_str(), osSQLCommand.size(), &hSQLStmt, NULL ); if( rc != SQLITE_OK ) { CPLError( CE_Failure, CPLE_AppDefined, "In ExecuteSQL(): sqlite3_prepare(%s):\n %s", pszSQLCommand, sqlite3_errmsg(m_poDb) ); if( hSQLStmt != NULL ) { sqlite3_finalize( hSQLStmt ); } return NULL; } /* -------------------------------------------------------------------- */ /* Do we get a resultset? */ /* -------------------------------------------------------------------- */ rc = sqlite3_step( hSQLStmt ); if( rc != SQLITE_ROW ) { if ( rc != SQLITE_DONE ) { CPLError( CE_Failure, CPLE_AppDefined, "In ExecuteSQL(): sqlite3_step(%s):\n %s", pszSQLCommand, sqlite3_errmsg(m_poDb) ); sqlite3_finalize( hSQLStmt ); return NULL; } if( EQUAL(pszSQLCommand, "VACUUM") ) { sqlite3_finalize( hSQLStmt ); /* VACUUM rewrites the DB, so we need to reset the application id */ SetApplicationId(); return NULL; } if( EQUALN(pszSQLCommand, "ALTER TABLE ", strlen("ALTER TABLE ")) ) { char **papszTokens = CSLTokenizeString( pszSQLCommand ); /* ALTER TABLE src_table RENAME TO dst_table */ if( CSLCount(papszTokens) == 6 && EQUAL(papszTokens[3], "RENAME") && EQUAL(papszTokens[4], "TO") ) { const char* pszSrcTableName = papszTokens[2]; const char* pszDstTableName = papszTokens[5]; OGRLayer* poSrcLayer = GetLayerByName(pszSrcTableName); if( poSrcLayer ) { /* We also need to update GeoPackage metadata tables */ char* pszSQL; pszSQL = sqlite3_mprintf( "UPDATE gpkg_geometry_columns SET table_name = '%s' WHERE table_name = '%s'", pszDstTableName, pszSrcTableName); SQLCommand(m_poDb, pszSQL); sqlite3_free(pszSQL); pszSQL = sqlite3_mprintf( "UPDATE gpkg_contents SET table_name = '%s' WHERE table_name = '%s'", pszDstTableName, pszSrcTableName); SQLCommand(m_poDb, pszSQL); sqlite3_free(pszSQL); } } CSLDestroy(papszTokens); } if( !EQUALN(pszSQLCommand, "SELECT ", 7) ) { sqlite3_finalize( hSQLStmt ); return NULL; } #if 0 bUseStatementForGetNextFeature = FALSE; bEmptyLayer = TRUE; #endif } /* -------------------------------------------------------------------- */ /* Create layer. */ /* -------------------------------------------------------------------- */ #if 0 OGRSQLiteSelectLayer *poLayer = NULL; CPLString osSQL = pszSQLCommand; poLayer = new OGRGeopackageSelectLayer( this, osSQL, hSQLStmt, bUseStatementForGetNextFeature, bEmptyLayer, TRUE ); if( poSpatialFilter != NULL ) poLayer->SetSpatialFilter( 0, poSpatialFilter ); return poLayer; #else return OGRDataSource::ExecuteSQL( pszSQLCommand, poSpatialFilter, pszDialect ); #endif }
OGRLayer * OGRCouchDBDataSource::ExecuteSQL( const char *pszSQLCommand, OGRGeometry *poSpatialFilter, const char *pszDialect ) { /* -------------------------------------------------------------------- */ /* Use generic implementation for recognized dialects */ /* -------------------------------------------------------------------- */ if( IsGenericSQLDialect(pszDialect) ) return OGRDataSource::ExecuteSQL( pszSQLCommand, poSpatialFilter, pszDialect ); /* -------------------------------------------------------------------- */ /* Special case DELLAYER: command. */ /* -------------------------------------------------------------------- */ if( STARTS_WITH_CI(pszSQLCommand, "DELLAYER:") ) { const char *pszLayerName = pszSQLCommand + 9; while( *pszLayerName == ' ' ) pszLayerName++; DeleteLayer( pszLayerName ); return NULL; } /* -------------------------------------------------------------------- */ /* Special case 'COMPACT ON ' command. */ /* -------------------------------------------------------------------- */ if( STARTS_WITH_CI(pszSQLCommand, "COMPACT ON ") ) { const char *pszLayerName = pszSQLCommand + 11; while( *pszLayerName == ' ' ) pszLayerName++; CPLString osURI("/"); osURI += pszLayerName; osURI += "/_compact"; json_object* poAnswerObj = POST(osURI, NULL); IsError(poAnswerObj, "Database compaction failed"); json_object_put(poAnswerObj); return NULL; } /* -------------------------------------------------------------------- */ /* Special case 'VIEW CLEANUP ON ' command. */ /* -------------------------------------------------------------------- */ if( STARTS_WITH_CI(pszSQLCommand, "VIEW CLEANUP ON ") ) { const char *pszLayerName = pszSQLCommand + 16; while( *pszLayerName == ' ' ) pszLayerName++; CPLString osURI("/"); osURI += pszLayerName; osURI += "/_view_cleanup"; json_object* poAnswerObj = POST(osURI, NULL); IsError(poAnswerObj, "View cleanup failed"); json_object_put(poAnswerObj); return NULL; } /* -------------------------------------------------------------------- */ /* Deal with "DELETE FROM layer_name WHERE expression" statement */ /* -------------------------------------------------------------------- */ if( STARTS_WITH_CI(pszSQLCommand, "DELETE FROM ") ) { const char* pszIter = pszSQLCommand + 12; while(*pszIter && *pszIter != ' ') pszIter ++; if (*pszIter == 0) { CPLError(CE_Failure, CPLE_AppDefined, "Invalid statement"); return NULL; } CPLString osName = pszSQLCommand + 12; osName.resize(pszIter - (pszSQLCommand + 12)); OGRCouchDBLayer* poLayer = (OGRCouchDBLayer*)GetLayerByName(osName); if (poLayer == NULL) { CPLError(CE_Failure, CPLE_AppDefined, "Unknown layer : %s", osName.c_str()); return NULL; } if (poLayer->GetLayerType() != COUCHDB_TABLE_LAYER) return NULL; OGRCouchDBTableLayer* poTableLayer = (OGRCouchDBTableLayer*)poLayer; while( *pszIter == ' ' ) pszIter ++; if (!STARTS_WITH_CI(pszIter, "WHERE ")) { CPLError(CE_Failure, CPLE_AppDefined, "WHERE clause missing"); return NULL; } pszIter += 5; const char* pszQuery = pszIter; /* Check with the generic SQL engine that this is a valid WHERE clause */ OGRFeatureQuery oQuery; OGRErr eErr = oQuery.Compile( poLayer->GetLayerDefn(), pszQuery ); if( eErr != OGRERR_NONE ) { return NULL; } swq_expr_node * pNode = (swq_expr_node *) oQuery.GetSWQExpr(); if (pNode->eNodeType == SNT_OPERATION && pNode->nOperation == SWQ_EQ && pNode->nSubExprCount == 2 && pNode->papoSubExpr[0]->eNodeType == SNT_COLUMN && pNode->papoSubExpr[1]->eNodeType == SNT_CONSTANT && pNode->papoSubExpr[0]->field_index == COUCHDB_ID_FIELD && pNode->papoSubExpr[1]->field_type == SWQ_STRING) { poTableLayer->DeleteFeature(pNode->papoSubExpr[1]->string_value); } else { CPLError(CE_Failure, CPLE_AppDefined, "Invalid WHERE clause. Expecting '_id' = 'a_value'"); return NULL; } return NULL; } /* -------------------------------------------------------------------- */ /* Try an optimized implementation when doing only stats */ /* -------------------------------------------------------------------- */ if (poSpatialFilter == NULL && STARTS_WITH_CI(pszSQLCommand, "SELECT")) { OGRLayer* poRet = ExecuteSQLStats(pszSQLCommand); if (poRet) return poRet; } return OGRDataSource::ExecuteSQL( pszSQLCommand, poSpatialFilter, pszDialect ); }
OGRFeature *OGRAeronavFAARouteLayer::GetNextRawFeature() { OGRFeature* poFeature = nullptr; OGRLineString* poLS = nullptr; while( true ) { const char* pszLine = nullptr; if (!osLastReadLine.empty()) pszLine = osLastReadLine.c_str(); else pszLine = CPLReadLine2L(fpAeronavFAA, 87, nullptr); osLastReadLine = ""; if (pszLine == nullptr) { bEOF = true; break; } if (strlen(pszLine) != 85) continue; if (bIsDPOrSTARS && STARTS_WITH(pszLine, "===") && pszLine[3] != '=') { osAPTName = pszLine + 3; const char* pszComma = strchr(pszLine + 3, ','); if (pszComma) { osAPTName.resize(pszComma - (pszLine + 3)); osStateName = pszComma + 2; const char* pszEqual = strchr(pszComma + 2, '='); if (pszEqual) osStateName.resize(pszEqual - (pszComma + 2)); } else { const char* pszEqual = strchr(pszLine + 3, '='); if (pszEqual) osAPTName.resize(pszEqual - (pszLine + 3)); osStateName = ""; } } if (STARTS_WITH(pszLine + 2, "FACILITY OR")) continue; if (STARTS_WITH(pszLine + 2, "INTERSECTION")) continue; if (strcmp(pszLine, "================================DELETIONS LIST=================================198326") == 0) { bEOF = true; break; } if (poFeature == nullptr) { if (pszLine[2] == ' ' || pszLine[2] == '-' ) { continue; } if (STARTS_WITH(pszLine + 29, " ") || strchr(pszLine, '(') != nullptr) { CPLString osName = pszLine + 2; osName.resize(60); while(!osName.empty() && osName.back() == ' ') { osName.resize(osName.size()-1); } if (strcmp(osName.c_str(), "(DELETIONS LIST)") == 0) { bEOF = true; return nullptr; } poFeature = new OGRFeature(poFeatureDefn); poFeature->SetFID(nNextFID ++); if (bIsDPOrSTARS) { poFeature->SetField(0, osAPTName); poFeature->SetField(1, osStateName); poFeature->SetField(2, osName); } else poFeature->SetField(0, osName); poLS = new OGRLineString(); } continue; } if (STARTS_WITH(pszLine, " 0")) { if (poLS->getNumPoints() == 0) continue; else break; } if (pszLine[29 - 1] == ' ' && pszLine[42 - 1] == ' ') continue; if (strstr(pszLine, "RWY") || strchr(pszLine, '(')) { osLastReadLine = pszLine; break; } double dfLat = 0.0; double dfLon = 0.0; GetLatLon(pszLine + 29 - 1, pszLine + 42 - 1, dfLat, dfLon); poLS->addPoint(dfLon, dfLat); } if( poFeature != nullptr ) poFeature->SetGeometryDirectly(poLS); return poFeature; }