LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/gml - gmlreaderp.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 67 69 97.1 %
Date: 2025-12-03 21:30:40 Functions: 29 30 96.7 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GML Reader
       4             :  * Purpose:  Private Declarations for OGR free GML Reader code.
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2002, Frank Warmerdam
       9             :  * Copyright (c) 2008-2013, Even Rouault <even dot rouault at spatialys.com>
      10             :  *
      11             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #ifndef CPL_GMLREADERP_H_INCLUDED
      15             : #define CPL_GMLREADERP_H_INCLUDED
      16             : 
      17             : #if defined(HAVE_XERCES)
      18             : 
      19             : #include "xercesc_headers.h"
      20             : #include "ogr_xerces.h"
      21             : 
      22             : #endif /* HAVE_XERCES */
      23             : 
      24             : #include "cpl_string.h"
      25             : #include "gmlreader.h"
      26             : #include "ogr_api.h"
      27             : #include "cpl_vsi.h"
      28             : #include "cpl_multiproc.h"
      29             : #include "gmlutils.h"
      30             : 
      31             : #include <map>
      32             : #include <string>
      33             : #include <vector>
      34             : 
      35             : #define PARSER_BUF_SIZE (10 * 8192)
      36             : 
      37             : class GMLReader;
      38             : 
      39             : typedef struct _GeometryNamesStruct GeometryNamesStruct;
      40             : 
      41             : bool OGRGMLIsGeometryElement(const char *pszElement);
      42             : 
      43             : /************************************************************************/
      44             : /*                        GFSTemplateList                               */
      45             : /************************************************************************/
      46             : 
      47             : class GFSTemplateItem;
      48             : 
      49             : class GFSTemplateList
      50             : {
      51             :   private:
      52             :     bool m_bSequentialLayers;
      53             :     GFSTemplateItem *pFirst;
      54             :     GFSTemplateItem *pLast;
      55             :     GFSTemplateItem *Insert(const char *pszName);
      56             : 
      57             :     CPL_DISALLOW_COPY_ASSIGN(GFSTemplateList)
      58             : 
      59             :   public:
      60             :     GFSTemplateList();
      61             :     ~GFSTemplateList();
      62             :     void Update(const char *pszName, int bHasGeom);
      63             : 
      64          10 :     GFSTemplateItem *GetFirst()
      65             :     {
      66          10 :         return pFirst;
      67             :     }
      68             : 
      69           5 :     bool HaveSequentialLayers()
      70             :     {
      71           5 :         return m_bSequentialLayers;
      72             :     }
      73             : 
      74             :     int GetClassCount();
      75             : };
      76             : 
      77             : void gmlUpdateFeatureClasses(GFSTemplateList *pCC, GMLReader *pReader,
      78             :                              int *pnHasSequentialLayers);
      79             : 
      80             : /************************************************************************/
      81             : /*                              GMLHandler                              */
      82             : /************************************************************************/
      83             : 
      84             : #define STACK_SIZE 5
      85             : 
      86             : typedef enum
      87             : {
      88             :     STATE_TOP,
      89             :     STATE_DEFAULT,
      90             :     STATE_FEATURE,
      91             :     STATE_PROPERTY,
      92             :     STATE_FEATUREPROPERTY,
      93             :     STATE_GEOMETRY,
      94             :     STATE_IGNORED_FEATURE,
      95             :     STATE_BOUNDED_BY,
      96             :     STATE_BOUNDED_BY_IN_FEATURE,
      97             :     STATE_CITYGML_ATTRIBUTE
      98             : } HandlerState;
      99             : 
     100             : typedef struct
     101             : {
     102             :     CPLXMLNode *psNode;
     103             :     CPLXMLNode *psLastChild;
     104             : } NodeLastChild;
     105             : 
     106             : typedef enum
     107             : {
     108             :     APPSCHEMA_GENERIC,
     109             :     APPSCHEMA_CITYGML,
     110             :     APPSCHEMA_AIXM,
     111             :     APPSCHEMA_MTKGML /* format of National Land Survey Finnish */
     112             : } GMLAppSchemaType;
     113             : 
     114             : class GMLHandler /* non final */
     115             : {
     116             :     char *m_pszCurField = nullptr;
     117             :     unsigned int m_nCurFieldAlloc = 0;
     118             :     unsigned int m_nCurFieldLen = 0;
     119             :     bool m_bInCurField = false;
     120             :     int m_nAttributeIndex = -1;
     121             :     int m_nAttributeDepth = 0;
     122             : 
     123             :     char *m_pszGeometry = nullptr;
     124             :     unsigned int m_nGeomAlloc = 0;
     125             :     unsigned int m_nGeomLen = 0;
     126             :     int m_nGeometryDepth = 0;
     127             :     bool m_bAlreadyFoundGeometry = false;
     128             :     int m_nGeometryPropertyIndex = 0;
     129             :     std::string m_osLastGeomPathInCurFeature{};
     130             :     std::map<std::string, CPLXMLNode *> m_oMapElementToSubstitute{};
     131             : 
     132             :     int m_nDepth = 0;
     133             :     int m_nDepthFeature = 0;
     134             :     int m_nUnlimitedDepth = -1;  // -1 unknown, 0=false, 1=true
     135             : 
     136             :     int m_inBoundedByDepth = 0;
     137             : 
     138             :     char *m_pszCityGMLGenericAttrName = nullptr;
     139             :     int m_inCityGMLGenericAttrDepth = 0;
     140             : 
     141             :     bool m_bReportHref = false;
     142             :     char *m_pszHref = nullptr;
     143             :     char *m_pszUom = nullptr;
     144             :     char *m_pszValue = nullptr;
     145             :     char *m_pszKieli = nullptr;
     146             : 
     147             :     GeometryNamesStruct *pasGeometryNames = nullptr;
     148             : 
     149             :     std::vector<NodeLastChild> apsXMLNode{};
     150             : 
     151             :     int m_nSRSDimensionIfMissing = 0;
     152             : 
     153             :     OGRErr startElementTop(const char *pszName, int nLenName, void *attr);
     154             : 
     155             :     OGRErr endElementIgnoredFeature();
     156             : 
     157             :     OGRErr startElementBoundedBy(const char *pszName, int nLenName, void *attr);
     158             :     OGRErr endElementBoundedBy();
     159             : 
     160             :     OGRErr endElementBoundedByInFeature();
     161             : 
     162             :     OGRErr startElementFeatureAttribute(const char *pszName, int nLenName,
     163             :                                         void *attr);
     164             :     OGRErr endElementFeature();
     165             : 
     166             :     OGRErr startElementCityGMLGenericAttr(const char *pszName, int nLenName,
     167             :                                           void *attr);
     168             :     OGRErr endElementCityGMLGenericAttr();
     169             : 
     170             :     OGRErr startElementGeometry(const char *pszName, int nLenName, void *attr);
     171             :     void ParseAIXMElevationProperties(const CPLXMLNode *);
     172             :     CPLXMLNode *ParseAIXMElevationPoint(CPLXMLNode *);
     173             :     OGRErr endElementGeometry();
     174             :     OGRErr dataHandlerGeometry(const char *data, int nLen);
     175             : 
     176             :     OGRErr endElementAttribute();
     177             :     OGRErr dataHandlerAttribute(const char *data, int nLen);
     178             : 
     179             :     OGRErr startElementDefault(const char *pszName, int nLenName, void *attr);
     180             :     OGRErr endElementDefault();
     181             : 
     182             :     OGRErr startElementFeatureProperty(const char *pszName, int nLenName,
     183             :                                        void *attr);
     184             :     OGRErr endElementFeatureProperty();
     185             : 
     186             :     void DealWithAttributes(const char *pszName, int nLenName, void *attr);
     187             :     bool IsConditionMatched(const char *pszCondition, void *attr);
     188             :     int FindRealPropertyByCheckingConditions(int nIdx, void *attr);
     189             : 
     190             :     CPL_DISALLOW_COPY_ASSIGN(GMLHandler)
     191             : 
     192             :   protected:
     193             :     explicit GMLHandler(GMLReader *poReader);
     194             : 
     195             :     GMLReader *m_poReader = nullptr;
     196             :     GMLAppSchemaType eAppSchemaType = APPSCHEMA_GENERIC;
     197             : 
     198             :     int nStackDepth = 0;
     199             :     HandlerState stateStack[STACK_SIZE];
     200             : 
     201             :     CPLString m_osFID{};
     202             :     virtual const char *GetFID(void *attr) = 0;
     203             : 
     204             :     virtual CPLXMLNode *AddAttributes(CPLXMLNode *psNode, void *attr) = 0;
     205             : 
     206             :     OGRErr startElement(const char *pszName, int nLenName, void *attr);
     207             :     OGRErr endElement();
     208             :     OGRErr dataHandler(const char *data, int nLen);
     209             : 
     210             :     bool IsGeometryElement(const char *pszElement);
     211             : 
     212             :   public:
     213             :     virtual ~GMLHandler();
     214             : 
     215             :     virtual char *GetAttributeValue(void *attr,
     216             :                                     const char *pszAttributeName) = 0;
     217             :     virtual char *GetAttributeByIdx(void *attr, unsigned int idx,
     218             :                                     char **ppszKey) = 0;
     219             : 
     220           5 :     GMLAppSchemaType GetAppSchemaType() const
     221             :     {
     222           5 :         return eAppSchemaType;
     223             :     }
     224             : };
     225             : 
     226             : #if defined(HAVE_XERCES)
     227             : 
     228             : /************************************************************************/
     229             : /*                         GMLXercesHandler                             */
     230             : /************************************************************************/
     231             : class GMLXercesHandler final : public DefaultHandler, public GMLHandler
     232             : {
     233             :     int m_nEntityCounter = 0;
     234             :     CPLString m_osElement{};
     235             :     CPLString m_osCharacters{};
     236             :     CPLString m_osAttrName{};
     237             :     CPLString m_osAttrValue{};
     238             : 
     239             :   public:
     240             :     explicit GMLXercesHandler(GMLReader *poReader);
     241             : 
     242             :     void startElement(const XMLCh *const uri, const XMLCh *const localname,
     243             :                       const XMLCh *const qname,
     244             :                       const Attributes &attrs) override;
     245             :     void endElement(const XMLCh *const uri, const XMLCh *const localname,
     246             :                     const XMLCh *const qname) override;
     247             :     void characters(const XMLCh *const chars, const XMLSize_t length) override;
     248             : 
     249             :     void fatalError(const SAXParseException &) override;
     250             : 
     251             :     void startEntity(const XMLCh *const name) override;
     252             : 
     253             :     const char *GetFID(void *attr) override;
     254             :     CPLXMLNode *AddAttributes(CPLXMLNode *psNode, void *attr) override;
     255             :     virtual char *GetAttributeValue(void *attr,
     256             :                                     const char *pszAttributeName) override;
     257             :     virtual char *GetAttributeByIdx(void *attr, unsigned int idx,
     258             :                                     char **ppszKey) override;
     259             : };
     260             : 
     261             : #endif
     262             : 
     263             : #if defined(HAVE_EXPAT)
     264             : 
     265             : #include "ogr_expat.h"
     266             : 
     267             : /************************************************************************/
     268             : /*                           GMLExpatHandler                            */
     269             : /************************************************************************/
     270             : class GMLExpatHandler final : public GMLHandler
     271             : {
     272             :     XML_Parser m_oParser = nullptr;
     273             :     bool m_bStopParsing = false;
     274             :     int m_nDataHandlerCounter = 0;
     275             : 
     276             :     void DealWithError(OGRErr eErr);
     277             : 
     278             :     CPL_DISALLOW_COPY_ASSIGN(GMLExpatHandler)
     279             : 
     280             :   public:
     281             :     GMLExpatHandler(GMLReader *poReader, XML_Parser oParser);
     282             : 
     283         600 :     bool HasStoppedParsing()
     284             :     {
     285         600 :         return m_bStopParsing;
     286             :     }
     287             : 
     288         605 :     void ResetDataHandlerCounter()
     289             :     {
     290         605 :         m_nDataHandlerCounter = 0;
     291         605 :     }
     292             : 
     293             :     const char *GetFID(void *attr) override;
     294             :     CPLXMLNode *AddAttributes(CPLXMLNode *psNode, void *attr) override;
     295             :     virtual char *GetAttributeValue(void *attr,
     296             :                                     const char *pszAttributeName) override;
     297             :     virtual char *GetAttributeByIdx(void *attr, unsigned int idx,
     298             :                                     char **ppszKey) override;
     299             : 
     300             :     static void XMLCALL startElementCbk(void *pUserData, const char *pszName,
     301             :                                         const char **ppszAttr);
     302             : 
     303             :     static void XMLCALL endElementCbk(void *pUserData, const char *pszName);
     304             : 
     305             :     static void XMLCALL dataHandlerCbk(void *pUserData, const char *data,
     306             :                                        int nLen);
     307             : };
     308             : 
     309             : #endif
     310             : 
     311             : /************************************************************************/
     312             : /*                             GMLReadState                             */
     313             : /************************************************************************/
     314             : 
     315             : class GMLReadState
     316             : {
     317             :     std::vector<std::string> aosPathComponents{};
     318             : 
     319             :     CPL_DISALLOW_COPY_ASSIGN(GMLReadState)
     320             : 
     321             :   public:
     322         939 :     GMLReadState() = default;
     323         939 :     ~GMLReadState() = default;
     324             : 
     325             :     void PushPath(const char *pszElement, int nLen = -1);
     326             :     void PopPath();
     327             : 
     328        6331 :     const char *GetLastComponent() const
     329             :     {
     330        6331 :         return (m_nPathLength == 0)
     331        6331 :                    ? ""
     332        6331 :                    : aosPathComponents[m_nPathLength - 1].c_str();
     333             :     }
     334             : 
     335        6147 :     size_t GetLastComponentLen() const
     336             :     {
     337        6147 :         return (m_nPathLength == 0)
     338        6147 :                    ? 0
     339        6147 :                    : aosPathComponents[m_nPathLength - 1].size();
     340             :     }
     341             : 
     342             :     void Reset();
     343             : 
     344             :     GMLFeature *m_poFeature = nullptr;
     345             :     GMLReadState *m_poParentState = nullptr;
     346             : 
     347             :     std::string osPath{};  // element path ... | as separator.
     348             :     int m_nPathLength = 0;
     349             : };
     350             : 
     351             : /************************************************************************/
     352             : /*                              GMLReader                               */
     353             : /************************************************************************/
     354             : 
     355             : class GMLReader final : public IGMLReader
     356             : {
     357             :   private:
     358             :     bool m_bClassListLocked = false;
     359             : 
     360             :     int m_nClassCount = 0;
     361             :     GMLFeatureClass **m_papoClass = nullptr;
     362             :     bool m_bLookForClassAtAnyLevel = false;
     363             : 
     364             :     char *m_pszFilename = nullptr;
     365             : 
     366             : #ifndef HAVE_XERCES
     367             :     bool bUseExpatReader = true;
     368             : #else
     369             :     bool bUseExpatReader = false;
     370             : #endif
     371             : 
     372             :     GMLHandler *m_poGMLHandler = nullptr;
     373             : 
     374             : #if defined(HAVE_XERCES)
     375             :     SAX2XMLReader *m_poSAXReader = nullptr;
     376             :     XMLPScanToken m_oToFill{};
     377             :     GMLFeature *m_poCompleteFeature = nullptr;
     378             :     InputSource *m_GMLInputSource = nullptr;
     379             :     bool m_bEOF = false;
     380             :     bool m_bXercesInitialized = false;
     381             :     bool SetupParserXerces();
     382             :     GMLFeature *NextFeatureXerces();
     383             : #endif
     384             : 
     385             : #if defined(HAVE_EXPAT)
     386             :     XML_Parser oParser = nullptr;
     387             :     GMLFeature **ppoFeatureTab = nullptr;
     388             :     int nFeatureTabLength = 0;
     389             :     int nFeatureTabIndex = 0;
     390             :     int nFeatureTabAlloc = 0;
     391             :     bool SetupParserExpat();
     392             :     GMLFeature *NextFeatureExpat();
     393             :     char *pabyBuf = nullptr;
     394             :     CPLString m_osErrorMessage{};
     395             : #endif
     396             : 
     397             :     VSILFILE *fpGML = nullptr;
     398             :     bool m_bReadStarted = false;
     399             : 
     400             :     GMLReadState *m_poState = nullptr;
     401             :     GMLReadState *m_poRecycledState = nullptr;
     402             : 
     403             :     bool m_bStopParsing = false;
     404             : 
     405             :     bool SetupParser();
     406             :     void CleanupParser();
     407             : 
     408             :     bool m_bFetchAllGeometries = false;
     409             : 
     410             :     bool m_bInvertAxisOrderIfLatLong = false;
     411             :     bool m_bConsiderEPSGAsURN = false;
     412             :     GMLSwapCoordinatesEnum m_eSwapCoordinates = GML_SWAP_AUTO;
     413             :     bool m_bGetSecondaryGeometryOption = false;
     414             : 
     415             :     int ParseFeatureType(CPLXMLNode *psSchemaNode, const char *pszName,
     416             :                          const char *pszType);
     417             : 
     418             :     char *m_pszGlobalSRSName = nullptr;
     419             :     bool m_bCanUseGlobalSRSName = false;
     420             : 
     421             :     char *m_pszFilteredClassName = nullptr;
     422             :     int m_nFilteredClassIndex = -1;
     423             : 
     424             :     int m_nHasSequentialLayers = -1;
     425             : 
     426             :     std::string osElemPath{};
     427             : 
     428             :     bool m_bFaceHoleNegative = false;
     429             : 
     430             :     bool m_bSetWidthFlag = true;
     431             : 
     432             :     bool m_bReportAllAttributes = false;
     433             : 
     434             :     bool m_bIsWFSJointLayer = false;
     435             : 
     436             :     bool m_bEmptyAsNull = true;
     437             : 
     438             :     bool m_bUseBBOX = false;
     439             : 
     440             :     bool ParseXMLHugeFile(const char *pszOutputFilename,
     441             :                           const bool bSqliteIsTempFile,
     442             :                           const int iSqliteCacheMB);
     443             : 
     444             :     CPL_DISALLOW_COPY_ASSIGN(GMLReader)
     445             : 
     446             :   public:
     447             :     GMLReader(bool bExpatReader, bool bInvertAxisOrderIfLatLong,
     448             :               bool bConsiderEPSGAsURN, GMLSwapCoordinatesEnum eSwapCoordinates,
     449             :               bool bGetSecondaryGeometryOption);
     450             :     ~GMLReader() override;
     451             : 
     452           0 :     bool IsClassListLocked() const override
     453             :     {
     454           0 :         return m_bClassListLocked;
     455             :     }
     456             : 
     457         466 :     void SetClassListLocked(bool bFlag) override
     458             :     {
     459         466 :         m_bClassListLocked = bFlag;
     460         466 :     }
     461             : 
     462             :     void SetSourceFile(const char *pszFilename) override;
     463             :     void SetFP(VSILFILE *fp) override;
     464             :     const char *GetSourceFileName() override;
     465             : 
     466        3713 :     int GetClassCount() const override
     467             :     {
     468        3713 :         return m_nClassCount;
     469             :     }
     470             : 
     471             :     GMLFeatureClass *GetClass(int i) const override;
     472             :     GMLFeatureClass *GetClass(const char *pszName) const override;
     473             : 
     474             :     int AddClass(GMLFeatureClass *poClass) override;
     475             :     void ClearClasses() override;
     476             : 
     477             :     GMLFeature *NextFeature() override;
     478             : 
     479             :     bool LoadClasses(const char *pszFile = nullptr) override;
     480             :     bool SaveClasses(const char *pszFile = nullptr) override;
     481             : 
     482             :     bool ResolveXlinks(const char *pszFile, bool *pbOutIsTempFile,
     483             :                        char **papszSkip = nullptr,
     484             :                        const bool bStrict = false) override;
     485             : 
     486             :     bool HugeFileResolver(const char *pszFile, bool bSqliteIsTempFile,
     487             :                           int iSqliteCacheMB) override;
     488             : 
     489             :     bool PrescanForSchema(bool bGetExtents = true,
     490             :                           bool bOnlyDetectSRS = false) override;
     491             :     bool PrescanForTemplate() override;
     492             :     bool ReArrangeTemplateClasses(GFSTemplateList *pCC);
     493             :     void ResetReading() override;
     494             : 
     495             :     // ---
     496             : 
     497       68340 :     GMLReadState *GetState() const
     498             :     {
     499       68340 :         return m_poState;
     500             :     }
     501             : 
     502             :     void PopState();
     503             :     void PushState(GMLReadState *);
     504             : 
     505        6984 :     bool ShouldLookForClassAtAnyLevel()
     506             :     {
     507        6984 :         return m_bLookForClassAtAnyLevel;
     508             :     }
     509             : 
     510             :     int GetFeatureElementIndex(const char *pszElement, int nLen,
     511             :                                GMLAppSchemaType eAppSchemaType);
     512             :     int GetAttributeElementIndex(const char *pszElement, int nLen,
     513             :                                  const char *pszAttrKey = nullptr);
     514             :     bool IsCityGMLGenericAttributeElement(const char *pszElement, void *attr);
     515             : 
     516             :     void PushFeature(const char *pszElement, const char *pszFID,
     517             :                      int nClassIndex);
     518             : 
     519             :     void SetFeaturePropertyDirectly(const char *pszElement, char *pszValue,
     520             :                                     int iPropertyIn,
     521             :                                     GMLPropertyType eType = GMLPT_Untyped);
     522             : 
     523           8 :     void SetWidthFlag(bool bFlag)
     524             :     {
     525           8 :         m_bSetWidthFlag = bFlag;
     526           8 :     }
     527             : 
     528         121 :     bool HasStoppedParsing() override
     529             :     {
     530         121 :         return m_bStopParsing;
     531             :     }
     532             : 
     533        4965 :     bool FetchAllGeometries()
     534             :     {
     535        4965 :         return m_bFetchAllGeometries;
     536             :     }
     537             : 
     538             :     void SetGlobalSRSName(const char *pszGlobalSRSName) override;
     539             : 
     540         519 :     const char *GetGlobalSRSName() override
     541             :     {
     542         519 :         return m_pszGlobalSRSName;
     543             :     }
     544             : 
     545        1103 :     bool CanUseGlobalSRSName() override
     546             :     {
     547        1103 :         return m_bCanUseGlobalSRSName;
     548             :     }
     549             : 
     550             :     bool SetFilteredClassName(const char *pszClassName) override;
     551             : 
     552        4328 :     const char *GetFilteredClassName() override
     553             :     {
     554        4328 :         return m_pszFilteredClassName;
     555             :     }
     556             : 
     557          49 :     int GetFilteredClassIndex()
     558             :     {
     559          49 :         return m_nFilteredClassIndex;
     560             :     }
     561             : 
     562          88 :     bool IsSequentialLayers() const override
     563             :     {
     564          88 :         return m_nHasSequentialLayers == TRUE;
     565             :     }
     566             : 
     567         457 :     void SetReportAllAttributes(bool bFlag)
     568             :     {
     569         457 :         m_bReportAllAttributes = bFlag;
     570         457 :     }
     571             : 
     572         511 :     bool ReportAllAttributes() const
     573             :     {
     574         511 :         return m_bReportAllAttributes;
     575             :     }
     576             : 
     577         457 :     void SetIsWFSJointLayer(bool bFlag)
     578             :     {
     579         457 :         m_bIsWFSJointLayer = bFlag;
     580         457 :     }
     581             : 
     582       29386 :     bool IsWFSJointLayer() const
     583             :     {
     584       29386 :         return m_bIsWFSJointLayer;
     585             :     }
     586             : 
     587         457 :     void SetEmptyAsNull(bool bFlag)
     588             :     {
     589         457 :         m_bEmptyAsNull = bFlag;
     590         457 :     }
     591             : 
     592          70 :     bool IsEmptyAsNull() const
     593             :     {
     594          70 :         return m_bEmptyAsNull;
     595             :     }
     596             : 
     597         457 :     void SetUseBBOX(bool bFlag)
     598             :     {
     599         457 :         m_bUseBBOX = bFlag;
     600         457 :     }
     601             : 
     602         909 :     bool UseBBOX() const
     603             :     {
     604         909 :         return m_bUseBBOX;
     605             :     }
     606             : 
     607             :     static CPLMutex *hMutex;
     608             : };
     609             : 
     610             : #endif /* CPL_GMLREADERP_H_INCLUDED */

Generated by: LCOV version 1.14