LTP GCOV extension - code coverage report
Current view: directory - ogr/ogrsf_frmts/geojson - ogrgeojsonreader.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 555
Code covered: 77.7 % Executed lines: 431

       1                 : /******************************************************************************
       2                 :  * $Id: ogrgeojsonreader.cpp 19506 2010-04-22 21:54:13Z rouault $
       3                 :  *
       4                 :  * Project:  OpenGIS Simple Features Reference Implementation
       5                 :  * Purpose:  Implementation of OGRGeoJSONReader class (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 "ogrgeojsonreader.h"
      30                 : #include "ogrgeojsonutils.h"
      31                 : #include "ogr_geojson.h"
      32                 : #include <jsonc/json.h> // JSON-C
      33                 : #include <jsonc/json_object_private.h> // json_object_iter, complete type required
      34                 : #include <ogr_api.h>
      35                 : 
      36                 : /************************************************************************/
      37                 : /*                           OGRGeoJSONReader                           */
      38                 : /************************************************************************/
      39                 : 
      40              22 : OGRGeoJSONReader::OGRGeoJSONReader()
      41                 :     : poGJObject_( NULL ), poLayer_( NULL ),
      42                 :         bGeometryPreserve_( true ),
      43              22 :         bAttributesSkip_( false )
      44                 : {
      45                 :     // Take a deep breath and get to work.
      46              22 : }
      47                 : 
      48                 : /************************************************************************/
      49                 : /*                          ~OGRGeoJSONReader                           */
      50                 : /************************************************************************/
      51                 : 
      52              22 : OGRGeoJSONReader::~OGRGeoJSONReader()
      53                 : {
      54              22 :     if( NULL != poGJObject_ )
      55                 :     {
      56              22 :         json_object_put(poGJObject_);
      57                 :     }
      58                 : 
      59              22 :     poGJObject_ = NULL;
      60              22 :     poLayer_ = NULL;
      61              22 : }
      62                 : 
      63                 : /************************************************************************/
      64                 : /*                           Parse                                      */
      65                 : /************************************************************************/
      66                 : 
      67              22 : OGRErr OGRGeoJSONReader::Parse( const char* pszText )
      68                 : {
      69              22 :     if( NULL != pszText )
      70                 :     {
      71              22 :         json_tokener* jstok = NULL;
      72              22 :         json_object* jsobj = NULL;
      73                 : 
      74              22 :         jstok = json_tokener_new();
      75              22 :         jsobj = json_tokener_parse_ex(jstok, pszText, -1);
      76              22 :         if( jstok->err != json_tokener_success)
      77                 :         {
      78                 :             CPLError( CE_Failure, CPLE_AppDefined,
      79                 :                       "GeoJSON parsing error: %s (at offset %d)",
      80               0 :                     json_tokener_errors[jstok->err], jstok->char_offset);
      81                 :             
      82               0 :             json_tokener_free(jstok);
      83               0 :             return OGRERR_CORRUPT_DATA;
      84                 :         }
      85              22 :         json_tokener_free(jstok);
      86                 : 
      87                 :         /* JSON tree is shared for while lifetime of the reader object
      88                 :          * and will be released in the destructor.
      89                 :          */
      90              22 :         poGJObject_ = jsobj;
      91                 :     }
      92                 : 
      93              22 :     return OGRERR_NONE;
      94                 : }
      95                 : 
      96                 : /************************************************************************/
      97                 : /*                           ReadLayer                                  */
      98                 : /************************************************************************/
      99                 : 
     100                 : OGRGeoJSONLayer* OGRGeoJSONReader::ReadLayer( const char* pszName,
     101              22 :                                               OGRGeoJSONDataSource* poDS )
     102                 : {
     103              22 :     CPLAssert( NULL == poLayer_ );
     104                 : 
     105              22 :     if( NULL == poGJObject_ )
     106                 :     {
     107                 :         CPLDebug( "GeoJSON",
     108               0 :                   "Missing parset GeoJSON data. Forgot to call Parse()?" );
     109               0 :         return NULL;
     110                 :     }
     111                 :         
     112                 :     poLayer_ = new OGRGeoJSONLayer( pszName, NULL,
     113                 :                                    OGRGeoJSONLayer::DefaultGeometryType,
     114              22 :                                    NULL, poDS );
     115                 : 
     116              22 :     if( !GenerateLayerDefn() )
     117                 :     {
     118                 :         CPLError( CE_Failure, CPLE_AppDefined,
     119               0 :             "Layer schema generation failed." );
     120                 : 
     121               0 :         delete poLayer_;
     122               0 :         return NULL;
     123                 :     }
     124                 : 
     125                 : /* -------------------------------------------------------------------- */
     126                 : /*      Translate single geometry-only Feature object.                  */
     127                 : /* -------------------------------------------------------------------- */
     128              22 :     GeoJSONObject::Type objType = OGRGeoJSONGetType( poGJObject_ );
     129                 : 
     130              31 :     if( GeoJSONObject::ePoint == objType
     131                 :         || GeoJSONObject::eMultiPoint == objType
     132                 :         || GeoJSONObject::eLineString == objType
     133                 :         || GeoJSONObject::eMultiLineString == objType
     134                 :         || GeoJSONObject::ePolygon == objType
     135                 :         || GeoJSONObject::eMultiPolygon == objType
     136                 :         || GeoJSONObject::eGeometryCollection == objType )
     137                 :     {
     138               9 :         OGRGeometry* poGeometry = NULL;
     139               9 :         poGeometry = ReadGeometry( poGJObject_ );
     140               9 :         if( !AddFeature( poGeometry ) )
     141                 :         {
     142                 :             CPLDebug( "GeoJSON",
     143               0 :                       "Translation of single geometry failed." );
     144               0 :             delete poLayer_;
     145               0 :             return NULL;
     146                 :         }
     147                 :     }
     148                 : /* -------------------------------------------------------------------- */
     149                 : /*      Translate single but complete Feature object.                   */
     150                 : /* -------------------------------------------------------------------- */
     151              13 :     else if( GeoJSONObject::eFeature == objType )
     152                 :     {
     153               0 :         OGRFeature* poFeature = NULL;
     154               0 :         poFeature = ReadFeature( poGJObject_ );
     155               0 :         if( !AddFeature( poFeature ) )
     156                 :         {
     157                 :             CPLDebug( "GeoJSON",
     158               0 :                       "Translation of single feature failed." );
     159                 : 
     160               0 :             delete poLayer_;
     161               0 :             return NULL;
     162                 :         }
     163                 :     }
     164                 : /* -------------------------------------------------------------------- */
     165                 : /*      Translate multi-feature FeatureCollection object.               */
     166                 : /* -------------------------------------------------------------------- */
     167              13 :     else if( GeoJSONObject::eFeatureCollection == objType )
     168                 :     {
     169              13 :         OGRGeoJSONLayer* poThisLayer = NULL;
     170              13 :         poThisLayer = ReadFeatureCollection( poGJObject_ );
     171              13 :         CPLAssert( poLayer_ == poThisLayer );
     172                 :     }
     173                 :     else
     174                 :     {
     175                 :         CPLError( CE_Failure, CPLE_AppDefined,
     176               0 :             "Unrecognized GeoJSON structure." );
     177                 : 
     178               0 :         delete poLayer_;
     179               0 :         return NULL;
     180                 :     }
     181                 : 
     182              22 :     OGRSpatialReference* poSRS = NULL;
     183              22 :     poSRS = OGRGeoJSONReadSpatialReference( poGJObject_ );
     184              22 :     if (poSRS == NULL ) {
     185                 :         // If there is none defined, we use 4326
     186              21 :         poSRS = new OGRSpatialReference();
     187              21 :         if( OGRERR_NONE != poSRS->importFromEPSG( 4326 ) )
     188                 :         {
     189               0 :             delete poSRS;
     190               0 :             poSRS = NULL;
     191                 :         }
     192              21 :         poLayer_->SetSpatialRef( poSRS );
     193              21 :         delete poSRS;
     194                 :     }
     195                 :     else {
     196               1 :         poLayer_->SetSpatialRef( poSRS );
     197               1 :         delete poSRS;
     198                 :     }
     199                 : 
     200                 :     // TODO: FeatureCollection
     201                 : 
     202              22 :     return poLayer_;
     203                 : }
     204                 : 
     205              24 : OGRSpatialReference* OGRGeoJSONReadSpatialReference( json_object* poObj) {
     206                 :     
     207                 : /* -------------------------------------------------------------------- */
     208                 : /*      Read spatial reference definition.                              */
     209                 : /* -------------------------------------------------------------------- */
     210              24 :     OGRSpatialReference* poSRS = NULL;
     211                 : 
     212              24 :     json_object* poObjSrs = OGRGeoJSONFindMemberByName( poObj, "crs" );
     213              24 :     if( NULL != poObjSrs )
     214                 :     {
     215               3 :         json_object* poObjSrsType = OGRGeoJSONFindMemberByName( poObjSrs, "type" );
     216               3 :         const char* pszSrsType = json_object_get_string( poObjSrsType );
     217                 : 
     218                 :         // TODO: Add URL and URN types support
     219               3 :         if( EQUALN( pszSrsType, "NAME", 4 ) )
     220                 :         {
     221               3 :             json_object* poObjSrsProps = OGRGeoJSONFindMemberByName( poObjSrs, "properties" );
     222               3 :             CPLAssert( NULL != poObjSrsProps );
     223                 : 
     224               3 :             json_object* poNameURL = OGRGeoJSONFindMemberByName( poObjSrsProps, "name" );
     225               3 :             CPLAssert( NULL != poNameURL );
     226                 : 
     227               3 :             const char* pszName = json_object_get_string( poNameURL );
     228                 : 
     229               3 :             poSRS = new OGRSpatialReference();
     230               3 :             if( OGRERR_NONE != poSRS->SetFromUserInput( pszName ) )
     231                 :             {
     232               0 :                 delete poSRS;
     233               0 :                 poSRS = NULL;
     234                 :             }
     235                 :         }
     236                 : 
     237               3 :         if( EQUALN( pszSrsType, "EPSG", 4 ) )
     238                 :         {
     239               0 :             json_object* poObjSrsProps = OGRGeoJSONFindMemberByName( poObjSrs, "properties" );
     240               0 :             CPLAssert( NULL != poObjSrsProps );
     241                 : 
     242               0 :             json_object* poObjCode = OGRGeoJSONFindMemberByName( poObjSrsProps, "code" );
     243               0 :             CPLAssert( NULL != poObjCode );
     244                 : 
     245               0 :             int nEPSG = json_object_get_int( poObjCode );
     246                 : 
     247               0 :             poSRS = new OGRSpatialReference();
     248               0 :             if( OGRERR_NONE != poSRS->importFromEPSG( nEPSG ) )
     249                 :             {
     250               0 :                 delete poSRS;
     251               0 :                 poSRS = NULL;
     252                 :             }
     253                 :         }
     254               3 :         if( EQUALN( pszSrsType, "URL", 3 ) || EQUALN( pszSrsType, "LINK", 4 )  )
     255                 :         {
     256               0 :             json_object* poObjSrsProps = OGRGeoJSONFindMemberByName( poObjSrs, "properties" );
     257               0 :             CPLAssert( NULL != poObjSrsProps );
     258                 : 
     259               0 :             json_object* poObjURL = OGRGeoJSONFindMemberByName( poObjSrsProps, "url" );
     260                 :             
     261               0 :             if (NULL == poObjURL) {
     262               0 :                 poObjURL = OGRGeoJSONFindMemberByName( poObjSrsProps, "href" );
     263                 :             }
     264               0 :             CPLAssert( NULL != poObjURL );
     265                 : 
     266               0 :             const char* pszURL = json_object_get_string( poObjURL );
     267                 : 
     268               0 :             poSRS = new OGRSpatialReference();
     269               0 :             if( OGRERR_NONE != poSRS->importFromUrl( pszURL ) )
     270                 :             {
     271               0 :                 delete poSRS;
     272               0 :                 poSRS = NULL;
     273                 : 
     274                 :             }
     275                 :         }
     276                 :     }
     277                 :     
     278              24 :     return poSRS;
     279                 : }
     280                 : /************************************************************************/
     281                 : /*                           SetPreserveGeometryType                    */
     282                 : /************************************************************************/
     283                 : 
     284               0 : void OGRGeoJSONReader::SetPreserveGeometryType( bool bPreserve )
     285                 : {
     286               0 :     bGeometryPreserve_ = bPreserve;
     287               0 : }
     288                 : 
     289                 : /************************************************************************/
     290                 : /*                           SetSkipAttributes                          */
     291                 : /************************************************************************/
     292                 : 
     293               0 : void OGRGeoJSONReader::SetSkipAttributes( bool bSkip )
     294                 : {
     295               0 :     bAttributesSkip_ = bSkip;
     296               0 : }
     297                 : 
     298                 : /************************************************************************/
     299                 : /*                           GenerateFeatureDefn                        */
     300                 : /************************************************************************/
     301                 : 
     302              22 : bool OGRGeoJSONReader::GenerateLayerDefn()
     303                 : {
     304              22 :     CPLAssert( NULL != poGJObject_ );
     305              22 :     CPLAssert( NULL != poLayer_->GetLayerDefn() );
     306              22 :     CPLAssert( 0 == poLayer_->GetLayerDefn()->GetFieldCount() );
     307                 : 
     308              22 :     bool bSuccess = true;
     309                 : 
     310              22 :     if( bAttributesSkip_ )
     311               0 :         return true;
     312                 : 
     313                 : /* -------------------------------------------------------------------- */
     314                 : /*      Scan all features and generate layer definition.        */
     315                 : /* -------------------------------------------------------------------- */
     316              22 :     GeoJSONObject::Type objType = OGRGeoJSONGetType( poGJObject_ );
     317              22 :     if( GeoJSONObject::eFeature == objType )
     318                 :     {
     319               0 :         bSuccess = GenerateFeatureDefn( poGJObject_ );
     320                 :     }
     321              22 :     else if( GeoJSONObject::eFeatureCollection == objType )
     322                 :     {
     323              13 :         json_object* poObjFeatures = NULL;
     324              13 :         poObjFeatures = OGRGeoJSONFindMemberByName( poGJObject_, "features" );
     325              13 :         if( NULL != poObjFeatures
     326                 :             && json_type_array == json_object_get_type( poObjFeatures ) )
     327                 :         {
     328              13 :             json_object* poObjFeature = NULL;
     329              13 :             const int nFeatures = json_object_array_length( poObjFeatures );
     330              48 :             for( int i = 0; i < nFeatures; ++i )
     331                 :             {
     332              35 :                 poObjFeature = json_object_array_get_idx( poObjFeatures, i );
     333              35 :                 if( !GenerateFeatureDefn( poObjFeature ) )
     334                 :                 {
     335               0 :                     CPLDebug( "GeoJSON", "Create feature schema failure." );
     336               0 :                     bSuccess = false;
     337                 :                 }
     338                 :             }
     339                 :         }
     340                 :         else
     341                 :         {
     342                 :             CPLError( CE_Failure, CPLE_AppDefined,
     343                 :                       "Invalid FeatureCollection object. "
     344               0 :                       "Missing \'features\' member." );
     345               0 :             bSuccess = false;
     346                 :         }
     347                 :     }
     348                 : 
     349                 : /* -------------------------------------------------------------------- */
     350                 : /*      Validate and add FID column if necessary.                       */
     351                 : /* -------------------------------------------------------------------- */
     352              22 :   OGRFeatureDefn* poLayerDefn = poLayer_->GetLayerDefn();
     353              22 :   CPLAssert( NULL != poLayerDefn );
     354                 : 
     355              22 :   bool bHasFID = false;
     356                 : 
     357              46 :   for( int i = 0; i < poLayerDefn->GetFieldCount(); ++i )
     358                 :   {
     359              24 :     OGRFieldDefn* poDefn = poLayerDefn->GetFieldDefn(i);
     360              24 :     if( EQUAL( poDefn->GetNameRef(), OGRGeoJSONLayer::DefaultFIDColumn )
     361                 :       && OFTInteger == poDefn->GetType() )
     362                 :     {
     363               0 :       poLayer_->SetFIDColumn( poDefn->GetNameRef() );
     364               0 :             bHasFID = true;
     365               0 :             break;
     366                 :     }
     367                 :   }
     368                 : 
     369                 :     // TODO - mloskot: This is wrong! We want to add only FID field if
     370                 :     // found in source layer (by default name or by FID_PROPERTY= specifier,
     371                 :     // the latter has to be implemented).
     372                 :     /*
     373                 :     if( !bHasFID )
     374                 :     {
     375                 :         OGRFieldDefn fldDefn( OGRGeoJSONLayer::DefaultFIDColumn, OFTInteger );
     376                 :         poLayerDefn->AddFieldDefn( &fldDefn );
     377                 :         poLayer_->SetFIDColumn( fldDefn.GetNameRef() );
     378                 :     }
     379                 :     */
     380                 : 
     381              22 :     return bSuccess;
     382                 : }
     383                 : 
     384              35 : bool OGRGeoJSONReader::GenerateFeatureDefn( json_object* poObj )
     385                 : {
     386              35 :     OGRFeatureDefn* poDefn = poLayer_->GetLayerDefn();
     387              35 :     CPLAssert( NULL != poDefn );
     388                 : 
     389              35 :     bool bSuccess = false;
     390                 : 
     391                 : /* -------------------------------------------------------------------- */
     392                 : /*      Read collection of properties.                  */
     393                 : /* -------------------------------------------------------------------- */
     394              35 :     json_object* poObjProps = NULL;
     395              35 :     poObjProps = OGRGeoJSONFindMemberByName( poObj, "properties" );
     396              35 :     if( NULL != poObjProps )
     397                 :     {
     398                 :         json_object_iter it;
     399              35 :         it.key = NULL;
     400              35 :         it.val = NULL;
     401              35 :         it.entry = NULL;
     402              59 :         json_object_object_foreachC( poObjProps, it )
     403                 :         {
     404              24 :             if( -1 == poDefn->GetFieldIndex( it.key ) )
     405                 :             {
     406                 :                 OGRFieldDefn fldDefn( it.key,
     407              24 :                     GeoJSONPropertyToFieldType( it.val ) );
     408              24 :                 poDefn->AddFieldDefn( &fldDefn );
     409                 :             }
     410                 :         }
     411                 : 
     412              35 :         bSuccess = true; // SUCCESS
     413                 :     }
     414                 :     else
     415                 :     {
     416                 :         CPLError( CE_Failure, CPLE_AppDefined,
     417                 :                   "Invalid Feature object. "
     418               0 :                   "Missing \'properties\' member." );
     419                 :     }
     420                 : 
     421              35 :     return bSuccess;
     422                 : }
     423                 : 
     424                 : /************************************************************************/
     425                 : /*                           AddFeature                                 */
     426                 : /************************************************************************/
     427                 : 
     428               9 : bool OGRGeoJSONReader::AddFeature( OGRGeometry* poGeometry )
     429                 : {
     430               9 :     bool bAdded = false;
     431                 : 
     432                 :     // TODO: Should we check if geometry is of type of 
     433                 :     //       wkbGeometryCollection ?
     434                 : 
     435               9 :     if( NULL != poGeometry )
     436                 :     {
     437               9 :         OGRFeature* poFeature = NULL;
     438               9 :         poFeature = new OGRFeature( poLayer_->GetLayerDefn() );
     439               9 :         poFeature->SetGeometryDirectly( poGeometry );
     440                 : 
     441               9 :         bAdded = AddFeature( poFeature );
     442                 :     }
     443                 :     
     444               9 :     return bAdded;
     445                 : }
     446                 : 
     447                 : /************************************************************************/
     448                 : /*                           AddFeature                                 */
     449                 : /************************************************************************/
     450                 : 
     451              44 : bool OGRGeoJSONReader::AddFeature( OGRFeature* poFeature )
     452                 : {
     453              44 :     bool bAdded = false;
     454                 :   
     455              44 :     if( NULL != poFeature )
     456                 :     {
     457              43 :         poLayer_->AddFeature( poFeature );
     458              43 :         bAdded = true;
     459              43 :         delete poFeature;
     460                 :     }
     461                 : 
     462              44 :     return bAdded;
     463                 : }
     464                 : 
     465                 : /************************************************************************/
     466                 : /*                           ReadGeometry                               */
     467                 : /************************************************************************/
     468                 : 
     469              43 : OGRGeometry* OGRGeoJSONReader::ReadGeometry( json_object* poObj )
     470                 : {
     471              43 :     OGRGeometry* poGeometry = NULL;
     472                 : 
     473              43 :     poGeometry = OGRGeoJSONReadGeometry( poObj );
     474                 : 
     475                 : /* -------------------------------------------------------------------- */
     476                 : /*      Wrap geometry with GeometryCollection as a common denominator.  */
     477                 : /*      Sometimes a GeoJSON text may consist of objects of different    */
     478                 : /*      geometry types. Users may request wrapping all geometries with  */
     479                 : /*      OGRGeometryCollection type by using option                      */
     480                 : /*      GEOMETRY_AS_COLLECTION=NO|YES (NO is default).                 */
     481                 : /* -------------------------------------------------------------------- */
     482              43 :     if( NULL != poGeometry )
     483                 :     {
     484              33 :         if( !bGeometryPreserve_ 
     485                 :             && wkbGeometryCollection != poGeometry->getGeometryType() )
     486                 :         {
     487               0 :             OGRGeometryCollection* poMetaGeometry = NULL;
     488               0 :             poMetaGeometry = new OGRGeometryCollection();
     489               0 :             poMetaGeometry->addGeometryDirectly( poGeometry );
     490               0 :             return poMetaGeometry;
     491                 :         }
     492                 :     }
     493                 : 
     494              43 :     return poGeometry;
     495                 : }
     496                 : 
     497                 : /************************************************************************/
     498                 : /*                           ReadFeature()                              */
     499                 : /************************************************************************/
     500                 : 
     501              35 : OGRFeature* OGRGeoJSONReader::ReadFeature( json_object* poObj )
     502                 : {
     503              35 :     CPLAssert( NULL != poObj );
     504              35 :     CPLAssert( NULL != poLayer_ );
     505                 : 
     506              35 :     OGRFeature* poFeature = NULL;
     507              35 :     poFeature = new OGRFeature( poLayer_->GetLayerDefn() );
     508                 : 
     509                 : /* -------------------------------------------------------------------- */
     510                 : /*      Translate GeoJSON "properties" object to feature attributes.    */
     511                 : /* -------------------------------------------------------------------- */
     512              35 :     CPLAssert( NULL != poFeature );
     513                 : 
     514              35 :     json_object* poObjProps = NULL;
     515              35 :     poObjProps = OGRGeoJSONFindMemberByName( poObj, "properties" );
     516              35 :     if( !bAttributesSkip_ && NULL != poObjProps )
     517                 :     {
     518              35 :         int nField = -1;
     519              35 :         OGRFieldDefn* poFieldDefn = NULL;
     520                 :         json_object_iter it;
     521              35 :         it.key = NULL;
     522              35 :         it.val = NULL;
     523              35 :         it.entry = NULL;
     524              59 :         json_object_object_foreachC( poObjProps, it )
     525                 :         {
     526              24 :             nField = poFeature->GetFieldIndex(it.key);
     527              24 :             poFieldDefn = poFeature->GetFieldDefnRef(nField);
     528              24 :             CPLAssert( NULL != poFieldDefn );
     529                 : 
     530                 :       /* Unset FID. */
     531              24 :       poFeature->SetFID( -1 );
     532                 : 
     533              24 :             if( OFTInteger == poFieldDefn->GetType() )
     534                 :       {
     535               0 :                 poFeature->SetField( nField, json_object_get_int(it.val) );
     536                 :         
     537                 :         /* Check if FID available and set correct value. */
     538               0 :         if( EQUAL( it.key, poLayer_->GetFIDColumn() ) )
     539               0 :           poFeature->SetFID( json_object_get_int(it.val) );
     540                 :       }
     541              24 :             else if( OFTReal == poFieldDefn->GetType() )
     542                 :       {
     543              12 :                 poFeature->SetField( nField, json_object_get_double(it.val) );
     544                 :       }
     545                 :             else
     546                 :       {
     547              12 :                 poFeature->SetField( nField, json_object_get_string(it.val) );
     548                 :       }
     549                 :         }
     550                 :     }
     551                 : 
     552                 : /* -------------------------------------------------------------------- */
     553                 : /*      If FID not set, try to use feature-level ID if available        */
     554                 : /*      and of integral type. Otherwise, leave unset (-1) then index    */
     555                 : /*      in features sequence will be used as FID.                       */
     556                 : /* -------------------------------------------------------------------- */
     557              35 :     if( -1 == poFeature->GetFID() )
     558                 :     {
     559              35 :         json_object* poObjId = NULL;
     560              35 :         poObjId = OGRGeoJSONFindMemberByName( poObj, OGRGeoJSONLayer::DefaultFIDColumn );
     561              35 :         if( NULL != poObjId
     562                 :             && EQUAL( OGRGeoJSONLayer::DefaultFIDColumn, poLayer_->GetFIDColumn() )
     563                 :             && OFTInteger == GeoJSONPropertyToFieldType( poObjId ) )
     564                 :         {
     565               0 :             poFeature->SetFID( json_object_get_int( poObjId ) );
     566               0 :             int nField = poFeature->GetFieldIndex( poLayer_->GetFIDColumn() );
     567               0 :             if( -1 != nField )
     568               0 :                 poFeature->SetField( nField, (int) poFeature->GetFID() );
     569                 :         }
     570                 :     }
     571                 : 
     572                 : /* -------------------------------------------------------------------- */
     573                 : /*      Translate geometry sub-object of GeoJSON Feature.               */
     574                 : /* -------------------------------------------------------------------- */
     575              35 :     json_object* poObjGeom = NULL;
     576                 : 
     577              35 :     json_object* poTmp = poObj;
     578                 : 
     579                 :     json_object_iter it;
     580              35 :     it.key = NULL;
     581              35 :     it.val = NULL;
     582              35 :     it.entry = NULL;    
     583             139 :     json_object_object_foreachC(poTmp, it)
     584                 :     {
     585             104 :         if( EQUAL( it.key, "geometry" ) ) {
     586              34 :             if (it.val != NULL)
     587              34 :                 poObjGeom = it.val;
     588                 :             // we're done.  They had 'geometry':null
     589                 :             else
     590               0 :                 return poFeature;
     591                 :         }
     592                 :     }
     593                 :     
     594              35 :     if( NULL != poObjGeom )
     595                 :     {
     596                 :         // NOTE: If geometry can not be parsed or read correctly
     597                 :         //       then NULL geometry is assigned to a feature and
     598                 :         //       geometry type for layer is classified as wkbUnknown.
     599              34 :         OGRGeometry* poGeometry = ReadGeometry( poObjGeom );
     600              34 :         if( NULL != poGeometry )
     601                 :         {
     602              24 :             poFeature->SetGeometryDirectly( poGeometry );
     603                 :         }
     604                 :     }
     605                 :     else
     606                 :     {
     607                 :         CPLError( CE_Failure, CPLE_AppDefined,
     608                 :                   "Invalid Feature object. "
     609               1 :                   "Missing \'geometry\' member." );
     610               1 :         delete poFeature;
     611               1 :         return NULL;
     612                 :     }
     613                 : 
     614              34 :     return poFeature;
     615                 : }
     616                 : 
     617                 : /************************************************************************/
     618                 : /*                           ReadFeatureCollection()                    */
     619                 : /************************************************************************/
     620                 : 
     621                 : OGRGeoJSONLayer*
     622              13 : OGRGeoJSONReader::ReadFeatureCollection( json_object* poObj )
     623                 : {
     624              13 :     CPLAssert( NULL != poLayer_ );
     625                 : 
     626              13 :     json_object* poObjFeatures = NULL;
     627              13 :     poObjFeatures = OGRGeoJSONFindMemberByName( poObj, "features" );
     628              13 :     if( NULL == poObjFeatures )
     629                 :     {
     630                 :         CPLError( CE_Failure, CPLE_AppDefined,
     631                 :                   "Invalid FeatureCollection object. "
     632               0 :                   "Missing \'features\' member." );
     633               0 :         return NULL;
     634                 :     }
     635                 : 
     636              13 :     if( json_type_array == json_object_get_type( poObjFeatures ) )
     637                 :     {
     638              13 :         bool bAdded = false;
     639              13 :         OGRFeature* poFeature = NULL;
     640              13 :         json_object* poObjFeature = NULL;
     641                 : 
     642              13 :         const int nFeatures = json_object_array_length( poObjFeatures );
     643              48 :         for( int i = 0; i < nFeatures; ++i )
     644                 :         {
     645              35 :             poObjFeature = json_object_array_get_idx( poObjFeatures, i );
     646              35 :             poFeature = OGRGeoJSONReader::ReadFeature( poObjFeature );
     647              35 :             bAdded = AddFeature( poFeature );
     648                 :             //CPLAssert( bAdded );
     649                 :         }
     650                 :         //CPLAssert( nFeatures == poLayer_->GetFeatureCount() );
     651                 :     }
     652                 : 
     653                 :     // We're returning class member to follow the same pattern of
     654                 :     // Read* functions call convention.
     655              13 :     CPLAssert( NULL != poLayer_ );
     656              13 :     return poLayer_;
     657                 : }
     658                 : 
     659                 : /************************************************************************/
     660                 : /*                           OGRGeoJSONFindMemberByName                 */
     661                 : /************************************************************************/
     662                 : 
     663                 : json_object* OGRGeoJSONFindMemberByName( json_object* poObj,
     664             352 :                                          const char* pszName )
     665                 : {
     666             352 :     if( NULL == pszName || NULL == poObj)
     667               0 :         return NULL;
     668                 : 
     669             352 :     json_object* poTmp = poObj;
     670                 : 
     671                 :     json_object_iter it;
     672             352 :     it.key = NULL;
     673             352 :     it.val = NULL;
     674             352 :     it.entry = NULL;
     675             352 :     if( NULL != json_object_get_object(poTmp) )
     676                 :     {
     677             352 :         CPLAssert( NULL != json_object_get_object(poTmp)->head );
     678                 : 
     679             747 :         for( it.entry = json_object_get_object(poTmp)->head;
     680                 :              ( it.entry ?
     681                 :                ( it.key = (char*)it.entry->k,
     682                 :                  it.val = (json_object*)it.entry->v, it.entry) : 0);
     683                 :              it.entry = it.entry->next)
     684                 :         {
     685             645 :             if( EQUAL( it.key, pszName ) )
     686             250 :                 return it.val;
     687                 :         }
     688                 :     }
     689                 : 
     690             102 :     return NULL;
     691                 : }
     692                 : 
     693                 : /************************************************************************/
     694                 : /*                           OGRGeoJSONGetType                          */
     695                 : /************************************************************************/
     696                 : 
     697              92 : GeoJSONObject::Type OGRGeoJSONGetType( json_object* poObj )
     698                 : {
     699              92 :     if( NULL == poObj )
     700               0 :         return GeoJSONObject::eUnknown;
     701                 : 
     702              92 :     json_object* poObjType = NULL;
     703              92 :     poObjType = OGRGeoJSONFindMemberByName( poObj, "type" );
     704              92 :     if( NULL == poObjType )
     705               0 :         return GeoJSONObject::eUnknown;
     706                 : 
     707              92 :     const char* name = json_object_get_string( poObjType );
     708              92 :     if( EQUAL( name, "Point" ) )
     709              12 :         return GeoJSONObject::ePoint;
     710              80 :     else if( EQUAL( name, "LineString" ) )
     711              11 :         return GeoJSONObject::eLineString;
     712              69 :     else if( EQUAL( name, "Polygon" ) )
     713               9 :         return GeoJSONObject::ePolygon;
     714              60 :     else if( EQUAL( name, "MultiPoint" ) )
     715               8 :         return GeoJSONObject::eMultiPoint;
     716              52 :     else if( EQUAL( name, "MultiLineString" ) )
     717               8 :         return GeoJSONObject::eMultiLineString;
     718              44 :     else if( EQUAL( name, "MultiPolygon" ) )
     719               9 :         return GeoJSONObject::eMultiPolygon;
     720              35 :     else if( EQUAL( name, "GeometryCollection" ) )
     721               9 :         return GeoJSONObject::eGeometryCollection;
     722              26 :     else if( EQUAL( name, "Feature" ) )
     723               0 :         return GeoJSONObject::eFeature;
     724              26 :     else if( EQUAL( name, "FeatureCollection" ) )
     725              26 :         return GeoJSONObject::eFeatureCollection;
     726                 :     else
     727               0 :         return GeoJSONObject::eUnknown;
     728                 : }
     729                 : 
     730                 : /************************************************************************/
     731                 : /*                           OGRGeoJSONReadGeometry                     */
     732                 : /************************************************************************/
     733                 : 
     734              48 : OGRGeometry* OGRGeoJSONReadGeometry( json_object* poObj )
     735                 : {
     736              48 :     OGRGeometry* poGeometry = NULL;
     737                 : 
     738              48 :     GeoJSONObject::Type objType = OGRGeoJSONGetType( poObj );
     739              48 :     if( GeoJSONObject::ePoint == objType )
     740               8 :         poGeometry = OGRGeoJSONReadPoint( poObj );
     741              40 :     else if( GeoJSONObject::eMultiPoint == objType )
     742               6 :         poGeometry = OGRGeoJSONReadMultiPoint( poObj );
     743              34 :     else if( GeoJSONObject::eLineString == objType )
     744               9 :         poGeometry = OGRGeoJSONReadLineString( poObj );
     745              25 :     else if( GeoJSONObject::eMultiLineString == objType )
     746               6 :         poGeometry = OGRGeoJSONReadMultiLineString( poObj );
     747              19 :     else if( GeoJSONObject::ePolygon == objType )
     748               7 :         poGeometry = OGRGeoJSONReadPolygon( poObj );
     749              12 :     else if( GeoJSONObject::eMultiPolygon == objType )
     750               7 :         poGeometry = OGRGeoJSONReadMultiPolygon( poObj );
     751               5 :     else if( GeoJSONObject::eGeometryCollection == objType )
     752               5 :         poGeometry = OGRGeoJSONReadGeometryCollection( poObj );
     753                 :     else
     754                 :     {
     755                 :         CPLDebug( "GeoJSON",
     756                 :                   "Unsupported geometry type detected. "
     757               0 :                   "Feature gets NULL geometry assigned." );
     758                 :     }
     759                 :     // If we have a crs object in the current object, let's try and 
     760                 :     // set it too.
     761                 :     
     762              48 :     json_object* poObjSrs = OGRGeoJSONFindMemberByName( poObj, "crs" );
     763              48 :     if (poObjSrs != NULL) {
     764               2 :         OGRSpatialReference* poSRS = OGRGeoJSONReadSpatialReference(poObj);
     765               2 :         if (poSRS != NULL) {
     766               2 :             poGeometry->assignSpatialReference(poSRS);
     767               2 :             poSRS->Release();
     768                 :         }
     769                 :     }
     770              48 :     return poGeometry;
     771                 : }
     772                 : 
     773                 : /************************************************************************/
     774                 : /*                           OGRGeoJSONReadRawPoint                     */
     775                 : /************************************************************************/
     776                 : 
     777             113 : bool OGRGeoJSONReadRawPoint( json_object* poObj, OGRPoint& point )
     778                 : {
     779             113 :     CPLAssert( NULL != poObj );
     780                 : 
     781             113 :     if( json_type_array == json_object_get_type( poObj ) ) 
     782                 :     {
     783             113 :         const int nSize = json_object_array_length( poObj );
     784             113 :         int iType = 0;
     785                 : 
     786             113 :         if( nSize != GeoJSONObject::eMinCoordinateDimension
     787                 :             && nSize != GeoJSONObject::eMaxCoordinateDimension )
     788                 :         {
     789                 :             CPLDebug( "GeoJSON",
     790               1 :                       "Invalid coord dimension. Only 2D and 3D supported." );
     791               1 :             return false;
     792                 :         }
     793                 : 
     794             112 :         json_object* poObjCoord = NULL;
     795                 : 
     796                 :         // Read X coordinate
     797             112 :         poObjCoord = json_object_array_get_idx( poObj, 0 );
     798                 :         
     799             112 :         iType = json_object_get_type(poObjCoord);
     800             112 :         if ( (json_type_double != iType) && (json_type_int != iType) )
     801                 :         {
     802                 :             CPLError( CE_Failure, CPLE_AppDefined,
     803                 :                       "Invalid X coordinate. Type is not double or integer for \'%s\'.",
     804               0 :                       json_object_to_json_string(poObj) );
     805               0 :             return false;
     806                 :         }
     807                 :         
     808             112 :         if (iType == json_type_double)
     809              98 :             point.setX(json_object_get_double( poObjCoord ));
     810                 :         else
     811              14 :             point.setX(json_object_get_int( poObjCoord ));
     812                 :         
     813                 :         // Read Y coordiante
     814             112 :         poObjCoord = json_object_array_get_idx( poObj, 1 );
     815                 :         
     816             112 :         iType = json_object_get_type(poObjCoord);
     817             112 :         if ( (json_type_double != iType) && (json_type_int != iType) )
     818                 :         {
     819                 :             CPLError( CE_Failure, CPLE_AppDefined,
     820                 :                       "Invalid Y coordinate. Type is not double or integer for \'%s\'.",
     821               0 :                       json_object_to_json_string(poObj) );
     822               0 :             return false;
     823                 :         }
     824                 : 
     825             112 :         if (iType == json_type_double)
     826              98 :             point.setY(json_object_get_double( poObjCoord ));
     827                 :         else
     828              14 :             point.setY(json_object_get_int( poObjCoord ));
     829                 :         
     830                 :         // Read Z coordinate
     831             112 :         if( nSize == GeoJSONObject::eMaxCoordinateDimension )
     832                 :         {
     833                 :             // Don't *expect* mixed-dimension geometries, although the 
     834                 :             // spec doesn't explicitly forbid this.
     835               0 :             poObjCoord = json_object_array_get_idx( poObj, 2 );
     836                 :             
     837               0 :             iType = json_object_get_type(poObjCoord);
     838               0 :             if ( (json_type_double != iType) && (json_type_int != iType) )
     839                 :             {
     840                 :                 CPLError( CE_Failure, CPLE_AppDefined,
     841                 :                           "Invalid Z coordinate. Type is not double or integer for \'%s\'.",
     842               0 :                           json_object_to_json_string(poObj) );
     843               0 :                 return false;
     844                 :             }
     845                 : 
     846               0 :             if (iType == json_type_double)
     847               0 :                 point.setZ(json_object_get_double( poObjCoord ));
     848                 :             else
     849               0 :                 point.setZ(json_object_get_int( poObjCoord ));
     850                 :         }
     851                 :         else
     852                 :         {
     853             112 :             point.flattenTo2D();
     854                 :         }
     855             112 :         return true;
     856                 :     }
     857                 :     
     858               0 :     return false;
     859                 : }
     860                 : 
     861                 : /************************************************************************/
     862                 : /*                           OGRGeoJSONReadPoint                        */
     863                 : /************************************************************************/
     864                 : 
     865               8 : OGRPoint* OGRGeoJSONReadPoint( json_object* poObj )
     866                 : {
     867               8 :     CPLAssert( NULL != poObj );
     868                 : 
     869               8 :     json_object* poObjCoords = NULL;
     870               8 :     poObjCoords = OGRGeoJSONFindMemberByName( poObj, "coordinates" );
     871               8 :     if( NULL == poObjCoords )
     872                 :     {
     873                 :         CPLError( CE_Failure, CPLE_AppDefined,
     874               1 :                   "Invalid Point object. Missing \'coordinates\' member." );
     875               1 :         return NULL;
     876                 :     }
     877                 : 
     878               7 :     OGRPoint* poPoint = new OGRPoint();
     879               7 :     if( !OGRGeoJSONReadRawPoint( poObjCoords, *poPoint ) )
     880                 :     {
     881               1 :         CPLDebug( "GeoJSON", "Point: raw point parsing failure." );
     882               1 :         delete poPoint;
     883               1 :         return NULL;
     884                 :     }
     885                 : 
     886               6 :     return poPoint;
     887                 : }
     888                 : 
     889                 : /************************************************************************/
     890                 : /*                           OGRGeoJSONReadMultiPoint                   */
     891                 : /************************************************************************/
     892                 : 
     893               6 : OGRMultiPoint* OGRGeoJSONReadMultiPoint( json_object* poObj )
     894                 : {
     895               6 :     CPLAssert( NULL != poObj );
     896                 : 
     897               6 :     OGRMultiPoint* poMultiPoint = NULL;
     898                 : 
     899               6 :     json_object* poObjPoints = NULL;
     900               6 :     poObjPoints = OGRGeoJSONFindMemberByName( poObj, "coordinates" );
     901               6 :     if( NULL == poObjPoints )
     902                 :     {
     903                 :         CPLError( CE_Failure, CPLE_AppDefined,
     904                 :                   "Invalid MultiPoint object. "
     905               1 :                   "Missing \'coordinates\' member." );
     906               1 :         return NULL;
     907                 :     }
     908                 : 
     909               5 :     if( json_type_array == json_object_get_type( poObjPoints ) )
     910                 :     {
     911               5 :         const int nPoints = json_object_array_length( poObjPoints );
     912                 : 
     913               5 :         poMultiPoint = new OGRMultiPoint();
     914                 : 
     915              16 :         for( int i = 0; i < nPoints; ++i)
     916                 :         {
     917              11 :             json_object* poObjCoords = NULL;
     918              11 :             poObjCoords = json_object_array_get_idx( poObjPoints, i );
     919                 : 
     920              11 :             OGRPoint pt;
     921              11 :             if( poObjCoords != NULL && !OGRGeoJSONReadRawPoint( poObjCoords, pt ) )
     922                 :             {
     923               0 :                 delete poMultiPoint;
     924                 :                 CPLDebug( "GeoJSON",
     925               0 :                           "LineString: raw point parsing failure." );
     926               0 :                 return NULL;
     927                 :             }
     928              11 :             poMultiPoint->addGeometry( &pt );
     929                 :         }
     930                 :     }
     931                 : 
     932               5 :     return poMultiPoint;
     933                 : }
     934                 : 
     935                 : /************************************************************************/
     936                 : /*                           OGRGeoJSONReadLineString                   */
     937                 : /************************************************************************/
     938                 : 
     939              18 : OGRLineString* OGRGeoJSONReadLineString( json_object* poObj , bool bRaw)
     940                 : {
     941              18 :     CPLAssert( NULL != poObj );
     942                 : 
     943              18 :     OGRLineString* poLine = NULL;
     944              18 :     json_object* poObjPoints = NULL;
     945                 :     
     946              18 :     if( !bRaw )
     947                 :     {
     948               9 :         poObjPoints = OGRGeoJSONFindMemberByName( poObj, "coordinates" );
     949               9 :         if( NULL == poObjPoints )
     950                 :         {
     951                 :             CPLError( CE_Failure, CPLE_AppDefined,
     952                 :                     "Invalid LineString object. "
     953               1 :                     "Missing \'coordinates\' member." );
     954               1 :                 return NULL;
     955                 :         }
     956                 :     }
     957                 :     else
     958                 :     {
     959               9 :         poObjPoints = poObj;
     960                 :     }
     961                 : 
     962              17 :     if( json_type_array == json_object_get_type( poObjPoints ) )
     963                 :     {
     964              17 :         const int nPoints = json_object_array_length( poObjPoints );
     965                 : 
     966              17 :         poLine = new OGRLineString();
     967              17 :         poLine->setNumPoints( nPoints );
     968                 : 
     969              45 :         for( int i = 0; i < nPoints; ++i)
     970                 :         {
     971              32 :             json_object* poObjCoords = NULL;
     972              32 :             poObjCoords = json_object_array_get_idx( poObjPoints, i );
     973              32 :             if (poObjCoords == NULL)
     974                 :             {
     975               4 :                 delete poLine;
     976                 :                 CPLDebug( "GeoJSON",
     977               4 :                           "LineString: got null object." );
     978               4 :                 return NULL;
     979                 :             }
     980                 :             
     981              28 :             OGRPoint pt;
     982              28 :             if( !OGRGeoJSONReadRawPoint( poObjCoords, pt ) )
     983                 :             {
     984               0 :                 delete poLine;
     985                 :                 CPLDebug( "GeoJSON",
     986               0 :                           "LineString: raw point parsing failure." );
     987               0 :                 return NULL;
     988                 :             }
     989              28 :             if (pt.getCoordinateDimension() == 2) {
     990              28 :                 poLine->setPoint( i, pt.getX(), pt.getY());
     991                 :             } else {
     992               0 :                 poLine->setPoint( i, pt.getX(), pt.getY(), pt.getZ() );
     993                 :             }
     994                 :             
     995                 :         }
     996                 :     }
     997                 : 
     998              13 :     return poLine;
     999                 : }
    1000                 : 
    1001                 : /************************************************************************/
    1002                 : /*                           OGRGeoJSONReadMultiLineString              */
    1003                 : /************************************************************************/
    1004                 : 
    1005               6 : OGRMultiLineString* OGRGeoJSONReadMultiLineString( json_object* poObj )
    1006                 : {
    1007               6 :     CPLAssert( NULL != poObj );
    1008                 : 
    1009               6 :     OGRMultiLineString* poMultiLine = NULL;
    1010                 : 
    1011               6 :     json_object* poObjLines = NULL;
    1012               6 :     poObjLines = OGRGeoJSONFindMemberByName( poObj, "coordinates" );
    1013               6 :     if( NULL == poObjLines )
    1014                 :     {
    1015                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1016                 :                   "Invalid MultiLineString object. "
    1017               1 :                   "Missing \'coordinates\' member." );
    1018               1 :         return NULL;
    1019                 :     }
    1020                 : 
    1021               5 :     if( json_type_array == json_object_get_type( poObjLines ) )
    1022                 :     {
    1023               5 :         const int nLines = json_object_array_length( poObjLines );
    1024                 : 
    1025               5 :         poMultiLine = new OGRMultiLineString();
    1026                 : 
    1027              16 :         for( int i = 0; i < nLines; ++i)
    1028                 :         {
    1029              11 :             json_object* poObjLine = NULL;
    1030              11 :             poObjLine = json_object_array_get_idx( poObjLines, i );
    1031                 : 
    1032                 :             OGRLineString* poLine;
    1033              11 :             if (poObjLine != NULL)
    1034               9 :                 poLine = OGRGeoJSONReadLineString( poObjLine , true );
    1035                 :             else
    1036               2 :                 poLine = new OGRLineString();
    1037                 : 
    1038              11 :             if( NULL != poLine )
    1039                 :             {
    1040               9 :                 poMultiLine->addGeometryDirectly( poLine );
    1041                 :             }
    1042                 :         }
    1043                 :     }
    1044                 : 
    1045               5 :     return poMultiLine;
    1046                 : }
    1047                 : 
    1048                 : /************************************************************************/
    1049                 : /*                           OGRGeoJSONReadLinearRing                   */
    1050                 : /************************************************************************/
    1051                 : 
    1052              15 : OGRLinearRing* OGRGeoJSONReadLinearRing( json_object* poObj )
    1053                 : {
    1054              15 :     CPLAssert( NULL != poObj );
    1055                 : 
    1056              15 :     OGRLinearRing* poRing = NULL;
    1057                 : 
    1058              15 :     if( json_type_array == json_object_get_type( poObj ) )
    1059                 :     {
    1060              15 :         const int nPoints = json_object_array_length( poObj );
    1061                 : 
    1062              15 :         poRing= new OGRLinearRing();
    1063              15 :         poRing->setNumPoints( nPoints );
    1064                 : 
    1065              85 :         for( int i = 0; i < nPoints; ++i)
    1066                 :         {
    1067              70 :             json_object* poObjCoords = NULL;
    1068              70 :             poObjCoords = json_object_array_get_idx( poObj, i );
    1069              70 :             if (poObjCoords == NULL)
    1070                 :             {
    1071               0 :                 delete poRing;
    1072                 :                 CPLDebug( "GeoJSON",
    1073               0 :                           "LinearRing: got null object." );
    1074               0 :                 return NULL;
    1075                 :             }
    1076                 : 
    1077              70 :             OGRPoint pt;
    1078              70 :             if( !OGRGeoJSONReadRawPoint( poObjCoords, pt ) )
    1079                 :             {
    1080               0 :                 delete poRing;
    1081                 :                 CPLDebug( "GeoJSON",
    1082               0 :                           "LinearRing: raw point parsing failure." );
    1083               0 :                 return NULL;
    1084                 :             }
    1085                 :             
    1086              70 :             if( 2 == pt.getCoordinateDimension() )
    1087              70 :                 poRing->setPoint( i, pt.getX(), pt.getY());
    1088                 :             else
    1089               0 :                 poRing->setPoint( i, pt.getX(), pt.getY(), pt.getZ() );
    1090                 :         }
    1091                 :     }
    1092                 : 
    1093              15 :     return poRing;
    1094                 : }
    1095                 : 
    1096                 : /************************************************************************/
    1097                 : /*                           OGRGeoJSONReadPolygon                      */
    1098                 : /************************************************************************/
    1099                 : 
    1100              18 : OGRPolygon* OGRGeoJSONReadPolygon( json_object* poObj , bool bRaw )
    1101                 : {
    1102              18 :     CPLAssert( NULL != poObj );
    1103                 : 
    1104              18 :     OGRPolygon* poPolygon = NULL;
    1105                 : 
    1106              18 :     json_object* poObjRings = NULL;
    1107                 :     
    1108              18 :     if( !bRaw )
    1109                 :     {
    1110               7 :         poObjRings = OGRGeoJSONFindMemberByName( poObj, "coordinates" );
    1111               7 :         if( NULL == poObjRings )
    1112                 :         {
    1113                 :             CPLError( CE_Failure, CPLE_AppDefined,
    1114                 :                       "Invalid Polygon object. "
    1115               1 :                       "Missing \'coordinates\' member." );
    1116               1 :             return NULL;
    1117                 :         }
    1118                 :     }
    1119                 :     else
    1120                 :     {
    1121              11 :         poObjRings = poObj;
    1122                 :     }
    1123                 :     
    1124              17 :     if( json_type_array == json_object_get_type( poObjRings ) )
    1125                 :     {
    1126              17 :         const int nRings = json_object_array_length( poObjRings );
    1127              17 :         if( nRings > 0 )
    1128                 :         {
    1129              15 :             json_object* poObjPoints = NULL;
    1130              15 :             poObjPoints = json_object_array_get_idx( poObjRings, 0 );
    1131              15 :             if (poObjPoints == NULL)
    1132                 :             {
    1133               2 :                 poPolygon = new OGRPolygon();
    1134               4 :                 poPolygon->addRingDirectly( new OGRLinearRing() );
    1135                 :             }
    1136                 :             else
    1137                 :             {
    1138              13 :                 OGRLinearRing* poRing = OGRGeoJSONReadLinearRing( poObjPoints );
    1139              13 :                 if( NULL != poRing )
    1140                 :                 {
    1141              13 :                     poPolygon = new OGRPolygon();
    1142              13 :                     poPolygon->addRingDirectly( poRing );
    1143                 :                 }
    1144                 :             }
    1145                 : 
    1146              18 :             for( int i = 1; i < nRings && NULL != poPolygon; ++i )
    1147                 :             {
    1148               3 :                 poObjPoints = json_object_array_get_idx( poObjRings, i );
    1149               3 :                 if (poObjPoints == NULL)
    1150                 :                 {
    1151               1 :                     poPolygon->addRingDirectly( new OGRLinearRing() );
    1152                 :                 }
    1153                 :                 else
    1154                 :                 {
    1155               2 :                     OGRLinearRing* poRing = OGRGeoJSONReadLinearRing( poObjPoints );
    1156               2 :                     if( NULL != poRing )
    1157                 :                     {
    1158               2 :                         poPolygon->addRingDirectly( poRing );
    1159                 :                     }
    1160                 :                 }
    1161                 :             }
    1162                 :         }
    1163                 :     }
    1164                 : 
    1165              17 :     return poPolygon;
    1166                 : }
    1167                 : 
    1168                 : /************************************************************************/
    1169                 : /*                           OGRGeoJSONReadMultiPolygon                 */
    1170                 : /************************************************************************/
    1171                 : 
    1172               7 : OGRMultiPolygon* OGRGeoJSONReadMultiPolygon( json_object* poObj )
    1173                 : {
    1174               7 :     CPLAssert( NULL != poObj );
    1175                 : 
    1176               7 :     OGRMultiPolygon* poMultiPoly = NULL;
    1177                 : 
    1178               7 :     json_object* poObjPolys = NULL;
    1179               7 :     poObjPolys = OGRGeoJSONFindMemberByName( poObj, "coordinates" );
    1180               7 :     if( NULL == poObjPolys )
    1181                 :     {
    1182                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1183                 :                   "Invalid MultiPolygon object. "
    1184               1 :                   "Missing \'coordinates\' member." );
    1185               1 :         return NULL;
    1186                 :     }
    1187                 : 
    1188               6 :     if( json_type_array == json_object_get_type( poObjPolys ) )
    1189                 :     {
    1190               6 :         const int nPolys = json_object_array_length( poObjPolys );
    1191                 : 
    1192               6 :         poMultiPoly = new OGRMultiPolygon();
    1193                 : 
    1194              20 :         for( int i = 0; i < nPolys; ++i)
    1195                 :         {
    1196                 : 
    1197              14 :             json_object* poObjPoly = NULL;
    1198              14 :             poObjPoly = json_object_array_get_idx( poObjPolys, i );
    1199              14 :             if (poObjPoly == NULL)
    1200                 :             {
    1201               3 :                 poMultiPoly->addGeometryDirectly( new OGRPolygon() );
    1202                 :             }
    1203                 :             else
    1204                 :             {
    1205              11 :                 OGRPolygon* poPoly = OGRGeoJSONReadPolygon( poObjPoly , true );
    1206              11 :                 if( NULL != poPoly )
    1207                 :                 {
    1208               9 :                     poMultiPoly->addGeometryDirectly( poPoly );
    1209                 :                 }
    1210                 :             }
    1211                 :         }
    1212                 :     }
    1213                 : 
    1214               6 :     return poMultiPoly;
    1215                 : }
    1216                 : /************************************************************************/
    1217                 : /*                           OGRGeoJSONReadGeometryCollection           */
    1218                 : /************************************************************************/
    1219                 : 
    1220               5 : OGRGeometryCollection* OGRGeoJSONReadGeometryCollection( json_object* poObj )
    1221                 : {
    1222               5 :     CPLAssert( NULL != poObj );
    1223                 : 
    1224               5 :     OGRGeometry* poGeometry = NULL;
    1225               5 :     OGRGeometryCollection* poCollection = NULL;
    1226                 : 
    1227               5 :     json_object* poObjGeoms = NULL;
    1228               5 :     poObjGeoms = OGRGeoJSONFindMemberByName( poObj, "geometries" );
    1229               5 :     if( NULL == poObjGeoms )
    1230                 :     {
    1231                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1232                 :                   "Invalid GeometryCollection object. "
    1233               1 :                   "Missing \'geometries\' member." );
    1234               1 :         return NULL;
    1235                 :     }
    1236                 : 
    1237               4 :     if( json_type_array == json_object_get_type( poObjGeoms ) )
    1238                 :     {
    1239               4 :         const int nGeoms = json_object_array_length( poObjGeoms );
    1240               4 :         if( nGeoms > 0 )
    1241                 :         {
    1242               4 :             poCollection = new OGRGeometryCollection();
    1243                 :         }
    1244                 : 
    1245               4 :         json_object* poObjGeom = NULL;
    1246              12 :         for( int i = 0; i < nGeoms; ++i )
    1247                 :         {
    1248               8 :             poObjGeom = json_object_array_get_idx( poObjGeoms, i );
    1249               8 :             if (poObjGeom == NULL)
    1250                 :             {
    1251               3 :                 CPLDebug( "GeoJSON", "Skipping null sub-geometry");
    1252               3 :                 continue;
    1253                 :             }
    1254                 : 
    1255               5 :             poGeometry = OGRGeoJSONReadGeometry( poObjGeom );
    1256               5 :             if( NULL != poGeometry )
    1257                 :             {
    1258               5 :                 poCollection->addGeometryDirectly( poGeometry );
    1259                 :             }
    1260                 :         }
    1261                 :     }
    1262                 : 
    1263               4 :     return poCollection;
    1264                 : }
    1265                 : 
    1266                 : /************************************************************************/
    1267                 : /*                           OGR_G_ExportToJson                         */
    1268                 : /************************************************************************/
    1269                 : 
    1270               0 : OGRGeometryH OGR_G_CreateGeometryFromJson( const char* pszJson )
    1271                 : {
    1272               0 :     VALIDATE_POINTER1( pszJson, "OGR_G_CreateGeometryFromJson", NULL );
    1273                 : 
    1274               0 :     if( NULL != pszJson )
    1275                 :     {
    1276               0 :         json_tokener* jstok = NULL;
    1277               0 :         json_object* poObj = NULL;
    1278                 : 
    1279               0 :         jstok = json_tokener_new();
    1280               0 :         poObj = json_tokener_parse_ex(jstok, pszJson, -1);
    1281               0 :         if( jstok->err != json_tokener_success)
    1282                 :         {
    1283                 :             CPLError( CE_Failure, CPLE_AppDefined,
    1284                 :                       "GeoJSON parsing error: %s (at offset %d)",
    1285               0 :                       json_tokener_errors[jstok->err], jstok->char_offset);
    1286               0 :             json_tokener_free(jstok);
    1287               0 :             return NULL;
    1288                 :         }
    1289               0 :         json_tokener_free(jstok);
    1290                 : 
    1291               0 :         OGRGeometry* poGeometry = NULL;
    1292               0 :         poGeometry = OGRGeoJSONReadGeometry( poObj );
    1293                 :         
    1294                 :         /* Release JSON tree. */
    1295               0 :         json_object_put( poObj );
    1296                 : 
    1297               0 :         return (OGRGeometryH)poGeometry;
    1298                 :     }
    1299                 : 
    1300                 :     /* Translation failed */
    1301               0 :     return NULL;
    1302                 : }
    1303                 : 

Generated by: LTP GCOV extension version 1.5