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-11-21 22:18:42 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             :  * SPDX-License-Identifier: MIT
      16             :  ****************************************************************************
      17             :  * Object Description Language (ODL) is used to encode data labels for PDS
      18             :  * and other NASA data systems. Refer to Chapter 12 of "PDS Standards
      19             :  * Reference" at http://pds.jpl.nasa.gov/tools/standards-reference.shtml for
      20             :  * further details about ODL.
      21             :  *
      22             :  * This is also known as PVL (Parameter Value Language) which is written
      23             :  * about at http://www.orrery.us/node/44 where it notes:
      24             :  *
      25             :  * The PVL syntax that the PDS uses is specified by the Consultative Committee
      26             :  * for Space Data Systems in their Blue Book publication: "Parameter Value
      27             :  * Language Specification (CCSD0006 and CCSD0008)", June 2000
      28             :  * [CCSDS 641.0-B-2], and Green Book publication: "Parameter Value Language -
      29             :  * A Tutorial", June 2000 [CCSDS 641.0-G-2]. PVL has also been accepted by the
      30             :  * International Standards Organization (ISO), as a Final Draft International
      31             :  * Standard (ISO 14961:2002) keyword value type language for naming and
      32             :  * expressing data values.
      33             :  * --
      34             :  * also of interest, on PDS ODL:
      35             :  *  http://pds.jpl.nasa.gov/documents/sr/Chapter12.pdf
      36             :  *
      37             :  ****************************************************************************/
      38             : 
      39             : #include "nasakeywordhandler.h"
      40             : #include "ogrlibjsonutils.h"
      41             : #include <vector>
      42             : 
      43             : //! @cond Doxygen_Suppress
      44             : 
      45             : /************************************************************************/
      46             : /* ==================================================================== */
      47             : /*                          NASAKeywordHandler                          */
      48             : /* ==================================================================== */
      49             : /************************************************************************/
      50             : 
      51             : /************************************************************************/
      52             : /*                         NASAKeywordHandler()                         */
      53             : /************************************************************************/
      54             : 
      55         501 : NASAKeywordHandler::NASAKeywordHandler()
      56         501 :     : pszHeaderNext(nullptr), m_bStripSurroundingQuotes(false)
      57             : {
      58         501 :     oJSon.Deinit();
      59         501 : }
      60             : 
      61             : /************************************************************************/
      62             : /*                        ~NASAKeywordHandler()                         */
      63             : /************************************************************************/
      64             : 
      65         501 : NASAKeywordHandler::~NASAKeywordHandler()
      66             : 
      67             : {
      68         501 : }
      69             : 
      70             : /************************************************************************/
      71             : /*                               Ingest()                               */
      72             : /************************************************************************/
      73             : 
      74         350 : bool NASAKeywordHandler::Ingest(VSILFILE *fp, int nOffset)
      75             : 
      76             : {
      77             :     /* -------------------------------------------------------------------- */
      78             :     /*      Read in buffer till we find END all on its own line.            */
      79             :     /* -------------------------------------------------------------------- */
      80         350 :     if (VSIFSeekL(fp, nOffset, SEEK_SET) != 0)
      81           0 :         return false;
      82             : 
      83         700 :     std::string osHeaderText;
      84             :     for (; true;)
      85             :     {
      86             :         char szChunk[513];
      87             : 
      88        4237 :         int nBytesRead = static_cast<int>(VSIFReadL(szChunk, 1, 512, fp));
      89             : 
      90        4237 :         szChunk[nBytesRead] = '\0';
      91        4237 :         osHeaderText += szChunk;
      92             : 
      93        4237 :         if (nBytesRead < 512)
      94         165 :             break;
      95             : 
      96        4072 :         const char *pszCheck = nullptr;
      97        4072 :         if (osHeaderText.size() > 520)
      98         532 :             pszCheck = osHeaderText.c_str() + (osHeaderText.size() - 520);
      99             :         else
     100        3540 :             pszCheck = szChunk;
     101             : 
     102        4072 :         if (strstr(pszCheck, "\r\nEND\r\n") != nullptr ||
     103        4057 :             strstr(pszCheck, "\nEND\n") != nullptr ||
     104        4005 :             strstr(pszCheck, "\r\nEnd\r\n") != nullptr ||
     105        4005 :             strstr(pszCheck, "\nEnd\n") != nullptr)
     106             :             break;
     107        3887 :     }
     108             : 
     109         350 :     return Parse(osHeaderText.c_str());
     110             : }
     111             : 
     112             : /************************************************************************/
     113             : /*                               Parse()                                */
     114             : /************************************************************************/
     115             : 
     116         376 : bool NASAKeywordHandler::Parse(const char *pszStr)
     117             : 
     118             : {
     119         376 :     pszHeaderNext = pszStr;
     120             : 
     121             :     /* -------------------------------------------------------------------- */
     122             :     /*      Process name/value pairs, keeping track of a "path stack".      */
     123             :     /* -------------------------------------------------------------------- */
     124         376 :     oJSon = CPLJSONObject();
     125         376 :     return ReadGroup("", oJSon, 0);
     126             : }
     127             : 
     128             : /************************************************************************/
     129             : /*                             ReadGroup()                              */
     130             : /************************************************************************/
     131             : 
     132        2758 : bool NASAKeywordHandler::ReadGroup(const std::string &osPathPrefix,
     133             :                                    CPLJSONObject &oCur, int nRecLevel)
     134             : 
     135             : {
     136        2758 :     if (osPathPrefix.size() > 256)
     137             :     {
     138           0 :         CPLError(CE_Failure, CPLE_NotSupported, "Too big prefix for GROUP");
     139           0 :         return false;
     140             :     }
     141        2758 :     if (nRecLevel == 100)
     142           0 :         return false;
     143             :     for (; true;)
     144             :     {
     145       15050 :         CPLString osName, osValue;
     146       15050 :         if (!ReadPair(osName, osValue, oCur))
     147           3 :             return false;
     148             : 
     149       15047 :         if (EQUAL(osName, "OBJECT") || EQUAL(osName, "GROUP"))
     150             :         {
     151        2382 :             CPLJSONObject oNewGroup;
     152        2382 :             oNewGroup.Add("_type",
     153        2382 :                           EQUAL(osName, "OBJECT") ? "object" : "group");
     154        2382 :             if (!ReadGroup((osPathPrefix + osValue + ".").c_str(), oNewGroup,
     155             :                            nRecLevel + 1))
     156             :             {
     157           0 :                 return false;
     158             :             }
     159        7146 :             CPLJSONObject oName = oNewGroup["Name"];
     160        2402 :             if ((osValue == "Table" || osValue == "Field") &&
     161          20 :                 (oName.GetType() == CPLJSONObject::Type::String))
     162             :             {
     163          20 :                 oCur.Add(osValue + "_" + oName.ToString(), oNewGroup);
     164          20 :                 oNewGroup.Add("_container_name", osValue);
     165             :             }
     166        2362 :             else if (oCur[osValue].IsValid())
     167             :             {
     168           4 :                 int nIter = 2;
     169           6 :                 while (oCur[osValue + CPLSPrintf("_%d", nIter)].IsValid())
     170             :                 {
     171           2 :                     nIter++;
     172             :                 }
     173           4 :                 oCur.Add(osValue + CPLSPrintf("_%d", nIter), oNewGroup);
     174           4 :                 oNewGroup.Add("_container_name", osValue);
     175             :             }
     176             :             else
     177             :             {
     178        2358 :                 oCur.Add(osValue, oNewGroup);
     179             :             }
     180             :         }
     181       23985 :         else if (EQUAL(osName, "END") || EQUAL(osName, "END_GROUP") ||
     182       11320 :                  EQUAL(osName, "END_OBJECT"))
     183             :         {
     184        2755 :             return true;
     185             :         }
     186             :         else
     187             :         {
     188        9910 :             osName = osPathPrefix + osName;
     189        9910 :             aosKeywordList.AddNameValue(osName, osValue);
     190             :         }
     191       12292 :     }
     192             : }
     193             : 
     194             : /************************************************************************/
     195             : /*                        StripQuotesIfNeeded()                         */
     196             : /************************************************************************/
     197             : 
     198        5363 : static CPLString StripQuotesIfNeeded(const CPLString &osWord,
     199             :                                      bool bQuotesAlreadyRemoved)
     200             : {
     201        5363 :     if (bQuotesAlreadyRemoved || osWord.size() < 2 || osWord[0] != '"')
     202        3542 :         return osWord;
     203        3642 :     return osWord.substr(1, osWord.size() - 2);
     204             : }
     205             : 
     206             : /************************************************************************/
     207             : /*                              ReadPair()                              */
     208             : /*                                                                      */
     209             : /*      Read a name/value pair from the input stream.  Strip off        */
     210             : /*      white space, ignore comments, split on '='.                     */
     211             : /*      Returns TRUE on success.                                        */
     212             : /************************************************************************/
     213             : 
     214       15050 : bool NASAKeywordHandler::ReadPair(CPLString &osName, CPLString &osValue,
     215             :                                   CPLJSONObject &oCur)
     216             : 
     217             : {
     218       15050 :     osName = "";
     219       15050 :     osValue = "";
     220             : 
     221       15050 :     if (!ReadWord(osName))
     222           0 :         return false;
     223             : 
     224       15050 :     SkipWhite();
     225             : 
     226       15050 :     if (EQUAL(osName, "END"))
     227         373 :         return true;
     228             : 
     229       14677 :     if (*pszHeaderNext != '=')
     230             :     {
     231             :         // ISIS3 does not have anything after the end group/object keyword.
     232        1753 :         if (EQUAL(osName, "End_Group") || EQUAL(osName, "End_Object"))
     233        1752 :             return true;
     234             : 
     235           1 :         return false;
     236             :     }
     237             : 
     238       12924 :     pszHeaderNext++;
     239             : 
     240       12924 :     SkipWhite();
     241             : 
     242       12924 :     osValue = "";
     243       12924 :     bool bIsString = true;
     244             : 
     245             :     // Handle value lists like:
     246             :     // Name   = (Red, Red) or  {Red, Red} or even ({Red, Red}, {Red, Red})
     247       25848 :     CPLJSONArray oArray;
     248       12924 :     if (*pszHeaderNext == '(' || *pszHeaderNext == '{')
     249             :     {
     250         533 :         std::vector<char> oStackArrayBeginChar;
     251         533 :         CPLString osWord;
     252             : 
     253         533 :         oStackArrayBeginChar.push_back(*pszHeaderNext);
     254         533 :         osValue += *pszHeaderNext;
     255         533 :         pszHeaderNext++;
     256             : 
     257        1617 :         while (ReadWord(osWord, m_bStripSurroundingQuotes, true, &bIsString))
     258             :         {
     259        1617 :             if (*pszHeaderNext == '(' || *pszHeaderNext == '{')
     260             :             {
     261           3 :                 oStackArrayBeginChar.push_back(*pszHeaderNext);
     262           3 :                 osValue += *pszHeaderNext;
     263           3 :                 pszHeaderNext++;
     264             :             }
     265             : 
     266             :             // TODO: we could probably do better with nested json arrays
     267             :             // instead of flattening when there are (( )) or ({ }) constructs
     268        1617 :             if (bIsString)
     269             :             {
     270        1051 :                 if (!(osWord.empty() &&
     271           8 :                       (*pszHeaderNext == '(' || *pszHeaderNext == '{' ||
     272           8 :                        *pszHeaderNext == ')' || *pszHeaderNext == '}')))
     273             :                 {
     274        1039 :                     oArray.Add(
     275        2078 :                         StripQuotesIfNeeded(osWord, m_bStripSurroundingQuotes));
     276             :                 }
     277             :             }
     278         574 :             else if (CPLGetValueType(osWord) == CPL_VALUE_INTEGER)
     279             :             {
     280         454 :                 oArray.Add(atoi(osWord));
     281             :             }
     282             :             else
     283             :             {
     284         120 :                 oArray.Add(CPLAtof(osWord));
     285             :             }
     286             : 
     287        1617 :             osValue += osWord;
     288        1630 :             while (isspace(static_cast<unsigned char>(*pszHeaderNext)))
     289             :             {
     290          13 :                 pszHeaderNext++;
     291             :             }
     292             : 
     293        1617 :             if (*pszHeaderNext == ')')
     294             :             {
     295         523 :                 osValue += *pszHeaderNext;
     296        1046 :                 if (oStackArrayBeginChar.empty() ||
     297         523 :                     oStackArrayBeginChar.back() != '(')
     298             :                 {
     299           1 :                     CPLDebug("PDS", "Unpaired ( ) for %s", osName.c_str());
     300           1 :                     return false;
     301             :                 }
     302         522 :                 oStackArrayBeginChar.pop_back();
     303         522 :                 pszHeaderNext++;
     304         522 :                 if (oStackArrayBeginChar.empty())
     305         521 :                     break;
     306             :             }
     307        1094 :             else if (*pszHeaderNext == '}')
     308             :             {
     309          13 :                 osValue += *pszHeaderNext;
     310          26 :                 if (oStackArrayBeginChar.empty() ||
     311          13 :                     oStackArrayBeginChar.back() != '{')
     312             :                 {
     313           1 :                     CPLDebug("PDS", "Unpaired { } for %s", osName.c_str());
     314           1 :                     return false;
     315             :                 }
     316          12 :                 oStackArrayBeginChar.pop_back();
     317          12 :                 pszHeaderNext++;
     318          12 :                 if (oStackArrayBeginChar.empty())
     319          10 :                     break;
     320             :             }
     321        1081 :             else if (*pszHeaderNext == ',')
     322             :             {
     323        1078 :                 osValue += *pszHeaderNext;
     324        1078 :                 pszHeaderNext++;
     325             :                 // Do not use SkipWhite() here to avoid being confuse by
     326             :                 // constructs like
     327             :                 // FOO = (#123456,
     328             :                 //        #123456)
     329             :                 // where we could confuse the second line with a comment.
     330        3511 :                 while (isspace(static_cast<unsigned char>(*pszHeaderNext)))
     331             :                 {
     332        2433 :                     pszHeaderNext++;
     333             :                 }
     334             :             }
     335        1084 :             SkipWhite();
     336         531 :         }
     337             :     }
     338             : 
     339             :     else  // Handle more normal "single word" values.
     340             :     {
     341       12391 :         if (!ReadWord(osValue, m_bStripSurroundingQuotes, false, &bIsString))
     342           0 :             return false;
     343             :     }
     344             : 
     345       12922 :     SkipWhite();
     346             : 
     347             :     // No units keyword?
     348       12922 :     if (*pszHeaderNext != '<')
     349             :     {
     350       12196 :         if (!EQUAL(osName, "OBJECT") && !EQUAL(osName, "GROUP"))
     351             :         {
     352        9814 :             if (oArray.Size() > 0)
     353             :             {
     354         527 :                 oCur.Add(osName, oArray);
     355             :             }
     356             :             else
     357             :             {
     358        9287 :                 if (bIsString)
     359             :                 {
     360        4324 :                     oCur.Add(osName, StripQuotesIfNeeded(
     361        4324 :                                          osValue, m_bStripSurroundingQuotes));
     362             :                 }
     363        4963 :                 else if (CPLGetValueType(osValue) == CPL_VALUE_INTEGER)
     364             :                 {
     365        3161 :                     oCur.Add(osName, atoi(osValue));
     366             :                 }
     367             :                 else
     368             :                 {
     369        1802 :                     oCur.Add(osName, CPLAtof(osValue));
     370             :                 }
     371             :             }
     372             :         }
     373       12196 :         return true;
     374             :     }
     375             : 
     376        1452 :     CPLString osValueNoUnit(osValue);
     377             :     // Append units keyword.  For lines that like like this:
     378             :     //  MAP_RESOLUTION               = 4.0 <PIXEL/DEGREE>
     379             : 
     380         726 :     osValue += " ";
     381             : 
     382        1452 :     CPLString osWord;
     383        1452 :     CPLString osUnit;
     384         726 :     while (ReadWord(osWord))
     385             :     {
     386         726 :         SkipWhite();
     387             : 
     388         726 :         osValue += osWord;
     389         726 :         osUnit = osWord;
     390         726 :         if (osWord.back() == '>')
     391         726 :             break;
     392             :     }
     393             : 
     394         726 :     if (osUnit[0] == '<')
     395         726 :         osUnit = osUnit.substr(1);
     396         726 :     if (!osUnit.empty() && osUnit.back() == '>')
     397         726 :         osUnit = osUnit.substr(0, osUnit.size() - 1);
     398             : 
     399         726 :     CPLJSONObject newObject;
     400         726 :     oCur.Add(osName, newObject);
     401             : 
     402         726 :     if (oArray.Size() > 0)
     403             :     {
     404           2 :         newObject.Add("value", oArray);
     405             :     }
     406             :     else
     407             :     {
     408         724 :         if (bIsString)
     409             :         {
     410          10 :             newObject.Add("value", osValueNoUnit);
     411             :         }
     412         714 :         else if (CPLGetValueType(osValueNoUnit) == CPL_VALUE_INTEGER)
     413             :         {
     414          38 :             newObject.Add("value", atoi(osValueNoUnit));
     415             :         }
     416             :         else
     417             :         {
     418         676 :             newObject.Add("value", CPLAtof(osValueNoUnit));
     419             :         }
     420             :     }
     421         726 :     newObject.Add("unit", osUnit);
     422             : 
     423         726 :     return true;
     424             : }
     425             : 
     426             : /************************************************************************/
     427             : /*                              ReadWord()                              */
     428             : /*  Returns TRUE on success                                             */
     429             : /************************************************************************/
     430             : 
     431       29784 : bool NASAKeywordHandler::ReadWord(CPLString &osWord,
     432             :                                   bool bStripSurroundingQuotes, bool bParseList,
     433             :                                   bool *pbIsString)
     434             : 
     435             : {
     436       29784 :     if (pbIsString)
     437       14008 :         *pbIsString = false;
     438       29784 :     osWord = "";
     439             : 
     440       29784 :     SkipWhite();
     441             : 
     442       29784 :     if (!(*pszHeaderNext != '\0' && *pszHeaderNext != '=' &&
     443       29784 :           !isspace(static_cast<unsigned char>(*pszHeaderNext))))
     444           0 :         return false;
     445             : 
     446             :     /* Extract a text string delimited by '\"' */
     447             :     /* Convert newlines (CR or LF) within quotes. While text strings
     448             :        support them as per ODL, the keyword list doesn't want them */
     449       29784 :     if (*pszHeaderNext == '"')
     450             :     {
     451        1849 :         if (pbIsString)
     452        1849 :             *pbIsString = true;
     453        1849 :         if (!bStripSurroundingQuotes)
     454        1823 :             osWord += *(pszHeaderNext);
     455        1849 :         pszHeaderNext++;
     456       27240 :         while (*pszHeaderNext != '"')
     457             :         {
     458       25391 :             if (*pszHeaderNext == '\0')
     459           0 :                 return false;
     460       25391 :             if (*pszHeaderNext == '\n')
     461             :             {
     462         121 :                 osWord += "\\n";
     463         121 :                 pszHeaderNext++;
     464         121 :                 continue;
     465             :             }
     466       25270 :             if (*pszHeaderNext == '\r')
     467             :             {
     468         118 :                 osWord += "\\r";
     469         118 :                 pszHeaderNext++;
     470         118 :                 continue;
     471             :             }
     472       25152 :             osWord += *(pszHeaderNext++);
     473             :         }
     474        1849 :         if (!bStripSurroundingQuotes)
     475        1823 :             osWord += *(pszHeaderNext);
     476        1849 :         pszHeaderNext++;
     477             : 
     478        1849 :         return true;
     479             :     }
     480             : 
     481             :     /* Extract a symbol string */
     482             :     /* These are expected to not have
     483             :        '\'' (delimiters),
     484             :        format effectors (should fit on a single line) or
     485             :        control characters.
     486             :     */
     487       27935 :     if (*pszHeaderNext == '\'')
     488             :     {
     489           8 :         if (pbIsString)
     490           8 :             *pbIsString = true;
     491           8 :         if (!bStripSurroundingQuotes)
     492           8 :             osWord += *(pszHeaderNext);
     493           8 :         pszHeaderNext++;
     494          32 :         while (*pszHeaderNext != '\'')
     495             :         {
     496          24 :             if (*pszHeaderNext == '\0')
     497           0 :                 return false;
     498             : 
     499          24 :             osWord += *(pszHeaderNext++);
     500             :         }
     501           8 :         if (!bStripSurroundingQuotes)
     502           8 :             osWord += *(pszHeaderNext);
     503           8 :         pszHeaderNext++;
     504           8 :         return true;
     505             :     }
     506             : 
     507             :     /*
     508             :      * Extract normal text.  Terminated by '=' or whitespace.
     509             :      *
     510             :      * A special exception is that a line may terminate with a '-'
     511             :      * which is taken as a line extender, and we suck up white space to new
     512             :      * text.
     513             :      */
     514      244628 :     while (
     515      272555 :         *pszHeaderNext != '\0' && *pszHeaderNext != '=' &&
     516      269946 :         ((bParseList && *pszHeaderNext != ',' && *pszHeaderNext != '(' &&
     517        6228 :           *pszHeaderNext != ')' && *pszHeaderNext != '{' &&
     518      269946 :           *pszHeaderNext != '}') ||
     519      263016 :          (!bParseList && !isspace(static_cast<unsigned char>(*pszHeaderNext)))))
     520             :     {
     521      244628 :         osWord += *pszHeaderNext;
     522      244628 :         pszHeaderNext++;
     523             : 
     524      244628 :         if (*pszHeaderNext == '-' &&
     525         141 :             (pszHeaderNext[1] == 10 || pszHeaderNext[1] == 13))
     526             :         {
     527           4 :             pszHeaderNext += 2;
     528           4 :             SkipWhite();
     529             :         }
     530             :     }
     531             : 
     532       27927 :     if (pbIsString)
     533       12151 :         *pbIsString = CPLGetValueType(osWord) == CPL_VALUE_STRING;
     534             : 
     535       27927 :     return true;
     536             : }
     537             : 
     538             : /************************************************************************/
     539             : /*                             SkipWhite()                              */
     540             : /*  Skip white spaces and C style comments                              */
     541             : /************************************************************************/
     542             : 
     543      249115 : void NASAKeywordHandler::SkipWhite()
     544             : 
     545             : {
     546             :     for (; true;)
     547             :     {
     548             :         // Skip C style comments
     549      249115 :         if (*pszHeaderNext == '/' && pszHeaderNext[1] == '*')
     550             :         {
     551         548 :             pszHeaderNext += 2;
     552             : 
     553       23046 :             while (*pszHeaderNext != '\0' &&
     554       23046 :                    (*pszHeaderNext != '*' || pszHeaderNext[1] != '/'))
     555             :             {
     556       22498 :                 pszHeaderNext++;
     557             :             }
     558         548 :             if (*pszHeaderNext == '\0')
     559           0 :                 return;
     560             : 
     561         548 :             pszHeaderNext += 2;
     562             : 
     563             :             // consume till end of line.
     564             :             // reduce sensibility to a label error
     565         548 :             while (*pszHeaderNext != '\0' && *pszHeaderNext != 10 &&
     566         294 :                    *pszHeaderNext != 13)
     567             :             {
     568           0 :                 pszHeaderNext++;
     569             :             }
     570         548 :             continue;
     571             :         }
     572             : 
     573             :         // Skip # style comments
     574      248567 :         if ((*pszHeaderNext == 10 || *pszHeaderNext == 13 ||
     575      228401 :              *pszHeaderNext == ' ' || *pszHeaderNext == '\t') &&
     576      176073 :             pszHeaderNext[1] == '#')
     577             :         {
     578          83 :             pszHeaderNext += 2;
     579             : 
     580             :             // consume till end of line.
     581        4138 :             while (*pszHeaderNext != '\0' && *pszHeaderNext != 10 &&
     582        4055 :                    *pszHeaderNext != 13)
     583             :             {
     584        4055 :                 pszHeaderNext++;
     585             :             }
     586          83 :             continue;
     587             :         }
     588             : 
     589             :         // Skip white space (newline, space, tab, etc )
     590      248484 :         if (isspace(static_cast<unsigned char>(*pszHeaderNext)))
     591             :         {
     592      175990 :             pszHeaderNext++;
     593      175990 :             continue;
     594             :         }
     595             : 
     596             :         // not white space, return.
     597       72494 :         return;
     598             :     }
     599             : }
     600             : 
     601             : /************************************************************************/
     602             : /*                             GetKeyword()                             */
     603             : /************************************************************************/
     604             : 
     605        9316 : const char *NASAKeywordHandler::GetKeyword(const char *pszPath,
     606             :                                            const char *pszDefault)
     607             : 
     608             : {
     609        9316 :     return aosKeywordList.FetchNameValueDef(pszPath, pszDefault);
     610             : }
     611             : 
     612             : /************************************************************************/
     613             : /*                             GetKeywordList()                         */
     614             : /************************************************************************/
     615             : 
     616           0 : char **NASAKeywordHandler::GetKeywordList()
     617             : {
     618           0 :     return aosKeywordList.List();
     619             : }
     620             : 
     621             : /************************************************************************/
     622             : /*                               StealJSon()                            */
     623             : /************************************************************************/
     624             : 
     625         321 : CPLJSONObject NASAKeywordHandler::GetJsonObject() const
     626             : {
     627         321 :     return oJSon;
     628             : }
     629             : 
     630             : //! @endcond

Generated by: LCOV version 1.14