LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/mssqlspatial - ogrmssqlgeometryparser.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 0 389 0.0 %
Date: 2024-11-21 22:18:42 Functions: 0 15 0.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  MSSQL Spatial driver
       4             :  * Purpose:  Implements OGRMSSQLGeometryParser class to parse native
       5             :  *SqlGeometries. Author:   Tamas Szekeres, szekerest at gmail.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2010, Tamas Szekeres
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "cpl_conv.h"
      14             : #include "ogr_mssqlspatial.h"
      15             : 
      16             : /*   SqlGeometry/SqlGeography serialization format
      17             : 
      18             : Simple Point (SerializationProps & IsSinglePoint)
      19             :   [SRID][0x01][SerializationProps][Point][z][m]
      20             : 
      21             : Simple Line Segment (SerializationProps & IsSingleLineSegment)
      22             :   [SRID][0x01][SerializationProps][Point1][Point2][z1][z2][m1][m2]
      23             : 
      24             : Complex Geometries
      25             :   [SRID][VersionAttribute][SerializationProps][NumPoints][Point1]..[PointN][z1]..[zN][m1]..[mN]
      26             :   [NumFigures][Figure]..[Figure][NumShapes][Shape]..[Shape]
      27             : 
      28             : Complex Geometries (FigureAttribute == Curve)
      29             :   [SRID][VersionAttribute][SerializationProps][NumPoints][Point1]..[PointN][z1]..[zN][m1]..[mN]
      30             :   [NumFigures][Figure]..[Figure][NumShapes][Shape]..[Shape][NumSegments][SegmentType]..[SegmentType]
      31             : 
      32             : VersionAttribute (1 byte)
      33             :   0x01 = Katmai (MSSQL2008+)
      34             :   0x02 = Denali (MSSQL2012+)
      35             : 
      36             : SRID
      37             :   Spatial Reference Id (4 bytes)
      38             : 
      39             : SerializationProps (bitmask) 1 byte
      40             :   0x01 = HasZValues
      41             :   0x02 = HasMValues
      42             :   0x04 = IsValid
      43             :   0x08 = IsSinglePoint
      44             :   0x10 = IsSingleLineSegment
      45             :   0x20 = IsLargerThanAHemisphere
      46             : 
      47             : Point (2-4)x8 bytes, size depends on SerializationProps & HasZValues &
      48             : HasMValues [x][y]                  - SqlGeometry [latitude][longitude]   -
      49             : SqlGeography
      50             : 
      51             : Figure
      52             :   [FigureAttribute][PointOffset]
      53             : 
      54             : FigureAttribute - Katmai (1 byte)
      55             :   0x00 = Interior Ring
      56             :   0x01 = Stroke
      57             :   0x02 = Exterior Ring
      58             : 
      59             : FigureAttribute - Denali (1 byte)
      60             :   0x00 = None
      61             :   0x01 = Line
      62             :   0x02 = Arc
      63             :   0x03 = Curve
      64             : 
      65             : Shape
      66             :   [ParentFigureOffset][FigureOffset][ShapeType]
      67             : 
      68             : ShapeType (1 byte)
      69             :   0x00 = Unknown
      70             :   0x01 = Point
      71             :   0x02 = LineString
      72             :   0x03 = Polygon
      73             :   0x04 = MultiPoint
      74             :   0x05 = MultiLineString
      75             :   0x06 = MultiPolygon
      76             :   0x07 = GeometryCollection
      77             :   -- Denali
      78             :   0x08 = CircularString
      79             :   0x09 = CompoundCurve
      80             :   0x0A = CurvePolygon
      81             :   0x0B = FullGlobe
      82             : 
      83             : SegmentType (1 byte)
      84             :   0x00 = Line
      85             :   0x01 = Arc
      86             :   0x02 = FirstLine
      87             :   0x03 = FirstArc
      88             : 
      89             : */
      90             : 
      91             : /************************************************************************/
      92             : /*                         Geometry parser macros                       */
      93             : /************************************************************************/
      94             : 
      95             : #define ReadInt32(nPos) (*((int *)(pszData + (nPos))))
      96             : 
      97             : #define ReadByte(nPos) (pszData[nPos])
      98             : 
      99             : #define ReadDouble(nPos) (*((double *)(pszData + (nPos))))
     100             : 
     101             : #define ParentOffset(iShape) (ReadInt32(nShapePos + (iShape)*9))
     102             : #define FigureOffset(iShape) (ReadInt32(nShapePos + (iShape)*9 + 4))
     103             : #define ShapeType(iShape) (ReadByte(nShapePos + (iShape)*9 + 8))
     104             : #define SegmentType(iSegment) (ReadByte(nSegmentPos + (iSegment)))
     105             : 
     106             : #define FigureAttribute(iFigure) (ReadByte(nFigurePos + (iFigure)*5))
     107             : #define PointOffset(iFigure) (ReadInt32(nFigurePos + (iFigure)*5 + 1))
     108             : #define NextPointOffset(iFigure)                                               \
     109             :     (iFigure + 1 < nNumFigures ? PointOffset((iFigure) + 1) : nNumPoints)
     110             : 
     111             : #define ReadX(iPoint) (ReadDouble(nPointPos + 16 * (iPoint)))
     112             : #define ReadY(iPoint) (ReadDouble(nPointPos + 16 * (iPoint) + 8))
     113             : #define ReadZ(iPoint) (ReadDouble(nPointPos + 16 * nNumPoints + 8 * (iPoint)))
     114             : #define ReadM(iPoint) (ReadDouble(nPointPos + 24 * nNumPoints + 8 * (iPoint)))
     115             : 
     116             : /************************************************************************/
     117             : /*                   OGRMSSQLGeometryParser()                           */
     118             : /************************************************************************/
     119             : 
     120           0 : OGRMSSQLGeometryParser::OGRMSSQLGeometryParser(int nGeomColumnType)
     121             : {
     122           0 :     nColType = nGeomColumnType;
     123           0 :     pszData = nullptr;
     124           0 :     chProps = 0;
     125           0 :     nPointSize = 0;
     126           0 :     nPointPos = 0;
     127           0 :     nNumPoints = 0;
     128           0 :     nFigurePos = 0;
     129           0 :     nNumFigures = 0;
     130           0 :     nShapePos = 0;
     131           0 :     nNumShapes = 0;
     132           0 :     nSegmentPos = 0;
     133           0 :     nNumSegments = 0;
     134           0 :     nSRSId = 0;
     135           0 :     chVersion = 0;
     136           0 :     iSegment = 0;
     137           0 : }
     138             : 
     139             : /************************************************************************/
     140             : /*                         ReadPoint()                                  */
     141             : /************************************************************************/
     142             : 
     143           0 : OGRPoint *OGRMSSQLGeometryParser::ReadPoint(int iFigure)
     144             : {
     145           0 :     if (iFigure == -1)
     146             :     {
     147             :         /* creating an empty point */
     148           0 :         OGRPoint *poPoint = new OGRPoint();
     149           0 :         if (chProps & SP_HASZVALUES)
     150           0 :             poPoint->setCoordinateDimension(3);
     151             : 
     152           0 :         if (chProps & SP_HASMVALUES)
     153           0 :             poPoint->setMeasured(TRUE);
     154             : 
     155           0 :         return poPoint;
     156             :     }
     157             : 
     158           0 :     if (iFigure < nNumFigures)
     159             :     {
     160           0 :         int iPoint = PointOffset(iFigure);
     161           0 :         if (iPoint < nNumPoints)
     162             :         {
     163           0 :             if (nColType == MSSQLCOLTYPE_GEOGRAPHY)
     164             :             {
     165           0 :                 if ((chProps & SP_HASZVALUES) && (chProps & SP_HASMVALUES))
     166           0 :                     return new OGRPoint(ReadY(iPoint), ReadX(iPoint),
     167           0 :                                         ReadZ(iPoint), ReadM(iPoint));
     168           0 :                 else if (chProps & SP_HASZVALUES)
     169           0 :                     return new OGRPoint(ReadY(iPoint), ReadX(iPoint),
     170           0 :                                         ReadZ(iPoint));
     171           0 :                 else if (chProps & SP_HASMVALUES)
     172             :                 {
     173             :                     OGRPoint *poPoint =
     174           0 :                         new OGRPoint(ReadY(iPoint), ReadX(iPoint));
     175           0 :                     poPoint->setM(ReadZ(iPoint));
     176           0 :                     return poPoint;
     177             :                 }
     178             :                 else
     179           0 :                     return new OGRPoint(ReadY(iPoint), ReadX(iPoint));
     180             :             }
     181             :             else
     182             :             {
     183           0 :                 if ((chProps & SP_HASZVALUES) && (chProps & SP_HASMVALUES))
     184           0 :                     return new OGRPoint(ReadX(iPoint), ReadY(iPoint),
     185           0 :                                         ReadZ(iPoint), ReadM(iPoint));
     186           0 :                 else if (chProps & SP_HASZVALUES)
     187           0 :                     return new OGRPoint(ReadX(iPoint), ReadY(iPoint),
     188           0 :                                         ReadZ(iPoint));
     189           0 :                 else if (chProps & SP_HASMVALUES)
     190             :                 {
     191             :                     OGRPoint *poPoint =
     192           0 :                         new OGRPoint(ReadX(iPoint), ReadY(iPoint));
     193           0 :                     poPoint->setM(ReadZ(iPoint));
     194           0 :                     return poPoint;
     195             :                 }
     196             :                 else
     197           0 :                     return new OGRPoint(ReadX(iPoint), ReadY(iPoint));
     198             :             }
     199             :         }
     200             :     }
     201           0 :     return nullptr;
     202             : }
     203             : 
     204             : /************************************************************************/
     205             : /*                         ReadMultiPoint()                             */
     206             : /************************************************************************/
     207             : 
     208           0 : OGRMultiPoint *OGRMSSQLGeometryParser::ReadMultiPoint(int iShape)
     209             : {
     210           0 :     OGRMultiPoint *poMultiPoint = new OGRMultiPoint();
     211             :     OGRGeometry *poGeom;
     212             : 
     213           0 :     for (int i = iShape + 1; i < nNumShapes; i++)
     214             :     {
     215           0 :         poGeom = nullptr;
     216           0 :         if (ParentOffset(i) == iShape)
     217             :         {
     218           0 :             if (ShapeType(i) == ST_POINT)
     219           0 :                 poGeom = ReadPoint(FigureOffset(i));
     220             :         }
     221           0 :         if (poGeom)
     222           0 :             poMultiPoint->addGeometryDirectly(poGeom);
     223             :     }
     224             : 
     225           0 :     return poMultiPoint;
     226             : }
     227             : 
     228             : /************************************************************************/
     229             : /*                         ReadSimpleCurve()                            */
     230             : /************************************************************************/
     231             : 
     232           0 : OGRErr OGRMSSQLGeometryParser::ReadSimpleCurve(OGRSimpleCurve *poCurve,
     233             :                                                int iPoint, int iNextPoint)
     234             : {
     235           0 :     if (iPoint >= iNextPoint)
     236           0 :         return OGRERR_NOT_ENOUGH_DATA;
     237             : 
     238           0 :     poCurve->setNumPoints(iNextPoint - iPoint);
     239           0 :     int i = 0;
     240           0 :     while (iPoint < iNextPoint)
     241             :     {
     242           0 :         if (nColType == MSSQLCOLTYPE_GEOGRAPHY)
     243             :         {
     244           0 :             if ((chProps & SP_HASZVALUES) && (chProps & SP_HASMVALUES))
     245           0 :                 poCurve->setPoint(i, ReadY(iPoint), ReadX(iPoint),
     246           0 :                                   ReadZ(iPoint), ReadM(iPoint));
     247           0 :             else if (chProps & SP_HASZVALUES)
     248           0 :                 poCurve->setPoint(i, ReadY(iPoint), ReadX(iPoint),
     249           0 :                                   ReadZ(iPoint));
     250           0 :             else if (chProps & SP_HASMVALUES)
     251           0 :                 poCurve->setPointM(i, ReadY(iPoint), ReadX(iPoint),
     252           0 :                                    ReadZ(iPoint));
     253             :             else
     254           0 :                 poCurve->setPoint(i, ReadY(iPoint), ReadX(iPoint));
     255             :         }
     256             :         else
     257             :         {
     258           0 :             if ((chProps & SP_HASZVALUES) && (chProps & SP_HASMVALUES))
     259           0 :                 poCurve->setPoint(i, ReadX(iPoint), ReadY(iPoint),
     260           0 :                                   ReadZ(iPoint), ReadM(iPoint));
     261           0 :             else if (chProps & SP_HASZVALUES)
     262           0 :                 poCurve->setPoint(i, ReadX(iPoint), ReadY(iPoint),
     263           0 :                                   ReadZ(iPoint));
     264           0 :             else if (chProps & SP_HASMVALUES)
     265           0 :                 poCurve->setPointM(i, ReadX(iPoint), ReadY(iPoint),
     266           0 :                                    ReadZ(iPoint));
     267             :             else
     268           0 :                 poCurve->setPoint(i, ReadX(iPoint), ReadY(iPoint));
     269             :         }
     270             : 
     271           0 :         ++iPoint;
     272           0 :         ++i;
     273             :     }
     274             : 
     275           0 :     return OGRERR_NONE;
     276             : }
     277             : 
     278             : /************************************************************************/
     279             : /*                         ReadLineString()                             */
     280             : /************************************************************************/
     281             : 
     282           0 : OGRLineString *OGRMSSQLGeometryParser::ReadLineString(int iFigure)
     283             : {
     284           0 :     OGRLineString *poLineString = new OGRLineString();
     285           0 :     if (iFigure == -1)
     286             :     {
     287           0 :         if (chProps & SP_HASZVALUES)
     288           0 :             poLineString->setCoordinateDimension(3);
     289             : 
     290           0 :         if (chProps & SP_HASMVALUES)
     291           0 :             poLineString->setMeasured(TRUE);
     292             :     }
     293             :     else
     294           0 :         ReadSimpleCurve(poLineString, PointOffset(iFigure),
     295           0 :                         NextPointOffset(iFigure));
     296             : 
     297           0 :     return poLineString;
     298             : }
     299             : 
     300             : /************************************************************************/
     301             : /*                         ReadLinearRing()                             */
     302             : /************************************************************************/
     303             : 
     304           0 : OGRLinearRing *OGRMSSQLGeometryParser::ReadLinearRing(int iFigure)
     305             : {
     306           0 :     OGRLinearRing *poLinearRing = new OGRLinearRing();
     307           0 :     ReadSimpleCurve(poLinearRing, PointOffset(iFigure),
     308           0 :                     NextPointOffset(iFigure));
     309           0 :     return poLinearRing;
     310             : }
     311             : 
     312             : /************************************************************************/
     313             : /*                         ReadCircularString()                         */
     314             : /************************************************************************/
     315             : 
     316           0 : OGRCircularString *OGRMSSQLGeometryParser::ReadCircularString(int iFigure)
     317             : {
     318           0 :     OGRCircularString *poCircularString = new OGRCircularString();
     319           0 :     if (iFigure == -1)
     320             :     {
     321           0 :         if (chProps & SP_HASZVALUES)
     322           0 :             poCircularString->setCoordinateDimension(3);
     323             : 
     324           0 :         if (chProps & SP_HASMVALUES)
     325           0 :             poCircularString->setMeasured(TRUE);
     326             :     }
     327             :     else
     328           0 :         ReadSimpleCurve(poCircularString, PointOffset(iFigure),
     329           0 :                         NextPointOffset(iFigure));
     330             : 
     331           0 :     return poCircularString;
     332             : }
     333             : 
     334             : /************************************************************************/
     335             : /*                         ReadMultiLineString()                        */
     336             : /************************************************************************/
     337             : 
     338           0 : OGRMultiLineString *OGRMSSQLGeometryParser::ReadMultiLineString(int iShape)
     339             : {
     340           0 :     OGRMultiLineString *poMultiLineString = new OGRMultiLineString();
     341             :     OGRGeometry *poGeom;
     342             : 
     343           0 :     for (int i = iShape + 1; i < nNumShapes; i++)
     344             :     {
     345           0 :         poGeom = nullptr;
     346           0 :         if (ParentOffset(i) == iShape)
     347             :         {
     348           0 :             if (ShapeType(i) == ST_LINESTRING)
     349           0 :                 poGeom = ReadLineString(FigureOffset(i));
     350             :         }
     351           0 :         if (poGeom)
     352           0 :             poMultiLineString->addGeometryDirectly(poGeom);
     353             :     }
     354             : 
     355           0 :     return poMultiLineString;
     356             : }
     357             : 
     358             : /************************************************************************/
     359             : /*                         ReadPolygon()                                */
     360             : /************************************************************************/
     361             : 
     362           0 : OGRPolygon *OGRMSSQLGeometryParser::ReadPolygon(int iShape)
     363             : {
     364             :     int iFigure, iNextFigure;
     365             : 
     366           0 :     OGRPolygon *poPoly = new OGRPolygon();
     367             : 
     368           0 :     if ((iFigure = FigureOffset(iShape)) == -1)
     369           0 :         return poPoly;
     370             : 
     371             :     /* find next shape that has a figure */
     372           0 :     iNextFigure = -1;
     373           0 :     while (++iShape < nNumShapes)
     374             :     {
     375           0 :         if ((iNextFigure = FigureOffset(iShape)) != -1)
     376           0 :             break;
     377             :     }
     378           0 :     if (iNextFigure == -1)
     379           0 :         iNextFigure = nNumFigures;
     380             : 
     381           0 :     while (iFigure < iNextFigure)
     382             :     {
     383           0 :         poPoly->addRingDirectly(ReadLinearRing(iFigure));
     384           0 :         ++iFigure;
     385             :     }
     386             : 
     387           0 :     poPoly->closeRings();
     388           0 :     return poPoly;
     389             : }
     390             : 
     391             : /************************************************************************/
     392             : /*                         ReadMultiPolygon()                           */
     393             : /************************************************************************/
     394             : 
     395           0 : OGRMultiPolygon *OGRMSSQLGeometryParser::ReadMultiPolygon(int iShape)
     396             : {
     397           0 :     OGRMultiPolygon *poMultiPolygon = new OGRMultiPolygon();
     398             :     OGRGeometry *poGeom;
     399             : 
     400           0 :     for (int i = iShape + 1; i < nNumShapes; i++)
     401             :     {
     402           0 :         poGeom = nullptr;
     403           0 :         if (ParentOffset(i) == iShape)
     404             :         {
     405           0 :             if (ShapeType(i) == ST_POLYGON)
     406           0 :                 poGeom = ReadPolygon(i);
     407             :         }
     408           0 :         if (poGeom)
     409           0 :             poMultiPolygon->addGeometryDirectly(poGeom);
     410             :     }
     411             : 
     412           0 :     return poMultiPolygon;
     413             : }
     414             : 
     415             : /************************************************************************/
     416             : /*                         AddCurveSegment()                            */
     417             : /************************************************************************/
     418             : 
     419           0 : void OGRMSSQLGeometryParser::AddCurveSegment(OGRCompoundCurve *poCompoundCurve,
     420             :                                              OGRSimpleCurve *poCurve,
     421             :                                              int iPoint, int iNextPoint)
     422             : {
     423           0 :     if (poCurve != nullptr)
     424             :     {
     425           0 :         if (iPoint < iNextPoint)
     426             :         {
     427           0 :             ReadSimpleCurve(poCurve, iPoint, iNextPoint);
     428           0 :             poCompoundCurve->addCurveDirectly(poCurve);
     429             :         }
     430             :         else
     431           0 :             delete poCurve;
     432             :     }
     433           0 : }
     434             : 
     435             : /************************************************************************/
     436             : /*                         ReadCompoundCurve()                          */
     437             : /************************************************************************/
     438             : 
     439           0 : OGRCompoundCurve *OGRMSSQLGeometryParser::ReadCompoundCurve(int iFigure)
     440             : {
     441             :     int iPoint, iNextPoint, nPointsPrepared;
     442           0 :     OGRCompoundCurve *poCompoundCurve = new OGRCompoundCurve();
     443             : 
     444           0 :     if (iFigure == -1)
     445             :     {
     446           0 :         if (chProps & SP_HASZVALUES)
     447           0 :             poCompoundCurve->setCoordinateDimension(3);
     448             : 
     449           0 :         if (chProps & SP_HASMVALUES)
     450           0 :             poCompoundCurve->setMeasured(TRUE);
     451             : 
     452           0 :         return poCompoundCurve;
     453             :     }
     454             : 
     455           0 :     iPoint = PointOffset(iFigure);
     456           0 :     iNextPoint = NextPointOffset(iFigure) - 1;
     457             : 
     458           0 :     OGRSimpleCurve *poCurve = nullptr;
     459             : 
     460           0 :     nPointsPrepared = 0;
     461           0 :     while (iPoint < iNextPoint && iSegment < nNumSegments)
     462             :     {
     463           0 :         switch (SegmentType(iSegment))
     464             :         {
     465           0 :             case SMT_FIRSTLINE:
     466           0 :                 AddCurveSegment(poCompoundCurve, poCurve,
     467             :                                 iPoint - nPointsPrepared, iPoint + 1);
     468           0 :                 poCurve = new OGRLineString();
     469           0 :                 nPointsPrepared = 1;
     470           0 :                 ++iPoint;
     471           0 :                 break;
     472           0 :             case SMT_LINE:
     473           0 :                 ++nPointsPrepared;
     474           0 :                 ++iPoint;
     475           0 :                 break;
     476           0 :             case SMT_FIRSTARC:
     477           0 :                 AddCurveSegment(poCompoundCurve, poCurve,
     478             :                                 iPoint - nPointsPrepared, iPoint + 1);
     479           0 :                 poCurve = new OGRCircularString();
     480           0 :                 nPointsPrepared = 2;
     481           0 :                 iPoint += 2;
     482           0 :                 break;
     483           0 :             case SMT_ARC:
     484           0 :                 nPointsPrepared += 2;
     485           0 :                 iPoint += 2;
     486           0 :                 break;
     487             :         }
     488           0 :         ++iSegment;
     489             :     }
     490             : 
     491             :     // adding the last curve
     492           0 :     if (iPoint == iNextPoint)
     493           0 :         AddCurveSegment(poCompoundCurve, poCurve, iPoint - nPointsPrepared,
     494             :                         iPoint + 1);
     495             :     else
     496           0 :         delete poCurve;
     497             : 
     498           0 :     return poCompoundCurve;
     499             : }
     500             : 
     501             : /************************************************************************/
     502             : /*                         ReadCurvePolygon()                         */
     503             : /************************************************************************/
     504             : 
     505           0 : OGRCurvePolygon *OGRMSSQLGeometryParser::ReadCurvePolygon(int iShape)
     506             : {
     507             :     int iFigure, iNextFigure;
     508             : 
     509           0 :     OGRCurvePolygon *poPoly = new OGRCurvePolygon();
     510             : 
     511           0 :     if ((iFigure = FigureOffset(iShape)) == -1)
     512           0 :         return poPoly;
     513             : 
     514             :     /* find next shape that has a figure */
     515           0 :     iNextFigure = -1;
     516           0 :     while (++iShape < nNumShapes)
     517             :     {
     518           0 :         if ((iNextFigure = FigureOffset(iShape)) != -1)
     519           0 :             break;
     520             :     }
     521           0 :     if (iNextFigure == -1)
     522           0 :         iNextFigure = nNumFigures;
     523             : 
     524           0 :     while (iFigure < iNextFigure)
     525             :     {
     526           0 :         switch (FigureAttribute(iFigure))
     527             :         {
     528           0 :             case FA_LINE:
     529           0 :                 poPoly->addRingDirectly(ReadLineString(iFigure));
     530           0 :                 break;
     531           0 :             case FA_ARC:
     532           0 :                 poPoly->addRingDirectly(ReadCircularString(iFigure));
     533           0 :                 break;
     534           0 :             case FA_CURVE:
     535           0 :                 poPoly->addRingDirectly(ReadCompoundCurve(iFigure));
     536           0 :                 break;
     537             :         }
     538           0 :         ++iFigure;
     539             :     }
     540           0 :     poPoly->closeRings();
     541           0 :     return poPoly;
     542             : }
     543             : 
     544             : /************************************************************************/
     545             : /*                         ReadGeometryCollection()                     */
     546             : /************************************************************************/
     547             : 
     548             : OGRGeometryCollection *
     549           0 : OGRMSSQLGeometryParser::ReadGeometryCollection(int iShape)
     550             : {
     551           0 :     OGRGeometryCollection *poGeomColl = new OGRGeometryCollection();
     552             :     OGRGeometry *poGeom;
     553             : 
     554           0 :     for (int i = iShape + 1; i < nNumShapes; i++)
     555             :     {
     556           0 :         poGeom = nullptr;
     557           0 :         if (ParentOffset(i) == iShape)
     558             :         {
     559           0 :             switch (ShapeType(i))
     560             :             {
     561           0 :                 case ST_POINT:
     562           0 :                     poGeom = ReadPoint(FigureOffset(i));
     563           0 :                     break;
     564           0 :                 case ST_LINESTRING:
     565           0 :                     poGeom = ReadLineString(FigureOffset(i));
     566           0 :                     break;
     567           0 :                 case ST_POLYGON:
     568           0 :                     poGeom = ReadPolygon(i);
     569           0 :                     break;
     570           0 :                 case ST_MULTIPOINT:
     571           0 :                     poGeom = ReadMultiPoint(i);
     572           0 :                     break;
     573           0 :                 case ST_MULTILINESTRING:
     574           0 :                     poGeom = ReadMultiLineString(i);
     575           0 :                     break;
     576           0 :                 case ST_MULTIPOLYGON:
     577           0 :                     poGeom = ReadMultiPolygon(i);
     578           0 :                     break;
     579           0 :                 case ST_GEOMETRYCOLLECTION:
     580           0 :                     poGeom = ReadGeometryCollection(i);
     581           0 :                     break;
     582           0 :                 case ST_CIRCULARSTRING:
     583           0 :                     poGeom = ReadCircularString(FigureOffset(i));
     584           0 :                     break;
     585           0 :                 case ST_COMPOUNDCURVE:
     586           0 :                     poGeom = ReadCompoundCurve(FigureOffset(i));
     587           0 :                     break;
     588           0 :                 case ST_CURVEPOLYGON:
     589           0 :                     poGeom = ReadCurvePolygon(i);
     590           0 :                     break;
     591             :             }
     592             :         }
     593           0 :         if (poGeom)
     594           0 :             poGeomColl->addGeometryDirectly(poGeom);
     595             :     }
     596             : 
     597           0 :     return poGeomColl;
     598             : }
     599             : 
     600             : /************************************************************************/
     601             : /*                         ParseSqlGeometry()                           */
     602             : /************************************************************************/
     603             : 
     604           0 : OGRErr OGRMSSQLGeometryParser::ParseSqlGeometry(unsigned char *pszInput,
     605             :                                                 int nLen, OGRGeometry **poGeom)
     606             : {
     607           0 :     if (nLen < 10)
     608           0 :         return OGRERR_NOT_ENOUGH_DATA;
     609             : 
     610           0 :     pszData = pszInput;
     611             : 
     612             :     /* store the SRS id for further use */
     613           0 :     nSRSId = ReadInt32(0);
     614             : 
     615           0 :     chVersion = ReadByte(4);
     616             : 
     617           0 :     if (chVersion == 0 || chVersion > 2)
     618             :     {
     619           0 :         return OGRERR_CORRUPT_DATA;
     620             :     }
     621             : 
     622           0 :     chProps = ReadByte(5);
     623             : 
     624           0 :     nPointSize = 16;
     625             : 
     626           0 :     if (chProps & SP_HASZVALUES)
     627           0 :         nPointSize += 8;
     628             : 
     629           0 :     if (chProps & SP_HASMVALUES)
     630           0 :         nPointSize += 8;
     631             : 
     632           0 :     if (chProps & SP_ISSINGLEPOINT)
     633             :     {
     634             :         // single point geometry
     635           0 :         nNumPoints = 1;
     636           0 :         nPointPos = 6;
     637             : 
     638           0 :         if (nLen < 6 + nPointSize)
     639             :         {
     640           0 :             return OGRERR_NOT_ENOUGH_DATA;
     641             :         }
     642             : 
     643           0 :         if (nColType == MSSQLCOLTYPE_GEOGRAPHY)
     644             :         {
     645           0 :             if ((chProps & SP_HASZVALUES) && (chProps & SP_HASMVALUES))
     646           0 :                 *poGeom = new OGRPoint(ReadY(0), ReadX(0), ReadZ(0), ReadM(0));
     647           0 :             else if (chProps & SP_HASZVALUES)
     648           0 :                 *poGeom = new OGRPoint(ReadY(0), ReadX(0), ReadZ(0));
     649           0 :             else if (chProps & SP_HASMVALUES)
     650             :             {
     651           0 :                 *poGeom = new OGRPoint(ReadY(0), ReadX(0));
     652           0 :                 ((OGRPoint *)(*poGeom))->setM(ReadZ(0));
     653             :             }
     654             :             else
     655           0 :                 *poGeom = new OGRPoint(ReadY(0), ReadX(0));
     656             :         }
     657             :         else
     658             :         {
     659           0 :             if ((chProps & SP_HASZVALUES) && (chProps & SP_HASMVALUES))
     660           0 :                 *poGeom = new OGRPoint(ReadX(0), ReadY(0), ReadZ(0), ReadM(0));
     661           0 :             else if (chProps & SP_HASZVALUES)
     662           0 :                 *poGeom = new OGRPoint(ReadX(0), ReadY(0), ReadZ(0));
     663           0 :             else if (chProps & SP_HASMVALUES)
     664             :             {
     665           0 :                 *poGeom = new OGRPoint(ReadX(0), ReadY(0));
     666           0 :                 ((OGRPoint *)(*poGeom))->setM(ReadZ(0));
     667             :             }
     668             :             else
     669           0 :                 *poGeom = new OGRPoint(ReadX(0), ReadY(0));
     670             :         }
     671             :     }
     672           0 :     else if (chProps & SP_ISSINGLELINESEGMENT)
     673             :     {
     674             :         // single line segment with 2 points
     675           0 :         nNumPoints = 2;
     676           0 :         nPointPos = 6;
     677             : 
     678           0 :         if (nLen < 6 + 2 * nPointSize)
     679             :         {
     680           0 :             return OGRERR_NOT_ENOUGH_DATA;
     681             :         }
     682             : 
     683           0 :         OGRLineString *line = new OGRLineString();
     684           0 :         line->setNumPoints(2);
     685             : 
     686           0 :         if (nColType == MSSQLCOLTYPE_GEOGRAPHY)
     687             :         {
     688           0 :             if ((chProps & SP_HASZVALUES) && (chProps & SP_HASMVALUES))
     689             :             {
     690           0 :                 line->setPoint(0, ReadY(0), ReadX(0), ReadZ(0), ReadM(0));
     691           0 :                 line->setPoint(1, ReadY(1), ReadX(1), ReadZ(1), ReadM(1));
     692             :             }
     693           0 :             else if (chProps & SP_HASZVALUES)
     694             :             {
     695           0 :                 line->setPoint(0, ReadY(0), ReadX(0), ReadZ(0));
     696           0 :                 line->setPoint(1, ReadY(1), ReadX(1), ReadZ(1));
     697             :             }
     698           0 :             else if (chProps & SP_HASMVALUES)
     699             :             {
     700           0 :                 line->setPointM(0, ReadY(0), ReadX(0), ReadZ(0));
     701           0 :                 line->setPointM(1, ReadY(1), ReadX(1), ReadZ(1));
     702             :             }
     703             :             else
     704             :             {
     705           0 :                 line->setPoint(0, ReadY(0), ReadX(0));
     706           0 :                 line->setPoint(1, ReadY(1), ReadX(1));
     707             :             }
     708             :         }
     709             :         else
     710             :         {
     711           0 :             if ((chProps & SP_HASZVALUES) && (chProps & SP_HASMVALUES))
     712             :             {
     713           0 :                 line->setPoint(0, ReadX(0), ReadY(0), ReadZ(0), ReadM(0));
     714           0 :                 line->setPoint(1, ReadX(1), ReadY(1), ReadZ(1), ReadM(1));
     715             :             }
     716           0 :             else if (chProps & SP_HASZVALUES)
     717             :             {
     718           0 :                 line->setPoint(0, ReadX(0), ReadY(0), ReadZ(0));
     719           0 :                 line->setPoint(1, ReadX(1), ReadY(1), ReadZ(1));
     720             :             }
     721           0 :             else if (chProps & SP_HASMVALUES)
     722             :             {
     723           0 :                 line->setPointM(0, ReadX(0), ReadY(0), ReadZ(0));
     724           0 :                 line->setPointM(1, ReadX(1), ReadY(1), ReadZ(1));
     725             :             }
     726             :             else
     727             :             {
     728           0 :                 line->setPoint(0, ReadX(0), ReadY(0));
     729           0 :                 line->setPoint(1, ReadX(1), ReadY(1));
     730             :             }
     731             :         }
     732             : 
     733           0 :         *poGeom = line;
     734             :     }
     735             :     else
     736             :     {
     737             :         // complex geometries
     738           0 :         nNumPoints = ReadInt32(6);
     739             : 
     740           0 :         if (nNumPoints < 0)
     741             :         {
     742           0 :             return OGRERR_NONE;
     743             :         }
     744             : 
     745             :         // position of the point array
     746           0 :         nPointPos = 10;
     747             : 
     748             :         // position of the figures
     749           0 :         nFigurePos = nPointPos + nPointSize * nNumPoints + 4;
     750             : 
     751           0 :         if (nLen < nFigurePos)
     752             :         {
     753           0 :             return OGRERR_NOT_ENOUGH_DATA;
     754             :         }
     755             : 
     756           0 :         nNumFigures = ReadInt32(nFigurePos - 4);
     757             : 
     758           0 :         if (nNumFigures < 0)
     759             :         {
     760           0 :             return OGRERR_NONE;
     761             :         }
     762             : 
     763             :         // position of the shapes
     764           0 :         nShapePos = nFigurePos + 5 * nNumFigures + 4;
     765             : 
     766           0 :         if (nLen < nShapePos)
     767             :         {
     768           0 :             return OGRERR_NOT_ENOUGH_DATA;
     769             :         }
     770             : 
     771           0 :         nNumShapes = ReadInt32(nShapePos - 4);
     772             : 
     773           0 :         if (nLen < nShapePos + 9 * nNumShapes)
     774             :         {
     775           0 :             return OGRERR_NOT_ENOUGH_DATA;
     776             :         }
     777             : 
     778           0 :         if (nNumShapes <= 0)
     779             :         {
     780           0 :             return OGRERR_NONE;
     781             :         }
     782             : 
     783             :         // position of the segments (for complex curve figures)
     784           0 :         if (chVersion == 0x02)
     785             :         {
     786           0 :             iSegment = 0;
     787           0 :             nSegmentPos = nShapePos + 9 * nNumShapes + 4;
     788           0 :             if (nLen > nSegmentPos)
     789             :             {
     790             :                 // segment array is present
     791           0 :                 nNumSegments = ReadInt32(nSegmentPos - 4);
     792           0 :                 if (nLen < nSegmentPos + nNumSegments)
     793             :                 {
     794           0 :                     return OGRERR_NOT_ENOUGH_DATA;
     795             :                 }
     796             :             }
     797             :         }
     798             : 
     799             :         // pick up the root shape
     800           0 :         if (ParentOffset(0) != -1)
     801             :         {
     802           0 :             return OGRERR_CORRUPT_DATA;
     803             :         }
     804             : 
     805             :         // determine the shape type
     806           0 :         switch (ShapeType(0))
     807             :         {
     808           0 :             case ST_POINT:
     809           0 :                 *poGeom = ReadPoint(FigureOffset(0));
     810           0 :                 break;
     811           0 :             case ST_LINESTRING:
     812           0 :                 *poGeom = ReadLineString(FigureOffset(0));
     813           0 :                 break;
     814           0 :             case ST_POLYGON:
     815           0 :                 *poGeom = ReadPolygon(0);
     816           0 :                 break;
     817           0 :             case ST_MULTIPOINT:
     818           0 :                 *poGeom = ReadMultiPoint(0);
     819           0 :                 break;
     820           0 :             case ST_MULTILINESTRING:
     821           0 :                 *poGeom = ReadMultiLineString(0);
     822           0 :                 break;
     823           0 :             case ST_MULTIPOLYGON:
     824           0 :                 *poGeom = ReadMultiPolygon(0);
     825           0 :                 break;
     826           0 :             case ST_GEOMETRYCOLLECTION:
     827           0 :                 *poGeom = ReadGeometryCollection(0);
     828           0 :                 break;
     829           0 :             case ST_CIRCULARSTRING:
     830           0 :                 *poGeom = ReadCircularString(FigureOffset(0));
     831           0 :                 break;
     832           0 :             case ST_COMPOUNDCURVE:
     833           0 :                 *poGeom = ReadCompoundCurve(FigureOffset(0));
     834           0 :                 break;
     835           0 :             case ST_CURVEPOLYGON:
     836           0 :                 *poGeom = ReadCurvePolygon(0);
     837           0 :                 break;
     838           0 :             default:
     839           0 :                 return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
     840             :         }
     841             :     }
     842             : 
     843           0 :     return OGRERR_NONE;
     844             : }
     845             : 
     846             : #undef ParentOffset
     847             : #undef FigureOffset
     848             : #undef ShapeType
     849             : #undef SegmentType
     850             : 
     851             : #undef FigureAttribute
     852             : #undef PointOffset
     853             : #undef NextPointOffset

Generated by: LCOV version 1.14