| 14 | namespace { |
| 15 | |
| 16 | cJSON * make_cjson(const Value & value) { |
| 17 | switch (value.kind()) { |
| 18 | case Value::Kind::Null: |
| 19 | return cJSON_CreateNull(); |
| 20 | case Value::Kind::Bool: |
| 21 | return cJSON_CreateBool(value.as_bool()); |
| 22 | case Value::Kind::Number: |
| 23 | return cJSON_CreateNumber(value.as_number()); |
| 24 | case Value::Kind::String: |
| 25 | return cJSON_CreateString(value.as_string().c_str()); |
| 26 | case Value::Kind::Array: { |
| 27 | cJSON * array_json = cJSON_CreateArray(); |
| 28 | if (array_json == nullptr) { |
| 29 | throw std::runtime_error("failed to create json array"); |
| 30 | } |
| 31 | const auto & array_values = value.as_array(); |
| 32 | for (const auto & child_value : array_values) { |
| 33 | cJSON * child = make_cjson(child_value); |
| 34 | if (child == nullptr) { |
| 35 | cJSON_Delete(array_json); |
| 36 | throw std::runtime_error("failed to create json array element"); |
| 37 | } |
| 38 | cJSON_AddItemToArray(array_json, child); |
| 39 | } |
| 40 | return array_json; |
| 41 | } |
| 42 | case Value::Kind::Object: { |
| 43 | cJSON * object = cJSON_CreateObject(); |
| 44 | if (object == nullptr) { |
| 45 | throw std::runtime_error("failed to create json object"); |
| 46 | } |
| 47 | for (const auto & [key, child] : value.as_object()) { |
| 48 | cJSON * child_json = make_cjson(child); |
| 49 | if (child_json == nullptr) { |
| 50 | cJSON_Delete(object); |
| 51 | throw std::runtime_error("failed to create json object field"); |
| 52 | } |
| 53 | if (!cJSON_AddItemToObject(object, key.c_str(), child_json)) { |
| 54 | cJSON_Delete(child_json); |
| 55 | cJSON_Delete(object); |
| 56 | throw std::runtime_error("failed to add json object field"); |
| 57 | } |
| 58 | } |
| 59 | return object; |
| 60 | } |
| 61 | } |
| 62 | throw std::runtime_error("unsupported json value kind"); |
| 63 | } |
| 64 | |
| 65 | std::string print_cjson(cJSON * root) { |
| 66 | if (root == nullptr) { |
no test coverage detected