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

Generated by: LCOV version 1.14