LCOV - code coverage report
Current view: top level - gcore - nasakeywordhandler.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 248 262 94.7 %
Date: 2024-05-04 12:52:34 Functions: 11 12 91.7 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  PDS Driver; Planetary Data System Format
       4             :  * Purpose:  Implementation of NASAKeywordHandler - a class to read
       5             :  *           keyword data from PDS, ISIS2 and ISIS3 data products.
       6             :  * Author:   Frank Warmerdam <warmerdam@pobox.com
       7             :  *
       8             :  ******************************************************************************
       9             :  * Copyright (c) 2006, Frank Warmerdam <warmerdam@pobox.com>
      10             :  * Copyright (c) 2008-2010, Even Rouault <even dot rouault at spatialys.com>
      11             :  * Copyright (c) 2017 Hobu Inc
      12             :  * Copyright (c) 2017, Dmitry Baryshnikov <polimax@mail.ru>
      13             :  * Copyright (c) 2017, NextGIS <info@nextgis.com>
      14             :  *
      15             :  * Permission is hereby granted, free of charge, to any person obtaining a
      16             :  * copy of this software and associated documentation files (the "Software"),
      17             :  * to deal in the Software without restriction, including without limitation
      18             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      19             :  * and/or sell copies of the Software, and to permit persons to whom the
      20             :  * Software is furnished to do so, subject to the following conditions:
      21             :  *
      22             :  * The above copyright notice and this permission notice shall be included
      23             :  * in all copies or substantial portions of the Software.
      24             :  *
      25             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      26             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      27             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      28             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      29             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      30             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      31             :  * DEALINGS IN THE SOFTWARE.
      32             :  ****************************************************************************
      33             :  * Object Description Language (ODL) is used to encode data labels for PDS
      34             :  * and other NASA data systems. Refer to Chapter 12 of "PDS Standards
      35             :  * Reference" at http://pds.jpl.nasa.gov/tools/standards-reference.shtml for
      36             :  * further details about ODL.
      37             :  *
      38             :  * This is also known as PVL (Parameter Value Language) which is written
      39             :  * about at http://www.orrery.us/node/44 where it notes:
      40             :  *
      41             :  * The PVL syntax that the PDS uses is specified by the Consultative Committee
      42             :  * for Space Data Systems in their Blue Book publication: "Parameter Value
      43             :  * Language Specification (CCSD0006 and CCSD0008)", June 2000
      44             :  * [CCSDS 641.0-B-2], and Green Book publication: "Parameter Value Language -
      45             :  * A Tutorial", June 2000 [CCSDS 641.0-G-2]. PVL has also been accepted by the
      46             :  * International Standards Organization (ISO), as a Final Draft International
      47             :  * Standard (ISO 14961:2002) keyword value type language for naming and
      48             :  * expressing data values.
      49             :  * --
      50             :  * also of interest, on PDS ODL:
      51             :  *  http://pds.jpl.nasa.gov/documents/sr/Chapter12.pdf
      52             :  *
      53             :  ****************************************************************************/
      54             : 
      55             : #include "nasakeywordhandler.h"
      56             : #include "ogrgeojsonreader.h"
      57             : #include <vector>
      58             : 
      59             : //! @cond Doxygen_Suppress
      60             : 
      61             : /************************************************************************/
      62             : /* ==================================================================== */
      63             : /*                          NASAKeywordHandler                          */
      64             : /* ==================================================================== */
      65             : /************************************************************************/
      66             : 
      67             : /************************************************************************/
      68             : /*                         NASAKeywordHandler()                         */
      69             : /************************************************************************/
      70             : 
      71         499 : NASAKeywordHandler::NASAKeywordHandler()
      72         499 :     : pszHeaderNext(nullptr), m_bStripSurroundingQuotes(false)
      73             : {
      74         499 :     oJSon.Deinit();
      75         499 : }
      76             : 
      77             : /************************************************************************/
      78             : /*                        ~NASAKeywordHandler()                         */
      79             : /************************************************************************/
      80             : 
      81         499 : NASAKeywordHandler::~NASAKeywordHandler()
      82             : 
      83             : {
      84         499 : }
      85             : 
      86             : /************************************************************************/
      87             : /*                               Ingest()                               */
      88             : /************************************************************************/
      89             : 
      90         348 : bool NASAKeywordHandler::Ingest(VSILFILE *fp, int nOffset)
      91             : 
      92             : {
      93             :     /* -------------------------------------------------------------------- */
      94             :     /*      Read in buffer till we find END all on its own line.            */
      95             :     /* -------------------------------------------------------------------- */
      96         348 :     if (VSIFSeekL(fp, nOffset, SEEK_SET) != 0)
      97           0 :         return false;
      98             : 
      99         696 :     std::string osHeaderText;
     100             :     for (; true;)
     101             :     {
     102             :         char szChunk[513];
     103             : 
     104        4241 :         int nBytesRead = static_cast<int>(VSIFReadL(szChunk, 1, 512, fp));
     105             : 
     106        4241 :         szChunk[nBytesRead] = '\0';
     107        4241 :         osHeaderText += szChunk;
     108             : 
     109        4241 :         if (nBytesRead < 512)
     110         165 :             break;
     111             : 
     112        4076 :         const char *pszCheck = nullptr;
     113        4076 :         if (osHeaderText.size() > 520)
     114         538 :             pszCheck = osHeaderText.c_str() + (osHeaderText.size() - 520);
     115             :         else
     116        3538 :             pszCheck = szChunk;
     117             : 
     118        4076 :         if (strstr(pszCheck, "\r\nEND\r\n") != nullptr ||
     119        4061 :             strstr(pszCheck, "\nEND\n") != nullptr ||
     120        4011 :             strstr(pszCheck, "\r\nEnd\r\n") != nullptr ||
     121        4011 :             strstr(pszCheck, "\nEnd\n") != nullptr)
     122             :             break;
     123        3893 :     }
     124             : 
     125         348 :     return Parse(osHeaderText.c_str());
     126             : }
     127             : 
     128             : /************************************************************************/
     129             : /*                               Parse()                                */
     130             : /************************************************************************/
     131             : 
     132         374 : bool NASAKeywordHandler::Parse(const char *pszStr)
     133             : 
     134             : {
     135         374 :     pszHeaderNext = pszStr;
     136             : 
     137             :     /* -------------------------------------------------------------------- */
     138             :     /*      Process name/value pairs, keeping track of a "path stack".      */
     139             :     /* -------------------------------------------------------------------- */
     140         374 :     oJSon = CPLJSONObject();
     141         374 :     return ReadGroup("", oJSon, 0);
     142             : }
     143             : 
     144             : /************************************************************************/
     145             : /*                             ReadGroup()                              */
     146             : /************************************************************************/
     147             : 
     148        2754 : bool NASAKeywordHandler::ReadGroup(const std::string &osPathPrefix,
     149             :                                    CPLJSONObject &oCur, int nRecLevel)
     150             : 
     151             : {
     152        2754 :     if (osPathPrefix.size() > 256)
     153             :     {
     154           0 :         CPLError(CE_Failure, CPLE_NotSupported, "Too big prefix for GROUP");
     155           0 :         return false;
     156             :     }
     157        2754 :     if (nRecLevel == 100)
     158           0 :         return false;
     159             :     for (; true;)
     160             :     {
     161       15026 :         CPLString osName, osValue;
     162       15026 :         if (!ReadPair(osName, osValue, oCur))
     163           3 :             return false;
     164             : 
     165       15023 :         if (EQUAL(osName, "OBJECT") || EQUAL(osName, "GROUP"))
     166             :         {
     167        2380 :             CPLJSONObject oNewGroup;
     168        2380 :             oNewGroup.Add("_type",
     169        2380 :                           EQUAL(osName, "OBJECT") ? "object" : "group");
     170        2380 :             if (!ReadGroup((osPathPrefix + osValue + ".").c_str(), oNewGroup,
     171             :                            nRecLevel + 1))
     172             :             {
     173           0 :                 return false;
     174             :             }
     175        7140 :             CPLJSONObject oName = oNewGroup["Name"];
     176        2400 :             if ((osValue == "Table" || osValue == "Field") &&
     177          20 :                 (oName.GetType() == CPLJSONObject::Type::String))
     178             :             {
     179          20 :                 oCur.Add(osValue + "_" + oName.ToString(), oNewGroup);
     180          20 :                 oNewGroup.Add("_container_name", osValue);
     181             :             }
     182        2360 :             else if (oCur[osValue].IsValid())
     183             :             {
     184           4 :                 int nIter = 2;
     185           6 :                 while (oCur[osValue + CPLSPrintf("_%d", nIter)].IsValid())
     186             :                 {
     187           2 :                     nIter++;
     188             :                 }
     189           4 :                 oCur.Add(osValue + CPLSPrintf("_%d", nIter), oNewGroup);
     190           4 :                 oNewGroup.Add("_container_name", osValue);
     191             :             }
     192             :             else
     193             :             {
     194        2356 :                 oCur.Add(osValue, oNewGroup);
     195             :             }
     196             :         }
     197       23943 :         else if (EQUAL(osName, "END") || EQUAL(osName, "END_GROUP") ||
     198       11300 :                  EQUAL(osName, "END_OBJECT"))
     199             :         {
     200        2751 :             return true;
     201             :         }
     202             :         else
     203             :         {
     204        9892 :             osName = osPathPrefix + osName;
     205        9892 :             aosKeywordList.AddNameValue(osName, osValue);
     206             :         }
     207       12272 :     }
     208             : }
     209             : 
     210             : /************************************************************************/
     211             : /*                        StripQuotesIfNeeded()                         */
     212             : /************************************************************************/
     213             : 
     214        5354 : static CPLString StripQuotesIfNeeded(const CPLString &osWord,
     215             :                                      bool bQuotesAlreadyRemoved)
     216             : {
     217        5354 :     if (bQuotesAlreadyRemoved || osWord.size() < 2 || osWord[0] != '"')
     218        3537 :         return osWord;
     219        3634 :     return osWord.substr(1, osWord.size() - 2);
     220             : }
     221             : 
     222             : /************************************************************************/
     223             : /*                              ReadPair()                              */
     224             : /*                                                                      */
     225             : /*      Read a name/value pair from the input stream.  Strip off        */
     226             : /*      white space, ignore comments, split on '='.                     */
     227             : /*      Returns TRUE on success.                                        */
     228             : /************************************************************************/
     229             : 
     230       15026 : bool NASAKeywordHandler::ReadPair(CPLString &osName, CPLString &osValue,
     231             :                                   CPLJSONObject &oCur)
     232             : 
     233             : {
     234       15026 :     osName = "";
     235       15026 :     osValue = "";
     236             : 
     237       15026 :     if (!ReadWord(osName))
     238           0 :         return false;
     239             : 
     240       15026 :     SkipWhite();
     241             : 
     242       15026 :     if (EQUAL(osName, "END"))
     243         371 :         return true;
     244             : 
     245       14655 :     if (*pszHeaderNext != '=')
     246             :     {
     247             :         // ISIS3 does not have anything after the end group/object keyword.
     248        1753 :         if (EQUAL(osName, "End_Group") || EQUAL(osName, "End_Object"))
     249        1752 :             return true;
     250             : 
     251           1 :         return false;
     252             :     }
     253             : 
     254       12902 :     pszHeaderNext++;
     255             : 
     256       12902 :     SkipWhite();
     257             : 
     258       12902 :     osValue = "";
     259       12902 :     bool bIsString = true;
     260             : 
     261             :     // Handle value lists like:
     262             :     // Name   = (Red, Red) or  {Red, Red} or even ({Red, Red}, {Red, Red})
     263       25804 :     CPLJSONArray oArray;
     264       12902 :     if (*pszHeaderNext == '(' || *pszHeaderNext == '{')
     265             :     {
     266         533 :         std::vector<char> oStackArrayBeginChar;
     267         533 :         CPLString osWord;
     268             : 
     269         533 :         oStackArrayBeginChar.push_back(*pszHeaderNext);
     270         533 :         osValue += *pszHeaderNext;
     271         533 :         pszHeaderNext++;
     272             : 
     273        1617 :         while (ReadWord(osWord, m_bStripSurroundingQuotes, true, &bIsString))
     274             :         {
     275        1617 :             if (*pszHeaderNext == '(' || *pszHeaderNext == '{')
     276             :             {
     277           3 :                 oStackArrayBeginChar.push_back(*pszHeaderNext);
     278           3 :                 osValue += *pszHeaderNext;
     279           3 :                 pszHeaderNext++;
     280             :             }
     281             : 
     282             :             // TODO: we could probably do better with nested json arrays
     283             :             // instead of flattening when there are (( )) or ({ }) constructs
     284        1617 :             if (bIsString)
     285             :             {
     286        1051 :                 if (!(osWord.empty() &&
     287           8 :                       (*pszHeaderNext == '(' || *pszHeaderNext == '{' ||
     288           8 :                        *pszHeaderNext == ')' || *pszHeaderNext == '}')))
     289             :                 {
     290        1039 :                     oArray.Add(
     291        2078 :                         StripQuotesIfNeeded(osWord, m_bStripSurroundingQuotes));
     292             :                 }
     293             :             }
     294         574 :             else if (CPLGetValueType(osWord) == CPL_VALUE_INTEGER)
     295             :             {
     296         454 :                 oArray.Add(atoi(osWord));
     297             :             }
     298             :             else
     299             :             {
     300         120 :                 oArray.Add(CPLAtof(osWord));
     301             :             }
     302             : 
     303        1617 :             osValue += osWord;
     304        1630 :             while (isspace(static_cast<unsigned char>(*pszHeaderNext)))
     305             :             {
     306          13 :                 pszHeaderNext++;
     307             :             }
     308             : 
     309        1617 :             if (*pszHeaderNext == ')')
     310             :             {
     311         523 :                 osValue += *pszHeaderNext;
     312        1046 :                 if (oStackArrayBeginChar.empty() ||
     313         523 :                     oStackArrayBeginChar.back() != '(')
     314             :                 {
     315           1 :                     CPLDebug("PDS", "Unpaired ( ) for %s", osName.c_str());
     316           1 :                     return false;
     317             :                 }
     318         522 :                 oStackArrayBeginChar.pop_back();
     319         522 :                 pszHeaderNext++;
     320         522 :                 if (oStackArrayBeginChar.empty())
     321         521 :                     break;
     322             :             }
     323        1094 :             else if (*pszHeaderNext == '}')
     324             :             {
     325          13 :                 osValue += *pszHeaderNext;
     326          26 :                 if (oStackArrayBeginChar.empty() ||
     327          13 :                     oStackArrayBeginChar.back() != '{')
     328             :                 {
     329           1 :                     CPLDebug("PDS", "Unpaired { } for %s", osName.c_str());
     330           1 :                     return false;
     331             :                 }
     332          12 :                 oStackArrayBeginChar.pop_back();
     333          12 :                 pszHeaderNext++;
     334          12 :                 if (oStackArrayBeginChar.empty())
     335          10 :                     break;
     336             :             }
     337        1081 :             else if (*pszHeaderNext == ',')
     338             :             {
     339        1078 :                 osValue += *pszHeaderNext;
     340        1078 :                 pszHeaderNext++;
     341             :                 // Do not use SkipWhite() here to avoid being confuse by
     342             :                 // constructs like
     343             :                 // FOO = (#123456,
     344             :                 //        #123456)
     345             :                 // where we could confuse the second line with a comment.
     346        3511 :                 while (isspace(static_cast<unsigned char>(*pszHeaderNext)))
     347             :                 {
     348        2433 :                     pszHeaderNext++;
     349             :                 }
     350             :             }
     351        1084 :             SkipWhite();
     352         531 :         }
     353             :     }
     354             : 
     355             :     else  // Handle more normal "single word" values.
     356             :     {
     357       12369 :         if (!ReadWord(osValue, m_bStripSurroundingQuotes, false, &bIsString))
     358           0 :             return false;
     359             :     }
     360             : 
     361       12900 :     SkipWhite();
     362             : 
     363             :     // No units keyword?
     364       12900 :     if (*pszHeaderNext != '<')
     365             :     {
     366       12174 :         if (!EQUAL(osName, "OBJECT") && !EQUAL(osName, "GROUP"))
     367             :         {
     368        9794 :             if (oArray.Size() > 0)
     369             :             {
     370         527 :                 oCur.Add(osName, oArray);
     371             :             }
     372             :             else
     373             :             {
     374        9267 :                 if (bIsString)
     375             :                 {
     376        4315 :                     oCur.Add(osName, StripQuotesIfNeeded(
     377        4315 :                                          osValue, m_bStripSurroundingQuotes));
     378             :                 }
     379        4952 :                 else if (CPLGetValueType(osValue) == CPL_VALUE_INTEGER)
     380             :                 {
     381        3150 :                     oCur.Add(osName, atoi(osValue));
     382             :                 }
     383             :                 else
     384             :                 {
     385        1802 :                     oCur.Add(osName, CPLAtof(osValue));
     386             :                 }
     387             :             }
     388             :         }
     389       12174 :         return true;
     390             :     }
     391             : 
     392        1452 :     CPLString osValueNoUnit(osValue);
     393             :     // Append units keyword.  For lines that like like this:
     394             :     //  MAP_RESOLUTION               = 4.0 <PIXEL/DEGREE>
     395             : 
     396         726 :     osValue += " ";
     397             : 
     398        1452 :     CPLString osWord;
     399        1452 :     CPLString osUnit;
     400         726 :     while (ReadWord(osWord))
     401             :     {
     402         726 :         SkipWhite();
     403             : 
     404         726 :         osValue += osWord;
     405         726 :         osUnit = osWord;
     406         726 :         if (osWord.back() == '>')
     407         726 :             break;
     408             :     }
     409             : 
     410         726 :     if (osUnit[0] == '<')
     411         726 :         osUnit = osUnit.substr(1);
     412         726 :     if (!osUnit.empty() && osUnit.back() == '>')
     413         726 :         osUnit = osUnit.substr(0, osUnit.size() - 1);
     414             : 
     415         726 :     CPLJSONObject newObject;
     416         726 :     oCur.Add(osName, newObject);
     417             : 
     418         726 :     if (oArray.Size() > 0)
     419             :     {
     420           2 :         newObject.Add("value", oArray);
     421             :     }
     422             :     else
     423             :     {
     424         724 :         if (bIsString)
     425             :         {
     426           8 :             newObject.Add("value", osValueNoUnit);
     427             :         }
     428         716 :         else if (CPLGetValueType(osValueNoUnit) == CPL_VALUE_INTEGER)
     429             :         {
     430          38 :             newObject.Add("value", atoi(osValueNoUnit));
     431             :         }
     432             :         else
     433             :         {
     434         678 :             newObject.Add("value", CPLAtof(osValueNoUnit));
     435             :         }
     436             :     }
     437         726 :     newObject.Add("unit", osUnit);
     438             : 
     439         726 :     return true;
     440             : }
     441             : 
     442             : /************************************************************************/
     443             : /*                              ReadWord()                              */
     444             : /*  Returns TRUE on success                                             */
     445             : /************************************************************************/
     446             : 
     447       29738 : bool NASAKeywordHandler::ReadWord(CPLString &osWord,
     448             :                                   bool bStripSurroundingQuotes, bool bParseList,
     449             :                                   bool *pbIsString)
     450             : 
     451             : {
     452       29738 :     if (pbIsString)
     453       13986 :         *pbIsString = false;
     454       29738 :     osWord = "";
     455             : 
     456       29738 :     SkipWhite();
     457             : 
     458       29738 :     if (!(*pszHeaderNext != '\0' && *pszHeaderNext != '=' &&
     459       29738 :           !isspace(static_cast<unsigned char>(*pszHeaderNext))))
     460           0 :         return false;
     461             : 
     462             :     /* Extract a text string delimited by '\"' */
     463             :     /* Convert newlines (CR or LF) within quotes. While text strings
     464             :        support them as per ODL, the keyword list doesn't want them */
     465       29738 :     if (*pszHeaderNext == '"')
     466             :     {
     467        1845 :         if (pbIsString)
     468        1845 :             *pbIsString = true;
     469        1845 :         if (!bStripSurroundingQuotes)
     470        1819 :             osWord += *(pszHeaderNext);
     471        1845 :         pszHeaderNext++;
     472       27198 :         while (*pszHeaderNext != '"')
     473             :         {
     474       25353 :             if (*pszHeaderNext == '\0')
     475           0 :                 return false;
     476       25353 :             if (*pszHeaderNext == '\n')
     477             :             {
     478         121 :                 osWord += "\\n";
     479         121 :                 pszHeaderNext++;
     480         121 :                 continue;
     481             :             }
     482       25232 :             if (*pszHeaderNext == '\r')
     483             :             {
     484         118 :                 osWord += "\\r";
     485         118 :                 pszHeaderNext++;
     486         118 :                 continue;
     487             :             }
     488       25114 :             osWord += *(pszHeaderNext++);
     489             :         }
     490        1845 :         if (!bStripSurroundingQuotes)
     491        1819 :             osWord += *(pszHeaderNext);
     492        1845 :         pszHeaderNext++;
     493             : 
     494        1845 :         return true;
     495             :     }
     496             : 
     497             :     /* Extract a symbol string */
     498             :     /* These are expected to not have
     499             :        '\'' (delimiters),
     500             :        format effectors (should fit on a single line) or
     501             :        control characters.
     502             :     */
     503       27893 :     if (*pszHeaderNext == '\'')
     504             :     {
     505           8 :         if (pbIsString)
     506           8 :             *pbIsString = true;
     507           8 :         if (!bStripSurroundingQuotes)
     508           8 :             osWord += *(pszHeaderNext);
     509           8 :         pszHeaderNext++;
     510          32 :         while (*pszHeaderNext != '\'')
     511             :         {
     512          24 :             if (*pszHeaderNext == '\0')
     513           0 :                 return false;
     514             : 
     515          24 :             osWord += *(pszHeaderNext++);
     516             :         }
     517           8 :         if (!bStripSurroundingQuotes)
     518           8 :             osWord += *(pszHeaderNext);
     519           8 :         pszHeaderNext++;
     520           8 :         return true;
     521             :     }
     522             : 
     523             :     /*
     524             :      * Extract normal text.  Terminated by '=' or whitespace.
     525             :      *
     526             :      * A special exception is that a line may terminate with a '-'
     527             :      * which is taken as a line extender, and we suck up white space to new
     528             :      * text.
     529             :      */
     530      245967 :     while (
     531      273852 :         *pszHeaderNext != '\0' && *pszHeaderNext != '=' &&
     532      271243 :         ((bParseList && *pszHeaderNext != ',' && *pszHeaderNext != '(' &&
     533        6228 :           *pszHeaderNext != ')' && *pszHeaderNext != '{' &&
     534      271243 :           *pszHeaderNext != '}') ||
     535      264313 :          (!bParseList && !isspace(static_cast<unsigned char>(*pszHeaderNext)))))
     536             :     {
     537      245967 :         osWord += *pszHeaderNext;
     538      245967 :         pszHeaderNext++;
     539             : 
     540      245967 :         if (*pszHeaderNext == '-' &&
     541         141 :             (pszHeaderNext[1] == 10 || pszHeaderNext[1] == 13))
     542             :         {
     543           4 :             pszHeaderNext += 2;
     544           4 :             SkipWhite();
     545             :         }
     546             :     }
     547             : 
     548       27885 :     if (pbIsString)
     549       12133 :         *pbIsString = CPLGetValueType(osWord) == CPL_VALUE_STRING;
     550             : 
     551       27885 :     return true;
     552             : }
     553             : 
     554             : /************************************************************************/
     555             : /*                             SkipWhite()                              */
     556             : /*  Skip white spaces and C style comments                              */
     557             : /************************************************************************/
     558             : 
     559      248363 : void NASAKeywordHandler::SkipWhite()
     560             : 
     561             : {
     562             :     for (; true;)
     563             :     {
     564             :         // Skip C style comments
     565      248363 :         if (*pszHeaderNext == '/' && pszHeaderNext[1] == '*')
     566             :         {
     567         548 :             pszHeaderNext += 2;
     568             : 
     569       23046 :             while (*pszHeaderNext != '\0' &&
     570       23046 :                    (*pszHeaderNext != '*' || pszHeaderNext[1] != '/'))
     571             :             {
     572       22498 :                 pszHeaderNext++;
     573             :             }
     574         548 :             if (*pszHeaderNext == '\0')
     575           0 :                 return;
     576             : 
     577         548 :             pszHeaderNext += 2;
     578             : 
     579             :             // consume till end of line.
     580             :             // reduce sensibility to a label error
     581         548 :             while (*pszHeaderNext != '\0' && *pszHeaderNext != 10 &&
     582         294 :                    *pszHeaderNext != 13)
     583             :             {
     584           0 :                 pszHeaderNext++;
     585             :             }
     586         548 :             continue;
     587             :         }
     588             : 
     589             :         // Skip # style comments
     590      247815 :         if ((*pszHeaderNext == 10 || *pszHeaderNext == 13 ||
     591      227673 :              *pszHeaderNext == ' ' || *pszHeaderNext == '\t') &&
     592      175435 :             pszHeaderNext[1] == '#')
     593             :         {
     594          83 :             pszHeaderNext += 2;
     595             : 
     596             :             // consume till end of line.
     597        4138 :             while (*pszHeaderNext != '\0' && *pszHeaderNext != 10 &&
     598        4055 :                    *pszHeaderNext != 13)
     599             :             {
     600        4055 :                 pszHeaderNext++;
     601             :             }
     602          83 :             continue;
     603             :         }
     604             : 
     605             :         // Skip white space (newline, space, tab, etc )
     606      247732 :         if (isspace(static_cast<unsigned char>(*pszHeaderNext)))
     607             :         {
     608      175352 :             pszHeaderNext++;
     609      175352 :             continue;
     610             :         }
     611             : 
     612             :         // not white space, return.
     613       72380 :         return;
     614             :     }
     615             : }
     616             : 
     617             : /************************************************************************/
     618             : /*                             GetKeyword()                             */
     619             : /************************************************************************/
     620             : 
     621        9312 : const char *NASAKeywordHandler::GetKeyword(const char *pszPath,
     622             :                                            const char *pszDefault)
     623             : 
     624             : {
     625        9312 :     return aosKeywordList.FetchNameValueDef(pszPath, pszDefault);
     626             : }
     627             : 
     628             : /************************************************************************/
     629             : /*                             GetKeywordList()                         */
     630             : /************************************************************************/
     631             : 
     632           0 : char **NASAKeywordHandler::GetKeywordList()
     633             : {
     634           0 :     return aosKeywordList.List();
     635             : }
     636             : 
     637             : /************************************************************************/
     638             : /*                               StealJSon()                            */
     639             : /************************************************************************/
     640             : 
     641         321 : CPLJSONObject NASAKeywordHandler::GetJsonObject() const
     642             : {
     643         321 :     return oJSon;
     644             : }
     645             : 
     646             : //! @endcond

Generated by: LCOV version 1.14