LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/mssqlspatial - ogrmssqlgeometryparser.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 191 0 0.0 %
Date: 2012-04-28 Functions: 10 0 0.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrmssqlgeometryparser.cpp 24330 2012-04-28 11:46:49Z tamas $
       3                 :  *
       4                 :  * Project:  MSSQL Spatial driver
       5                 :  * Purpose:  Implements OGRMSSQLGeometryParser class to parse native SqlGeometries.
       6                 :  * Author:   Tamas Szekeres, szekerest at gmail.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2010, Tamas Szekeres
      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                 : 
      30                 : #include "cpl_conv.h"
      31                 : #include "ogr_mssqlspatial.h"
      32                 : 
      33                 : CPL_CVSID("$Id: ogrmssqlgeometryparser.cpp 24330 2012-04-28 11:46:49Z tamas $");
      34                 : 
      35                 : /************************************************************************/
      36                 : /*                         Geometry parser macros                       */
      37                 : /************************************************************************/
      38                 : 
      39                 : #define SP_NONE 0
      40                 : #define SP_HASZVALUES 1
      41                 : #define SP_HASMVALUES 2
      42                 : #define SP_ISVALID 4
      43                 : #define SP_ISSINGLEPOINT 8
      44                 : #define SP_ISSINGLELINESEGMENT 0x10
      45                 : #define SP_ISWHOLEGLOBE 0x20
      46                 : 
      47                 : #define ST_UNKNOWN 0
      48                 : #define ST_POINT 1
      49                 : #define ST_LINESTRING 2
      50                 : #define ST_POLYGON 3
      51                 : #define ST_MULTIPOINT 4
      52                 : #define ST_MULTILINESTRING 5
      53                 : #define ST_MULTIPOLYGON 6
      54                 : #define ST_GEOMETRYCOLLECTION 7
      55                 : 
      56                 : #define ReadInt32(nPos) (*((unsigned int*)(pszData + (nPos))))
      57                 : 
      58                 : #define ReadByte(nPos) (pszData[nPos])
      59                 : 
      60                 : #define ReadDouble(nPos) (*((double*)(pszData + (nPos))))
      61                 : 
      62                 : #define ParentOffset(iShape) (ReadInt32(nShapePos + (iShape) * 9 ))
      63                 : #define FigureOffset(iShape) (ReadInt32(nShapePos + (iShape) * 9 + 4))
      64                 : #define ShapeType(iShape) (ReadByte(nShapePos + (iShape) * 9 + 8))
      65                 : 
      66                 : #define NextFigureOffset(iShape) (iShape + 1 < nNumShapes? FigureOffset((iShape) +1) : nNumFigures)
      67                 : 
      68                 : #define FigureAttribute(iFigure) (ReadByte(nFigurePos + (iFigure) * 5))
      69                 : #define PointOffset(iFigure) (ReadInt32(nFigurePos + (iFigure) * 5 + 1))
      70                 : #define NextPointOffset(iFigure) (iFigure + 1 < nNumFigures? PointOffset((iFigure) +1) : nNumPoints)
      71                 : 
      72                 : #define ReadX(iPoint) (ReadDouble(nPointPos + nPointSize * (iPoint)))
      73                 : #define ReadY(iPoint) (ReadDouble(nPointPos + nPointSize * (iPoint) + 8))
      74                 : #define ReadZ(iPoint) (ReadDouble(nPointPos + nPointSize * (iPoint) + 16))
      75                 : 
      76                 : /************************************************************************/
      77                 : /*                   OGRMSSQLGeometryParser()                           */
      78                 : /************************************************************************/
      79                 : 
      80               0 : OGRMSSQLGeometryParser::OGRMSSQLGeometryParser(int nGeomColumnType)
      81                 : {
      82               0 :     nColType = nGeomColumnType;
      83               0 : }
      84                 : 
      85                 : /************************************************************************/
      86                 : /*                         ReadPoint()                                  */
      87                 : /************************************************************************/
      88                 : 
      89               0 : OGRPoint* OGRMSSQLGeometryParser::ReadPoint(int iShape)
      90                 : {
      91               0 :     int iFigure = FigureOffset(iShape);
      92               0 :     if ( iFigure < nNumFigures )
      93                 :     {
      94               0 :         int iPoint = PointOffset(iFigure);
      95               0 :         if ( iPoint < nNumPoints )
      96                 :         {
      97               0 :             if (nColType == MSSQLCOLTYPE_GEOGRAPHY)
      98                 :             {
      99               0 :                 if ( chProps & SP_HASZVALUES )
     100               0 :                     return new OGRPoint( ReadY(iPoint), ReadX(iPoint), ReadZ(iPoint) );
     101                 :                 else
     102               0 :                     return new OGRPoint( ReadY(iPoint), ReadX(iPoint) );
     103                 :             }
     104                 :             else
     105                 :             {
     106               0 :                 if ( chProps & SP_HASZVALUES )
     107               0 :                     return new OGRPoint( ReadX(iPoint), ReadY(iPoint), ReadZ(iPoint) );
     108                 :                 else
     109               0 :                     return new OGRPoint( ReadX(iPoint), ReadY(iPoint) );
     110                 :             }
     111                 :         }
     112                 :     }
     113               0 :     return NULL;
     114                 : }
     115                 : 
     116                 : /************************************************************************/
     117                 : /*                         ReadMultiPoint()                             */
     118                 : /************************************************************************/
     119                 : 
     120               0 : OGRMultiPoint* OGRMSSQLGeometryParser::ReadMultiPoint(int iShape)
     121                 : {
     122                 :     int iFigure, iPoint, iNextPoint;
     123               0 :     iFigure = FigureOffset(iShape);
     124                 : 
     125               0 :     OGRMultiPoint* poMultiPoint = new OGRMultiPoint();
     126               0 :     iNextPoint = NextPointOffset(iFigure);
     127               0 :     for (iPoint = PointOffset(iFigure); iPoint < iNextPoint; iPoint++)
     128                 :     {
     129                 :         OGRPoint* poPoint;
     130                 :         
     131               0 :         if (nColType == MSSQLCOLTYPE_GEOGRAPHY)
     132                 :         {
     133               0 :             if ( chProps & SP_HASZVALUES )
     134               0 :                 poPoint = new OGRPoint( ReadY(iPoint), ReadX(iPoint), ReadZ(iPoint) );
     135                 :             else
     136               0 :                 poPoint = new OGRPoint( ReadY(iPoint), ReadX(iPoint) );
     137                 :         }
     138                 :         else
     139                 :         {
     140               0 :             if ( chProps & SP_HASZVALUES )
     141               0 :                 poPoint = new OGRPoint( ReadX(iPoint), ReadY(iPoint), ReadZ(iPoint) );
     142                 :             else
     143               0 :                 poPoint = new OGRPoint( ReadX(iPoint), ReadY(iPoint) );
     144                 :         }
     145                 : 
     146               0 :         if ( poPoint )
     147               0 :             poMultiPoint->addGeometryDirectly( poPoint );
     148                 :     }
     149                 : 
     150               0 :     return poMultiPoint;
     151                 : }
     152                 : 
     153                 : /************************************************************************/
     154                 : /*                         ReadLineString()                             */
     155                 : /************************************************************************/
     156                 : 
     157               0 : OGRLineString* OGRMSSQLGeometryParser::ReadLineString(int iShape)
     158                 : {
     159                 :     int iFigure, iPoint, iNextPoint, i;
     160               0 :     iFigure = FigureOffset(iShape);
     161                 : 
     162               0 :     OGRLineString* poLineString = new OGRLineString();
     163               0 :     iPoint = PointOffset(iFigure);
     164               0 :     iNextPoint = NextPointOffset(iFigure);
     165               0 :     poLineString->setNumPoints(iNextPoint - iPoint);
     166               0 :     i = 0;
     167               0 :     while (iPoint < iNextPoint)
     168                 :     {
     169               0 :         if (nColType == MSSQLCOLTYPE_GEOGRAPHY)
     170                 :         {
     171               0 :             if ( chProps & SP_HASZVALUES )
     172               0 :                 poLineString->setPoint(i, ReadY(iPoint), ReadX(iPoint), ReadZ(iPoint) );
     173                 :             else
     174               0 :                 poLineString->setPoint(i, ReadY(iPoint), ReadX(iPoint) );
     175                 :         }
     176                 :         else
     177                 :         {
     178               0 :             if ( chProps & SP_HASZVALUES )
     179               0 :                 poLineString->setPoint(i, ReadX(iPoint), ReadY(iPoint), ReadZ(iPoint) );
     180                 :             else
     181               0 :                 poLineString->setPoint(i, ReadX(iPoint), ReadY(iPoint) );
     182                 :         }
     183                 :         
     184               0 :         ++iPoint;
     185               0 :         ++i;
     186                 :     }
     187                 : 
     188               0 :     return poLineString;
     189                 : }
     190                 : 
     191                 : /************************************************************************/
     192                 : /*                         ReadMultiLineString()                        */
     193                 : /************************************************************************/
     194                 : 
     195               0 : OGRMultiLineString* OGRMSSQLGeometryParser::ReadMultiLineString(int iShape)
     196                 : {
     197                 :     int i;
     198               0 :     OGRMultiLineString* poMultiLineString = new OGRMultiLineString();
     199                 :     OGRGeometry* poGeom;
     200                 : 
     201               0 :     for (i = iShape + 1; i < nNumShapes; i++)
     202                 :     {
     203               0 :         poGeom = NULL;
     204               0 :         if (ParentOffset(i) == (unsigned int)iShape)
     205                 :         {
     206               0 :             if  ( ShapeType(i) == ST_LINESTRING )
     207               0 :                 poGeom = ReadLineString(i);
     208                 :         }
     209               0 :         if ( poGeom )
     210               0 :             poMultiLineString->addGeometryDirectly( poGeom );
     211                 :     }
     212                 : 
     213               0 :     return poMultiLineString;
     214                 : }
     215                 : 
     216                 : /************************************************************************/
     217                 : /*                         ReadPolygon()                                */
     218                 : /************************************************************************/
     219                 : 
     220               0 : OGRPolygon* OGRMSSQLGeometryParser::ReadPolygon(int iShape)
     221                 : {
     222                 :     int iFigure, iPoint, iNextPoint, i;
     223               0 :     int iNextFigure = NextFigureOffset(iShape);
     224                 :     
     225               0 :     OGRPolygon* poPoly = new OGRPolygon();
     226               0 :     for (iFigure = FigureOffset(iShape); iFigure < iNextFigure; iFigure++)
     227                 :     {
     228               0 :         OGRLinearRing* poRing = new OGRLinearRing();
     229               0 :         iPoint = PointOffset(iFigure);
     230               0 :         iNextPoint = NextPointOffset(iFigure);
     231               0 :         poRing->setNumPoints(iNextPoint - iPoint);
     232               0 :         i = 0;
     233               0 :         while (iPoint < iNextPoint)
     234                 :         {
     235               0 :             if (nColType == MSSQLCOLTYPE_GEOGRAPHY)
     236                 :             {  
     237               0 :                 if ( chProps & SP_HASZVALUES )
     238               0 :                     poRing->setPoint(i, ReadY(iPoint), ReadX(iPoint), ReadZ(iPoint) );
     239                 :                 else
     240               0 :                     poRing->setPoint(i, ReadY(iPoint), ReadX(iPoint) );
     241                 :             }
     242                 :             else
     243                 :             {
     244               0 :                 if ( chProps & SP_HASZVALUES )
     245               0 :                     poRing->setPoint(i, ReadX(iPoint), ReadY(iPoint), ReadZ(iPoint) );
     246                 :                 else
     247               0 :                     poRing->setPoint(i, ReadX(iPoint), ReadY(iPoint) );
     248                 :             }
     249                 : 
     250               0 :             ++iPoint;
     251               0 :             ++i;
     252                 :         }
     253               0 :         poPoly->addRingDirectly( poRing );
     254                 :     }
     255               0 :     return poPoly;
     256                 : }
     257                 : 
     258                 : /************************************************************************/
     259                 : /*                         ReadMultiPolygon()                           */
     260                 : /************************************************************************/
     261                 : 
     262               0 : OGRMultiPolygon* OGRMSSQLGeometryParser::ReadMultiPolygon(int iShape)
     263                 : {
     264                 :     int i;
     265               0 :     OGRMultiPolygon* poMultiPolygon = new OGRMultiPolygon();
     266                 :     OGRGeometry* poGeom;
     267                 : 
     268               0 :     for (i = iShape + 1; i < nNumShapes; i++)
     269                 :     {
     270               0 :         poGeom = NULL;
     271               0 :         if (ParentOffset(i) == (unsigned int)iShape)
     272                 :         {
     273               0 :             if ( ShapeType(i) == ST_POLYGON )
     274               0 :                 poGeom = ReadPolygon(i);
     275                 :         }
     276               0 :         if ( poGeom )
     277               0 :             poMultiPolygon->addGeometryDirectly( poGeom );
     278                 :     }
     279                 : 
     280               0 :     return poMultiPolygon;
     281                 : }
     282                 : 
     283                 : /************************************************************************/
     284                 : /*                         ReadGeometryCollection()                     */
     285                 : /************************************************************************/
     286                 : 
     287               0 : OGRGeometryCollection* OGRMSSQLGeometryParser::ReadGeometryCollection(int iShape)
     288                 : {
     289                 :     int i;
     290               0 :     OGRGeometryCollection* poGeomColl = new OGRGeometryCollection();
     291                 :     OGRGeometry* poGeom;
     292                 : 
     293               0 :     for (i = iShape + 1; i < nNumShapes; i++)
     294                 :     {
     295               0 :         poGeom = NULL;
     296               0 :         if (ParentOffset(i) == (unsigned int)iShape)
     297                 :         {
     298               0 :             switch (ShapeType(i))
     299                 :             {
     300                 :             case ST_POINT:
     301               0 :                 poGeom = ReadPoint(i);
     302               0 :                 break;
     303                 :             case ST_LINESTRING:
     304               0 :                 poGeom = ReadLineString(i);
     305               0 :                 break;
     306                 :             case ST_POLYGON:
     307               0 :                 poGeom = ReadPolygon(i);
     308               0 :                 break;
     309                 :             case ST_MULTIPOINT:
     310               0 :                 poGeom = ReadMultiPoint(i);
     311               0 :                 break;
     312                 :             case ST_MULTILINESTRING:
     313               0 :                 poGeom = ReadMultiLineString(i);
     314               0 :                 break;
     315                 :             case ST_MULTIPOLYGON:
     316               0 :                 poGeom = ReadMultiPolygon(i);
     317               0 :                 break;
     318                 :             case ST_GEOMETRYCOLLECTION:
     319               0 :                 poGeom = ReadGeometryCollection(i);
     320                 :                 break;
     321                 :             }
     322                 :         }
     323               0 :         if ( poGeom )
     324               0 :             poGeomColl->addGeometryDirectly( poGeom );
     325                 :     }
     326                 : 
     327               0 :     return poGeomColl;
     328                 : }
     329                 : 
     330                 : /************************************************************************/
     331                 : /*                         ParseSqlGeometry()                           */
     332                 : /************************************************************************/
     333                 : 
     334                 : 
     335               0 : OGRErr OGRMSSQLGeometryParser::ParseSqlGeometry(unsigned char* pszInput, 
     336                 :                                 int nLen, OGRGeometry **poGeom)
     337                 : {
     338               0 :     if (nLen < 10)
     339               0 :         return OGRERR_NOT_ENOUGH_DATA;
     340                 : 
     341               0 :     pszData = pszInput;
     342                 :     
     343                 :     /* store the SRS id for further use */
     344               0 :     nSRSId = ReadInt32(0);
     345                 :     
     346               0 :     if ( ReadByte(4) != 1 )
     347                 :     {
     348               0 :         return OGRERR_CORRUPT_DATA;
     349                 :     }
     350                 : 
     351               0 :     chProps = ReadByte(5);
     352                 : 
     353               0 :     if ( chProps & SP_HASMVALUES )
     354               0 :         nPointSize = 32;
     355               0 :     else if ( chProps & SP_HASZVALUES )
     356               0 :         nPointSize = 24;
     357                 :     else
     358               0 :         nPointSize = 16;
     359                 : 
     360               0 :     if ( chProps & SP_ISSINGLEPOINT )
     361                 :     {
     362                 :         // single point geometry
     363               0 :         nPointPos = 6;
     364                 : 
     365               0 :         if (nLen < 6 + nPointSize)
     366                 :         {
     367               0 :             return OGRERR_NOT_ENOUGH_DATA;
     368                 :         }
     369                 : 
     370               0 :         if (nColType == MSSQLCOLTYPE_GEOGRAPHY)
     371                 :         {
     372               0 :             if (chProps & SP_HASZVALUES)
     373               0 :                 *poGeom = new OGRPoint(ReadY(0), ReadX(0), ReadZ(0));
     374                 :             else
     375               0 :                 *poGeom = new OGRPoint(ReadY(0), ReadX(0));
     376                 :         }
     377                 :         else
     378                 :         {
     379               0 :             if (chProps & SP_HASZVALUES)
     380               0 :                 *poGeom = new OGRPoint(ReadX(0), ReadY(0), ReadZ(0));
     381                 :             else
     382               0 :                 *poGeom = new OGRPoint(ReadX(0), ReadY(0));
     383                 :         }
     384                 :     }
     385               0 :     else if ( chProps & SP_ISSINGLELINESEGMENT )
     386                 :     {
     387                 :         // single line segment with 2 points
     388               0 :         nPointPos = 6;
     389                 : 
     390               0 :         if (nLen < 6 + 2 * nPointSize)
     391                 :         {
     392               0 :             return OGRERR_NOT_ENOUGH_DATA;
     393                 :         }
     394                 : 
     395               0 :         OGRLineString* line = new OGRLineString();
     396               0 :         line->setNumPoints(2);
     397                 :         
     398               0 :         if (nColType == MSSQLCOLTYPE_GEOGRAPHY)
     399                 :         {
     400               0 :             if ( chProps & SP_HASZVALUES )
     401                 :             {
     402               0 :                 line->setPoint(0, ReadY(0), ReadX(0), ReadZ(0));
     403               0 :                 line->setPoint(1, ReadY(1), ReadX(1), ReadZ(1));
     404                 :             }
     405                 :             else
     406                 :             {
     407               0 :                 line->setPoint(0, ReadY(0), ReadX(0));
     408               0 :                 line->setPoint(1, ReadY(1), ReadX(1));
     409                 :             }
     410                 :         }
     411                 :         else
     412                 :         {
     413               0 :             if ( chProps & SP_HASZVALUES )
     414                 :             {
     415               0 :                 line->setPoint(0, ReadX(0), ReadY(0), ReadZ(0));
     416               0 :                 line->setPoint(1, ReadX(1), ReadY(1), ReadZ(1));
     417                 :             }
     418                 :             else
     419                 :             {
     420               0 :                 line->setPoint(0, ReadX(0), ReadY(0));
     421               0 :                 line->setPoint(1, ReadX(1), ReadY(1));
     422                 :             }
     423                 :         }
     424                 :         
     425               0 :         *poGeom = line;
     426                 :     }
     427                 :     else
     428                 :     {
     429                 :         // complex geometries
     430               0 :         nNumPoints = ReadInt32(6);
     431                 : 
     432               0 :         if ( nNumPoints <= 0 )
     433                 :         {
     434               0 :             return OGRERR_NONE;
     435                 :         }
     436                 : 
     437                 :         // position of the point array
     438               0 :         nPointPos = 10;
     439                 : 
     440                 :         // position of the figures
     441               0 :         nFigurePos = nPointPos + nPointSize * nNumPoints + 4;
     442                 :         
     443               0 :         if (nLen < nFigurePos)
     444                 :         {
     445               0 :             return OGRERR_NOT_ENOUGH_DATA;
     446                 :         }
     447                 : 
     448               0 :         nNumFigures = ReadInt32(nFigurePos - 4);
     449                 : 
     450               0 :         if ( nNumFigures <= 0 )
     451                 :         {
     452               0 :             return OGRERR_NONE;
     453                 :         }
     454                 :         
     455                 :         // position of the shapes
     456               0 :         nShapePos = nFigurePos + 5 * nNumFigures + 4;
     457                 : 
     458               0 :         if (nLen < nShapePos)
     459                 :         {
     460               0 :             return OGRERR_NOT_ENOUGH_DATA;
     461                 :         }
     462                 : 
     463               0 :         nNumShapes = ReadInt32(nShapePos - 4);
     464                 : 
     465               0 :         if (nLen < nShapePos + 9 * nNumShapes)
     466                 :         {
     467               0 :             return OGRERR_NOT_ENOUGH_DATA;
     468                 :         }
     469                 : 
     470               0 :         if ( nNumShapes <= 0 )
     471                 :         {
     472               0 :             return OGRERR_NONE;
     473                 :         }
     474                 : 
     475                 :         // pick up the root shape
     476               0 :         if ( ParentOffset(0) != 0xFFFFFFFF)
     477                 :         {
     478               0 :             return OGRERR_CORRUPT_DATA;
     479                 :         }
     480                 : 
     481                 :         // determine the shape type
     482               0 :         switch (ShapeType(0))
     483                 :         {
     484                 :         case ST_POINT:
     485               0 :             *poGeom = ReadPoint(0);
     486               0 :             break;
     487                 :         case ST_LINESTRING:
     488               0 :             *poGeom = ReadLineString(0);
     489               0 :             break;
     490                 :         case ST_POLYGON:
     491               0 :             *poGeom = ReadPolygon(0);
     492               0 :             break;
     493                 :         case ST_MULTIPOINT:
     494               0 :             *poGeom = ReadMultiPoint(0);
     495               0 :             break;
     496                 :         case ST_MULTILINESTRING:
     497               0 :             *poGeom = ReadMultiLineString(0);
     498               0 :             break;
     499                 :         case ST_MULTIPOLYGON:
     500               0 :             *poGeom = ReadMultiPolygon(0);
     501               0 :             break;
     502                 :         case ST_GEOMETRYCOLLECTION:
     503               0 :             *poGeom = ReadGeometryCollection(0);
     504               0 :             break;
     505                 :         default:
     506               0 :             return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
     507                 :         }
     508                 :     }
     509                 : 
     510               0 :     return OGRERR_NONE;
     511                 : }
     512                 : 

Generated by: LCOV version 1.7