LCOV - code coverage report
Current view: top level - muse/framework/global/serialization - json.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 55.0 % 464 255
Test Date: 2026-11-05 04:07:02

            Line data    Source code
       1              : /*
       2              :  * SPDX-License-Identifier: GPL-3.0-only
       3              :  * MuseScore-CLA-applies
       4              :  *
       5              :  * MuseScore Studio
       6              :  * Music Composition & Notation
       7              :  *
       8              :  * Copyright (C) 2021 MuseScore Limited and others
       9              :  *
      10              :  * This program is free software: you can redistribute it and/or modify
      11              :  * it under the terms of the GNU General Public License version 3 as
      12              :  * published by the Free Software Foundation.
      13              :  *
      14              :  * This program is distributed in the hope that it will be useful,
      15              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17              :  * GNU General Public License for more details.
      18              :  *
      19              :  * You should have received a copy of the GNU General Public License
      20              :  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
      21              :  */
      22              : #include "json.h"
      23              : 
      24              : #include <cmath>
      25              : #include <cassert>
      26              : 
      27              : #define PICOJSON_USE_LOCALE 1
      28              : #define PICOJSON_ASSERT assert
      29              : #include "picojson.h"
      30              : 
      31              : #include "log.h"
      32              : 
      33              : using namespace muse;
      34              : 
      35              : struct muse::JsonData
      36              : {
      37              :     picojson::value val;
      38              : };
      39              : 
      40       800205 : static inline const picojson::value& val_const(const std::shared_ptr<JsonData>& d)
      41              : {
      42       800205 :     return d->val;
      43              : }
      44              : 
      45         5225 : static inline picojson::value& val_mut(std::shared_ptr<JsonData>& d)
      46              : {
      47         5225 :     return d->val;
      48              : }
      49              : 
      50              : // =======================================
      51              : // JsonValue
      52              : // =======================================
      53          106 : JsonValue::JsonValue(bool v)
      54          106 :     : m_data(std::make_shared<JsonData>())
      55              : {
      56          106 :     val_mut(m_data).set<bool>(v);
      57          106 : }
      58              : 
      59         5102 : JsonValue::JsonValue(int v)
      60         5102 :     : m_data(std::make_shared<JsonData>())
      61              : {
      62         5102 :     double d = static_cast<double>(v);
      63         5102 :     val_mut(m_data).set<double>(d);
      64         5102 : }
      65              : 
      66            0 : JsonValue::JsonValue(double v)
      67            0 :     : m_data(std::make_shared<JsonData>())
      68              : {
      69            0 :     val_mut(m_data).set<double>(v);
      70            0 : }
      71              : 
      72            0 : JsonValue::JsonValue(const String& v)
      73            0 :     : m_data(std::make_shared<JsonData>())
      74              : {
      75            0 :     val_mut(m_data).set<std::string>(v.toStdString());
      76            0 : }
      77              : 
      78           17 : JsonValue::JsonValue(const std::string& v)
      79           17 :     : m_data(std::make_shared<JsonData>())
      80              : {
      81           17 :     val_mut(m_data).set<std::string>(v);
      82           17 : }
      83              : 
      84            0 : JsonValue::JsonValue(const char* v)
      85            0 :     : m_data(std::make_shared<JsonData>())
      86              : {
      87            0 :     val_mut(m_data).set<std::string>(std::string(v));
      88            0 : }
      89              : 
      90            0 : JsonValue::JsonValue(const JsonArray& v)
      91            0 :     : m_data(v.m_data)
      92              : {
      93            0 :     if (!m_data) {
      94            0 :         m_data = std::make_shared<JsonData>();
      95              :     }
      96            0 : }
      97              : 
      98            0 : JsonValue::JsonValue(const JsonObject& v)
      99            0 :     : m_data(v.m_data)
     100              : {
     101            0 :     if (!m_data) {
     102            0 :         m_data = std::make_shared<JsonData>();
     103              :     }
     104            0 : }
     105              : 
     106       628933 : JsonValue::JsonValue(std::shared_ptr<JsonData> d)
     107       628933 :     : m_data(d)
     108              : {
     109       628933 :     if (!m_data) {
     110       276723 :         m_data = std::make_shared<JsonData>();
     111              :     }
     112       628933 : }
     113              : 
     114            0 : void JsonValue::detach()
     115              : {
     116            0 :     if (!m_data) {
     117            0 :         return;
     118              :     }
     119              : 
     120            0 :     if (m_data.use_count() == 1) {
     121            0 :         return;
     122              :     }
     123              : 
     124            0 :     m_data = std::make_shared<JsonData>(*m_data);
     125              : }
     126              : 
     127         4400 : bool JsonValue::isNull() const
     128              : {
     129         4400 :     return val_const(m_data).is<picojson::null>();
     130              : }
     131              : 
     132            0 : void JsonValue::setNull()
     133              : {
     134            0 :     detach();
     135            0 :     val_mut(m_data) = picojson::value();
     136            0 : }
     137              : 
     138           25 : bool JsonValue::isBool() const
     139              : {
     140           25 :     return val_const(m_data).is<bool>();
     141              : }
     142              : 
     143          136 : bool JsonValue::toBool() const
     144              : {
     145          136 :     return val_const(m_data).evaluate_as_boolean();
     146              : }
     147              : 
     148            0 : JsonValue& JsonValue::operator=(bool v)
     149              : {
     150            0 :     detach();
     151            0 :     val_mut(m_data).set<bool>(v);
     152            0 :     return *this;
     153              : }
     154              : 
     155       125813 : bool JsonValue::isNumber() const
     156              : {
     157       125813 :     return val_const(m_data).is<double>();
     158              : }
     159              : 
     160          100 : int JsonValue::toInt() const
     161              : {
     162          100 :     if (!isNumber()) {
     163            8 :         return 0;
     164              :     }
     165           92 :     return static_cast<int>(std::round(val_const(m_data).get<double>()));
     166              : }
     167              : 
     168       125685 : double JsonValue::toDouble() const
     169              : {
     170       125685 :     if (!isNumber()) {
     171           32 :         return 0.0;
     172              :     }
     173       125653 :     return val_const(m_data).get<double>();
     174              : }
     175              : 
     176            0 : JsonValue& JsonValue::operator=(int v)
     177              : {
     178            0 :     detach();
     179            0 :     double d = static_cast<double>(v);
     180            0 :     val_mut(m_data).set<double>(d);
     181            0 :     return *this;
     182              : }
     183              : 
     184            0 : JsonValue& JsonValue::operator=(double v)
     185              : {
     186            0 :     detach();
     187            0 :     val_mut(m_data).set<double>(v);
     188            0 :     return *this;
     189              : }
     190              : 
     191       109634 : bool JsonValue::isString() const
     192              : {
     193       109634 :     return val_const(m_data).is<std::string>();
     194              : }
     195              : 
     196       102149 : String JsonValue::toString() const
     197              : {
     198       102149 :     if (!isString()) {
     199        47506 :         static String dummy;
     200        47506 :         return dummy;
     201              :     }
     202        54643 :     return String::fromStdString(val_const(m_data).get<std::string>());
     203              : }
     204              : 
     205         7417 : const std::string& JsonValue::toStdString() const
     206              : {
     207         7417 :     if (!isString()) {
     208            8 :         static std::string dummy;
     209            8 :         return dummy;
     210              :     }
     211         7409 :     return val_const(m_data).get<std::string>();
     212              : }
     213              : 
     214            0 : JsonValue& JsonValue::operator=(const String& str)
     215              : {
     216            0 :     detach();
     217            0 :     val_mut(m_data).set<std::string>(str.toStdString());
     218            0 :     return *this;
     219              : }
     220              : 
     221            0 : JsonValue& JsonValue::operator=(const std::string& str)
     222              : {
     223            0 :     detach();
     224            0 :     val_mut(m_data).set<std::string>(str);
     225            0 :     return *this;
     226              : }
     227              : 
     228            0 : JsonValue& JsonValue::operator=(const char* str)
     229              : {
     230            0 :     detach();
     231            0 :     val_mut(m_data).set<std::string>(std::string(str));
     232            0 :     return *this;
     233              : }
     234              : 
     235           34 : bool JsonValue::isArray() const
     236              : {
     237           34 :     return val_const(m_data).is<picojson::array>();
     238              : }
     239              : 
     240        65646 : JsonArray JsonValue::toArray() const
     241              : {
     242        65646 :     return JsonArray(m_data);
     243              : }
     244              : 
     245            0 : JsonValue& JsonValue::operator=(const JsonArray& arr)
     246              : {
     247            0 :     detach();
     248            0 :     val_mut(m_data) = val_const(arr.m_data);
     249            0 :     return *this;
     250              : }
     251              : 
     252          140 : bool JsonValue::isObject() const
     253              : {
     254          140 :     return val_const(m_data).is<picojson::object>();
     255              : }
     256              : 
     257       104860 : JsonObject JsonValue::toObject() const
     258              : {
     259       104860 :     return JsonObject(m_data);
     260              : }
     261              : 
     262            0 : JsonValue& JsonValue::operator=(const JsonObject& obj)
     263              : {
     264            0 :     detach();
     265            0 :     val_mut(m_data) = val_const(obj.m_data);
     266            0 :     return *this;
     267              : }
     268              : 
     269            0 : Val JsonValue::toVal() const
     270              : {
     271            0 :     if (isNull()) {
     272            0 :         return Val();
     273              :     }
     274            0 :     if (isBool()) {
     275            0 :         return Val(toBool());
     276              :     }
     277            0 :     if (isNumber()) {
     278            0 :         return Val(toDouble());
     279              :     }
     280            0 :     if (isString()) {
     281            0 :         return Val(toStdString());
     282              :     }
     283            0 :     if (isArray()) {
     284            0 :         muse::ValList list;
     285            0 :         const JsonArray array = toArray();
     286            0 :         for (size_t i = 0; i < array.size(); ++i) {
     287            0 :             list.emplace_back(array[i].toVal());
     288              :         }
     289            0 :         return Val(list);
     290            0 :     }
     291            0 :     if (isObject()) {
     292            0 :         muse::ValMap map;
     293            0 :         const JsonObject object = toObject();
     294            0 :         for (const auto& key : object.keys()) {
     295            0 :             map[key] = object[key].toVal();
     296            0 :         }
     297            0 :         return muse::Val(map);
     298            0 :     }
     299              : 
     300            0 :     return muse::Val();
     301              : }
     302              : 
     303            0 : JsonValue JsonValue::fromVal(const Val& val)
     304              : {
     305            0 :     switch (val.type()) {
     306            0 :     case Val::Type::Undefined: return JsonValue();
     307            0 :     case Val::Type::Bool: return JsonValue(val.toBool());
     308            0 :     case Val::Type::Int: return JsonValue(val.toInt());
     309            0 :     case Val::Type::Int64: return JsonValue(val.toString());  // as string
     310            0 :     case Val::Type::Double: return JsonValue(val.toDouble());
     311            0 :     case Val::Type::String: return JsonValue(val.toString());
     312            0 :     case Val::Type::List: {
     313            0 :         JsonArray array;
     314            0 :         for (const auto& item : val.toList()) {
     315            0 :             array.append(fromVal(item));
     316            0 :         }
     317            0 :         return array;
     318            0 :     }
     319            0 :     case Val::Type::Map: {
     320            0 :         JsonObject object;
     321            0 :         for (const auto& [key, value] : val.toMap()) {
     322            0 :             object[key] = fromVal(value);
     323            0 :         }
     324            0 :         return object;
     325            0 :     }
     326            0 :     default: {
     327            0 :         NOT_SUPPORTED << "data type: " << (int)val.type();
     328              :     }
     329              :     }
     330              : 
     331            0 :     return JsonValue();
     332              : }
     333              : 
     334              : // =======================================
     335              : // JsonValueRef
     336              : // =======================================
     337              : 
     338        13330 : JsonValueRef::JsonValueRef(const std::string& key, JsonObject* o)
     339        13330 :     : m_key(key), m_object(o)
     340              : {
     341        13330 : }
     342              : 
     343            0 : JsonValueRef::JsonValueRef(size_t i, JsonArray* a)
     344            0 :     : m_idx(i), m_array(a)
     345              : {
     346            0 : }
     347              : 
     348         2505 : JsonValueRef& JsonValueRef::operator=(bool v)
     349              : {
     350         2505 :     if (m_object) {
     351         2505 :         m_object->set(m_key, v);
     352            0 :     } else if (m_array) {
     353            0 :         m_array->set(m_idx, v);
     354              :     }
     355         2505 :     return *this;
     356              : }
     357              : 
     358         4628 : JsonValueRef& JsonValueRef::operator=(int v)
     359              : {
     360         4628 :     if (m_object) {
     361         4628 :         m_object->set(m_key, v);
     362            0 :     } else if (m_array) {
     363            0 :         m_array->set(m_idx, v);
     364              :     }
     365         4628 :     return *this;
     366              : }
     367              : 
     368         1231 : JsonValueRef& JsonValueRef::operator=(double v)
     369              : {
     370         1231 :     if (m_object) {
     371         1231 :         m_object->set(m_key, v);
     372            0 :     } else if (m_array) {
     373            0 :         m_array->set(m_idx, v);
     374              :     }
     375         1231 :     return *this;
     376              : }
     377              : 
     378          637 : JsonValueRef& JsonValueRef::operator=(const String& v)
     379              : {
     380          637 :     if (m_object) {
     381          637 :         m_object->set(m_key, v);
     382            0 :     } else if (m_array) {
     383            0 :         m_array->set(m_idx, v);
     384              :     }
     385          637 :     return *this;
     386              : }
     387              : 
     388          952 : JsonValueRef& JsonValueRef::operator=(const std::string& v)
     389              : {
     390          952 :     if (m_object) {
     391          952 :         m_object->set(m_key, v);
     392            0 :     } else if (m_array) {
     393            0 :         m_array->set(m_idx, v);
     394              :     }
     395          952 :     return *this;
     396              : }
     397              : 
     398            8 : JsonValueRef& JsonValueRef::operator=(const char* v)
     399              : {
     400            8 :     if (m_object) {
     401            8 :         m_object->set(m_key, v);
     402            0 :     } else if (m_array) {
     403            0 :         m_array->set(m_idx, v);
     404              :     }
     405            8 :     return *this;
     406              : }
     407              : 
     408            1 : JsonValueRef& JsonValueRef::operator=(const JsonValue& v)
     409              : {
     410            1 :     if (m_object) {
     411            1 :         m_object->set(m_key, v);
     412            0 :     } else if (m_array) {
     413            0 :         m_array->set(m_idx, v);
     414              :     }
     415            1 :     return *this;
     416              : }
     417              : 
     418         1715 : JsonValueRef& JsonValueRef::operator=(const JsonArray& v)
     419              : {
     420         1715 :     if (m_object) {
     421         1715 :         m_object->set(m_key, v);
     422            0 :     } else if (m_array) {
     423            0 :         m_array->set(m_idx, v);
     424              :     }
     425         1715 :     return *this;
     426              : }
     427              : 
     428         1653 : JsonValueRef& JsonValueRef::operator=(const JsonObject& v)
     429              : {
     430         1653 :     if (m_object) {
     431         1653 :         m_object->set(m_key, v);
     432            0 :     } else if (m_array) {
     433            0 :         m_array->set(m_idx, v);
     434              :     }
     435         1653 :     return *this;
     436              : }
     437              : 
     438              : // =======================================
     439              : // JsonArray
     440              : // =======================================
     441              : 
     442       137272 : static inline const picojson::array& array_const(const std::shared_ptr<JsonData>& d)
     443              : {
     444       137272 :     return d->val.get<picojson::array>();
     445              : }
     446              : 
     447         7744 : static inline picojson::array& array_mut(std::shared_ptr<JsonData>& d)
     448              : {
     449         7744 :     return d->val.get<picojson::array>();
     450              : }
     451              : 
     452        66922 : JsonArray::JsonArray(std::shared_ptr<JsonData> d)
     453        66922 :     : m_data(d)
     454              : {
     455        66922 :     if (!m_data) {
     456         1195 :         m_data = std::make_shared<JsonData>();
     457         1195 :         m_data->val = picojson::value(picojson::array());
     458              :     }
     459        66922 : }
     460              : 
     461         1120 : JsonArray::JsonArray(std::initializer_list<JsonValue> args)
     462              : {
     463         1120 :     m_data = std::make_shared<JsonData>();
     464         1120 :     m_data->val = picojson::value(picojson::array());
     465              : 
     466         1120 :     array_mut(m_data).reserve(args.size());
     467         6221 :     for (const JsonValue& v : args) {
     468         5101 :         array_mut(m_data).push_back(v.m_data->val);
     469              :     }
     470         1120 : }
     471              : 
     472         1523 : void JsonArray::detach()
     473              : {
     474         1523 :     if (!m_data) {
     475            0 :         return;
     476              :     }
     477              : 
     478         1523 :     if (m_data.use_count() == 1) {
     479         1523 :         return;
     480              :     }
     481              : 
     482            0 :     m_data = std::make_shared<JsonData>(*m_data);
     483              : }
     484              : 
     485         7805 : size_t JsonArray::size() const
     486              : {
     487         7805 :     return array_const(m_data).size();
     488              : }
     489              : 
     490            0 : void JsonArray::resize(size_t i)
     491              : {
     492            0 :     detach();
     493            0 :     array_mut(m_data).resize(i);
     494            0 : }
     495              : 
     496           18 : bool JsonArray::empty() const
     497              : {
     498           18 :     return array_const(m_data).size() == 0;
     499              : }
     500              : 
     501       129449 : JsonValue JsonArray::at(size_t i) const
     502              : {
     503       129449 :     std::shared_ptr<JsonData> d = std::make_shared<JsonData>();
     504       129449 :     d->val = array_const(m_data).at(i);
     505       258898 :     return JsonValue(d);
     506       129449 : }
     507              : 
     508            0 : JsonArray& JsonArray::set(size_t i, bool v)
     509              : {
     510            0 :     detach();
     511            0 :     array_mut(m_data)[i] = picojson::value(v);
     512            0 :     return *this;
     513              : }
     514              : 
     515            0 : JsonArray& JsonArray::set(size_t i, int v)
     516              : {
     517            0 :     detach();
     518            0 :     array_mut(m_data)[i] = picojson::value(static_cast<double>(v));
     519            0 :     return *this;
     520              : }
     521              : 
     522            0 : JsonArray& JsonArray::set(size_t i, double v)
     523              : {
     524            0 :     detach();
     525            0 :     array_mut(m_data)[i] = picojson::value(v);
     526            0 :     return *this;
     527              : }
     528              : 
     529            0 : JsonArray& JsonArray::set(size_t i, const String& str)
     530              : {
     531            0 :     detach();
     532            0 :     array_mut(m_data)[i] = picojson::value(str.toStdString());
     533            0 :     return *this;
     534              : }
     535              : 
     536            0 : JsonArray& JsonArray::set(size_t i, const std::string& str)
     537              : {
     538            0 :     detach();
     539            0 :     array_mut(m_data)[i] = picojson::value(str);
     540            0 :     return *this;
     541              : }
     542              : 
     543            0 : JsonArray& JsonArray::set(size_t i, const char* str)
     544              : {
     545            0 :     detach();
     546            0 :     array_mut(m_data)[i] = picojson::value(std::string(str));
     547            0 :     return *this;
     548              : }
     549              : 
     550            0 : JsonArray& JsonArray::set(size_t i, const JsonValue& v)
     551              : {
     552            0 :     detach();
     553            0 :     array_mut(m_data)[i] = v.m_data->val;
     554            0 :     return *this;
     555              : }
     556              : 
     557            0 : JsonArray& JsonArray::set(size_t i, const JsonArray& v)
     558              : {
     559            0 :     detach();
     560            0 :     array_mut(m_data)[i] = v.m_data->val;
     561            0 :     return *this;
     562              : }
     563              : 
     564            0 : JsonArray& JsonArray::set(size_t i, const JsonObject& v)
     565              : {
     566            0 :     detach();
     567            0 :     array_mut(m_data)[i] = v.m_data->val;
     568            0 :     return *this;
     569              : }
     570              : 
     571            0 : JsonArray& JsonArray::append(bool v)
     572              : {
     573            0 :     detach();
     574            0 :     array_mut(m_data).push_back(picojson::value(v));
     575            0 :     return *this;
     576              : }
     577              : 
     578            4 : JsonArray& JsonArray::append(int v)
     579              : {
     580            4 :     detach();
     581            4 :     array_mut(m_data).push_back(picojson::value(static_cast<double>(v)));
     582            4 :     return *this;
     583              : }
     584              : 
     585            0 : JsonArray& JsonArray::append(double v)
     586              : {
     587            0 :     detach();
     588            0 :     array_mut(m_data).push_back(picojson::value(v));
     589            0 :     return *this;
     590              : }
     591              : 
     592            0 : JsonArray& JsonArray::append(const String& str)
     593              : {
     594            0 :     detach();
     595            0 :     array_mut(m_data).push_back(picojson::value(str.toStdString()));
     596            0 :     return *this;
     597              : }
     598              : 
     599            0 : JsonArray& JsonArray::append(const std::string& str)
     600              : {
     601            0 :     detach();
     602            0 :     array_mut(m_data).push_back(picojson::value(str));
     603            0 :     return *this;
     604              : }
     605              : 
     606            0 : JsonArray& JsonArray::append(const char* str)
     607              : {
     608            0 :     detach();
     609            0 :     array_mut(m_data).push_back(picojson::value(std::string(str)));
     610            0 :     return *this;
     611              : }
     612              : 
     613           16 : JsonArray& JsonArray::append(const JsonValue& v)
     614              : {
     615           16 :     detach();
     616           16 :     array_mut(m_data).push_back(val_const(v.m_data));
     617           16 :     return *this;
     618              : }
     619              : 
     620          476 : JsonArray& JsonArray::append(const JsonArray& v)
     621              : {
     622          476 :     detach();
     623          476 :     array_mut(m_data).push_back(val_const(v.m_data));
     624          476 :     return *this;
     625              : }
     626              : 
     627         1027 : JsonArray& JsonArray::append(const JsonObject& v)
     628              : {
     629         1027 :     detach();
     630         1027 :     array_mut(m_data).push_back(val_const(v.m_data));
     631         1027 :     return *this;
     632              : }
     633              : 
     634            0 : JsonValue JsonArray::operator [](size_t i) const
     635              : {
     636            0 :     return at(i);
     637              : }
     638              : 
     639            0 : JsonValueRef JsonArray::operator [](size_t i)
     640              : {
     641            0 :     return JsonValueRef(i, this);
     642              : }
     643              : 
     644              : // =======================================
     645              : // JsonObject
     646              : // =======================================
     647       321559 : static const picojson::object& object_const(const std::shared_ptr<JsonData>& d)
     648              : {
     649       321559 :     return d->val.get<picojson::object>();
     650              : }
     651              : 
     652        13686 : static picojson::object& object_mut(std::shared_ptr<JsonData>& d)
     653              : {
     654        13686 :     return d->val.get<picojson::object>();
     655              : }
     656              : 
     657       107814 : JsonObject::JsonObject(std::shared_ptr<JsonData> d)
     658       107814 :     : m_data(d)
     659              : {
     660       107814 :     if (!m_data) {
     661         2792 :         m_data = std::make_shared<JsonData>();
     662         2792 :         m_data->val = picojson::value(picojson::object());
     663              :     }
     664       107814 : }
     665              : 
     666        13686 : void JsonObject::detach()
     667              : {
     668        13686 :     if (!m_data) {
     669            0 :         return;
     670              :     }
     671              : 
     672        13686 :     if (m_data.use_count() == 1) {
     673        13686 :         return;
     674              :     }
     675              : 
     676            0 :     m_data = std::make_shared<JsonData>(*m_data);
     677              : }
     678              : 
     679       370707 : bool JsonObject::isValid() const
     680              : {
     681       370707 :     return val_const(m_data).is<picojson::object>();
     682              : }
     683              : 
     684           55 : bool JsonObject::empty() const
     685              : {
     686           55 :     if (!isValid()) {
     687            0 :         return true;
     688              :     }
     689              : 
     690           55 :     return object_const(m_data).size() == 0;
     691              : }
     692              : 
     693            1 : size_t JsonObject::size() const
     694              : {
     695            1 :     if (!isValid()) {
     696            0 :         return 0;
     697              :     }
     698              : 
     699            1 :     return object_const(m_data).size();
     700              : }
     701              : 
     702         8989 : bool JsonObject::contains(const std::string& key) const
     703              : {
     704         8989 :     if (!isValid()) {
     705            0 :         return false;
     706              :     }
     707              : 
     708         8989 :     const picojson::object& o = object_const(m_data);
     709         8989 :     return o.find(key) != o.cend();
     710              : }
     711              : 
     712       272446 : JsonValue JsonObject::value(const std::string& key, JsonValue def) const
     713              : {
     714       272446 :     if (!isValid()) {
     715            0 :         return def;
     716              :     }
     717              : 
     718       272446 :     const picojson::object& o = object_const(m_data);
     719       272446 :     auto it = o.find(key);
     720       272446 :     if (it != o.cend()) {
     721       222761 :         std::shared_ptr<JsonData> d = std::make_shared<JsonData>();
     722       222761 :         d->val = it->second;
     723       222761 :         return JsonValue(d);
     724       222761 :     }
     725        49685 :     return def;
     726              : }
     727              : 
     728         2513 : JsonObject& JsonObject::set(const std::string& key, bool v)
     729              : {
     730         2513 :     detach();
     731         2513 :     object_mut(m_data).insert_or_assign(key, picojson::value(v));
     732         2513 :     return *this;
     733              : }
     734              : 
     735         4652 : JsonObject& JsonObject::set(const std::string& key, int v)
     736              : {
     737         4652 :     detach();
     738         4652 :     object_mut(m_data).insert_or_assign(key, picojson::value(static_cast<double>(v)));
     739         4652 :     return *this;
     740              : }
     741              : 
     742         1231 : JsonObject& JsonObject::set(const std::string& key, double v)
     743              : {
     744         1231 :     detach();
     745         1231 :     object_mut(m_data).insert_or_assign(key, picojson::value(v));
     746         1231 :     return *this;
     747              : }
     748              : 
     749         1183 : JsonObject& JsonObject::set(const std::string& key, const std::string& v)
     750              : {
     751         1183 :     detach();
     752         1183 :     object_mut(m_data).insert_or_assign(key, picojson::value(v));
     753         1183 :     return *this;
     754              : }
     755              : 
     756            8 : JsonObject& JsonObject::set(const std::string& key, const char* str)
     757              : {
     758            8 :     detach();
     759           16 :     object_mut(m_data).insert_or_assign(key, picojson::value(std::string(str)));
     760            8 :     return *this;
     761              : }
     762              : 
     763          637 : JsonObject& JsonObject::set(const std::string& key, const String& str)
     764              : {
     765          637 :     detach();
     766          637 :     object_mut(m_data).insert_or_assign(key, picojson::value(str.toStdString()));
     767          637 :     return *this;
     768              : }
     769              : 
     770           14 : JsonObject& JsonObject::set(const std::string& key, const JsonValue& v)
     771              : {
     772           14 :     detach();
     773           14 :     object_mut(m_data).insert_or_assign(key, v.m_data->val);
     774           14 :     return *this;
     775              : }
     776              : 
     777         1730 : JsonObject& JsonObject::set(const std::string& key, const JsonArray& v)
     778              : {
     779         1730 :     detach();
     780         1730 :     object_mut(m_data).insert_or_assign(key, v.m_data->val);
     781         1730 :     return *this;
     782              : }
     783              : 
     784         1718 : JsonObject& JsonObject::set(const std::string& key, const JsonObject& v)
     785              : {
     786         1718 :     detach();
     787         1718 :     object_mut(m_data).insert_or_assign(key, v.m_data->val);
     788         1718 :     return *this;
     789              : }
     790              : 
     791           42 : JsonValue JsonObject::operator [](const std::string& key) const
     792              : {
     793           42 :     return value(key);
     794              : }
     795              : 
     796        13330 : JsonValueRef JsonObject::operator [](const std::string& key)
     797              : {
     798        13330 :     return JsonValueRef(key, this);
     799              : }
     800              : 
     801        40068 : std::vector<std::string> JsonObject::keys() const
     802              : {
     803        40068 :     std::vector<std::string> result;
     804        40068 :     const picojson::object& o = object_const(m_data);
     805       158566 :     for (auto&& p : o) {
     806       118498 :         result.push_back(p.first);
     807              :     }
     808        40068 :     return result;
     809            0 : }
     810              : 
     811              : // =======================================
     812              : // JsonDocument
     813              : // =======================================
     814          243 : JsonDocument::JsonDocument(std::shared_ptr<JsonData> d)
     815          243 :     : m_data(d)
     816              : {
     817          243 : }
     818              : 
     819           28 : JsonDocument::JsonDocument(JsonObject o)
     820           28 :     : m_data(o.m_data)
     821              : {
     822           28 : }
     823              : 
     824           86 : JsonDocument::JsonDocument(JsonArray a)
     825           86 :     : m_data(a.m_data)
     826              : {
     827           86 : }
     828              : 
     829          114 : ByteArray JsonDocument::toJson(Format format) const
     830              : {
     831          114 :     std::string json = m_data->val.serialize(format == Format::Indented);
     832          228 :     return ByteArray(json.c_str(), json.size());
     833          114 : }
     834              : 
     835          243 : JsonDocument JsonDocument::fromJson(const ByteArray& ba, std::string* err)
     836              : {
     837          243 :     std::shared_ptr<JsonData> d = std::make_shared<JsonData>();
     838              : 
     839          243 :     std::string_view json(ba.constChar(), ba.size());
     840              : 
     841          243 :     const char* currentLoc = setlocale(LC_NUMERIC, "C");
     842          243 :     picojson::parse(d->val, json.begin(), json.end(), err);
     843          243 :     setlocale(LC_NUMERIC, currentLoc);
     844              : 
     845          243 :     JsonDocument doc(d);
     846          243 :     return doc;
     847          243 : }
     848              : 
     849           10 : bool JsonDocument::isObject() const
     850              : {
     851           10 :     return m_data->val.is<picojson::object>();
     852              : }
     853              : 
     854           80 : bool JsonDocument::isArray() const
     855              : {
     856           80 :     return m_data->val.is<picojson::array>();
     857              : }
     858              : 
     859          162 : JsonObject JsonDocument::rootObject() const
     860              : {
     861          162 :     return JsonObject(m_data);
     862              : }
     863              : 
     864           81 : JsonArray JsonDocument::rootArray() const
     865              : {
     866           81 :     return JsonArray(m_data);
     867              : }
        

Generated by: LCOV version 2.0-1