LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/sxf - ogrsxflayer.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 468 835 56.0 %
Date: 2024-04-27 17:22:41 Functions: 21 21 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  SXF Translator
       4             :  * Purpose:  Definition of classes for OGR SXF Layers.
       5             :  * Author:   Ben Ahmed Daho Ali, bidandou(at)yahoo(dot)fr
       6             :  *           Dmitry Baryshnikov, polimax@mail.ru
       7             :  *           Alexandr Lisovenko, alexander.lisovenko@gmail.com
       8             :  *
       9             :  ******************************************************************************
      10             :  * Copyright (c) 2011, Ben Ahmed Daho Ali
      11             :  * Copyright (c) 2013, NextGIS
      12             :  * Copyright (c) 2014, Even Rouault <even dot rouault at spatialys.com>
      13             :  *
      14             :  * Permission is hereby granted, free of charge, to any person obtaining a
      15             :  * copy of this software and associated documentation files (the "Software"),
      16             :  * to deal in the Software without restriction, including without limitation
      17             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      18             :  * and/or sell copies of the Software, and to permit persons to whom the
      19             :  * Software is furnished to do so, subject to the following conditions:
      20             :  *
      21             :  * The above copyright notice and this permission notice shall be included
      22             :  * in all copies or substantial portions of the Software.
      23             :  *
      24             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      25             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      26             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      27             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      28             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      29             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      30             :  * DEALINGS IN THE SOFTWARE.
      31             :  ****************************************************************************/
      32             : 
      33             : #include "ogr_sxf.h"
      34             : #include "cpl_conv.h"
      35             : #include "cpl_string.h"
      36             : #include "ogr_p.h"
      37             : #include "ogr_srs_api.h"
      38             : #include "cpl_multiproc.h"
      39             : 
      40             : /************************************************************************/
      41             : /*                        OGRSXFLayer()                                 */
      42             : /************************************************************************/
      43             : 
      44          82 : OGRSXFLayer::OGRSXFLayer(VSILFILE *fp, CPLMutex **hIOMutex, GByte nID,
      45             :                          const char *pszLayerName, int nVer,
      46          82 :                          const SXFMapDescription &sxfMapDesc)
      47          82 :     : OGRLayer(), poFeatureDefn(new OGRFeatureDefn(pszLayerName)), fpSXF(fp),
      48             :       nLayerID(nID), stSXFMapDescription(sxfMapDesc), m_nSXFFormatVer(nVer),
      49             :       sFIDColumn_("ogc_fid"), m_hIOMutex(hIOMutex),
      50          82 :       m_dfCoeff(sxfMapDesc.nResolution == 0
      51           0 :                     ? 0.0
      52         164 :                     : sxfMapDesc.dfScale / sxfMapDesc.nResolution)
      53             : {
      54          82 :     stSXFMapDescription.pSpatRef->Reference();
      55          82 :     oNextIt = mnRecordDesc.begin();
      56          82 :     SetDescription(poFeatureDefn->GetName());
      57          82 :     poFeatureDefn->Reference();
      58             : 
      59          82 :     poFeatureDefn->SetGeomType(wkbUnknown);
      60          82 :     if (poFeatureDefn->GetGeomFieldCount() != 0)
      61          82 :         poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(
      62          82 :             stSXFMapDescription.pSpatRef);
      63             : 
      64         164 :     OGRFieldDefn oFIDField(sFIDColumn_, OFTInteger);
      65          82 :     poFeatureDefn->AddFieldDefn(&oFIDField);
      66             : 
      67         164 :     OGRFieldDefn oClCodeField("CLCODE", OFTInteger);
      68          82 :     oClCodeField.SetWidth(10);
      69          82 :     poFeatureDefn->AddFieldDefn(&oClCodeField);
      70             : 
      71         164 :     OGRFieldDefn oClNameField("CLNAME", OFTString);
      72          82 :     oClNameField.SetWidth(32);
      73          82 :     poFeatureDefn->AddFieldDefn(&oClNameField);
      74             : 
      75         164 :     OGRFieldDefn oNumField("OBJECTNUMB", OFTInteger);
      76          82 :     oNumField.SetWidth(10);
      77          82 :     poFeatureDefn->AddFieldDefn(&oNumField);
      78             : 
      79         164 :     OGRFieldDefn oAngField("ANGLE", OFTReal);
      80          82 :     poFeatureDefn->AddFieldDefn(&oAngField);
      81             : 
      82         164 :     OGRFieldDefn oTextField("TEXT", OFTString);
      83          82 :     oTextField.SetWidth(255);
      84          82 :     poFeatureDefn->AddFieldDefn(&oTextField);
      85          82 : }
      86             : 
      87             : /************************************************************************/
      88             : /*                         ~OGRSXFLayer()                               */
      89             : /************************************************************************/
      90             : 
      91         164 : OGRSXFLayer::~OGRSXFLayer()
      92             : {
      93          82 :     stSXFMapDescription.pSpatRef->Release();
      94          82 :     poFeatureDefn->Release();
      95         164 : }
      96             : 
      97             : /************************************************************************/
      98             : /*                AddClassifyCode(unsigned nClassCode)                  */
      99             : /* Add layer supported classify codes. Only records with this code can  */
     100             : /* be in layer                                                          */
     101             : /************************************************************************/
     102             : 
     103        2155 : void OGRSXFLayer::AddClassifyCode(unsigned nClassCode, const char *szName)
     104             : {
     105        2155 :     if (szName != nullptr)
     106             :     {
     107        2140 :         mnClassificators[nClassCode] = CPLString(szName);
     108             :     }
     109             :     else
     110             :     {
     111          15 :         mnClassificators[nClassCode] = CPLString().Printf("%d", nClassCode);
     112             :     }
     113        2155 : }
     114             : 
     115             : /************************************************************************/
     116             : /*                           AddRecord()                                */
     117             : /************************************************************************/
     118             : 
     119        4643 : bool OGRSXFLayer::AddRecord(long nFID, unsigned nClassCode,
     120             :                             vsi_l_offset nOffset, bool bHasSemantic,
     121             :                             size_t nSemanticsSize)
     122             : {
     123        9085 :     if (mnClassificators.find(nClassCode) != mnClassificators.end() ||
     124        4442 :         EQUAL(GetName(), "Not_Classified"))
     125             :     {
     126         390 :         mnRecordDesc[nFID] = nOffset;
     127             :         // Add additional semantics (attribute fields).
     128         390 :         if (bHasSemantic)
     129             :         {
     130         250 :             size_t offset = 0;
     131             : 
     132         610 :             while (offset < nSemanticsSize)
     133             :             {
     134             :                 SXFRecordAttributeInfo stAttrInfo;
     135         360 :                 bool bAddField = false;
     136         360 :                 size_t nCurrOff = 0;
     137             :                 int nReadObj =
     138         360 :                     static_cast<int>(VSIFReadL(&stAttrInfo, 4, 1, fpSXF));
     139         360 :                 if (nReadObj == 1)
     140             :                 {
     141         360 :                     CPL_LSBPTR16(&(stAttrInfo.nCode));
     142         720 :                     CPLString oFieldName;
     143         360 :                     if (snAttributeCodes.find(stAttrInfo.nCode) ==
     144         720 :                         snAttributeCodes.end())
     145             :                     {
     146         142 :                         bAddField = true;
     147         142 :                         snAttributeCodes.insert(stAttrInfo.nCode);
     148         142 :                         oFieldName.Printf("SC_%d", stAttrInfo.nCode);
     149             :                     }
     150             : 
     151         360 :                     SXFRecordAttributeType eType =
     152         360 :                         (SXFRecordAttributeType)stAttrInfo.nType;
     153             : 
     154         360 :                     offset += 4;
     155             : 
     156         360 :                     switch (eType)  // TODO: set field type form RSC as here
     157             :                                     // sometimes we have the codes and string
     158             :                                     // values can be get from RSC by this code
     159             :                     {
     160           0 :                         case SXF_RAT_ASCIIZ_DOS:
     161             :                         {
     162           0 :                             if (bAddField)
     163             :                             {
     164           0 :                                 OGRFieldDefn oField(oFieldName, OFTString);
     165           0 :                                 oField.SetWidth(255);
     166           0 :                                 poFeatureDefn->AddFieldDefn(&oField);
     167             :                             }
     168           0 :                             offset += stAttrInfo.nScale + 1;
     169           0 :                             nCurrOff = stAttrInfo.nScale + 1;
     170           0 :                             break;
     171             :                         }
     172           0 :                         case SXF_RAT_ONEBYTE:
     173             :                         {
     174           0 :                             if (bAddField)
     175             :                             {
     176           0 :                                 OGRFieldDefn oField(oFieldName, OFTReal);
     177           0 :                                 poFeatureDefn->AddFieldDefn(&oField);
     178             :                             }
     179           0 :                             offset += 1;
     180           0 :                             nCurrOff = 1;
     181           0 :                             break;
     182             :                         }
     183         140 :                         case SXF_RAT_TWOBYTE:
     184             :                         {
     185         140 :                             if (bAddField)
     186             :                             {
     187         164 :                                 OGRFieldDefn oField(oFieldName, OFTReal);
     188          82 :                                 poFeatureDefn->AddFieldDefn(&oField);
     189             :                             }
     190         140 :                             offset += 2;
     191         140 :                             nCurrOff = 2;
     192         140 :                             break;
     193             :                         }
     194           5 :                         case SXF_RAT_FOURBYTE:
     195             :                         {
     196           5 :                             if (bAddField)
     197             :                             {
     198           0 :                                 OGRFieldDefn oField(oFieldName, OFTReal);
     199           0 :                                 poFeatureDefn->AddFieldDefn(&oField);
     200             :                             }
     201           5 :                             offset += 4;
     202           5 :                             nCurrOff = 4;
     203           5 :                             break;
     204             :                         }
     205          50 :                         case SXF_RAT_EIGHTBYTE:
     206             :                         {
     207          50 :                             if (bAddField)
     208             :                             {
     209          56 :                                 OGRFieldDefn oField(oFieldName, OFTReal);
     210          28 :                                 poFeatureDefn->AddFieldDefn(&oField);
     211             :                             }
     212          50 :                             offset += 8;
     213          50 :                             nCurrOff = 8;
     214          50 :                             break;
     215             :                         }
     216         165 :                         case SXF_RAT_ANSI_WIN:
     217             :                         {
     218         165 :                             if (bAddField)
     219             :                             {
     220          64 :                                 OGRFieldDefn oField(oFieldName, OFTString);
     221          32 :                                 oField.SetWidth(255);
     222          32 :                                 poFeatureDefn->AddFieldDefn(&oField);
     223             :                             }
     224         165 :                             unsigned nLen = unsigned(stAttrInfo.nScale) + 1;
     225         165 :                             offset += nLen;
     226         165 :                             nCurrOff = nLen;
     227         165 :                             break;
     228             :                         }
     229           0 :                         case SXF_RAT_UNICODE:
     230             :                         {
     231           0 :                             if (bAddField)
     232             :                             {
     233           0 :                                 OGRFieldDefn oField(oFieldName, OFTString);
     234           0 :                                 oField.SetWidth(255);
     235           0 :                                 poFeatureDefn->AddFieldDefn(&oField);
     236             :                             }
     237           0 :                             unsigned nLen =
     238           0 :                                 (unsigned(stAttrInfo.nScale) + 1) * 2;
     239           0 :                             offset += nLen;
     240           0 :                             nCurrOff = nLen;
     241           0 :                             break;
     242             :                         }
     243           0 :                         case SXF_RAT_BIGTEXT:
     244             :                         {
     245           0 :                             if (bAddField)
     246             :                             {
     247           0 :                                 OGRFieldDefn oField(oFieldName, OFTString);
     248           0 :                                 oField.SetWidth(1024);
     249           0 :                                 poFeatureDefn->AddFieldDefn(&oField);
     250             :                             }
     251           0 :                             GUInt32 scale2 = 0;
     252           0 :                             VSIFReadL(&scale2, sizeof(GUInt32), 1, fpSXF);
     253           0 :                             CPL_LSBPTR32(&scale2);
     254             : 
     255           0 :                             offset += scale2;
     256           0 :                             nCurrOff = scale2;
     257           0 :                             break;
     258             :                         }
     259           0 :                         default:
     260           0 :                             break;
     261             :                     }
     262             :                 }
     263         360 :                 if (nCurrOff == 0)
     264           0 :                     break;
     265         360 :                 VSIFSeekL(fpSXF, nCurrOff, SEEK_CUR);
     266             :             }
     267             :         }
     268         390 :         return true;
     269             :     }
     270             : 
     271        4253 :     return false;
     272             : }
     273             : 
     274             : /************************************************************************/
     275             : /*                           SetNextByIndex()                           */
     276             : /************************************************************************/
     277             : 
     278          28 : OGRErr OGRSXFLayer::SetNextByIndex(GIntBig nIndex)
     279             : {
     280          28 :     if (nIndex < 0 || nIndex > (long)mnRecordDesc.size())
     281          18 :         return OGRERR_FAILURE;
     282             : 
     283          10 :     oNextIt = mnRecordDesc.begin();
     284          10 :     std::advance(oNextIt, static_cast<size_t>(nIndex));
     285             : 
     286          10 :     return OGRERR_NONE;
     287             : }
     288             : 
     289             : /************************************************************************/
     290             : /*                             GetFeature()                             */
     291             : /************************************************************************/
     292             : 
     293          60 : OGRFeature *OGRSXFLayer::GetFeature(GIntBig nFID)
     294             : {
     295          60 :     const auto IT = mnRecordDesc.find(static_cast<long>(nFID));
     296          60 :     if (IT != mnRecordDesc.end())
     297             :     {
     298          33 :         VSIFSeekL(fpSXF, IT->second, SEEK_SET);
     299          33 :         OGRFeature *poFeature = GetNextRawFeature(IT->first);
     300          66 :         if (poFeature != nullptr && poFeature->GetGeometryRef() != nullptr &&
     301          33 :             GetSpatialRef() != nullptr)
     302             :         {
     303          66 :             poFeature->GetGeometryRef()->assignSpatialReference(
     304          33 :                 GetSpatialRef());
     305             :         }
     306          33 :         return poFeature;
     307             :     }
     308             : 
     309          27 :     return nullptr;
     310             : }
     311             : 
     312             : /************************************************************************/
     313             : /*                           GetSpatialRef()                            */
     314             : /************************************************************************/
     315             : 
     316        2925 : OGRSpatialReference *OGRSXFLayer::GetSpatialRef()
     317             : {
     318        2925 :     return stSXFMapDescription.pSpatRef;
     319             : }
     320             : 
     321             : /************************************************************************/
     322             : /*                             GetExtent()                              */
     323             : /************************************************************************/
     324             : 
     325          36 : OGRErr OGRSXFLayer::GetExtent(OGREnvelope *psExtent, int bForce)
     326             : {
     327          36 :     if (bForce)
     328             :     {
     329          36 :         return OGRLayer::GetExtent(psExtent, bForce);
     330             :     }
     331             :     else
     332             :     {
     333           0 :         psExtent->MinX = stSXFMapDescription.Env.MinX;
     334           0 :         psExtent->MaxX = stSXFMapDescription.Env.MaxX;
     335           0 :         psExtent->MinY = stSXFMapDescription.Env.MinY;
     336           0 :         psExtent->MaxY = stSXFMapDescription.Env.MaxY;
     337             : 
     338           0 :         return OGRERR_NONE;
     339             :     }
     340             : }
     341             : 
     342             : /************************************************************************/
     343             : /*                          GetFeatureCount()                           */
     344             : /************************************************************************/
     345             : 
     346         208 : GIntBig OGRSXFLayer::GetFeatureCount(int bForce)
     347             : {
     348         208 :     if (m_poFilterGeom == nullptr && m_poAttrQuery == nullptr)
     349         154 :         return static_cast<int>(mnRecordDesc.size());
     350             :     else
     351          54 :         return OGRLayer::GetFeatureCount(bForce);
     352             : }
     353             : 
     354             : /************************************************************************/
     355             : /*                            ResetReading()                            */
     356             : /************************************************************************/
     357             : 
     358         858 : void OGRSXFLayer::ResetReading()
     359             : 
     360             : {
     361         858 :     oNextIt = mnRecordDesc.begin();
     362         858 : }
     363             : 
     364             : /************************************************************************/
     365             : /*                           GetNextFeature()                           */
     366             : /************************************************************************/
     367             : 
     368        1686 : OGRFeature *OGRSXFLayer::GetNextFeature()
     369             : {
     370        3372 :     CPLMutexHolderD(m_hIOMutex);
     371        2605 :     while (oNextIt != mnRecordDesc.end())
     372             :     {
     373        2344 :         VSIFSeekL(fpSXF, oNextIt->second, SEEK_SET);
     374        2344 :         OGRFeature *poFeature = GetNextRawFeature(oNextIt->first);
     375             : 
     376        2344 :         ++oNextIt;
     377             : 
     378        2344 :         if (poFeature == nullptr)
     379           0 :             continue;
     380             : 
     381        5546 :         if ((m_poFilterGeom == nullptr ||
     382        4125 :              FilterGeometry(poFeature->GetGeometryRef())) &&
     383        1781 :             (m_poAttrQuery == nullptr || m_poAttrQuery->Evaluate(poFeature)))
     384             :         {
     385        2850 :             if (poFeature->GetGeometryRef() != nullptr &&
     386        1425 :                 GetSpatialRef() != nullptr)
     387             :             {
     388        2850 :                 poFeature->GetGeometryRef()->assignSpatialReference(
     389        1425 :                     GetSpatialRef());
     390             :             }
     391             : 
     392        1425 :             return poFeature;
     393             :         }
     394             : 
     395         919 :         delete poFeature;
     396             :     }
     397         261 :     return nullptr;
     398             : }
     399             : 
     400             : /************************************************************************/
     401             : /*                           TestCapability()                           */
     402             : /************************************************************************/
     403             : 
     404         324 : int OGRSXFLayer::TestCapability(const char *pszCap)
     405             : 
     406             : {
     407         765 :     if (EQUAL(pszCap, OLCStringsAsUTF8) &&
     408         441 :         CPLCanRecode("test", "CP1251", CPL_ENC_UTF8) &&
     409         117 :         CPLCanRecode("test", "KOI8-R", CPL_ENC_UTF8))
     410         117 :         return TRUE;
     411         207 :     else if (EQUAL(pszCap, OLCRandomRead))
     412           0 :         return TRUE;
     413         207 :     else if (EQUAL(pszCap, OLCFastFeatureCount))
     414           0 :         return TRUE;
     415         207 :     else if (EQUAL(pszCap, OLCFastGetExtent))
     416          18 :         return TRUE;
     417         189 :     else if (EQUAL(pszCap, OLCFastSetNextByIndex))
     418           0 :         return TRUE;
     419         189 :     else if (EQUAL(pszCap, OLCZGeometries))
     420          27 :         return TRUE;
     421             : 
     422         162 :     return FALSE;
     423             : }
     424             : 
     425             : /************************************************************************/
     426             : /*                                TranslateXYH()                        */
     427             : /************************************************************************/
     428             : /****
     429             :  * TODO : Take into account information given in the passport
     430             :  * like unit of measurement, type and dimensions (integer, float, double) of
     431             :  * coordinate, the vector format, etc.
     432             :  */
     433             : 
     434       58546 : GUInt32 OGRSXFLayer::TranslateXYH(const SXFRecordDescription &certifInfo,
     435             :                                   const char *psBuff, GUInt32 nBufLen,
     436             :                                   double *dfX, double *dfY, double *dfH)
     437             : {
     438             :     // Xp, Yp(м) = Xo, Yo(м) + (Xd, Yd / R * S), (1)
     439             : 
     440       58546 :     int offset = 0;
     441       58546 :     switch (certifInfo.eValType)
     442             :     {
     443           0 :         case SXF_VT_SHORT:
     444             :         {
     445           0 :             if (nBufLen < 4)
     446           0 :                 return 0;
     447           0 :             GInt16 x = 0;
     448           0 :             GInt16 y = 0;
     449           0 :             memcpy(&y, psBuff, 2);
     450           0 :             CPL_LSBPTR16(&y);
     451           0 :             memcpy(&x, psBuff + 2, 2);
     452           0 :             CPL_LSBPTR16(&x);
     453             : 
     454           0 :             if (stSXFMapDescription.bIsRealCoordinates)
     455             :             {
     456           0 :                 *dfX = (double)x;
     457           0 :                 *dfY = (double)y;
     458             :             }
     459             :             else
     460             :             {
     461           0 :                 if (m_nSXFFormatVer == 3)
     462             :                 {
     463           0 :                     *dfX = stSXFMapDescription.dfXOr + (double)x * m_dfCoeff;
     464           0 :                     *dfY = stSXFMapDescription.dfYOr + (double)y * m_dfCoeff;
     465             :                 }
     466           0 :                 else if (m_nSXFFormatVer == 4)
     467             :                 {
     468             :                     // TODO: check on real data
     469           0 :                     *dfX = stSXFMapDescription.dfXOr + (double)x * m_dfCoeff;
     470           0 :                     *dfY = stSXFMapDescription.dfYOr + (double)y * m_dfCoeff;
     471             :                 }
     472             :             }
     473             : 
     474           0 :             offset += 4;
     475             : 
     476           0 :             if (dfH != nullptr)
     477             :             {
     478           0 :                 if (nBufLen < 4 + 4)
     479           0 :                     return 0;
     480           0 :                 float h = 0.0f;
     481           0 :                 memcpy(&h, psBuff + 4, 4);  // H always in float
     482           0 :                 CPL_LSBPTR32(&h);
     483           0 :                 *dfH = (double)h;
     484             : 
     485           0 :                 offset += 4;
     486             :             }
     487             :         }
     488           0 :         break;
     489           0 :         case SXF_VT_FLOAT:
     490             :         {
     491           0 :             if (nBufLen < 8)
     492           0 :                 return 0;
     493           0 :             float y = 0.0f;
     494           0 :             memcpy(&y, psBuff, 4);
     495           0 :             CPL_LSBPTR32(&y);
     496           0 :             float x = 0.0f;
     497           0 :             memcpy(&x, psBuff + 4, 4);
     498           0 :             CPL_LSBPTR32(&x);
     499             : 
     500           0 :             if (stSXFMapDescription.bIsRealCoordinates)
     501             :             {
     502           0 :                 *dfX = (double)x;
     503           0 :                 *dfY = (double)y;
     504             :             }
     505             :             else
     506             :             {
     507           0 :                 *dfX = stSXFMapDescription.dfXOr + (double)x * m_dfCoeff;
     508           0 :                 *dfY = stSXFMapDescription.dfYOr + (double)y * m_dfCoeff;
     509             :             }
     510             : 
     511           0 :             offset += 8;
     512             : 
     513           0 :             if (dfH != nullptr)
     514             :             {
     515           0 :                 if (nBufLen < 8 + 4)
     516           0 :                     return 0;
     517           0 :                 float h = 0.0f;
     518           0 :                 memcpy(&h, psBuff + 8, 4);  // H always in float
     519           0 :                 CPL_LSBPTR32(&h);
     520           0 :                 *dfH = (double)h;
     521             : 
     522           0 :                 offset += 4;
     523             :             }
     524             :         }
     525           0 :         break;
     526           0 :         case SXF_VT_INT:
     527             :         {
     528           0 :             if (nBufLen < 8)
     529           0 :                 return 0;
     530             :             GInt32 x, y;
     531           0 :             memcpy(&y, psBuff, 4);
     532           0 :             CPL_LSBPTR32(&y);
     533           0 :             memcpy(&x, psBuff + 4, 4);
     534           0 :             CPL_LSBPTR32(&x);
     535             : 
     536           0 :             if (stSXFMapDescription.bIsRealCoordinates)
     537             :             {
     538           0 :                 *dfX = (double)x;
     539           0 :                 *dfY = (double)y;
     540             :             }
     541             :             else
     542             :             {
     543             :                 // TODO: check on real data
     544           0 :                 if (m_nSXFFormatVer == 3)
     545             :                 {
     546           0 :                     *dfX = stSXFMapDescription.dfXOr + (double)x * m_dfCoeff;
     547           0 :                     *dfY = stSXFMapDescription.dfYOr + (double)y * m_dfCoeff;
     548             :                 }
     549           0 :                 else if (m_nSXFFormatVer == 4)
     550             :                 {
     551           0 :                     *dfX = stSXFMapDescription.dfXOr + (double)x * m_dfCoeff;
     552           0 :                     *dfY = stSXFMapDescription.dfYOr + (double)y * m_dfCoeff;
     553             :                 }
     554             :             }
     555           0 :             offset += 8;
     556             : 
     557           0 :             if (dfH != nullptr)
     558             :             {
     559           0 :                 if (nBufLen < 8 + 4)
     560           0 :                     return 0;
     561           0 :                 float h = 0.0f;
     562           0 :                 memcpy(&h, psBuff + 8, 4);  // H always in float
     563           0 :                 CPL_LSBPTR32(&h);
     564           0 :                 *dfH = (double)h;
     565             : 
     566           0 :                 offset += 4;
     567             :             }
     568             :         }
     569           0 :         break;
     570       58546 :         case SXF_VT_DOUBLE:
     571             :         {
     572       58546 :             if (nBufLen < 16)
     573           0 :                 return 0;
     574       58546 :             double x = 0.0;
     575       58546 :             double y = 0.0;
     576       58546 :             memcpy(&y, psBuff, 8);
     577       58546 :             CPL_LSBPTR64(&y);
     578       58546 :             memcpy(&x, psBuff + 8, 8);
     579       58546 :             CPL_LSBPTR64(&x);
     580             : 
     581       58546 :             if (stSXFMapDescription.bIsRealCoordinates)
     582             :             {
     583       58546 :                 *dfX = x;
     584       58546 :                 *dfY = y;
     585             :             }
     586             :             else
     587             :             {
     588           0 :                 *dfX = stSXFMapDescription.dfXOr + x * m_dfCoeff;
     589           0 :                 *dfY = stSXFMapDescription.dfYOr + y * m_dfCoeff;
     590             :             }
     591             : 
     592       58546 :             offset += 16;
     593             : 
     594       58546 :             if (dfH != nullptr)
     595             :             {
     596           0 :                 if (nBufLen < 16 + 8)
     597           0 :                     return 0;
     598           0 :                 double h = 0.0;
     599           0 :                 memcpy(&h, psBuff + 16, 8);  // H in double
     600           0 :                 CPL_LSBPTR64(&h);
     601           0 :                 *dfH = (double)h;
     602             : 
     603           0 :                 offset += 8;
     604             :             }
     605             :         }
     606       58546 :         break;
     607             :     };
     608             : 
     609       58546 :     return offset;
     610             : }
     611             : 
     612             : /************************************************************************/
     613             : /*                         GetNextRawFeature()                          */
     614             : /************************************************************************/
     615             : 
     616        2377 : OGRFeature *OGRSXFLayer::GetNextRawFeature(long nFID)
     617             : {
     618             :     SXFRecordHeader stRecordHeader;
     619             :     int nObjectRead = static_cast<int>(
     620        2377 :         VSIFReadL(&stRecordHeader, sizeof(SXFRecordHeader), 1, fpSXF));
     621             : 
     622        2377 :     if (nObjectRead != 1)
     623             :     {
     624           0 :         CPLError(CE_Failure, CPLE_FileIO, "SXF. Read record failed.");
     625           0 :         return nullptr;
     626             :     }
     627        2377 :     CPL_LSBPTR32(&(stRecordHeader.nID));
     628        2377 :     if (stRecordHeader.nID != IDSXFOBJ)
     629             :     {
     630           0 :         CPLError(CE_Failure, CPLE_FileIO, "SXF. Read record failed.");
     631           0 :         return nullptr;
     632             :     }
     633        2377 :     CPL_LSBPTR32(&(stRecordHeader.nFullLength));
     634        2377 :     CPL_LSBPTR32(&(stRecordHeader.nGeometryLength));
     635        2377 :     CPL_LSBPTR32(&(stRecordHeader.nClassifyCode));
     636        2377 :     CPL_LSBPTR16(&(stRecordHeader.anGroup[0]));
     637        2377 :     CPL_LSBPTR16(&(stRecordHeader.anGroup[1]));
     638        2377 :     CPL_LSBPTR32(&(stRecordHeader.nPointCount));
     639        2377 :     CPL_LSBPTR16(&(stRecordHeader.nSubObjectCount));
     640        2377 :     CPL_LSBPTR16(&(stRecordHeader.nPointCountSmall));
     641             : 
     642        2377 :     SXFGeometryType eGeomType = SXF_GT_Unknown;
     643        2377 :     GByte code = 0;
     644             : 
     645        2377 :     if (m_nSXFFormatVer == 3)
     646             :     {
     647           0 :         if (CHECK_BIT(stRecordHeader.nRef[2], 3))
     648             :         {
     649           0 :             if (CHECK_BIT(stRecordHeader.nRef[2], 4))
     650             :             {
     651           0 :                 code = 0x22;
     652           0 :                 stRecordHeader.nSubObjectCount = 0;
     653             :             }
     654             :             else
     655             :             {
     656           0 :                 code = 0x21;
     657           0 :                 stRecordHeader.nSubObjectCount = 0;
     658             :             }
     659             :         }
     660             :         else
     661             :         {
     662           0 :             code = stRecordHeader.nRef[0] & 3;  // get first 2 bits
     663             :         }
     664             :     }
     665        2377 :     else if (m_nSXFFormatVer == 4)
     666             :     {
     667        2377 :         if (CHECK_BIT(stRecordHeader.nRef[2], 5))
     668             :         {
     669           0 :             stRecordHeader.nSubObjectCount = 0;
     670             :         }
     671             : 
     672             :         // check if vector
     673        2377 :         code = stRecordHeader.nRef[0] & 15;  // get first 4 bits
     674        2377 :         if (code == 0x04)                    // xxxx0100
     675             :         {
     676         420 :             code = 0x21;
     677         420 :             stRecordHeader.nSubObjectCount = 0;
     678             :             // if (CHECK_BIT(stRecordHeader.nRef[2], 5))
     679             :             //{
     680             :             //     code = 0x22;
     681             :             //     stRecordHeader.nSubObjectCount = 0;
     682             :             // }
     683             :             // else
     684             :             //{
     685             :             //     code = 0x21;
     686             :             //     stRecordHeader.nSubObjectCount = 0;
     687             :             // }
     688             :             // if (CHECK_BIT(stRecordHeader.nRef[2], 4))
     689             :             //{
     690             :             // }
     691             :             // else
     692             :             //{
     693             :             // }
     694             :         }
     695             :     }
     696             : 
     697        2377 :     if (code == 0x00)  // xxxx0000
     698         984 :         eGeomType = SXF_GT_Line;
     699        1393 :     else if (code == 0x01)  // xxxx0001
     700         510 :         eGeomType = SXF_GT_Polygon;
     701         883 :     else if (code == 0x02)  // xxxx0010
     702         323 :         eGeomType = SXF_GT_Point;
     703         560 :     else if (code == 0x03)  // xxxx0011
     704         140 :         eGeomType = SXF_GT_Text;
     705             : #ifdef not_possible_given_above_code /* see below code too if re-enabling this \
     706             :                                       */
     707             :     // beginning 4.0
     708             :     else if (code == 0x04)  // xxxx0100
     709             :     {
     710             :         CPLError(CE_Warning, CPLE_NotSupported, "SXF. Not support type.");
     711             :         eGeomType = SXF_GT_Vector;
     712             :     }
     713             : #endif
     714         420 :     else if (code == 0x05)  // xxxx0101
     715           0 :         eGeomType = SXF_GT_TextTemplate;
     716         420 :     else if (code == 0x21)
     717         420 :         eGeomType = SXF_GT_VectorAngle;
     718           0 :     else if (code == 0x22)
     719           0 :         eGeomType = SXF_GT_VectorScaled;
     720             : 
     721        2377 :     bool bHasAttributes = CHECK_BIT(stRecordHeader.nRef[1], 1);
     722        2377 :     bool bHasRefVector = CHECK_BIT(stRecordHeader.nRef[1], 3);
     723        2377 :     if (bHasRefVector == true)
     724           0 :         CPLError(CE_Failure, CPLE_NotSupported,
     725             :                  "SXF. Parsing the vector of the tying not support.");
     726             : 
     727             :     SXFRecordDescription stCertInfo;
     728        2377 :     if (stRecordHeader.nPointCountSmall == 65535)
     729             :     {
     730           0 :         stCertInfo.nPointCount = stRecordHeader.nPointCount;
     731             :     }
     732             :     else
     733             :     {
     734        2377 :         stCertInfo.nPointCount = stRecordHeader.nPointCountSmall;
     735             :     }
     736        2377 :     stCertInfo.nSubObjectCount = stRecordHeader.nSubObjectCount;
     737             : 
     738        2377 :     bool bFloatType(false), bBigType(false);
     739        2377 :     bool b3D(true);
     740        2377 :     if (m_nSXFFormatVer == 3)
     741             :     {
     742           0 :         b3D = CHECK_BIT(stRecordHeader.nRef[2], 1);
     743           0 :         bFloatType = CHECK_BIT(stRecordHeader.nRef[2], 2);
     744           0 :         bBigType = CHECK_BIT(stRecordHeader.nRef[1], 2);
     745           0 :         stCertInfo.bHasTextSign = CHECK_BIT(stRecordHeader.nRef[2], 5);
     746             :     }
     747        2377 :     else if (m_nSXFFormatVer == 4)
     748             :     {
     749        2377 :         b3D = CHECK_BIT(stRecordHeader.nRef[2], 1);
     750        2377 :         bFloatType = CHECK_BIT(stRecordHeader.nRef[2], 2);
     751        2377 :         bBigType = CHECK_BIT(stRecordHeader.nRef[1], 2);
     752        2377 :         stCertInfo.bHasTextSign = CHECK_BIT(stRecordHeader.nRef[2], 3);
     753             :     }
     754             :     // Else trouble.
     755             : 
     756        2377 :     if (b3D)  // xxxxxx1x
     757           0 :         stCertInfo.bDim = 1;
     758             :     else
     759        2377 :         stCertInfo.bDim = 0;
     760             : 
     761        2377 :     if (bFloatType)
     762             :     {
     763        2377 :         if (bBigType)
     764             :         {
     765        2377 :             stCertInfo.eValType = SXF_VT_DOUBLE;
     766             :         }
     767             :         else
     768             :         {
     769           0 :             stCertInfo.eValType = SXF_VT_FLOAT;
     770             :         }
     771             :     }
     772             :     else
     773             :     {
     774           0 :         if (bBigType)
     775             :         {
     776           0 :             stCertInfo.eValType = SXF_VT_INT;
     777             :         }
     778             :         else
     779             :         {
     780           0 :             stCertInfo.eValType = SXF_VT_SHORT;
     781             :         }
     782             :     }
     783             : 
     784        2377 :     stCertInfo.bFormat = CHECK_BIT(stRecordHeader.nRef[2], 0);
     785        2377 :     stCertInfo.eGeomType = eGeomType;
     786             : 
     787        2377 :     OGRFeature *poFeature = nullptr;
     788        2377 :     if (stRecordHeader.nGeometryLength > 100 * 1024 * 1024)
     789           0 :         return nullptr;
     790             :     char *recordCertifBuf =
     791        2377 :         (char *)VSI_MALLOC_VERBOSE(stRecordHeader.nGeometryLength);
     792        2377 :     if (recordCertifBuf == nullptr)
     793           0 :         return nullptr;
     794        2377 :     nObjectRead = static_cast<int>(
     795        2377 :         VSIFReadL(recordCertifBuf, stRecordHeader.nGeometryLength, 1, fpSXF));
     796        2377 :     if (nObjectRead != 1)
     797             :     {
     798           0 :         CPLError(CE_Failure, CPLE_FileIO, "SXF. Read geometry failed.");
     799           0 :         CPLFree(recordCertifBuf);
     800           0 :         return nullptr;
     801             :     }
     802             : 
     803        2377 :     if (eGeomType == SXF_GT_Point)
     804         323 :         poFeature = TranslatePoint(stCertInfo, recordCertifBuf,
     805             :                                    stRecordHeader.nGeometryLength);
     806        2054 :     else if (eGeomType == SXF_GT_Line || eGeomType == SXF_GT_VectorScaled)
     807         984 :         poFeature = TranslateLine(stCertInfo, recordCertifBuf,
     808             :                                   stRecordHeader.nGeometryLength);
     809        1070 :     else if (eGeomType == SXF_GT_Polygon)
     810         510 :         poFeature = TranslatePolygon(stCertInfo, recordCertifBuf,
     811             :                                      stRecordHeader.nGeometryLength);
     812         560 :     else if (eGeomType == SXF_GT_Text)
     813         140 :         poFeature = TranslateText(stCertInfo, recordCertifBuf,
     814             :                                   stRecordHeader.nGeometryLength);
     815         420 :     else if (eGeomType == SXF_GT_VectorAngle)
     816             :     {
     817         420 :         poFeature = TranslateVetorAngle(stCertInfo, recordCertifBuf,
     818             :                                         stRecordHeader.nGeometryLength);
     819             :     }
     820             : #ifdef not_possible_given_above_code
     821             :     else if (eGeomType == SXF_GT_Vector)
     822             :     {
     823             :         CPLError(CE_Warning, CPLE_NotSupported,
     824             :                  "SXF. Geometry type Vector do not support.");
     825             :         CPLFree(recordCertifBuf);
     826             :         return NULL;
     827             :     }
     828             : #endif
     829           0 :     else if (eGeomType == SXF_GT_TextTemplate)  // TODO realize this
     830             :     {
     831           0 :         CPLError(CE_Warning, CPLE_NotSupported,
     832             :                  "SXF. Geometry type Text Template do not support.");
     833           0 :         CPLFree(recordCertifBuf);
     834           0 :         return nullptr;
     835             :     }
     836             :     else
     837             :     {
     838           0 :         CPLError(CE_Failure, CPLE_NotSupported,
     839             :                  "SXF. Unsupported geometry type.");
     840           0 :         CPLFree(recordCertifBuf);
     841           0 :         return nullptr;
     842             :     }
     843             : 
     844        2377 :     if (poFeature == nullptr)
     845             :     {
     846           0 :         CPLFree(recordCertifBuf);
     847           0 :         return nullptr;
     848             :     }
     849             : 
     850        2377 :     poFeature->SetField(sFIDColumn_, (int)nFID);
     851             : 
     852        2377 :     poFeature->SetField("CLCODE", (int)stRecordHeader.nClassifyCode);
     853             : 
     854        4754 :     CPLString szName = mnClassificators[stRecordHeader.nClassifyCode];
     855             : 
     856        2377 :     if (szName.empty())
     857             :     {
     858         813 :         szName.Printf("%d", stRecordHeader.nClassifyCode);
     859             :     }
     860        2377 :     poFeature->SetField("CLNAME", szName);
     861             : 
     862        2377 :     poFeature->SetField("OBJECTNUMB", stRecordHeader.nSubObjectCount);
     863             : 
     864        2377 :     if (bHasAttributes)
     865             :     {
     866        1548 :         if (stRecordHeader.nFullLength < 32 ||
     867        1548 :             stRecordHeader.nGeometryLength > stRecordHeader.nFullLength - 32)
     868             :         {
     869           0 :             CPLFree(recordCertifBuf);
     870           0 :             delete poFeature;
     871           0 :             return nullptr;
     872             :         }
     873        1548 :         size_t nSemanticsSize =
     874        1548 :             stRecordHeader.nFullLength - 32 - stRecordHeader.nGeometryLength;
     875        1548 :         if (nSemanticsSize > 1024 * 1024)
     876             :         {
     877           0 :             CPLFree(recordCertifBuf);
     878           0 :             delete poFeature;
     879           0 :             return nullptr;
     880             :         }
     881        1548 :         char *psSemanticsdBuf = (char *)VSI_MALLOC_VERBOSE(nSemanticsSize);
     882        1548 :         if (psSemanticsdBuf == nullptr)
     883             :         {
     884           0 :             CPLFree(recordCertifBuf);
     885           0 :             delete poFeature;
     886           0 :             return nullptr;
     887             :         }
     888        1548 :         char *psSemanticsdBufOrig = psSemanticsdBuf;
     889        1548 :         nObjectRead = static_cast<int>(
     890        1548 :             VSIFReadL(psSemanticsdBuf, nSemanticsSize, 1, fpSXF));
     891        1548 :         if (nObjectRead == 1)
     892             :         {
     893        1548 :             size_t offset = 0;
     894        1548 :             double nVal = 0;
     895             : 
     896        3839 :             while (offset + sizeof(SXFRecordAttributeInfo) < nSemanticsSize)
     897             :             {
     898        2291 :                 char *psSemanticsdBufBeg = psSemanticsdBuf + offset;
     899        2291 :                 SXFRecordAttributeInfo stAttInfo =
     900             :                     *(SXFRecordAttributeInfo *)psSemanticsdBufBeg;
     901        2291 :                 CPL_LSBPTR16(&(stAttInfo.nCode));
     902        2291 :                 offset += 4;
     903             : 
     904        2291 :                 CPLString oFieldName;
     905        2291 :                 oFieldName.Printf("SC_%d", stAttInfo.nCode);
     906             : 
     907        2291 :                 CPLString oFieldValue;
     908             : 
     909        2291 :                 SXFRecordAttributeType eType =
     910        2291 :                     (SXFRecordAttributeType)stAttInfo.nType;
     911             : 
     912        2291 :                 switch (eType)
     913             :                 {
     914           0 :                     case SXF_RAT_ASCIIZ_DOS:
     915             :                     {
     916           0 :                         unsigned nLen = unsigned(stAttInfo.nScale) + 1;
     917           0 :                         if (nLen > nSemanticsSize ||
     918           0 :                             nSemanticsSize - nLen < offset)
     919             :                         {
     920           0 :                             nSemanticsSize = 0;
     921           0 :                             break;
     922             :                         }
     923           0 :                         char *value = (char *)CPLMalloc(nLen);
     924           0 :                         memcpy(value, psSemanticsdBuf + offset, nLen);
     925           0 :                         value[nLen - 1] = 0;
     926             :                         char *pszRecoded =
     927           0 :                             CPLRecode(value, "CP866", CPL_ENC_UTF8);
     928           0 :                         poFeature->SetField(oFieldName, pszRecoded);
     929           0 :                         CPLFree(pszRecoded);
     930           0 :                         CPLFree(value);
     931             : 
     932           0 :                         offset += stAttInfo.nScale + 1;
     933           0 :                         break;
     934             :                     }
     935           0 :                     case SXF_RAT_ONEBYTE:
     936             :                     {
     937           0 :                         if (offset + sizeof(GByte) > nSemanticsSize)
     938             :                         {
     939           0 :                             nSemanticsSize = 0;
     940           0 :                             break;
     941             :                         }
     942           0 :                         GByte nTmpVal = 0;
     943           0 :                         memcpy(&nTmpVal, psSemanticsdBuf + offset,
     944             :                                sizeof(GByte));
     945           0 :                         nVal = double(nTmpVal) *
     946           0 :                                pow(10.0, (double)stAttInfo.nScale);
     947             : 
     948           0 :                         poFeature->SetField(oFieldName, nVal);
     949           0 :                         offset += 1;
     950           0 :                         break;
     951             :                     }
     952         914 :                     case SXF_RAT_TWOBYTE:
     953             :                     {
     954         914 :                         if (offset + sizeof(GInt16) > nSemanticsSize)
     955             :                         {
     956           0 :                             nSemanticsSize = 0;
     957           0 :                             break;
     958             :                         }
     959         914 :                         GInt16 nTmpVal = 0;
     960         914 :                         memcpy(&nTmpVal, psSemanticsdBuf + offset,
     961             :                                sizeof(GInt16));
     962         914 :                         nVal = double(CPL_LSBWORD16(nTmpVal)) *
     963         914 :                                pow(10.0, (double)stAttInfo.nScale);
     964             : 
     965         914 :                         poFeature->SetField(oFieldName, nVal);
     966         914 :                         offset += 2;
     967         914 :                         break;
     968             :                     }
     969          28 :                     case SXF_RAT_FOURBYTE:
     970             :                     {
     971          28 :                         if (offset + sizeof(GInt32) > nSemanticsSize)
     972             :                         {
     973           0 :                             nSemanticsSize = 0;
     974           0 :                             break;
     975             :                         }
     976          28 :                         GInt32 nTmpVal = 0;
     977          28 :                         memcpy(&nTmpVal, psSemanticsdBuf + offset,
     978             :                                sizeof(GInt32));
     979          28 :                         nVal = double(CPL_LSBWORD32(nTmpVal)) *
     980          28 :                                pow(10.0, (double)stAttInfo.nScale);
     981             : 
     982          28 :                         poFeature->SetField(oFieldName, nVal);
     983          28 :                         offset += 4;
     984          28 :                         break;
     985             :                     }
     986         340 :                     case SXF_RAT_EIGHTBYTE:
     987             :                     {
     988         340 :                         if (offset + sizeof(double) > nSemanticsSize)
     989             :                         {
     990           0 :                             nSemanticsSize = 0;
     991           0 :                             break;
     992             :                         }
     993         340 :                         double dfTmpVal = 0.0;
     994         340 :                         memcpy(&dfTmpVal, psSemanticsdBuf + offset,
     995             :                                sizeof(double));
     996         340 :                         CPL_LSBPTR64(&dfTmpVal);
     997             :                         const double d =
     998         340 :                             dfTmpVal * pow(10.0, (double)stAttInfo.nScale);
     999             : 
    1000         340 :                         poFeature->SetField(oFieldName, d);
    1001             : 
    1002         340 :                         offset += 8;
    1003         340 :                         break;
    1004             :                     }
    1005        1009 :                     case SXF_RAT_ANSI_WIN:
    1006             :                     {
    1007        1009 :                         unsigned nLen = unsigned(stAttInfo.nScale) + 1;
    1008        1009 :                         if (nLen > nSemanticsSize ||
    1009        1009 :                             nSemanticsSize - nLen < offset)
    1010             :                         {
    1011           0 :                             nSemanticsSize = 0;
    1012           0 :                             break;
    1013             :                         }
    1014        1009 :                         char *value = (char *)CPLMalloc(nLen);
    1015        1009 :                         memcpy(value, psSemanticsdBuf + offset, nLen);
    1016        1009 :                         value[nLen - 1] = 0;
    1017             :                         char *pszRecoded =
    1018        1009 :                             CPLRecode(value, "CP1251", CPL_ENC_UTF8);
    1019        1009 :                         poFeature->SetField(oFieldName, pszRecoded);
    1020        1009 :                         CPLFree(pszRecoded);
    1021        1009 :                         CPLFree(value);
    1022             : 
    1023        1009 :                         offset += nLen;
    1024        1009 :                         break;
    1025             :                     }
    1026           0 :                     case SXF_RAT_UNICODE:
    1027             :                     {
    1028           0 :                         uint64_t nLen64 =
    1029           0 :                             (static_cast<uint64_t>(stAttInfo.nScale) + 1) * 2;
    1030           0 :                         unsigned nLen = static_cast<unsigned>(nLen64);
    1031           0 :                         if (/* nLen < 2 || */ nLen64 > nSemanticsSize ||
    1032           0 :                             nSemanticsSize - nLen < offset)
    1033             :                         {
    1034           0 :                             nSemanticsSize = 0;
    1035           0 :                             break;
    1036             :                         }
    1037           0 :                         char *value = (char *)CPLMalloc(nLen);
    1038           0 :                         memcpy(value, psSemanticsdBuf + offset, nLen - 2);
    1039           0 :                         value[nLen - 1] = 0;
    1040           0 :                         value[nLen - 2] = 0;
    1041           0 :                         char *dst = (char *)CPLMalloc(nLen);
    1042           0 :                         int nCount = 0;
    1043           0 :                         for (int i = 0; (unsigned)i < nLen; i += 2)
    1044             :                         {
    1045           0 :                             unsigned char ucs = value[i];
    1046             : 
    1047           0 :                             if (ucs < 0x80U)
    1048             :                             {
    1049           0 :                                 dst[nCount++] = ucs;
    1050             :                             }
    1051             :                             else
    1052             :                             {
    1053           0 :                                 dst[nCount++] = 0xc0 | (ucs >> 6);
    1054           0 :                                 dst[nCount++] = 0x80 | (ucs & 0x3F);
    1055             :                             }
    1056             :                         }
    1057             : 
    1058           0 :                         poFeature->SetField(oFieldName, dst);
    1059           0 :                         CPLFree(dst);
    1060           0 :                         CPLFree(value);
    1061             : 
    1062           0 :                         offset += nLen;
    1063           0 :                         break;
    1064             :                     }
    1065           0 :                     case SXF_RAT_BIGTEXT:
    1066             :                     {
    1067           0 :                         if (offset + sizeof(GUInt32) > nSemanticsSize)
    1068             :                         {
    1069           0 :                             nSemanticsSize = 0;
    1070           0 :                             break;
    1071             :                         }
    1072           0 :                         GUInt32 scale2 = 0;
    1073           0 :                         memcpy(&scale2, psSemanticsdBuf + offset,
    1074             :                                sizeof(GUInt32));
    1075           0 :                         CPL_LSBPTR32(&scale2);
    1076             :                         /* FIXME add ?: offset += sizeof(GUInt32); */
    1077           0 :                         if (scale2 > nSemanticsSize - 1 ||
    1078           0 :                             nSemanticsSize - (scale2 + 1) < offset)
    1079             :                         {
    1080           0 :                             nSemanticsSize = 0;
    1081           0 :                             break;
    1082             :                         }
    1083             : 
    1084           0 :                         char *value = (char *)CPLMalloc(scale2 + 1);
    1085           0 :                         memcpy(value, psSemanticsdBuf + offset, scale2 + 1);
    1086           0 :                         value[scale2] = 0;
    1087             :                         char *pszRecoded =
    1088           0 :                             CPLRecode(value, CPL_ENC_UTF16, CPL_ENC_UTF8);
    1089           0 :                         poFeature->SetField(oFieldName, pszRecoded);
    1090           0 :                         CPLFree(pszRecoded);
    1091           0 :                         CPLFree(value);
    1092             : 
    1093           0 :                         offset += scale2;
    1094           0 :                         break;
    1095             :                     }
    1096           0 :                     default:
    1097           0 :                         CPLFree(recordCertifBuf);
    1098           0 :                         CPLFree(psSemanticsdBufOrig);
    1099           0 :                         delete poFeature;
    1100           0 :                         return nullptr;
    1101             :                 }
    1102             :             }
    1103             :         }
    1104        1548 :         CPLFree(psSemanticsdBufOrig);
    1105             :     }
    1106             : 
    1107        2377 :     poFeature->SetFID(nFID);
    1108             : 
    1109        2377 :     CPLFree(recordCertifBuf);
    1110             : 
    1111        2377 :     return poFeature;
    1112             : }
    1113             : 
    1114             : /************************************************************************/
    1115             : /*                         TranslatePoint   ()                          */
    1116             : /************************************************************************/
    1117             : 
    1118         323 : OGRFeature *OGRSXFLayer::TranslatePoint(const SXFRecordDescription &certifInfo,
    1119             :                                         const char *psRecordBuf,
    1120             :                                         GUInt32 nBufLen)
    1121             : {
    1122         323 :     double dfX = 1.0;
    1123         323 :     double dfY = 1.0;
    1124         323 :     double dfZ = 0.0;
    1125         323 :     GUInt32 nOffset = 0;
    1126         323 :     GUInt32 nDelta = 0;
    1127             : 
    1128         323 :     if (certifInfo.bDim == 1)
    1129             :     {
    1130             :         nDelta =
    1131           0 :             TranslateXYH(certifInfo, psRecordBuf, nBufLen, &dfX, &dfY, &dfZ);
    1132             :     }
    1133             :     else
    1134             :     {
    1135         323 :         nDelta = TranslateXYH(certifInfo, psRecordBuf, nBufLen, &dfX, &dfY);
    1136             :     }
    1137             : 
    1138         323 :     if (nDelta == 0)
    1139           0 :         return nullptr;
    1140         323 :     nOffset += nDelta;
    1141             : 
    1142             :     // OGRFeatureDefn *fd = poFeatureDefn->Clone();
    1143             :     // fd->SetGeomType( wkbMultiPoint );
    1144             :     //   OGRFeature *poFeature = new OGRFeature(fd);
    1145         323 :     OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
    1146         323 :     OGRMultiPoint *poMPt = new OGRMultiPoint();
    1147             : 
    1148         323 :     poMPt->addGeometryDirectly(new OGRPoint(dfX, dfY, dfZ));
    1149             : 
    1150             :     /*---------------------- Reading SubObjects
    1151             :      * --------------------------------*/
    1152             : 
    1153         323 :     for (int count = 0; count < certifInfo.nSubObjectCount; count++)
    1154             :     {
    1155           0 :         if (nOffset + 4 > nBufLen)
    1156           0 :             break;
    1157             : 
    1158           0 :         GUInt16 nSubObj = 0;
    1159           0 :         memcpy(&nSubObj, psRecordBuf + nOffset, 2);
    1160           0 :         CPL_LSBPTR16(&nSubObj);
    1161             : 
    1162           0 :         GUInt16 nCoords = 0;
    1163           0 :         memcpy(&nCoords, psRecordBuf + nOffset + 2, 2);
    1164           0 :         CPL_LSBPTR16(&nCoords);
    1165             : 
    1166           0 :         nOffset += 4;
    1167             : 
    1168           0 :         for (int i = 0; i < nCoords; i++)
    1169             :         {
    1170           0 :             const char *psCoords = psRecordBuf + nOffset;
    1171             : 
    1172           0 :             if (certifInfo.bDim == 1)
    1173             :             {
    1174           0 :                 nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset,
    1175             :                                       &dfX, &dfY, &dfZ);
    1176             :             }
    1177             :             else
    1178             :             {
    1179           0 :                 dfZ = 0.0;
    1180           0 :                 nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset,
    1181             :                                       &dfX, &dfY);
    1182             :             }
    1183             : 
    1184           0 :             if (nDelta == 0)
    1185           0 :                 break;
    1186           0 :             nOffset += nDelta;
    1187             : 
    1188           0 :             poMPt->addGeometryDirectly(new OGRPoint(dfX, dfY, dfZ));
    1189             :         }
    1190             :     }
    1191             : 
    1192             :     /*****
    1193             :      * TODO :
    1194             :      *          - Translate graphics
    1195             :      *          - Translate 3D vector
    1196             :      */
    1197             : 
    1198         323 :     poFeature->SetGeometryDirectly(poMPt);
    1199             : 
    1200         323 :     return poFeature;
    1201             : }
    1202             : 
    1203             : /************************************************************************/
    1204             : /*                         TranslateLine    ()                          */
    1205             : /************************************************************************/
    1206             : 
    1207         984 : OGRFeature *OGRSXFLayer::TranslateLine(const SXFRecordDescription &certifInfo,
    1208             :                                        const char *psRecordBuf, GUInt32 nBufLen)
    1209             : {
    1210         984 :     double dfX = 1.0;
    1211         984 :     double dfY = 1.0;
    1212         984 :     double dfZ = 0.0;
    1213         984 :     GUInt32 nOffset = 0;
    1214             : 
    1215             :     // OGRFeatureDefn *fd = poFeatureDefn->Clone();
    1216             :     // fd->SetGeomType( wkbMultiLineString );
    1217             :     //   OGRFeature *poFeature = new OGRFeature(fd);
    1218             : 
    1219         984 :     OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
    1220         984 :     OGRMultiLineString *poMLS = new OGRMultiLineString();
    1221             : 
    1222             :     /*---------------------- Reading Primary Line
    1223             :      * --------------------------------*/
    1224             : 
    1225         984 :     OGRLineString *poLS = new OGRLineString();
    1226             : 
    1227       29158 :     for (GUInt32 count = 0; count < certifInfo.nPointCount; count++)
    1228             :     {
    1229       28174 :         const char *psCoords = psRecordBuf + nOffset;
    1230             : 
    1231             :         GInt32 nDelta;
    1232       28174 :         if (certifInfo.bDim == 1)
    1233             :         {
    1234           0 :             nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset, &dfX,
    1235             :                                   &dfY, &dfZ);
    1236             :         }
    1237             :         else
    1238             :         {
    1239       28174 :             dfZ = 0.0;
    1240       28174 :             nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset, &dfX,
    1241             :                                   &dfY);
    1242             :         }
    1243             : 
    1244       28174 :         if (nDelta == 0)
    1245           0 :             break;
    1246       28174 :         nOffset += nDelta;
    1247             : 
    1248       28174 :         poLS->addPoint(dfX, dfY, dfZ);
    1249             :     }
    1250             : 
    1251         984 :     poMLS->addGeometry(poLS);
    1252             : 
    1253             :     /*---------------------- Reading Sub Lines
    1254             :      * --------------------------------*/
    1255             : 
    1256         984 :     for (GUInt16 count = 0; count < certifInfo.nSubObjectCount; count++)
    1257             :     {
    1258           0 :         poLS->empty();
    1259             : 
    1260           0 :         if (nOffset + 4 > nBufLen)
    1261           0 :             break;
    1262             : 
    1263           0 :         GUInt16 nSubObj = 0;
    1264           0 :         memcpy(&nSubObj, psRecordBuf + nOffset, 2);
    1265           0 :         CPL_LSBPTR16(&nSubObj);
    1266             : 
    1267           0 :         GUInt16 nCoords = 0;
    1268           0 :         memcpy(&nCoords, psRecordBuf + nOffset + 2, 2);
    1269           0 :         CPL_LSBPTR16(&nCoords);
    1270             : 
    1271           0 :         nOffset += 4;
    1272             : 
    1273           0 :         for (GUInt16 i = 0; i < nCoords; i++)
    1274             :         {
    1275           0 :             const char *psCoords = psRecordBuf + nOffset;
    1276             :             GInt32 nDelta;
    1277           0 :             if (certifInfo.bDim == 1)
    1278             :             {
    1279           0 :                 nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset,
    1280             :                                       &dfX, &dfY, &dfZ);
    1281             :             }
    1282             :             else
    1283             :             {
    1284           0 :                 dfZ = 0.0;
    1285           0 :                 nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset,
    1286             :                                       &dfX, &dfY);
    1287             :             }
    1288             : 
    1289           0 :             if (nDelta == 0)
    1290           0 :                 break;
    1291           0 :             nOffset += nDelta;
    1292             : 
    1293           0 :             poLS->addPoint(dfX, dfY, dfZ);
    1294             :         }
    1295             : 
    1296           0 :         poMLS->addGeometry(poLS);
    1297             :     }  // for
    1298             : 
    1299         984 :     delete poLS;
    1300         984 :     poFeature->SetGeometryDirectly(poMLS);
    1301             : 
    1302             :     /*****
    1303             :      * TODO :
    1304             :      *          - Translate graphics
    1305             :      *          - Translate 3D vector
    1306             :      */
    1307             : 
    1308         984 :     return poFeature;
    1309             : }
    1310             : 
    1311             : /************************************************************************/
    1312             : /*                       TranslateVetorAngle()                          */
    1313             : /************************************************************************/
    1314             : 
    1315             : OGRFeature *
    1316         420 : OGRSXFLayer::TranslateVetorAngle(const SXFRecordDescription &certifInfo,
    1317             :                                  const char *psRecordBuf, GUInt32 nBufLen)
    1318             : {
    1319         420 :     if (certifInfo.nPointCount != 2)
    1320             :     {
    1321           0 :         CPLError(CE_Failure, CPLE_NotSupported,
    1322             :                  "SXF. The vector object should have 2 points, but not.");
    1323           0 :         return nullptr;
    1324             :     }
    1325             : 
    1326         420 :     GUInt32 nOffset = 0;
    1327             : 
    1328         420 :     OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
    1329         420 :     OGRPoint *poPT = new OGRPoint();
    1330             : 
    1331             :     /*---------------------- Reading Primary Line
    1332             :      * --------------------------------*/
    1333             : 
    1334         420 :     OGRLineString *poLS = new OGRLineString();
    1335             : 
    1336        1260 :     for (GUInt32 count = 0; count < certifInfo.nPointCount; count++)
    1337             :     {
    1338         840 :         const char *psCoords = psRecordBuf + nOffset;
    1339             : 
    1340         840 :         double dfX = 1.0;
    1341         840 :         double dfY = 1.0;
    1342         840 :         double dfZ = 0.0;
    1343             :         GInt32 nDelta;
    1344         840 :         if (certifInfo.bDim == 1)
    1345             :         {
    1346           0 :             nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset, &dfX,
    1347             :                                   &dfY, &dfZ);
    1348             :         }
    1349             :         else
    1350             :         {
    1351         840 :             dfZ = 0.0;
    1352         840 :             nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset, &dfX,
    1353             :                                   &dfY);
    1354             :         }
    1355         840 :         if (nDelta == 0)
    1356           0 :             break;
    1357         840 :         nOffset += nDelta;
    1358             : 
    1359         840 :         poLS->addPoint(dfX, dfY, dfZ);
    1360             :     }
    1361             : 
    1362         420 :     poLS->StartPoint(poPT);
    1363             : 
    1364         420 :     OGRPoint *poAngPT = new OGRPoint();
    1365         420 :     poLS->EndPoint(poAngPT);
    1366             : 
    1367         420 :     const double xDiff = poPT->getX() - poAngPT->getX();
    1368         420 :     const double yDiff = poPT->getY() - poAngPT->getY();
    1369         420 :     double dfAngle = atan2(xDiff, yDiff) * TO_DEGREES - 90;
    1370         420 :     if (dfAngle < 0)
    1371         280 :         dfAngle += 360;
    1372             : 
    1373         420 :     poFeature->SetGeometryDirectly(poPT);
    1374         420 :     poFeature->SetField("ANGLE", dfAngle);
    1375             : 
    1376         420 :     delete poAngPT;
    1377         420 :     delete poLS;
    1378             : 
    1379         420 :     return poFeature;
    1380             : }
    1381             : 
    1382             : /************************************************************************/
    1383             : /*                         TranslatePolygon ()                          */
    1384             : /************************************************************************/
    1385             : 
    1386             : OGRFeature *
    1387         510 : OGRSXFLayer::TranslatePolygon(const SXFRecordDescription &certifInfo,
    1388             :                               const char *psRecordBuf, GUInt32 nBufLen)
    1389             : {
    1390         510 :     double dfX = 1.0;
    1391         510 :     double dfY = 1.0;
    1392         510 :     double dfZ = 0.0;
    1393         510 :     GUInt32 nOffset = 0;
    1394         510 :     GUInt32 nDelta = 0;
    1395             : 
    1396         510 :     OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
    1397         510 :     OGRPolygon *poPoly = new OGRPolygon();
    1398         510 :     OGRLineString *poLS = new OGRLineString();
    1399             : 
    1400             :     /*---------------------- Reading Primary Polygon
    1401             :      * --------------------------------*/
    1402       28991 :     for (GUInt32 count = 0; count < certifInfo.nPointCount; count++)
    1403             :     {
    1404       28481 :         const char *psBuf = psRecordBuf + nOffset;
    1405       28481 :         if (certifInfo.bDim == 1)
    1406             :         {
    1407           0 :             nDelta = TranslateXYH(certifInfo, psBuf, nBufLen - nOffset, &dfX,
    1408             :                                   &dfY, &dfZ);
    1409             :         }
    1410             :         else
    1411             :         {
    1412       28481 :             dfZ = 0.0;
    1413             :             nDelta =
    1414       28481 :                 TranslateXYH(certifInfo, psBuf, nBufLen - nOffset, &dfX, &dfY);
    1415             :         }
    1416             : 
    1417       28481 :         if (nDelta == 0)
    1418           0 :             break;
    1419       28481 :         nOffset += nDelta;
    1420       28481 :         poLS->addPoint(dfX, dfY, dfZ);
    1421             :     }  // for
    1422             : 
    1423         510 :     OGRLinearRing *poLR = new OGRLinearRing();
    1424         510 :     poLR->addSubLineString(poLS, 0);
    1425             : 
    1426         510 :     poPoly->addRingDirectly(poLR);
    1427             : 
    1428             :     /*---------------------- Reading Sub Lines
    1429             :      * --------------------------------*/
    1430             : 
    1431         542 :     for (int count = 0; count < certifInfo.nSubObjectCount; count++)
    1432             :     {
    1433          32 :         poLS->empty();
    1434             : 
    1435          32 :         if (nOffset + 4 > nBufLen)
    1436           0 :             break;
    1437             : 
    1438          32 :         GUInt16 nSubObj = 0;
    1439          32 :         memcpy(&nSubObj, psRecordBuf + nOffset, 2);
    1440          32 :         CPL_LSBPTR16(&nSubObj);
    1441             : 
    1442          32 :         GUInt16 nCoords = 0;
    1443          32 :         memcpy(&nCoords, psRecordBuf + nOffset + 2, 2);
    1444          32 :         CPL_LSBPTR16(&nCoords);
    1445             : 
    1446             :         // TODO: Is this really what the buffer size should be?
    1447          32 :         if (nCoords * nDelta != nBufLen - nOffset + 2 - 6)
    1448             :         {
    1449           0 :             CPLError(CE_Warning, CPLE_FileIO,
    1450             :                      "SXF raw feature size incorrect.  "
    1451             :                      "%d %d",
    1452           0 :                      nCoords * nDelta, nBufLen - nOffset + 2 - 6);
    1453             :             // TODO: How best to gracefully exit and report an issue?
    1454             :             // break; or cleanup and return NULL?
    1455             :         }
    1456             : 
    1457          32 :         nOffset += 4;
    1458             : 
    1459         480 :         for (int i = 0; i < nCoords; i++)
    1460             :         {
    1461         448 :             const char *psCoords = psRecordBuf + nOffset;
    1462         448 :             if (certifInfo.bDim == 1)
    1463             :             {
    1464           0 :                 nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset,
    1465             :                                       &dfX, &dfY, &dfZ);
    1466             :             }
    1467             :             else
    1468             :             {
    1469         448 :                 dfZ = 0.0;
    1470         448 :                 nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset,
    1471             :                                       &dfX, &dfY);
    1472             :             }
    1473             : 
    1474         448 :             if (nDelta == 0)
    1475           0 :                 break;
    1476         448 :             nOffset += nDelta;
    1477             : 
    1478         448 :             poLS->addPoint(dfX, dfY, dfZ);
    1479             :         }
    1480             : 
    1481          32 :         poLR = new OGRLinearRing();
    1482          32 :         poLR->addSubLineString(poLS, 0);
    1483             : 
    1484          32 :         poPoly->addRingDirectly(poLR);
    1485             :     }  // for
    1486             : 
    1487         510 :     poFeature->SetGeometryDirectly(poPoly);  // poLS);
    1488         510 :     delete poLS;
    1489             : 
    1490             :     /*****
    1491             :      * TODO :
    1492             :      *          - Translate graphics
    1493             :      *          - Translate 3D vector
    1494             :      */
    1495         510 :     return poFeature;
    1496             : }
    1497             : 
    1498             : /************************************************************************/
    1499             : /*                         TranslateText    ()                          */
    1500             : /************************************************************************/
    1501         140 : OGRFeature *OGRSXFLayer::TranslateText(const SXFRecordDescription &certifInfo,
    1502             :                                        const char *psRecordBuf, GUInt32 nBufLen)
    1503             : {
    1504         140 :     double dfX = 1.0;
    1505         140 :     double dfY = 1.0;
    1506         140 :     double dfZ = 0.0;
    1507         140 :     GUInt32 nOffset = 0;
    1508             : 
    1509         140 :     OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
    1510         140 :     OGRMultiLineString *poMLS = new OGRMultiLineString();
    1511             : 
    1512             :     /*---------------------- Reading Primary Line
    1513             :      * --------------------------------*/
    1514             : 
    1515         140 :     OGRLineString *poLS = new OGRLineString();
    1516             : 
    1517         420 :     for (GUInt32 count = 0; count < certifInfo.nPointCount; count++)
    1518             :     {
    1519         280 :         const char *psCoords = psRecordBuf + nOffset;
    1520             : 
    1521             :         GUInt32 nDelta;
    1522         280 :         if (certifInfo.bDim == 1)
    1523             :         {
    1524           0 :             nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset, &dfX,
    1525             :                                   &dfY, &dfZ);
    1526             :         }
    1527             :         else
    1528             :         {
    1529         280 :             dfZ = 0.0;
    1530         280 :             nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset, &dfX,
    1531             :                                   &dfY);
    1532             :         }
    1533             : 
    1534         280 :         if (nDelta == 0)
    1535           0 :             break;
    1536         280 :         nOffset += nDelta;
    1537             : 
    1538         280 :         poLS->addPoint(dfX, dfY, dfZ);
    1539             :     }
    1540             : 
    1541         140 :     poMLS->addGeometry(poLS);
    1542             : 
    1543             :     /*------------------     READING TEXT VALUE
    1544             :      * --------------------------------*/
    1545         280 :     CPLString soText;
    1546             : 
    1547         140 :     if (certifInfo.bHasTextSign)
    1548             :     {
    1549         140 :         if (nOffset + 1 > nBufLen)
    1550           0 :             return poFeature;
    1551         140 :         const char *pszTxt = psRecordBuf + nOffset;
    1552         140 :         GByte nTextL = (GByte)*pszTxt;
    1553         140 :         if (nOffset + 1 + nTextL > nBufLen)
    1554           0 :             return poFeature;
    1555             : 
    1556         140 :         char *pszTextBuf = (char *)CPLMalloc(nTextL + 1);
    1557             : 
    1558         140 :         strncpy(pszTextBuf, (pszTxt + 1), nTextL);
    1559         140 :         pszTextBuf[nTextL] = '\0';
    1560             : 
    1561             :         // TODO: Check encoding from sxf
    1562         140 :         char *pszRecoded = CPLRecode(pszTextBuf, "CP1251", CPL_ENC_UTF8);
    1563         140 :         soText += pszRecoded;
    1564         140 :         CPLFree(pszRecoded);
    1565             : 
    1566         140 :         CPLFree(pszTextBuf);
    1567             : 
    1568         140 :         nOffset += nTextL + 2;
    1569             :     }
    1570             : 
    1571             :     /*---------------------- Reading Sub Lines
    1572             :      * --------------------------------*/
    1573             : 
    1574         140 :     for (int count = 0; count < certifInfo.nSubObjectCount; count++)
    1575             :     {
    1576           0 :         poLS->empty();
    1577             : 
    1578           0 :         if (nOffset + 4 > nBufLen)
    1579           0 :             break;
    1580             : 
    1581           0 :         GUInt16 nSubObj = 0;
    1582           0 :         memcpy(&nSubObj, psRecordBuf + nOffset, 2);
    1583           0 :         CPL_LSBPTR16(&nSubObj);
    1584             : 
    1585           0 :         GUInt16 nCoords = 0;
    1586           0 :         memcpy(&nCoords, psRecordBuf + nOffset + 2, 2);
    1587           0 :         CPL_LSBPTR16(&nCoords);
    1588             : 
    1589           0 :         nOffset += 4;
    1590             : 
    1591           0 :         for (int i = 0; i < nCoords; i++)
    1592             :         {
    1593           0 :             const char *psCoords = psRecordBuf + nOffset;
    1594             :             GUInt32 nDelta;
    1595           0 :             if (certifInfo.bDim == 1)
    1596             :             {
    1597           0 :                 nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset,
    1598             :                                       &dfX, &dfY, &dfZ);
    1599             :             }
    1600             :             else
    1601             :             {
    1602           0 :                 dfZ = 0.0;
    1603           0 :                 nDelta = TranslateXYH(certifInfo, psCoords, nBufLen - nOffset,
    1604             :                                       &dfX, &dfY);
    1605             :             }
    1606             : 
    1607           0 :             if (nDelta == 0)
    1608           0 :                 break;
    1609           0 :             nOffset += nDelta;
    1610             : 
    1611           0 :             poLS->addPoint(dfX, dfY, dfZ);
    1612             :         }
    1613             : 
    1614           0 :         poMLS->addGeometry(poLS);
    1615             : 
    1616           0 :         if (certifInfo.bHasTextSign)
    1617             :         {
    1618           0 :             if (nOffset + 1 > nBufLen)
    1619           0 :                 return poFeature;
    1620           0 :             const char *pszTxt = psRecordBuf + nOffset;
    1621           0 :             GByte nTextL = (GByte)*pszTxt;
    1622           0 :             if (nOffset + 1 + nTextL > nBufLen)
    1623           0 :                 return poFeature;
    1624             : 
    1625           0 :             char *pszTextBuf = (char *)CPLMalloc(nTextL + 1);
    1626             : 
    1627           0 :             strncpy(pszTextBuf, (pszTxt + 1), nTextL);
    1628           0 :             pszTextBuf[nTextL] = '\0';
    1629             : 
    1630             :             // TODO: Check encoding from sxf
    1631           0 :             char *pszRecoded = CPLRecode(pszTextBuf, "CP1251", CPL_ENC_UTF8);
    1632           0 :             soText += " " + CPLString(pszRecoded);
    1633           0 :             CPLFree(pszRecoded);
    1634             : 
    1635           0 :             CPLFree(pszTextBuf);
    1636             : 
    1637           0 :             nOffset += nTextL + 2;
    1638             :         }
    1639             :     }  // for
    1640             : 
    1641         140 :     delete poLS;
    1642         140 :     poFeature->SetGeometryDirectly(poMLS);
    1643             : 
    1644         140 :     poFeature->SetField("TEXT", soText);
    1645         140 :     return poFeature;
    1646             : }
    1647             : 
    1648         297 : const char *OGRSXFLayer::GetFIDColumn()
    1649             : {
    1650         297 :     return sFIDColumn_.c_str();
    1651             : }

Generated by: LCOV version 1.14