static int ptarray_to_kml2_sb(const POINTARRAY *pa, int precision, stringbuffer_t *sb) { int i, j; int dims = FLAGS_GET_Z(pa->flags) ? 3 : 2; POINT4D pt; double *d; for ( i = 0; i < pa->npoints; i++ ) { getPoint4d_p(pa, i, &pt); d = (double*)(&pt); if ( i ) stringbuffer_append(sb," "); for (j = 0; j < dims; j++) { if ( j ) stringbuffer_append(sb,","); if( fabs(d[j]) < OUT_MAX_DOUBLE ) { if ( stringbuffer_aprintf(sb, "%.*f", precision, d[j]) < 0 ) return LW_FAILURE; } else { if ( stringbuffer_aprintf(sb, "%g", d[j]) < 0 ) return LW_FAILURE; } stringbuffer_trim_trailing_zeroes(sb); } } return LW_SUCCESS; }
char * pc_point_to_string(const PCPOINT *pt) { /* { "pcid":1, "values":[<dim1>, <dim2>, <dim3>, <dim4>] }*/ stringbuffer_t *sb = stringbuffer_create(); char *str; int i; stringbuffer_aprintf(sb, "{\"pcid\":%d,\"pt\":[", pt->schema->pcid); for ( i = 0; i < pt->schema->ndims; i++ ) { double d; if ( ! pc_point_get_double_by_index(pt, i, &d) ) { pcerror("pc_point_to_string: unable to read double at position %d", i); } if ( i ) { stringbuffer_append(sb, ","); } stringbuffer_aprintf(sb, "%g", d); } stringbuffer_append(sb, "]}"); str = stringbuffer_getstringcopy(sb); stringbuffer_destroy(sb); return str; }
static int lwpoint_to_kml2_sb(const LWPOINT *point, int precision, const char *prefix, stringbuffer_t *sb) { /* Open point */ if ( stringbuffer_aprintf(sb, "<%sPoint><%scoordinates>", prefix, prefix) < 0 ) return LW_FAILURE; /* Coordinate array */ if ( ptarray_to_kml2_sb(point->point, precision, sb) == LW_FAILURE ) return LW_FAILURE; /* Close point */ if ( stringbuffer_aprintf(sb, "</%scoordinates></%sPoint>", prefix, prefix) < 0 ) return LW_FAILURE; return LW_SUCCESS; }
static int lwline_to_kml2_sb(const LWLINE *line, int precision, const char *prefix, stringbuffer_t *sb) { /* Open linestring */ if ( stringbuffer_aprintf(sb, "<%sLineString><%scoordinates>", prefix, prefix) < 0 ) return LW_FAILURE; /* Coordinate array */ if ( ptarray_to_kml2_sb(line->points, precision, sb) == LW_FAILURE ) return LW_FAILURE; /* Close linestring */ if ( stringbuffer_aprintf(sb, "</%scoordinates></%sLineString>", prefix, prefix) < 0 ) return LW_FAILURE; return LW_SUCCESS; }
char * pc_patch_dimensional_bytes_array_to_string(PCPATCH_DIMENSIONAL* pd) { int i; char *str; stringbuffer_t *sb = stringbuffer_create(); stringbuffer_append(sb, "{"); if ( pd->schema->ndims ) { stringbuffer_append(sb, "\"bytes\" : [\n"); for ( i = 0; i < pd->schema->ndims; i++ ) { if ( pd->bytes[i].bytes ) { PCBYTES *d = &pd->bytes[i]; if ( i ) stringbuffer_append(sb, ","); stringbuffer_append(sb, "\n { \n"); stringbuffer_aprintf(sb, " %s ", pc_bytes_to_string(d)); stringbuffer_append(sb, " }"); } } stringbuffer_append(sb, "\n]\n"); } stringbuffer_append(sb, "}\n"); str = stringbuffer_getstringcopy(sb); stringbuffer_destroy(sb); return str; }
/* Return a pointer to an allocated string containing the header for the specified loader state */ int ShpLoaderGetSQLFooter(SHPLOADERSTATE *state, char **strfooter) { stringbuffer_t *sb; char *ret; /* Create the stringbuffer containing the header; we use this API as it's easier for handling string resizing during append */ sb = stringbuffer_create(); stringbuffer_clear(sb); /* Create gist index if specified and not in "prepare" mode */ if (state->config->readshape && state->config->createindex) { stringbuffer_aprintf(sb, "CREATE INDEX ON "); /* Schema is optional, include if present. */ if (state->config->schema) { stringbuffer_aprintf(sb, "\"%s\".",state->config->schema); } stringbuffer_aprintf(sb, "\"%s\" USING GIST (\"%s\")", state->config->table, state->geo_col); /* Tablespace is also optional. */ if (state->config->idxtablespace != NULL) { stringbuffer_aprintf(sb, " TABLESPACE \"%s\"", state->config->idxtablespace); } stringbuffer_aprintf(sb, ";\n"); } /* End the transaction if there is one. */ if (state->config->usetransaction) { stringbuffer_aprintf(sb, "COMMIT;\n"); } /* Always ANALYZE the resulting table, for better stats */ stringbuffer_aprintf(sb, "ANALYZE "); if (state->config->schema) { stringbuffer_aprintf(sb, "\"%s\".", state->config->schema); } stringbuffer_aprintf(sb, "\"%s\";\n", state->config->table); /* Copy the string buffer into a new string, destroying the string buffer */ ret = (char *)malloc(strlen((char *)stringbuffer_getstring(sb)) + 1); strcpy(ret, (char *)stringbuffer_getstring(sb)); stringbuffer_destroy(sb); *strfooter = ret; return SHPLOADEROK; }
static int lwcollection_to_kml2_sb(const LWCOLLECTION *col, int precision, const char *prefix, stringbuffer_t *sb) { int i, rv; /* Open geometry */ if ( stringbuffer_aprintf(sb, "<%sMultiGeometry>", prefix) < 0 ) return LW_FAILURE; for ( i = 0; i < col->ngeoms; i++ ) { rv = lwgeom_to_kml2_sb(col->geoms[i], precision, prefix, sb); if ( rv == LW_FAILURE ) return LW_FAILURE; } /* Close geometry */ if ( stringbuffer_aprintf(sb, "</%sMultiGeometry>", prefix) < 0 ) return LW_FAILURE; return LW_SUCCESS; }
static int lwpoly_to_kml2_sb(const LWPOLY *poly, int precision, const char *prefix, stringbuffer_t *sb) { int i, rv; /* Open polygon */ if ( stringbuffer_aprintf(sb, "<%sPolygon>", prefix) < 0 ) return LW_FAILURE; for ( i = 0; i < poly->nrings; i++ ) { /* Inner or outer ring opening tags */ if( i ) rv = stringbuffer_aprintf(sb, "<%sinnerBoundaryIs><%sLinearRing><%scoordinates>", prefix, prefix, prefix); else rv = stringbuffer_aprintf(sb, "<%souterBoundaryIs><%sLinearRing><%scoordinates>", prefix, prefix, prefix); if ( rv < 0 ) return LW_FAILURE; /* Coordinate array */ if ( ptarray_to_kml2_sb(poly->rings[i], precision, sb) == LW_FAILURE ) return LW_FAILURE; /* Inner or outer ring closing tags */ if( i ) rv = stringbuffer_aprintf(sb, "</%scoordinates></%sLinearRing></%sinnerBoundaryIs>", prefix, prefix, prefix); else rv = stringbuffer_aprintf(sb, "</%scoordinates></%sLinearRing></%souterBoundaryIs>", prefix, prefix, prefix); if ( rv < 0 ) return LW_FAILURE; } /* Close polygon */ if ( stringbuffer_aprintf(sb, "</%sPolygon>", prefix) < 0 ) return LW_FAILURE; return LW_SUCCESS; }
static void test_stringbuffer_aprintf(void) { stringbuffer_t *sb; const char *str; sb = stringbuffer_create_with_size(2); stringbuffer_aprintf(sb, "hello %dth world", 14); str = stringbuffer_getstring(sb); CU_ASSERT_STRING_EQUAL("hello 14th world", str); stringbuffer_destroy(sb); }
/* TODO: expose to API ? Would require also exposing stringbuffer * See https://github.com/pgpointcloud/pointcloud/issues/74 */ static int pc_patch_uncompressed_to_stringbuffer(const PCPATCH_UNCOMPRESSED *patch, stringbuffer_t *sb) { PCPOINTLIST *pl; int i, j; /* { "pcid":1, "points":[[<dim1>, <dim2>, <dim3>, <dim4>],[<dim1>, <dim2>, <dim3>, <dim4>]] }*/ /* TODO: reserve space in buffer ? */ pl = pc_pointlist_from_uncompressed(patch); stringbuffer_aprintf(sb, "{\"pcid\":%d,\"pts\":[", patch->schema->pcid); for ( i = 0; i < pl->npoints; i++ ) { PCPOINT *pt = pc_pointlist_get_point(pl, i); if ( i ) stringbuffer_append(sb, ",["); else stringbuffer_append(sb, "["); for ( j = 0; j < pt->schema->ndims; j++ ) { double d; if ( ! pc_point_get_double_by_index(pt, j, &d)) { pcerror("%s: unable to read double at index %d", __func__, j); return PC_FAILURE; } if ( j ) stringbuffer_aprintf(sb, ",%g", d); else stringbuffer_aprintf(sb, "%g", d); } stringbuffer_append(sb, "]"); } stringbuffer_append(sb, "]}"); /* All done, copy and clean up */ pc_pointlist_free(pl); return PC_SUCCESS; }
/** Convert a PCSCHEMA to a human-readable JSON string */ char * pc_schema_to_json(const PCSCHEMA *pcs) { int i; char *str; stringbuffer_t *sb = stringbuffer_create(); stringbuffer_append(sb, "{"); if ( pcs->pcid ) stringbuffer_aprintf(sb, "\"pcid\" : %d,\n", pcs->pcid); if ( pcs->ndims ) stringbuffer_aprintf(sb, "\"ndims\" : %d,\n", pcs->ndims); if ( pcs->srid ) stringbuffer_aprintf(sb, "\"srid\" : %d,\n", pcs->srid); if ( pcs->compression ) stringbuffer_aprintf(sb, "\"compression\" : %d,\n", pcs->compression); if ( pcs->size ) stringbuffer_aprintf(sb, "\"size\" : %zu,\n", pcs->size); if ( pcs->x_position>=0 ) stringbuffer_aprintf(sb, "\"x_position\" : %d,\n", pcs->x_position); if ( pcs->y_position >=0) stringbuffer_aprintf(sb, "\"y_position\" : %d,\n", pcs->y_position); if ( pcs->namehash->entrycount ) stringbuffer_aprintf(sb, "\"namehash->entrycount\" : %d,\n", pcs->namehash->entrycount); if ( pcs->ndims ) { stringbuffer_append(sb, "\"dims\" : [\n"); for ( i = 0; i < pcs->ndims; i++ ) { stringbuffer_append(sb,pc_dimension_to_json(pcs->dims[i] ) ); } stringbuffer_append(sb, "\n]\n"); } stringbuffer_append(sb, "}\n"); str = stringbuffer_getstringcopy(sb); stringbuffer_destroy(sb); return str; }
/**@brief * Convert a PCSDIMENSION to a human-readable JSON string * @param the PCDIMENSION we want to print * @return q pointer to the string buff describing the object * */ char * pc_dimension_to_json(const PCDIMENSION *d) { int i; char *str; stringbuffer_t *sb = stringbuffer_create(); stringbuffer_append(sb, "{"); if ( d ) { if ( i ) stringbuffer_append(sb, ","); stringbuffer_append(sb, "\n { \n"); if ( d->name ) stringbuffer_aprintf(sb, " \"name\" : \"%s\",\n", d->name); if ( d->description ) stringbuffer_aprintf(sb, " \"description\" : \"%s\",\n", d->description); stringbuffer_aprintf(sb, " \"size\" : %d,\n", d->size); stringbuffer_aprintf(sb, " \"byteoffset\" : %d,\n", d->byteoffset); stringbuffer_aprintf(sb, " \"scale\" : %g,\n", d->scale); stringbuffer_aprintf(sb, " \"interpretation\" : \"%s\",\n", pc_interpretation_string(d->interpretation)); stringbuffer_aprintf(sb, " \"offset\" : %g,\n", d->offset); stringbuffer_aprintf(sb, " \"active\" : %d\n", d->active); stringbuffer_append(sb, " }"); } stringbuffer_append(sb, "}\n"); str = stringbuffer_getstringcopy(sb); stringbuffer_destroy(sb); return str; }
/* * Point array is a list of coordinates. Depending on output mode, * we may suppress some dimensions. ISO and Extended formats include * all dimensions. Standard OGC output only includes X/Y coordinates. */ static void ptarray_to_wkt_sb(const POINTARRAY *ptarray, stringbuffer_t *sb, int precision, uint8_t variant) { /* OGC only includes X/Y */ int dimensions = 2; int i, j; /* ISO and extended formats include all dimensions */ if ( variant & ( WKT_ISO | WKT_EXTENDED ) ) dimensions = FLAGS_NDIMS(ptarray->flags); /* Opening paren? */ if ( ! (variant & WKT_NO_PARENS) ) stringbuffer_append(sb, "("); /* Digits and commas */ for (i = 0; i < ptarray->npoints; i++) { uint8_t *p = getPoint_internal(ptarray, i); double d; /* Commas before ever coord but the first */ if ( i > 0 ) stringbuffer_append(sb, ","); for (j = 0; j < dimensions; j++) { memcpy(&d, p + j * sizeof(double), sizeof(double)); /* Spaces before every ordinate but the first */ if ( j > 0 ) stringbuffer_append(sb, " "); stringbuffer_aprintf(sb, "%.*g", precision, d); } } /* Closing paren? */ if ( ! (variant & WKT_NO_PARENS) ) stringbuffer_append(sb, ")"); }
/** * WKT emitter function. Allocates a new *char and fills it with the WKT * representation. If size_out is not NULL, it will be set to the size of the * allocated *char. * * @param variant Bitmasked value, accepts one of WKT_ISO, WKT_SFSQL, WKT_EXTENDED. * @param precision Number of significant digits in the output doubles. * @param size_out If supplied, will return the size of the returned string, * including the null terminator. */ char* lwgeom_to_wkt(const LWGEOM *geom, uint8_t variant, int precision, size_t *size_out) { stringbuffer_t *sb; char *str = NULL; if ( geom == NULL ) return NULL; sb = stringbuffer_create(); /* Extended mode starts with an "SRID=" section for geoms that have one */ if ( (variant & WKT_EXTENDED) && lwgeom_has_srid(geom) ) { stringbuffer_aprintf(sb, "SRID=%d;", geom->srid); } lwgeom_to_wkt_sb(geom, sb, precision, variant); if ( stringbuffer_getstring(sb) == NULL ) { lwerror("Uh oh"); return NULL; } str = stringbuffer_getstringcopy(sb); if ( size_out ) *size_out = stringbuffer_getlength(sb) + 1; stringbuffer_destroy(sb); return str; }
/** Convert a PCSCHEMA to a human-readable JSON string */ char * pc_schema_to_json(const PCSCHEMA *pcs) { int i; char *str; stringbuffer_t *sb = stringbuffer_create(); stringbuffer_append(sb, "{"); if ( pcs->pcid ) stringbuffer_aprintf(sb, "\"pcid\" : %d,\n", pcs->pcid); if ( pcs->srid ) stringbuffer_aprintf(sb, "\"srid\" : %d,\n", pcs->srid); if ( pcs->compression ) stringbuffer_aprintf(sb, "\"compression\" : %d,\n", pcs->compression); if ( pcs->ndims ) { stringbuffer_append(sb, "\"dims\" : [\n"); for ( i = 0; i < pcs->ndims; i++ ) { if ( pcs->dims[i] ) { PCDIMENSION *d = pcs->dims[i]; if ( i ) stringbuffer_append(sb, ","); stringbuffer_append(sb, "\n { \n"); if ( d->name ) stringbuffer_aprintf(sb, " \"name\" : \"%s\",\n", d->name); if ( d->description ) stringbuffer_aprintf(sb, " \"description\" : \"%s\",\n", d->description); stringbuffer_aprintf(sb, " \"size\" : %d,\n", d->size); stringbuffer_aprintf(sb, " \"byteoffset\" : %d,\n", d->byteoffset); stringbuffer_aprintf(sb, " \"scale\" : %g,\n", d->scale); stringbuffer_aprintf(sb, " \"interpretation\" : \"%s\",\n", pc_interpretation_string(d->interpretation)); stringbuffer_aprintf(sb, " \"offset\" : %g,\n", d->offset); stringbuffer_aprintf(sb, " \"active\" : %d\n", d->active); stringbuffer_append(sb, " }"); } } stringbuffer_append(sb, "\n]\n"); } stringbuffer_append(sb, "}\n"); str = stringbuffer_getstringcopy(sb); stringbuffer_destroy(sb); return str; }
/* Return a pointer to an allocated string containing the header for the specified loader state */ int ShpLoaderGetSQLHeader(SHPLOADERSTATE *state, char **strheader) { stringbuffer_t *sb; char *ret; int j; /* Create the stringbuffer containing the header; we use this API as it's easier for handling string resizing during append */ sb = stringbuffer_create(); stringbuffer_clear(sb); /* Set the client encoding if required */ if (state->config->encoding) { stringbuffer_aprintf(sb, "SET CLIENT_ENCODING TO UTF8;\n"); } /* Use SQL-standard string escaping rather than PostgreSQL standard */ stringbuffer_aprintf(sb, "SET STANDARD_CONFORMING_STRINGS TO ON;\n"); /* Drop table if requested */ if (state->config->opt == 'd') { /** * TODO: if the table has more then one geometry column * the DROP TABLE call will leave spurious records in * geometry_columns. * * If the geometry column in the table being dropped * does not match 'the_geom' or the name specified with * -g an error is returned by DropGeometryColumn. * * The table to be dropped might not exist. */ if (state->config->schema) { if (state->config->readshape == 1 && (! state->config->geography) ) { stringbuffer_aprintf(sb, "SELECT DropGeometryColumn('%s','%s','%s');\n", state->config->schema, state->config->table, state->geo_col); } stringbuffer_aprintf(sb, "DROP TABLE \"%s\".\"%s\";\n", state->config->schema, state->config->table); } else { if (state->config->readshape == 1 && (! state->config->geography) ) { stringbuffer_aprintf(sb, "SELECT DropGeometryColumn('','%s','%s');\n", state->config->table, state->geo_col); } stringbuffer_aprintf(sb, "DROP TABLE \"%s\";\n", state->config->table); } } /* Start of transaction if we are using one */ if (state->config->usetransaction) { stringbuffer_aprintf(sb, "BEGIN;\n"); } /* If not in 'append' mode create the spatial table */ if (state->config->opt != 'a') { /* * Create a table for inserting the shapes into with appropriate * columns and types */ if (state->config->schema) { stringbuffer_aprintf(sb, "CREATE TABLE \"%s\".\"%s\" (gid serial", state->config->schema, state->config->table); } else { stringbuffer_aprintf(sb, "CREATE TABLE \"%s\" (gid serial", state->config->table); } /* Generate the field types based upon the shapefile information */ for (j = 0; j < state->num_fields; j++) { stringbuffer_aprintf(sb, ",\n\"%s\" ", state->field_names[j]); /* First output the raw field type string */ stringbuffer_aprintf(sb, "%s", state->pgfieldtypes[j]); /* Some types do have typmods though... */ if (!strcmp("varchar", state->pgfieldtypes[j])) stringbuffer_aprintf(sb, "(%d)", state->widths[j]); if (!strcmp("numeric", state->pgfieldtypes[j])) { /* Doubles we just allow PostgreSQL to auto-detect the size */ if (state->types[j] != FTDouble) stringbuffer_aprintf(sb, "(%d,0)", state->widths[j]); } } /* Add the geography column directly to the table definition, we don't need to do an AddGeometryColumn() call. */ if (state->config->readshape == 1 && state->config->geography) { char *dimschar; if (state->pgdims == 4) dimschar = "ZM"; else dimschar = ""; if (state->to_srid != SRID_UNKNOWN && state->to_srid != 4326) { snprintf(state->message, SHPLOADERMSGLEN, _("Invalid SRID for geography type: %d"), state->to_srid); stringbuffer_destroy(sb); return SHPLOADERERR; } stringbuffer_aprintf(sb, ",\n\"%s\" geography(%s%s,%d)", state->geo_col, state->pgtype, dimschar, 4326); } stringbuffer_aprintf(sb, ")"); /* Tablespace is optional. */ if (state->config->tablespace != NULL) { stringbuffer_aprintf(sb, " TABLESPACE \"%s\"", state->config->tablespace); } stringbuffer_aprintf(sb, ";\n"); /* Create the primary key. This is done separately because the index for the PK needs * to be in the correct tablespace. */ /* TODO: Currently PostgreSQL does not allow specifying an index to use for a PK (so you get * a default one called table_pkey) and it does not provide a way to create a PK index * in a specific tablespace. So as a hacky solution we create the PK, then move the * index to the correct tablespace. Eventually this should be: * CREATE INDEX table_pkey on table(gid) TABLESPACE tblspc; * ALTER TABLE table ADD PRIMARY KEY (gid) USING INDEX table_pkey; * A patch has apparently been submitted to PostgreSQL to enable this syntax, see this thread: * http://archives.postgresql.org/pgsql-hackers/2011-01/msg01405.php */ stringbuffer_aprintf(sb, "ALTER TABLE "); /* Schema is optional, include if present. */ if (state->config->schema) { stringbuffer_aprintf(sb, "\"%s\".",state->config->schema); } stringbuffer_aprintf(sb, "\"%s\" ADD PRIMARY KEY (gid);\n", state->config->table); /* Tablespace is optional for the index. */ if (state->config->idxtablespace != NULL) { stringbuffer_aprintf(sb, "ALTER INDEX "); if (state->config->schema) { stringbuffer_aprintf(sb, "\"%s\".",state->config->schema); } /* WARNING: We're assuming the default "table_pkey" name for the primary * key index. PostgreSQL may use "table_pkey1" or similar in the * case of a name conflict, so you may need to edit the produced * SQL in this rare case. */ stringbuffer_aprintf(sb, "\"%s_pkey\" SET TABLESPACE \"%s\";\n", state->config->table, state->config->idxtablespace); } /* Create the geometry column with an addgeometry call */ if (state->config->readshape == 1 && (!state->config->geography)) { /* If they didn't specify a target SRID, see if they specified a source SRID. */ int srid = state->to_srid; if (state->config->schema) { stringbuffer_aprintf(sb, "SELECT AddGeometryColumn('%s','%s','%s','%d',", state->config->schema, state->config->table, state->geo_col, srid); } else { stringbuffer_aprintf(sb, "SELECT AddGeometryColumn('','%s','%s','%d',", state->config->table, state->geo_col, srid); } stringbuffer_aprintf(sb, "'%s',%d);\n", state->pgtype, state->pgdims); } } /* Copy the string buffer into a new string, destroying the string buffer */ ret = (char *)malloc(strlen((char *)stringbuffer_getstring(sb)) + 1); strcpy(ret, (char *)stringbuffer_getstring(sb)); stringbuffer_destroy(sb); *strheader = ret; return SHPLOADEROK; }
/* Return an allocated string representation of a specified record item */ int ShpLoaderGenerateSQLRowStatement(SHPLOADERSTATE *state, int item, char **strrecord) { SHPObject *obj = NULL; stringbuffer_t *sb; stringbuffer_t *sbwarn; char val[MAXVALUELEN]; char *escval; char *geometry=NULL, *ret; char *utf8str; int res, i; int rv; /* Clear the stringbuffers */ sbwarn = stringbuffer_create(); stringbuffer_clear(sbwarn); sb = stringbuffer_create(); stringbuffer_clear(sb); /* If we are reading the DBF only and the record has been marked deleted, return deleted record status */ if (state->config->readshape == 0 && DBFIsRecordDeleted(state->hDBFHandle, item)) { *strrecord = NULL; return SHPLOADERRECDELETED; } /* If we are reading the shapefile, open the specified record */ if (state->config->readshape == 1) { obj = SHPReadObject(state->hSHPHandle, item); if (!obj) { snprintf(state->message, SHPLOADERMSGLEN, _("Error reading shape object %d"), item); return SHPLOADERERR; } /* If we are set to skip NULLs, return a NULL record status */ if (state->config->null_policy == POLICY_NULL_SKIP && obj->nVertices == 0 ) { SHPDestroyObject(obj); *strrecord = NULL; return SHPLOADERRECISNULL; } } /* If not in dump format, generate the INSERT string */ if (!state->config->dump_format) { if (state->config->schema) { stringbuffer_aprintf(sb, "INSERT INTO \"%s\".\"%s\" %s VALUES (", state->config->schema, state->config->table, state->col_names); } else { stringbuffer_aprintf(sb, "INSERT INTO \"%s\" %s VALUES (", state->config->table, state->col_names); } } /* Read all of the attributes from the DBF file for this item */ for (i = 0; i < DBFGetFieldCount(state->hDBFHandle); i++) { /* Special case for NULL attributes */ if (DBFIsAttributeNULL(state->hDBFHandle, item, i)) { if (state->config->dump_format) stringbuffer_aprintf(sb, "\\N"); else stringbuffer_aprintf(sb, "NULL"); } else { /* Attribute NOT NULL */ switch (state->types[i]) { case FTInteger: case FTDouble: rv = snprintf(val, MAXVALUELEN, "%s", DBFReadStringAttribute(state->hDBFHandle, item, i)); if (rv >= MAXVALUELEN || rv == -1) { stringbuffer_aprintf(sbwarn, "Warning: field %d name truncated\n", i); val[MAXVALUELEN - 1] = '\0'; } /* If the value is an empty string, change to 0 */ if (val[0] == '\0') { val[0] = '0'; val[1] = '\0'; } /* If the value ends with just ".", remove the dot */ if (val[strlen(val) - 1] == '.') val[strlen(val) - 1] = '\0'; break; case FTString: case FTLogical: case FTDate: rv = snprintf(val, MAXVALUELEN, "%s", DBFReadStringAttribute(state->hDBFHandle, item, i)); if (rv >= MAXVALUELEN || rv == -1) { stringbuffer_aprintf(sbwarn, "Warning: field %d name truncated\n", i); val[MAXVALUELEN - 1] = '\0'; } break; default: snprintf(state->message, SHPLOADERMSGLEN, _("Error: field %d has invalid or unknown field type (%d)"), i, state->types[i]); SHPDestroyObject(obj); stringbuffer_destroy(sbwarn); stringbuffer_destroy(sb); return SHPLOADERERR; } if (state->config->encoding) { char *encoding_msg = _("Try \"LATIN1\" (Western European), or one of the values described at http://www.postgresql.org/docs/current/static/multibyte.html."); rv = utf8(state->config->encoding, val, &utf8str); if (rv != UTF8_GOOD_RESULT) { if ( rv == UTF8_BAD_RESULT ) snprintf(state->message, SHPLOADERMSGLEN, _("Unable to convert data value \"%s\" to UTF-8 (iconv reports \"%s\"). Current encoding is \"%s\". %s"), utf8str, strerror(errno), state->config->encoding, encoding_msg); else if ( rv == UTF8_NO_RESULT ) snprintf(state->message, SHPLOADERMSGLEN, _("Unable to convert data value to UTF-8 (iconv reports \"%s\"). Current encoding is \"%s\". %s"), strerror(errno), state->config->encoding, encoding_msg); else snprintf(state->message, SHPLOADERMSGLEN, _("Unexpected return value from utf8()")); if ( rv == UTF8_BAD_RESULT ) free(utf8str); return SHPLOADERERR; } strncpy(val, utf8str, MAXVALUELEN); free(utf8str); } /* Escape attribute correctly according to dump format */ if (state->config->dump_format) { escval = escape_copy_string(val); stringbuffer_aprintf(sb, "%s", escval); } else { escval = escape_insert_string(val); stringbuffer_aprintf(sb, "'%s'", escval); } /* Free the escaped version if required */ if (val != escval) free(escval); } /* Only put in delimeter if not last field or a shape will follow */ if (state->config->readshape == 1 || i < DBFGetFieldCount(state->hDBFHandle) - 1) { if (state->config->dump_format) stringbuffer_aprintf(sb, "\t"); else stringbuffer_aprintf(sb, ","); } /* End of DBF attribute loop */ } /* Add the shape attribute if we are reading it */ if (state->config->readshape == 1) { /* Handle the case of a NULL shape */ if (obj->nVertices == 0) { if (state->config->dump_format) stringbuffer_aprintf(sb, "\\N"); else stringbuffer_aprintf(sb, "NULL"); } else { /* Handle all other shape attributes */ switch (obj->nSHPType) { case SHPT_POLYGON: case SHPT_POLYGONM: case SHPT_POLYGONZ: res = GeneratePolygonGeometry(state, obj, &geometry); break; case SHPT_POINT: case SHPT_POINTM: case SHPT_POINTZ: res = GeneratePointGeometry(state, obj, &geometry, 0); break; case SHPT_MULTIPOINT: case SHPT_MULTIPOINTM: case SHPT_MULTIPOINTZ: /* Force it to multi unless using -S */ res = GeneratePointGeometry(state, obj, &geometry, state->config->simple_geometries ? 0 : 1); break; case SHPT_ARC: case SHPT_ARCM: case SHPT_ARCZ: res = GenerateLineStringGeometry(state, obj, &geometry); break; default: snprintf(state->message, SHPLOADERMSGLEN, _("Shape type is not supported, type id = %d"), obj->nSHPType); SHPDestroyObject(obj); stringbuffer_destroy(sbwarn); stringbuffer_destroy(sb); return SHPLOADERERR; } /* The default returns out of the function, so res will always have been set. */ if (res != SHPLOADEROK) { /* Error message has already been set */ SHPDestroyObject(obj); stringbuffer_destroy(sbwarn); stringbuffer_destroy(sb); return SHPLOADERERR; } /* Now generate the geometry string according to the current configuration */ if (!state->config->dump_format) { if (state->to_srid != state->from_srid) { stringbuffer_aprintf(sb, "ST_Transform("); } stringbuffer_aprintf(sb, "'"); } stringbuffer_aprintf(sb, "%s", geometry); if (!state->config->dump_format) { stringbuffer_aprintf(sb, "'"); /* Close the ST_Transform if reprojecting. */ if (state->to_srid != state->from_srid) { /* We need to add an explicit cast to geography/geometry to ensure that PostgreSQL doesn't get confused with the ST_Transform() raster function. */ if (state->config->geography) stringbuffer_aprintf(sb, "::geometry, %d)::geography", state->to_srid); else stringbuffer_aprintf(sb, "::geometry, %d)", state->to_srid); } } free(geometry); } /* Tidy up everything */ SHPDestroyObject(obj); } /* Close the line correctly for dump/insert format */ if (!state->config->dump_format) stringbuffer_aprintf(sb, ");"); /* Copy the string buffer into a new string, destroying the string buffer */ ret = (char *)malloc(strlen((char *)stringbuffer_getstring(sb)) + 1); strcpy(ret, (char *)stringbuffer_getstring(sb)); stringbuffer_destroy(sb); *strrecord = ret; /* If any warnings occurred, set the returned message string and warning status */ if (strlen((char *)stringbuffer_getstring(sbwarn)) > 0) { snprintf(state->message, SHPLOADERMSGLEN, "%s", stringbuffer_getstring(sbwarn)); stringbuffer_destroy(sbwarn); return SHPLOADERWARN; } else { /* Everything went okay */ stringbuffer_destroy(sbwarn); return SHPLOADEROK; } }