LCOV - code coverage report
Current view: top level - jdx/util - PeakTableParser.cpp (source / functions) Hit Total Coverage
Test: coverage_filtered.info Lines: 49 51 96.1 %
Date: 2025-06-15 16:18:27 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /* Copyright (C) 2025 Robert Schiwon
       2             :  *
       3             :  * This file is part of libjdx.
       4             :  *
       5             :  * libjdx is free software: you can redistribute it and/or modify it under the
       6             :  * terms of the GNU Lesser General Public License as published by the Free
       7             :  * Software Foundation, either version 3 of the License, or (at your option) any
       8             :  * later version.
       9             :  *
      10             :  * libjdx is distributed in the hope that it will be useful, but WITHOUT ANY
      11             :  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
      12             :  * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
      13             :  * details.
      14             :  *
      15             :  * You should have received a copy of the GNU Lesser General Public License
      16             :  * along with libjdx. If not, see <https://www.gnu.org/licenses/>.
      17             :  */
      18             : #include "util/PeakTableParser.hpp"
      19             : #include "jdx/ParseException.hpp"
      20             : #include "jdx/Peak.hpp"
      21             : #include "util/LdrUtils.hpp"
      22             : #include "util/StringUtils.hpp"
      23             : 
      24             : #include <algorithm>
      25             : #include <regex>
      26             : 
      27          15 : libjdx::jdx::util::PeakTableParser::PeakTableParser(
      28          15 :     io::TextReader& reader, std::string variableList)
      29          15 :     : TuplesParser(std::move(variableList), "peak table")
      30          30 :     , m_reader{reader}
      31             : {
      32          15 : }
      33             : 
      34          52 : std::optional<libjdx::jdx::Peak> libjdx::jdx::util::PeakTableParser::next()
      35             : {
      36          52 :     return TuplesParser::next<Peak>([this]() { return nextTuple(); },
      37          97 :         [this](const std::string& tuple) { return createPeak(tuple); });
      38             :     // alternative without lambdas:
      39             :     // return TuplesParser::next<Peak>(
      40             :     //    std::bind(&PeakTableParser::nextTuple, this),
      41             :     //    std::bind(&PeakTableParser::createPeak, this, std::placeholders::_1));
      42             : }
      43             : 
      44          79 : std::optional<std::string> libjdx::jdx::util::PeakTableParser::nextTuple()
      45             : {
      46          79 :     while (m_tuples.empty())
      47             :     {
      48          38 :         if (m_reader.eof())
      49             :         {
      50          11 :             return std::nullopt;
      51             :         }
      52             : 
      53          38 :         auto pos = m_reader.tellg();
      54          38 :         auto nextLine = m_reader.readLine();
      55          38 :         if (util::isLdrStart(nextLine))
      56             :         {
      57             :             // next LDR => end of PEAK TABLE
      58          11 :             m_reader.seekg(pos);
      59          11 :             return std::nullopt;
      60             :         }
      61             : 
      62          27 :         auto value = util::stripLineComment(nextLine, true).first;
      63          27 :         if (value.empty())
      64             :         {
      65             :             // skip pure comments
      66           0 :             continue;
      67             :         }
      68             :         auto tuples
      69          81 :             = util::split(value, R"([^,\s](\s*(?:\s|;)\s*)[^,\s])", true, 1);
      70          27 :         if (tuples.empty())
      71             :         {
      72             :             throw ParseException(
      73             :                 "Unexpected content found while parsing PEAK TABLE: "
      74           0 :                 + nextLine);
      75             :         }
      76             :         // add to queue
      77          68 :         for (auto& tuple : tuples)
      78             :         {
      79          41 :             m_tuples.push(tuple);
      80             :         }
      81             :     }
      82             : 
      83          82 :     auto tuple = m_tuples.front();
      84          41 :     m_tuples.pop();
      85          41 :     return tuple;
      86             : }
      87             : 
      88          41 : libjdx::jdx::Peak libjdx::jdx::util::PeakTableParser::createPeak(
      89             :     const std::string& tuple) const
      90             : {
      91             :     // tokenize
      92             :     // token[0] is the full match so extract 1 + 3 tokens for 3 groups
      93          80 :     const auto tokens = extractTokens(tuple, m_regex, 1 + 3);
      94          39 :     const auto& varList = getVariableList();
      95             : 
      96             :     // error conditions {varList, {error condition, error message}}
      97             :     const std::multimap<std::string, std::tuple<bool, std::string>> errorMap{
      98          39 :         {s_varLists.at(0),
      99         117 :             {tokens.at(3).has_value(), std::string{"Illegal "} + s_ldrName
     100         117 :                                            + " entry for " + s_varLists.at(0)
     101          78 :                                            + ": " + tuple}},
     102          39 :         {s_varLists.at(1),
     103         117 :             {!tokens.at(3), std::string{"Illegal "} + s_ldrName + " entry for "
     104         117 :                                 + s_varLists.at(1) + ": " + tuple}},
     105          39 :         {s_varLists.at(2),
     106         117 :             {!tokens.at(3), std::string{"Illegal "} + s_ldrName + " entry for "
     107         117 :                                 + s_varLists.at(2) + ": " + tuple}},
     108         429 :     };
     109             : 
     110          43 :     checkForErrors(varList, errorMap, s_ldrName);
     111             : 
     112             :     // map
     113          37 :     Peak peak{};
     114          37 :     peak.x = parseDoubleToken(tokens.at(1));
     115          37 :     peak.y = parseDoubleToken(tokens.at(2));
     116             :     // nothing to do for varLists[0]
     117          37 :     if (s_varLists.at(1) == varList)
     118             :     {
     119           7 :         peak.w = parseDoubleToken(tokens.at(3));
     120             :     }
     121          30 :     else if (s_varLists.at(2) == varList)
     122             :     {
     123           1 :         peak.m = tokens.at(3);
     124             :     }
     125             : 
     126          74 :     return peak;
     127             : }

Generated by: LCOV version 1.14