You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
149 lines
4.6 KiB
C++
149 lines
4.6 KiB
C++
#include "json_utils.h"
|
|
#include <cctype>
|
|
|
|
std::string json_trim(const std::string& s)
|
|
{
|
|
size_t b = s.find_first_not_of(" \t\r\n");
|
|
if (b == std::string::npos) return "";
|
|
size_t e = s.find_last_not_of(" \t\r\n");
|
|
return s.substr(b, e - b + 1);
|
|
}
|
|
|
|
static bool is_ws(char c) { return c == ' ' || c == '\t' || c == '\r' || c == '\n'; }
|
|
|
|
std::string json_get_raw(const std::string& text, const std::string& key)
|
|
{
|
|
std::string k = "\"" + key + "\"";
|
|
size_t pos = 0;
|
|
while ((pos = text.find(k, pos)) != std::string::npos)
|
|
{
|
|
bool key_ok = true;
|
|
if (pos > 0)
|
|
{
|
|
char c = text[pos - 1];
|
|
if (isalnum((unsigned char)c) || c == '_') key_ok = false;
|
|
}
|
|
if (key_ok)
|
|
{
|
|
size_t p = pos + k.size();
|
|
while (p < text.size() && is_ws(text[p])) ++p; // 跳过空白
|
|
if (p >= text.size()) return "";
|
|
if (text[p] != ':') { pos = pos + 1; continue; }
|
|
++p;
|
|
while (p < text.size() && is_ws(text[p])) ++p; // 跳过冒号后空白
|
|
if (p >= text.size()) return "";
|
|
char c = text[p];
|
|
if (c == '"')
|
|
{
|
|
// 字符串:读到配对引号
|
|
size_t q = p + 1;
|
|
while (q < text.size() && text[q] != '"') ++q;
|
|
return text.substr(p, q - p + 1);
|
|
}
|
|
else if (c == '{' || c == '[')
|
|
{
|
|
char close = (c == '{') ? '}' : ']';
|
|
int depth = 0;
|
|
size_t q = p;
|
|
for (; q < text.size(); ++q)
|
|
{
|
|
if (text[q] == '"')
|
|
{
|
|
++q;
|
|
while (q < text.size() && text[q] != '"') ++q;
|
|
}
|
|
else if (text[q] == c) ++depth;
|
|
else if (text[q] == close)
|
|
{
|
|
--depth;
|
|
if (depth == 0) { ++q; break; }
|
|
}
|
|
}
|
|
return text.substr(p, q - p);
|
|
}
|
|
else
|
|
{
|
|
// 数字 / true / false / null
|
|
size_t q = p;
|
|
while (q < text.size() && text[q] != ',' && text[q] != '}' && text[q] != ']' && !is_ws(text[q]))
|
|
++q;
|
|
return text.substr(p, q - p);
|
|
}
|
|
}
|
|
pos = pos + 1;
|
|
}
|
|
return "";
|
|
}
|
|
|
|
static std::string unquote(const std::string& raw)
|
|
{
|
|
std::string t = json_trim(raw);
|
|
if (t.size() >= 2 && t[0] == '"' && t[t.size() - 1] == '"')
|
|
return t.substr(1, t.size() - 2);
|
|
return t;
|
|
}
|
|
|
|
bool json_get_string(const std::string& text, const std::string& key, std::string& out)
|
|
{
|
|
std::string raw = json_get_raw(text, key);
|
|
if (raw.empty()) return false;
|
|
out = unquote(raw);
|
|
return true;
|
|
}
|
|
|
|
bool json_get_number(const std::string& text, const std::string& key, double& out)
|
|
{
|
|
std::string raw = json_get_raw(text, key);
|
|
if (raw.empty()) return false;
|
|
std::string t = json_trim(raw);
|
|
if (t.empty()) return false;
|
|
try { out = std::stod(t); return true; }
|
|
catch (...) { return false; }
|
|
}
|
|
|
|
bool json_get_bool(const std::string& text, const std::string& key, bool& out)
|
|
{
|
|
std::string raw = json_get_raw(text, key);
|
|
if (raw.empty()) return false;
|
|
std::string t = json_trim(raw);
|
|
if (t == "true") { out = true; return true; }
|
|
if (t == "false") { out = false; return true; }
|
|
double d;
|
|
if (json_get_number(text, key, d)) { out = (d != 0); return true; }
|
|
return false;
|
|
}
|
|
|
|
int json_get_point_array(const std::string& text, const std::string& key,
|
|
std::vector<std::pair<double, double>>& out)
|
|
{
|
|
std::string raw = json_get_raw(text, key);
|
|
if (raw.empty()) return 0;
|
|
std::string t = json_trim(raw);
|
|
if (t.empty() || t[0] != '[') return 0;
|
|
// 逐个匹配 "[数,数]" 子元素
|
|
size_t i = 1;
|
|
int cnt = 0;
|
|
while (i < t.size())
|
|
{
|
|
size_t l = t.find('[', i);
|
|
if (l == std::string::npos) break;
|
|
size_t r = t.find(']', l);
|
|
if (r == std::string::npos) break;
|
|
std::string ele = t.substr(l + 1, r - l - 1);
|
|
size_t comma = ele.find(',');
|
|
if (comma != std::string::npos)
|
|
{
|
|
try
|
|
{
|
|
double a = std::stod(json_trim(ele.substr(0, comma)));
|
|
double b = std::stod(json_trim(ele.substr(comma + 1)));
|
|
out.push_back(std::make_pair(a, b));
|
|
++cnt;
|
|
}
|
|
catch (...) {}
|
|
}
|
|
i = r + 1;
|
|
}
|
|
return cnt;
|
|
}
|