Joedb 9.1.4
The Journal-Only Embedded Database
Loading...
Searching...
No Matches
json.cpp
Go to the documentation of this file.
1#include "joedb/ui/json.h"
2#include "joedb/ui/type_io.h"
3#include "joedb/ui/base64.h"
4#include "joedb/Readable.h"
6
7#include <iostream>
8#include <cmath>
9#include <vector>
10
11namespace joedb
12{
13 /////////////////////////////////////////////////////////////////////////////
15 /////////////////////////////////////////////////////////////////////////////
16 (
17 std::ostream &out,
18 const Readable &db,
19 bool base64
20 )
21 {
22 int result = JSON_Error::ok;
23
24 //
25 // First, create reference translations
26 //
27 std::map<Table_Id, std::vector<int64_t>> reference_translation;
28 std::map<Table_Id, int64_t> table_size;
29 for (const auto &[tid, tname]: db.get_tables())
30 {
31 const Record_Id last_record_id = db.get_last_record_id(tid);
32 std::vector<int64_t> &v = reference_translation[tid];
33 v.resize(size_t(db.get_last_record_id(tid)) + 1);
34 v[0] = -1;
35 int64_t position = 0;
36 for (Record_Id record_id = Record_Id(1); record_id <= last_record_id; ++record_id)
37 {
38 if (!db.is_used(tid, record_id))
39 v[size_t(record_id)] = -1;
40 else
41 v[size_t(record_id)] = position++;
42 }
43 table_size[tid] = position;
44 }
45
46 //
47 // Write output
48 //
49 out << "{\n";
50
51 bool first_table = true;
52 for (const auto &[tid, tname]: db.get_tables())
53 {
54 const Record_Id last_record_id = db.get_last_record_id(tid);
55
56 if (first_table)
57 first_table = false;
58 else
59 out << ",\n";
60
61 out << " \"" << tname << "\":\n {\n";
62
63 out << " \"__size\": " << table_size[tid];
64
65 for (const auto &[fid, fname]: db.get_fields(tid))
66 {
67 const Type &type = db.get_field_type(tid, fid);
68 out << ",\n";
69
70 out << " \"" << fname << "\": [";
71
72 bool first_value = true;
73 for (Record_Id record_id = Record_Id(1); record_id <= last_record_id; ++record_id)
74 {
75 if (db.is_used(tid, record_id))
76 {
77 if (first_value)
78 first_value = false;
79 else
80 out << ", ";
81
82 switch (type.get_type_id())
83 {
85 break;
86
87 case Type::Type_Id::reference:
88 {
89 Record_Id i = db.get_reference(tid, record_id, fid);
90 const auto it = reference_translation.find(type.get_table_id());
91 if (it != reference_translation.end())
92 {
93 const std::vector<int64_t> &v = it->second;
94 if (size_t(i) >= v.size())
95 i = Record_Id(0);
96 out << v[size_t(i)];
97 }
98 else
99 out << i; // reference to a missing table
100 }
101 break;
102
103 case Type::Type_Id::string:
104 {
105 const std::string &s = db.get_string(tid, record_id, fid);
106 result |= write_json_string(out, s, base64);
107 }
108 break;
109
110 case Type::Type_Id::blob:
111 {
112 const Blob blob = db.get_blob(tid, record_id, fid);
113 out << blob.get_position();
114 }
115 break;
116
117 #define TYPE_MACRO(type, return_type, type_id, R, W)\
118 case Type::Type_Id::type_id:\
119 {\
120 const auto x = db.get_##type_id(tid, record_id, fid);\
121 if (std::isnan(x) || std::isinf(x))\
122 {\
123 out << '0';\
124 result |= JSON_Error::infnan;\
125 }\
126 else\
127 write_##type_id(out, x);\
128 }\
129 break;
130 #define TYPE_MACRO_NO_REFERENCE
131 #define TYPE_MACRO_NO_STRING
132 #define TYPE_MACRO_NO_BLOB
133 #define TYPE_MACRO_NO_INT
134 #include "joedb/TYPE_MACRO.h"
135
136 #define TYPE_MACRO(type, return_type, type_id, R, W)\
137 case Type::Type_Id::type_id:\
138 {\
139 const auto x = db.get_##type_id(tid, record_id, fid);\
140 write_##type_id(out, x);\
141 }\
142 break;
143 #define TYPE_MACRO_NO_REFERENCE
144 #define TYPE_MACRO_NO_STRING
145 #define TYPE_MACRO_NO_BLOB
146 #define TYPE_MACRO_NO_FLOAT
147 #include "joedb/TYPE_MACRO.h"
148 }
149 }
150 }
151
152 out << "]";
153 }
154
155 out << "\n }";
156 }
157
158 out << "\n}\n";
159
160 return result;
161 }
162
163 /////////////////////////////////////////////////////////////////////////////
165 /////////////////////////////////////////////////////////////////////////////
166 (
167 std::ostream &out,
168 const std::string &s,
169 bool base64
170 )
171 {
172 if (base64)
173 {
174 out << '"';
175 out << base64_encode(s);
176 out << '"';
177 }
178 else
179 {
180 try
181 {
182 write_string(out, s, true);
183 }
184 catch (const Exception &)
185 {
186 out << "!!! This string is not utf8 !!!\"";
187 return JSON_Error::utf8;
188 }
189 }
190
191 return 0;
192 }
193}
int64_t get_position() const noexcept
Definition Blob.h:28
Table_Id get_table_id() const
Definition Type.h:41
Type_Id get_type_id() const
Definition Type.h:40
void write_string(std::ostream &out, const std::string &s, bool json)
std::string base64_encode(const std::string &input)
Definition base64.cpp:11
int write_json_string(std::ostream &out, const std::string &s, bool base64)
Definition json.cpp:166
int write_json(std::ostream &out, const Readable &db, bool base64)
Definition json.cpp:16
@ ok
Definition json.h:12
@ utf8
Definition json.h:12
Definition Blob.h:7