LCOV - code coverage report
Current view: top level - AP_JSON - AP_JSON.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 203 333 61.0 %
Date: 2026-09-09 11:02:08 Functions: 50 78 64.1 %

          Line data    Source code
       1             : /*
       2             :   ArduPilot JSON parser, based on picojson.h cloned from:
       3             :     https://github.com/kazuho/picojson
       4             :  */
       5             : /*
       6             :   Picojson copyright:
       7             : 
       8             :  * Copyright 2009-2010 Cybozu Labs, Inc.
       9             :  * Copyright 2011-2014 Kazuho Oku
      10             :  * All rights reserved.
      11             :  *
      12             :  * Redistribution and use in source and binary forms, with or without
      13             :  * modification, are permitted provided that the following conditions are met:
      14             :  *
      15             :  * 1. Redistributions of source code must retain the above copyright notice,
      16             :  *    this list of conditions and the following disclaimer.
      17             :  *
      18             :  * 2. Redistributions in binary form must reproduce the above copyright notice,
      19             :  *    this list of conditions and the following disclaimer in the documentation
      20             :  *    and/or other materials provided with the distribution.
      21             :  *
      22             :  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
      23             :  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      24             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      25             :  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
      26             :  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      27             :  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      28             :  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      29             :  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      30             :  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      31             :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      32             :  * POSSIBILITY OF SUCH DAMAGE.
      33             :  */
      34             : 
      35             : #pragma GCC optimize("Os")
      36             : 
      37             : #define AP_MATH_ALLOW_DOUBLE_FUNCTIONS 1
      38             : 
      39             : #include "AP_JSON.h"
      40             : #include <AP_Filesystem/AP_Filesystem.h>
      41             : #include <AP_Math/AP_Math.h>
      42             : #include <stdio.h>
      43             : 
      44             : /*
      45             :   load JSON file, returning a value object or nullptr on failure
      46             :  */
      47        2123 : AP_JSON::value *AP_JSON::load_json(const char *filename)
      48             : {
      49             :     struct stat st;
      50        2123 :     if (AP::FS().stat(filename, &st) != 0) {
      51           0 :         ::printf("No such json file %s\n", filename);
      52           0 :         return nullptr;
      53             :     }
      54        2123 :     int fd = AP::FS().open(filename, O_RDONLY);
      55        2123 :     if (fd == -1) {
      56           0 :         ::printf("failed to open json %s\n", filename);
      57           0 :         return nullptr;
      58             :     }
      59        2123 :     char *buf = NEW_NOTHROW char[st.st_size+1];
      60        2123 :     if (buf == nullptr) {
      61           0 :         AP::FS().close(fd);
      62           0 :         ::printf("failed to allocate json %s\n", filename);
      63           0 :         return nullptr;
      64             :     }
      65        2123 :     if (AP::FS().read(fd, buf, st.st_size) != st.st_size) {
      66           0 :         ::printf("failed to read json %s\n", filename);
      67           0 :         delete[] buf;
      68           0 :         AP::FS().close(fd);
      69           0 :         return nullptr;
      70             :     }
      71        2123 :     AP::FS().close(fd);
      72             : 
      73        2123 :     char *start = strchr(buf, '{');
      74        2123 :     if (!start) {
      75           0 :         ::printf("Invalid json %s\n", filename);
      76           0 :         delete[] buf;
      77           0 :         return nullptr;
      78             :     }
      79             : 
      80             :     /*
      81             :       remove comments, as not allowed by the parser
      82             :      */
      83        2906 :     for (char *p = strchr(start,'#'); p; p=strchr(p+1, '#')) {
      84             :         // clear to end of line
      85             :         do {
      86       21561 :             *p++ = ' ';
      87       21561 :         } while (*p != '\n' && *p != '\r' && *p);
      88             :     }
      89             : 
      90        2123 :     AP_JSON::value *obj = NEW_NOTHROW AP_JSON::value;
      91        2123 :     if (obj == nullptr) {
      92           0 :         ::printf("Invalid allocate json for %s\n", filename);
      93           0 :         delete[] buf;
      94           0 :         return nullptr;
      95             :     }
      96        2123 :     std::string err = AP_JSON::parse(*obj, start);
      97        2123 :     if (!err.empty()) {
      98           0 :         ::printf("parse failed for json %s\n", filename);
      99           0 :         delete obj;
     100           0 :         delete[] buf;
     101           0 :         return nullptr;
     102             :     }
     103             : 
     104        2123 :     delete[] buf;
     105        2123 :     return obj;
     106        2123 : }
     107             : 
     108             : typedef AP_JSON::value::array array;
     109             : typedef AP_JSON::value::object object;
     110             : typedef AP_JSON::value value;
     111             : typedef AP_JSON::null null;
     112             : 
     113             : enum {
     114             :     null_type,
     115             :     boolean_type,
     116             :     number_type,
     117             :     string_type,
     118             :     array_type,
     119             :     object_type
     120             : };
     121             : 
     122             : 
     123     1154490 : AP_JSON::value::value() : type_(null_type), u_()
     124             : {
     125     1154490 : }
     126             : 
     127     1122413 : AP_JSON::value::value(int type, bool) : type_(type), u_()
     128             : {
     129     1122413 :     switch (type) {
     130             : #define INIT(p, v)                           \
     131             :   case p##type:                              \
     132             :     u_.p = v;                                \
     133             :     break
     134             :         INIT(boolean_, false);
     135             :         INIT(number_, 0.0);
     136      688926 :         INIT(string_, NEW_NOTHROW std::string());
     137      180084 :         INIT(array_, NEW_NOTHROW array());
     138      253403 :         INIT(object_, NEW_NOTHROW object());
     139             : #undef INIT
     140             :     default:
     141             :         break;
     142             :     }
     143     1122413 : }
     144             : 
     145       29316 : AP_JSON::value::value(bool b) : type_(boolean_type), u_()
     146             : {
     147       29316 :     u_.boolean_ = b;
     148       29316 : }
     149             : 
     150         638 : AP_JSON::value::value(double n) : type_(number_type), u_()
     151             : {
     152         638 :     u_.number_ = n;
     153         638 : }
     154             : 
     155           0 : AP_JSON::value::value(const std::string &s) : type_(string_type), u_()
     156             : {
     157           0 :     u_.string_ = NEW_NOTHROW std::string(s);
     158           0 : }
     159             : 
     160           0 : AP_JSON::value::value(const array &a) : type_(array_type), u_()
     161             : {
     162           0 :     u_.array_ = NEW_NOTHROW array(a);
     163           0 : }
     164             : 
     165           0 : AP_JSON::value::value(const object &o) : type_(object_type), u_()
     166             : {
     167           0 :     u_.object_ = NEW_NOTHROW object(o);
     168           0 : }
     169             : 
     170           0 : AP_JSON::value::value(std::string &&s) : type_(string_type), u_()
     171             : {
     172           0 :     u_.string_ = NEW_NOTHROW std::string(std::move(s));
     173           0 : }
     174             : 
     175           0 : AP_JSON::value::value(array &&a) : type_(array_type), u_()
     176             : {
     177           0 :     u_.array_ = NEW_NOTHROW array(std::move(a));
     178           0 : }
     179             : 
     180           0 : AP_JSON::value::value(object &&o) : type_(object_type), u_()
     181             : {
     182           0 :     u_.object_ = NEW_NOTHROW object(std::move(o));
     183           0 : }
     184             : 
     185           0 : AP_JSON::value::value(const char *s) : type_(string_type), u_()
     186             : {
     187           0 :     u_.string_ = NEW_NOTHROW std::string(s);
     188           0 : }
     189             : 
     190           0 : AP_JSON::value::value(const char *s, size_t len) : type_(string_type), u_()
     191             : {
     192           0 :     u_.string_ = NEW_NOTHROW std::string(s, len);
     193           0 : }
     194             : 
     195     2937515 : void AP_JSON::value::clear()
     196             : {
     197     2937515 :     switch (type_) {
     198             : #define DEINIT(p)           \
     199             :   case p##type:             \
     200             :     delete u_.p;            \
     201             :     break
     202      931830 :         DEINIT(string_);
     203      180084 :         DEINIT(array_);
     204      253403 :         DEINIT(object_);
     205             : #undef DEINIT
     206             :     default:
     207             :         break;
     208             :     }
     209     2937515 : }
     210             : 
     211     2937515 : AP_JSON::value::~value()
     212             : {
     213     2937515 :     clear();
     214     2937515 : }
     215             : 
     216      247022 : AP_JSON::value::value(const value &x) : type_(x.type_), u_()
     217             : {
     218      247022 :     switch (type_) {
     219             : #define INIT(p, v)          \
     220             :   case p##type:             \
     221             :     u_.p = v;               \
     222             :     break
     223      242904 :         INIT(string_, NEW_NOTHROW std::string(*x.u_.string_));
     224           0 :         INIT(array_, NEW_NOTHROW array(*x.u_.array_));
     225           0 :         INIT(object_, NEW_NOTHROW object(*x.u_.object_));
     226             : #undef INIT
     227        4118 :     default:
     228        4118 :         u_ = x.u_;
     229        4118 :         break;
     230             :     }
     231      247022 : }
     232             : 
     233           0 : value &AP_JSON::value::operator=(const value &x)
     234             : {
     235           0 :     if (this != &x) {
     236           0 :         value t(x);
     237           0 :         swap(t);
     238           0 :     }
     239           0 :     return *this;
     240             : }
     241             : 
     242      385296 : AP_JSON::value::value(value &&x) : type_(null_type), u_()
     243             : {
     244      385296 :     swap(x);
     245      385296 : }
     246     1152367 : value &AP_JSON::value::operator=(value &&x)
     247             : {
     248     1152367 :     swap(x);
     249     1152367 :     return *this;
     250             : }
     251             : 
     252     1537663 : void AP_JSON::value::swap(value &x)
     253             : {
     254     1537663 :     std::swap(type_, x.type_);
     255     1537663 :     std::swap(u_, x.u_);
     256     1537663 : }
     257             : 
     258             : #define IS(ctype, jtype)                                    \
     259             :   template <> bool AP_JSON::value::is<ctype>() const {      \
     260             :     return type_ == jtype##_type;                           \
     261             :   }
     262        5574 : IS(null, null)
     263           0 : IS(bool, boolean)
     264        5186 : IS(std::string, string)
     265         621 : IS(array, array)
     266        5782 : IS(object, object)
     267             : #undef IS
     268         638 : template <> bool AP_JSON::value::is<double>() const
     269             : {
     270         638 :     return type_ == number_type;
     271             : }
     272             : 
     273             : #define GET(ctype, var)                                                \
     274             :   template <> const ctype &AP_JSON::value::get<ctype>() const {        \
     275             :     return var;                                                        \
     276             :   }                                                                    \
     277             :   template <> ctype &AP_JSON::value::get<ctype>() {                    \
     278             :     return var;                                                        \
     279             :   }
     280           0 : GET(bool, u_.boolean_)
     281      692221 : GET(std::string, *u_.string_)
     282      385917 : GET(array, *u_.array_)
     283      765097 : GET(object, *u_.object_)
     284         638 : GET(double, u_.number_)
     285             : #undef GET
     286             : 
     287             : #define SET(ctype, jtype, setter)                                      \
     288             :   template <> void AP_JSON::value::set<ctype>(const ctype &_val) {     \
     289             :     clear();                                                           \
     290             :     type_ = jtype##_type;                                              \
     291             :     setter                                                             \
     292             :   }
     293           0 : SET(bool, boolean, u_.boolean_ = _val;)
     294           0 : SET(std::string, string, u_.string_ = NEW_NOTHROW std::string(_val);)
     295           0 : SET(array, array, u_.array_ = NEW_NOTHROW array(_val);)
     296           0 : SET(object, object, u_.object_ = NEW_NOTHROW object(_val);)
     297           0 : SET(double, number, u_.number_ = _val;)
     298             : #undef SET
     299             : 
     300             : #define MOVESET(ctype, jtype, setter)                                  \
     301             :   template <> void AP_JSON::value::set<ctype>(ctype && _val) {         \
     302             :     clear();                                                           \
     303             :     type_ = jtype##_type;                                              \
     304             :     setter                                                             \
     305             :   }
     306           0 : MOVESET(std::string, string, u_.string_ = NEW_NOTHROW std::string(std::move(_val));)
     307           0 : MOVESET(array, array, u_.array_ = NEW_NOTHROW array(std::move(_val));)
     308           0 : MOVESET(object, object, u_.object_ = NEW_NOTHROW object(std::move(_val));)
     309             : #undef MOVESET
     310             : 
     311           0 : bool AP_JSON::value::evaluate_as_boolean() const
     312             : {
     313           0 :     switch (type_) {
     314             :     case null_type:
     315             :         return false;
     316           0 :     case boolean_type:
     317           0 :         return u_.boolean_;
     318           0 :     case number_type:
     319           0 :         return !is_zero(u_.number_);
     320           0 :     case string_type:
     321           0 :         return !u_.string_->empty();
     322           0 :     default:
     323           0 :         return true;
     324             :     }
     325             : }
     326             : 
     327           0 : const value &AP_JSON::value::get(const size_t idx) const
     328             : {
     329           0 :     static value s_null;
     330           0 :     return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null;
     331             : }
     332             : 
     333           0 : value &AP_JSON::value::get(const size_t idx)
     334             : {
     335           0 :     static value s_null;
     336           0 :     return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null;
     337             : }
     338             : 
     339        9833 : const value &AP_JSON::value::get(const std::string &key) const
     340             : {
     341        9833 :     static value s_null;
     342        9833 :     object::const_iterator i = u_.object_->find(key);
     343        9833 :     return i != u_.object_->end() ? i->second : s_null;
     344             : }
     345             : 
     346        3480 : value &AP_JSON::value::get(const std::string &key)
     347             : {
     348        3480 :     static value s_null;
     349        3480 :     object::iterator i = u_.object_->find(key);
     350        3480 :     return i != u_.object_->end() ? i->second : s_null;
     351             : }
     352             : 
     353           0 : bool AP_JSON::value::contains(const size_t idx) const
     354             : {
     355           0 :     return idx < u_.array_->size();
     356             : }
     357             : 
     358        4308 : bool AP_JSON::value::contains(const std::string &key) const
     359             : {
     360        4308 :     object::const_iterator i = u_.object_->find(key);
     361        4308 :     return i != u_.object_->end();
     362             : }
     363             : 
     364           0 : std::string AP_JSON::value::to_str() const
     365             : {
     366           0 :     switch (type_) {
     367           0 :     case null_type:
     368           0 :         return "null";
     369           0 :     case boolean_type:
     370           0 :         return u_.boolean_ ? "true" : "false";
     371           0 :     case number_type: {
     372             :         char buf[256];
     373             :         double tmp;
     374           0 :         snprintf(buf, sizeof(buf), fabs(u_.number_) < (1ULL << 53) && is_zero(modf(u_.number_, &tmp)) ? "%.f" : "%.17g", u_.number_);
     375           0 :         return buf;
     376             :     }
     377           0 :     case string_type:
     378           0 :         return *u_.string_;
     379           0 :     case array_type:
     380           0 :         return "array";
     381           0 :     case object_type:
     382           0 :         return "object";
     383             :     default:
     384             :         break;
     385             :     }
     386           0 :     return std::string();
     387             : }
     388             : 
     389             : template <typename Iter> void copy(const std::string &s, Iter oi)
     390             : {
     391             :     std::copy(s.begin(), s.end(), oi);
     392             : }
     393             : 
     394             : template <typename Iter> class input
     395             : {
     396             : protected:
     397             :     Iter cur_, end_;
     398             :     bool consumed_;
     399             :     int line_;
     400             : 
     401             : public:
     402        2123 :     input(const Iter &first, const Iter &last) : cur_(first), end_(last), consumed_(false), line_(1)
     403             :     {
     404        2123 :     }
     405    64122947 :     int getc()
     406             :     {
     407    64122947 :         if (consumed_) {
     408    58553093 :             if (*cur_ == '\n') {
     409     1549148 :                 ++line_;
     410             :             }
     411    58553093 :             ++cur_;
     412             :         }
     413    64122947 :         if (cur_ == end_) {
     414           0 :             consumed_ = false;
     415           0 :             return -1;
     416             :         }
     417    64122947 :         consumed_ = true;
     418    64122947 :         return *cur_ & 0xff;
     419             :     }
     420     5567731 :     void ungetc()
     421             :     {
     422     5567731 :         consumed_ = false;
     423     5567731 :     }
     424        2123 :     Iter cur() const
     425             :     {
     426        2123 :         if (consumed_) {
     427             :             input<Iter> *self = const_cast<input<Iter> *>(this);
     428        2123 :             self->consumed_ = false;
     429        2123 :             ++self->cur_;
     430             :         }
     431        2123 :         return cur_;
     432             :     }
     433           0 :     int line() const
     434             :     {
     435           0 :         return line_;
     436             :     }
     437     4699481 :     void skip_ws()
     438             :     {
     439             :         while (1) {
     440    30651136 :             int ch = getc();
     441    30651136 :             if (!(ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')) {
     442     4699481 :                 ungetc();
     443             :                 break;
     444             :             }
     445             :         }
     446     4699481 :     }
     447     3547114 :     bool expect(const int expected)
     448             :     {
     449     3547114 :         skip_ws();
     450     3547114 :         if (getc() != expected) {
     451      866974 :             ungetc();
     452      866974 :             return false;
     453             :         }
     454             :         return true;
     455             :     }
     456       29316 :     bool match(const std::string &pattern)
     457             :     {
     458      117264 :         for (std::string::const_iterator pi(pattern.begin()); pi != pattern.end(); ++pi) {
     459       87948 :             if (getc() != *pi) {
     460           0 :                 ungetc();
     461           0 :                 return false;
     462             :             }
     463             :         }
     464       29316 :         return true;
     465             :     }
     466             : };
     467             : 
     468             : template <typename Iter> int _parse_quadhex(input<Iter> &in)
     469             : {
     470             :     int uni_ch = 0, hex;
     471             :     for (int i = 0; i < 4; i++) {
     472             :         if ((hex = in.getc()) == -1) {
     473             :             return -1;
     474             :         }
     475             :         if ('0' <= hex && hex <= '9') {
     476             :             hex -= '0';
     477             :         } else if ('A' <= hex && hex <= 'F') {
     478             :             hex -= 'A' - 0xa;
     479             :         } else if ('a' <= hex && hex <= 'f') {
     480             :             hex -= 'a' - 0xa;
     481             :         } else {
     482             :             in.ungetc();
     483             :             return -1;
     484             :         }
     485             :         uni_ch = uni_ch * 16 + hex;
     486             :     }
     487             :     return uni_ch;
     488             : }
     489             : 
     490     1453874 : template <typename String, typename Iter> bool _parse_string(String &out, input<Iter> &in)
     491             : {
     492             :     while (1) {
     493    28681442 :         int ch = in.getc();
     494    28681442 :         if (ch < ' ') {
     495           0 :             in.ungetc();
     496           0 :             return false;
     497    28681442 :         } else if (ch == '"') {
     498             :             return true;
     499    27227568 :         } else if (ch == '\\') {
     500           0 :             if ((ch = in.getc()) == -1) {
     501             :                 return false;
     502             :             }
     503           0 :             switch (ch) {
     504             : #define MAP(sym, val)                                                                                                              \
     505             :   case sym:                                                                                                                        \
     506             :     out.push_back(val);                                                                                                            \
     507             :     break
     508           0 :                 MAP('"', '\"');
     509           0 :                 MAP('\\', '\\');
     510           0 :                 MAP('/', '/');
     511           0 :                 MAP('b', '\b');
     512           0 :                 MAP('f', '\f');
     513           0 :                 MAP('n', '\n');
     514           0 :                 MAP('r', '\r');
     515           0 :                 MAP('t', '\t');
     516             : #undef MAP
     517             :             default:
     518             :                 return false;
     519             :             }
     520             :         } else {
     521    27227568 :             out.push_back(static_cast<char>(ch));
     522             :         }
     523             :     }
     524             :     return false;
     525             : }
     526             : 
     527      180084 : template <typename Context, typename Iter> bool _parse_array(Context &ctx, input<Iter> &in)
     528             : {
     529      180084 :     if (!ctx.parse_array_start()) {
     530             :         return false;
     531             :     }
     532             :     size_t idx = 0;
     533      180084 :     if (in.expect(']')) {
     534           0 :         return ctx.parse_array_stop(idx);
     535             :     }
     536             :     do {
     537      385296 :         if (!ctx.parse_array_item(in, idx)) {
     538             :             return false;
     539             :         }
     540      385296 :         idx++;
     541      385296 :     } while (in.expect(','));
     542      180084 :     return in.expect(']') && ctx.parse_array_stop(idx);
     543             : }
     544             : 
     545      253403 : template <typename Context, typename Iter> bool _parse_object(Context &ctx, input<Iter> &in)
     546             : {
     547      253403 :     if (!ctx.parse_object_start()) {
     548             :         return false;
     549             :     }
     550      253403 :     if (in.expect('}')) {
     551             :         return true;
     552             :     }
     553             :     do {
     554      764948 :         std::string key;
     555      764948 :         if (!in.expect('"') || !_parse_string(key, in) || !in.expect(':')) {
     556           0 :             return false;
     557             :         }
     558      764948 :         if (!ctx.parse_object_item(in, key)) {
     559             :             return false;
     560             :         }
     561      764948 :     } while (in.expect(','));
     562      253403 :     return in.expect('}');
     563             : }
     564             : 
     565         638 : template <typename Iter> std::string _parse_number(input<Iter> &in)
     566             : {
     567         638 :     std::string num_str;
     568             :     while (1) {
     569        2940 :         int ch = in.getc();
     570        2940 :         if (('0' <= ch && ch <= '9') || ch == '+' || ch == '-' || ch == 'e' || ch == 'E') {
     571        1897 :             num_str.push_back(static_cast<char>(ch));
     572        1043 :         } else if (ch == '.') {
     573         405 :             num_str.push_back('.');
     574             :         } else {
     575         638 :             in.ungetc();
     576             :             break;
     577             :         }
     578             :     }
     579         638 :     return num_str;
     580             : }
     581             : 
     582     1152367 : template <typename Context, typename Iter> bool _parse(Context &ctx, input<Iter> &in)
     583             : {
     584     1152367 :     in.skip_ws();
     585     1152367 :     int ch = in.getc();
     586     1152367 :     switch (ch) {
     587             : #define IS(ch, text, op)                                                                                                           \
     588             :   case ch:                                                                                                                         \
     589             :     if (in.match(text) && op) {                                                                                                    \
     590             :       return true;                                                                                                                 \
     591             :     } else {                                                                                                                       \
     592             :       return false;                                                                                                                \
     593             :     }
     594           0 :         IS('n', "ull", ctx.set_null());
     595           0 :         IS('f', "alse", ctx.set_bool(false));
     596       29316 :         IS('t', "rue", ctx.set_bool(true));
     597             : #undef IS
     598      688926 :     case '"':
     599      688926 :         return ctx.parse_string(in);
     600      180084 :     case '[':
     601      180084 :         return _parse_array(ctx, in);
     602      253403 :     case '{':
     603      253403 :         return _parse_object(ctx, in);
     604         638 :     default:
     605         638 :         if (('0' <= ch && ch <= '9') || ch == '-') {
     606             :             double f;
     607             :             char *endp;
     608         638 :             in.ungetc();
     609         638 :             std::string num_str(_parse_number(in));
     610         638 :             if (num_str.empty()) {
     611             :                 return false;
     612             :             }
     613         638 :             f = strtod(num_str.c_str(), &endp);
     614         638 :             if (endp == num_str.c_str() + num_str.size()) {
     615         638 :                 ctx.set_number(f);
     616         638 :                 return true;
     617             :             }
     618             :             return false;
     619         638 :         }
     620             :         break;
     621             :     }
     622           0 :     in.ungetc();
     623           0 :     return false;
     624             : }
     625             : 
     626             : class default_parse_context
     627             : {
     628             : protected:
     629             :     value *out_;
     630             : 
     631             : public:
     632     1152367 :     default_parse_context(value *out) : out_(out)
     633             :     {
     634     1152367 :     }
     635           0 :     bool set_null()
     636             :     {
     637           0 :         *out_ = value();
     638           0 :         return true;
     639             :     }
     640       29316 :     bool set_bool(bool b)
     641             :     {
     642       29316 :         *out_ = value(b);
     643       29316 :         return true;
     644             :     }
     645         638 :     bool set_number(double f)
     646             :     {
     647         638 :         *out_ = value(f);
     648         638 :         return true;
     649             :     }
     650      688926 :     template <typename Iter> bool parse_string(input<Iter> &in)
     651             :     {
     652      688926 :         *out_ = value(string_type, false);
     653      688926 :         return _parse_string(out_->get<std::string>(), in);
     654             :     }
     655      180084 :     bool parse_array_start()
     656             :     {
     657      180084 :         *out_ = value(array_type, false);
     658      180084 :         return true;
     659             :     }
     660      385296 :     template <typename Iter> bool parse_array_item(input<Iter> &in, size_t)
     661             :     {
     662      385296 :         array &a = out_->get<array>();
     663      385296 :         a.push_back(value());
     664      385296 :         default_parse_context ctx(&a.back());
     665      385296 :         return _parse(ctx, in);
     666             :     }
     667      180084 :     bool parse_array_stop(size_t)
     668             :     {
     669      180084 :         return true;
     670             :     }
     671      253403 :     bool parse_object_start()
     672             :     {
     673      253403 :         *out_ = value(object_type, false);
     674      253403 :         return true;
     675             :     }
     676      764948 :     template <typename Iter> bool parse_object_item(input<Iter> &in, const std::string &key)
     677             :     {
     678      764948 :         object &o = out_->get<object>();
     679      764948 :         default_parse_context ctx(&o[key]);
     680      764948 :         return _parse(ctx, in);
     681             :     }
     682             : 
     683             : private:
     684             :     default_parse_context(const default_parse_context &);
     685             :     default_parse_context &operator=(const default_parse_context &);
     686             : };
     687             : 
     688        2123 : template <typename Context, typename Iter> Iter _parse(Context &ctx, const Iter &first, const Iter &last, std::string *err)
     689             : {
     690        2123 :     input<Iter> in(first, last);
     691        2123 :     if (!_parse(ctx, in) && err != NULL) {
     692             :         char buf[64];
     693           0 :         snprintf(buf, sizeof(buf), "syntax error at line %d near: ", in.line());
     694           0 :         *err = buf;
     695             :         while (1) {
     696           0 :             int ch = in.getc();
     697           0 :             if (ch == -1 || ch == '\n') {
     698             :                 break;
     699           0 :             } else if (ch >= ' ') {
     700           0 :                 err->push_back(static_cast<char>(ch));
     701             :             }
     702             :         }
     703             :     }
     704        2123 :     return in.cur();
     705             : }
     706             : 
     707        2123 : template <typename Iter> Iter parse(value &out, const Iter &first, const Iter &last, std::string *err)
     708             : {
     709        2123 :     default_parse_context ctx(&out);
     710        2123 :     return _parse(ctx, first, last, err);
     711             : }
     712             : 
     713        2123 : std::string AP_JSON::parse(value &out, const std::string &s)
     714             : {
     715        2123 :     std::string err;
     716        2123 :     ::parse(out, s.begin(), s.end(), &err);
     717        2123 :     return err;
     718             : }

Generated by: LCOV version 1.14