1 : /******************************************************************************
2 : * $Id: ogrgeojsonutils.cpp 23293 2011-10-30 11:11:39Z rouault $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: Implementation of private utilities used within OGR GeoJSON Driver.
6 : * Author: Mateusz Loskot, mateusz@loskot.net
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2007, Mateusz Loskot
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 : #include "ogrgeojsonutils.h"
30 : #include <cpl_port.h>
31 : #include <cpl_conv.h>
32 : #include <ogr_geometry.h>
33 : #include <jsonc/json.h> // JSON-C
34 :
35 : /************************************************************************/
36 : /* GeoJSONIsObject() */
37 : /************************************************************************/
38 :
39 882 : int GeoJSONIsObject( const char* pszText )
40 : {
41 882 : if( NULL == pszText )
42 0 : return FALSE;
43 :
44 : /* -------------------------------------------------------------------- */
45 : /* This is a primitive test, but we need to perform it fast. */
46 : /* -------------------------------------------------------------------- */
47 1764 : while( *pszText != '\0' && isspace( (unsigned char)*pszText ) )
48 0 : pszText++;
49 :
50 882 : if( EQUALN( pszText, "{", 1) )
51 88 : return TRUE;
52 :
53 794 : return FALSE;
54 : }
55 :
56 : /************************************************************************/
57 : /* GeoJSONFileIsObject() */
58 : /************************************************************************/
59 :
60 794 : int GeoJSONFileIsObject( const char* pszSource )
61 : {
62 794 : CPLAssert( NULL != pszSource );
63 :
64 794 : VSILFILE* fp = NULL;
65 794 : fp = VSIFOpenL( pszSource, "rb" );
66 794 : if( NULL == fp )
67 : {
68 336 : return FALSE;
69 : }
70 :
71 : // by default read first 6000 bytes
72 : // 6000 was chosen as enough bytes to
73 : // enable all current tests to pass
74 458 : vsi_l_offset nToReadLen = 6000;
75 458 : vsi_l_offset nDataLen = 0;
76 :
77 458 : char* pszGeoData = (char*)VSIMalloc((size_t)(nToReadLen + 1));
78 458 : if( NULL == pszGeoData )
79 : {
80 0 : VSIFCloseL(fp);
81 0 : return FALSE;
82 : }
83 :
84 458 : nDataLen = VSIFReadL( pszGeoData, 1, (size_t)nToReadLen, fp );
85 458 : pszGeoData[nDataLen] = '\0';
86 458 : if( nDataLen == 0 )
87 : {
88 28 : VSIFCloseL( fp );
89 28 : CPLFree( pszGeoData );
90 28 : return FALSE;
91 : }
92 430 : VSIFCloseL( fp );
93 :
94 430 : char* pszIter = pszGeoData;
95 896 : while( *pszIter != '\0' && isspace( (unsigned char)*pszIter ) )
96 36 : pszIter++;
97 :
98 430 : if( *pszIter != '{' )
99 : {
100 404 : CPLFree( pszGeoData );
101 404 : return FALSE;
102 : }
103 :
104 26 : int bRet = FALSE;
105 :
106 26 : if ((strstr(pszGeoData, "\"type\"") != NULL && strstr(pszGeoData, "\"coordinates\"") != NULL)
107 : || strstr(pszGeoData, "\"FeatureCollection\"") != NULL
108 : || (strstr(pszGeoData, "\"geometryType\"") != NULL && strstr(pszGeoData, "\"esriGeometry") != NULL))
109 26 : bRet = TRUE;
110 :
111 26 : CPLFree( pszGeoData );
112 26 : return bRet;
113 : }
114 :
115 : /************************************************************************/
116 : /* GeoJSONGetSourceType() */
117 : /************************************************************************/
118 :
119 850 : GeoJSONSourceType GeoJSONGetSourceType( const char* pszSource )
120 : {
121 850 : GeoJSONSourceType srcType = eGeoJSONSourceUnknown;
122 :
123 : // NOTE: Sometimes URL ends with .geojson token, for example
124 : // http://example/path/2232.geojson
125 : // It's important to test beginning of source first.
126 850 : if ( eGeoJSONProtocolUnknown != GeoJSONGetProtocolType( pszSource ) )
127 : {
128 0 : srcType = eGeoJSONSourceService;
129 : }
130 850 : else if( EQUAL( CPLGetExtension( pszSource ), "geojson" )
131 : || EQUAL( CPLGetExtension( pszSource ), "json" )
132 : || ((EQUALN( pszSource, "/vsigzip/", 9) || EQUALN( pszSource, "/vsizip/", 8)) &&
133 : (strstr( pszSource, ".json") || strstr( pszSource, ".JSON") ||
134 : strstr( pszSource, ".geojson") || strstr( pszSource, ".GEOJSON")) ))
135 : {
136 50 : srcType = eGeoJSONSourceFile;
137 : }
138 800 : else if( GeoJSONIsObject( pszSource ) )
139 : {
140 6 : srcType = eGeoJSONSourceText;
141 : }
142 794 : else if( GeoJSONFileIsObject( pszSource ) )
143 : {
144 26 : srcType = eGeoJSONSourceFile;
145 : }
146 :
147 850 : return srcType;
148 : }
149 :
150 : /************************************************************************/
151 : /* GeoJSONGetProtocolType() */
152 : /************************************************************************/
153 :
154 850 : GeoJSONProtocolType GeoJSONGetProtocolType( const char* pszSource )
155 : {
156 850 : GeoJSONProtocolType ptclType = eGeoJSONProtocolUnknown;
157 :
158 850 : if( EQUALN( pszSource, "http:", 5 ) )
159 0 : ptclType = eGeoJSONProtocolHTTP;
160 850 : else if( EQUALN( pszSource, "https:", 6 ) )
161 0 : ptclType = eGeoJSONProtocolHTTPS;
162 850 : else if( EQUALN( pszSource, "ftp:", 4 ) )
163 0 : ptclType = eGeoJSONProtocolFTP;
164 :
165 850 : return ptclType;
166 : }
167 :
168 : /************************************************************************/
169 : /* GeoJSONPropertyToFieldType() */
170 : /************************************************************************/
171 :
172 118 : OGRFieldType GeoJSONPropertyToFieldType( json_object* poObject )
173 : {
174 118 : if (poObject == NULL) { return OFTString; }
175 :
176 118 : json_type type = json_object_get_type( poObject );
177 :
178 118 : if( json_type_boolean == type )
179 0 : return OFTInteger;
180 118 : else if( json_type_double == type )
181 58 : return OFTReal;
182 60 : else if( json_type_int == type )
183 4 : return OFTInteger;
184 56 : else if( json_type_string == type )
185 56 : return OFTString;
186 0 : else if( json_type_array == type )
187 : {
188 0 : int nSize = json_object_array_length(poObject);
189 0 : if (nSize == 0)
190 0 : return OFTStringList; /* we don't know, so let's assume it's a string list */
191 0 : OGRFieldType eType = OFTIntegerList;
192 0 : for(int i=0;i<nSize;i++)
193 : {
194 0 : json_object* poRow = json_object_array_get_idx(poObject, i);
195 0 : if (poRow != NULL)
196 : {
197 0 : type = json_object_get_type( poRow );
198 0 : if (type == json_type_string)
199 0 : return OFTStringList;
200 0 : else if (type == json_type_double)
201 0 : eType = OFTRealList;
202 0 : else if (type != json_type_int &&
203 : type != json_type_boolean)
204 0 : return OFTString;
205 : }
206 : }
207 0 : return eType;
208 : }
209 : else
210 0 : return OFTString; /* null, object */
211 : }
212 :
213 : /************************************************************************/
214 : /* OGRGeoJSONGetGeometryName() */
215 : /************************************************************************/
216 :
217 60 : const char* OGRGeoJSONGetGeometryName( OGRGeometry const* poGeometry )
218 : {
219 60 : CPLAssert( NULL != poGeometry );
220 :
221 60 : OGRwkbGeometryType eType = poGeometry->getGeometryType();
222 :
223 60 : if( wkbPoint == eType || wkbPoint25D == eType )
224 14 : return "Point";
225 46 : else if( wkbLineString == eType || wkbLineString25D == eType )
226 6 : return "LineString";
227 40 : else if( wkbPolygon == eType || wkbPolygon25D == eType )
228 10 : return "Polygon";
229 30 : else if( wkbMultiPoint == eType || wkbMultiPoint25D == eType )
230 8 : return "MultiPoint";
231 22 : else if( wkbMultiLineString == eType || wkbMultiLineString25D == eType )
232 8 : return "MultiLineString";
233 14 : else if( wkbMultiPolygon == eType || wkbMultiPolygon25D == eType )
234 10 : return "MultiPolygon";
235 4 : else if( wkbGeometryCollection == eType || wkbGeometryCollection25D == eType )
236 4 : return "GeometryCollection";
237 : else
238 0 : return "Unknown";
239 : }
240 :
|