18bf80f4bSopenharmony_ci/*
28bf80f4bSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
38bf80f4bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
48bf80f4bSopenharmony_ci * you may not use this file except in compliance with the License.
58bf80f4bSopenharmony_ci * You may obtain a copy of the License at
68bf80f4bSopenharmony_ci *
78bf80f4bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
88bf80f4bSopenharmony_ci *
98bf80f4bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
108bf80f4bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
118bf80f4bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
128bf80f4bSopenharmony_ci * See the License for the specific language governing permissions and
138bf80f4bSopenharmony_ci * limitations under the License.
148bf80f4bSopenharmony_ci */
158bf80f4bSopenharmony_ci
168bf80f4bSopenharmony_ci#ifndef API_UTIL_JSON_H
178bf80f4bSopenharmony_ci#define API_UTIL_JSON_H
188bf80f4bSopenharmony_ci
198bf80f4bSopenharmony_ci#include <core/json/json.h>
208bf80f4bSopenharmony_ci
218bf80f4bSopenharmony_ci#include <util/namespace.h>
228bf80f4bSopenharmony_ci
238bf80f4bSopenharmony_ciUTIL_BEGIN_NAMESPACE()
248bf80f4bSopenharmony_ci
258bf80f4bSopenharmony_ciconstexpr int JSON_DEFAULT_INDENTATION = 2;
268bf80f4bSopenharmony_ci
278bf80f4bSopenharmony_citemplate<typename T>
288bf80f4bSopenharmony_ciBASE_NS::string to_formatted_string(const CORE_NS::json::value_t<T>& value,
298bf80f4bSopenharmony_ci    const size_t indentation = JSON_DEFAULT_INDENTATION, const size_t currentIndentation = 0);
308bf80f4bSopenharmony_ci
318bf80f4bSopenharmony_ci#ifdef JSON_IMPL
328bf80f4bSopenharmony_ciusing namespace CORE_NS::json;
338bf80f4bSopenharmony_ci
348bf80f4bSopenharmony_citemplate<typename T>
358bf80f4bSopenharmony_civoid append(BASE_NS::string& out, const typename value_t<T>::string& string)
368bf80f4bSopenharmony_ci{
378bf80f4bSopenharmony_ci    out += '"';
388bf80f4bSopenharmony_ci    out.append(escape(string));
398bf80f4bSopenharmony_ci    out += '"';
408bf80f4bSopenharmony_ci}
418bf80f4bSopenharmony_ci
428bf80f4bSopenharmony_citemplate<typename T>
438bf80f4bSopenharmony_civoid append(BASE_NS::string& out, const typename value_t<T>::object& object, const size_t indentation,
448bf80f4bSopenharmony_ci    size_t currentIndentation)
458bf80f4bSopenharmony_ci{
468bf80f4bSopenharmony_ci    if (object.empty()) {
478bf80f4bSopenharmony_ci        // Keep empty objects on one row.
488bf80f4bSopenharmony_ci        out.append("{}");
498bf80f4bSopenharmony_ci        return;
508bf80f4bSopenharmony_ci    }
518bf80f4bSopenharmony_ci
528bf80f4bSopenharmony_ci    out += "{\n";
538bf80f4bSopenharmony_ci    currentIndentation += indentation;
548bf80f4bSopenharmony_ci    out.append(currentIndentation, ' ');
558bf80f4bSopenharmony_ci
568bf80f4bSopenharmony_ci    int count = 0;
578bf80f4bSopenharmony_ci    for (const auto& v : object) {
588bf80f4bSopenharmony_ci        if (count++) {
598bf80f4bSopenharmony_ci            out += ",\n";
608bf80f4bSopenharmony_ci            out.append(currentIndentation, ' ');
618bf80f4bSopenharmony_ci        }
628bf80f4bSopenharmony_ci        append<T>(out, v.key);
638bf80f4bSopenharmony_ci        out += ": ";
648bf80f4bSopenharmony_ci        out += to_formatted_string(v.value, indentation, currentIndentation);
658bf80f4bSopenharmony_ci    }
668bf80f4bSopenharmony_ci    currentIndentation -= indentation;
678bf80f4bSopenharmony_ci    out += '\n';
688bf80f4bSopenharmony_ci    out.append(currentIndentation, ' ');
698bf80f4bSopenharmony_ci    out += '}';
708bf80f4bSopenharmony_ci}
718bf80f4bSopenharmony_ci
728bf80f4bSopenharmony_citemplate<typename T>
738bf80f4bSopenharmony_civoid append(
748bf80f4bSopenharmony_ci    BASE_NS::string& out, const typename value_t<T>::array& array, const size_t indentation, size_t currentIndentation)
758bf80f4bSopenharmony_ci{
768bf80f4bSopenharmony_ci    if (array.empty()) {
778bf80f4bSopenharmony_ci        // Keep empty arrays on one row.
788bf80f4bSopenharmony_ci        out.append("[]");
798bf80f4bSopenharmony_ci        return;
808bf80f4bSopenharmony_ci    }
818bf80f4bSopenharmony_ci
828bf80f4bSopenharmony_ci    out += "[\n";
838bf80f4bSopenharmony_ci    currentIndentation += indentation;
848bf80f4bSopenharmony_ci    out.append(currentIndentation, ' ');
858bf80f4bSopenharmony_ci    int count = 0;
868bf80f4bSopenharmony_ci    for (const auto& v : array) {
878bf80f4bSopenharmony_ci        if (count++) {
888bf80f4bSopenharmony_ci            out += ",\n";
898bf80f4bSopenharmony_ci            out.append(currentIndentation, ' ');
908bf80f4bSopenharmony_ci        }
918bf80f4bSopenharmony_ci        out += to_formatted_string(v, indentation, currentIndentation);
928bf80f4bSopenharmony_ci    }
938bf80f4bSopenharmony_ci    currentIndentation -= indentation;
948bf80f4bSopenharmony_ci    out += '\n';
958bf80f4bSopenharmony_ci    out.append(currentIndentation, ' ');
968bf80f4bSopenharmony_ci    out += ']';
978bf80f4bSopenharmony_ci}
988bf80f4bSopenharmony_ci
998bf80f4bSopenharmony_citemplate<typename T>
1008bf80f4bSopenharmony_civoid append(BASE_NS::string& out, const double floatingPoint)
1018bf80f4bSopenharmony_ci{
1028bf80f4bSopenharmony_ci    constexpr const char* FLOATING_FORMAT_STR = "%.17g";
1038bf80f4bSopenharmony_ci    const int size = snprintf(nullptr, 0, FLOATING_FORMAT_STR, floatingPoint);
1048bf80f4bSopenharmony_ci    const size_t oldSize = out.size();
1058bf80f4bSopenharmony_ci    out.resize(oldSize + size);
1068bf80f4bSopenharmony_ci    const size_t newSize = out.size();
1078bf80f4bSopenharmony_ci    // "At most bufsz - 1 characters are written." string has size() characters + 1 for null so use size() +
1088bf80f4bSopenharmony_ci    // 1 as the total size. If resize() failed string size() hasn't changed, buffer will point to the null
1098bf80f4bSopenharmony_ci    // character and bufsz will be 1 i.e. only the null character will be written.
1108bf80f4bSopenharmony_ci}
1118bf80f4bSopenharmony_ci
1128bf80f4bSopenharmony_citemplate<typename T>
1138bf80f4bSopenharmony_ciBASE_NS::string to_formatted_string(const value_t<T>& value, const size_t indentation, const size_t currentIndentation)
1148bf80f4bSopenharmony_ci{
1158bf80f4bSopenharmony_ci    BASE_NS::string out;
1168bf80f4bSopenharmony_ci    switch (value.type) {
1178bf80f4bSopenharmony_ci        case type::uninitialized:
1188bf80f4bSopenharmony_ci            out += "{}";
1198bf80f4bSopenharmony_ci            break;
1208bf80f4bSopenharmony_ci
1218bf80f4bSopenharmony_ci        case type::object:
1228bf80f4bSopenharmony_ci            append<T>(out, value.object_, indentation, currentIndentation);
1238bf80f4bSopenharmony_ci            break;
1248bf80f4bSopenharmony_ci
1258bf80f4bSopenharmony_ci        case type::array:
1268bf80f4bSopenharmony_ci            append<T>(out, value.array_, indentation, currentIndentation);
1278bf80f4bSopenharmony_ci            break;
1288bf80f4bSopenharmony_ci
1298bf80f4bSopenharmony_ci        case type::string:
1308bf80f4bSopenharmony_ci            append<T>(out, value.string_);
1318bf80f4bSopenharmony_ci            break;
1328bf80f4bSopenharmony_ci
1338bf80f4bSopenharmony_ci        case type::floating_point:
1348bf80f4bSopenharmony_ci            append<T>(out, value.float_);
1358bf80f4bSopenharmony_ci            break;
1368bf80f4bSopenharmony_ci
1378bf80f4bSopenharmony_ci        case type::signed_int:
1388bf80f4bSopenharmony_ci            out += BASE_NS::to_string(value.signed_);
1398bf80f4bSopenharmony_ci            break;
1408bf80f4bSopenharmony_ci
1418bf80f4bSopenharmony_ci        case type::unsigned_int:
1428bf80f4bSopenharmony_ci            out += BASE_NS::to_string(value.unsigned_);
1438bf80f4bSopenharmony_ci            break;
1448bf80f4bSopenharmony_ci
1458bf80f4bSopenharmony_ci        case type::boolean:
1468bf80f4bSopenharmony_ci            if (value.boolean_) {
1478bf80f4bSopenharmony_ci                out += "true";
1488bf80f4bSopenharmony_ci            } else {
1498bf80f4bSopenharmony_ci                out += "false";
1508bf80f4bSopenharmony_ci            }
1518bf80f4bSopenharmony_ci            break;
1528bf80f4bSopenharmony_ci
1538bf80f4bSopenharmony_ci        case type::null:
1548bf80f4bSopenharmony_ci            out += "null";
1558bf80f4bSopenharmony_ci            break;
1568bf80f4bSopenharmony_ci
1578bf80f4bSopenharmony_ci        default:
1588bf80f4bSopenharmony_ci            break;
1598bf80f4bSopenharmony_ci    }
1608bf80f4bSopenharmony_ci    return out;
1618bf80f4bSopenharmony_ci}
1628bf80f4bSopenharmony_ci
1638bf80f4bSopenharmony_ci// Explicit template instantiation for the needed types.
1648bf80f4bSopenharmony_citemplate BASE_NS::string to_formatted_string(
1658bf80f4bSopenharmony_ci    const value& value, const size_t indentation, const size_t currentIndentation);
1668bf80f4bSopenharmony_citemplate BASE_NS::string to_formatted_string(
1678bf80f4bSopenharmony_ci    const standalone_value& value, const size_t indentation, const size_t currentIndentation);
1688bf80f4bSopenharmony_ci
1698bf80f4bSopenharmony_ci#endif // JSON_IMPL
1708bf80f4bSopenharmony_ci
1718bf80f4bSopenharmony_ciUTIL_END_NAMESPACE()
1728bf80f4bSopenharmony_ci
1738bf80f4bSopenharmony_ci#endif // API_UTIL_JSON_H
174