json: reshuffle C++ converter
This commit is contained in:
parent
886ffadbaa
commit
60b2df61cd
1 changed files with 50 additions and 51 deletions
|
@ -392,6 +392,12 @@ static std::string format_literal(const std::string & literal) {
|
||||||
return "\"" + escaped + "\"";
|
return "\"" + escaped + "\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t json_schema_ref_curl_write_callback(char *ptr, size_t size, size_t nmemb, void *data) {
|
||||||
|
auto &response = *static_cast<std::ostringstream *>(data);
|
||||||
|
response.write((char *)ptr, size * nmemb);
|
||||||
|
return size * nmemb;
|
||||||
|
}
|
||||||
|
|
||||||
class SchemaConverter {
|
class SchemaConverter {
|
||||||
private:
|
private:
|
||||||
std::function<json(const std::string &)> _fetch_json;
|
std::function<json(const std::string &)> _fetch_json;
|
||||||
|
@ -801,12 +807,50 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SchemaConverter(
|
SchemaConverter(bool dotall) : _dotall(dotall)
|
||||||
const std::function<json(const std::string &)> & fetch_json,
|
|
||||||
bool dotall)
|
|
||||||
: _fetch_json(fetch_json), _dotall(dotall)
|
|
||||||
{
|
{
|
||||||
_rules["space"] = SPACE_RULE;
|
_rules["space"] = SPACE_RULE;
|
||||||
|
|
||||||
|
#if defined(LLAMA_USE_CURL)
|
||||||
|
_fetch_json = [&](const std::string & url) {
|
||||||
|
// TODO: implement HTTP caching semantics.
|
||||||
|
static std::unordered_map<std::string, json> cache;
|
||||||
|
auto it = cache.find(url);
|
||||||
|
if (it != cache.end()) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
std::unique_ptr<CURL, decltype(&curl_easy_cleanup)> curl(curl_easy_init(), &curl_easy_cleanup);
|
||||||
|
if (!curl) {
|
||||||
|
fprintf(stderr, "%s: error initializing libcurl\n", __func__);
|
||||||
|
return json::object();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostringstream response;
|
||||||
|
curl_easy_setopt(curl.get(), CURLOPT_URL, url.c_str());
|
||||||
|
curl_easy_setopt(curl.get(), CURLOPT_FOLLOWLOCATION, 1L);
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
// CURLSSLOPT_NATIVE_CA tells libcurl to use standard certificate store of
|
||||||
|
// operating system. Currently implemented under MS-Windows.
|
||||||
|
curl_easy_setopt(curl.get(), CURLOPT_SSL_OPTIONS, CURLSSLOPT_NATIVE_CA);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
curl_easy_setopt(curl.get(), CURLOPT_NOPROGRESS, 1L); // hide head request progress
|
||||||
|
curl_easy_setopt(curl.get(), CURLOPT_WRITEFUNCTION, &json_schema_ref_curl_write_callback);
|
||||||
|
curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, &response);
|
||||||
|
CURLcode res = curl_easy_perform(curl.get());
|
||||||
|
if (res != CURLE_OK) {
|
||||||
|
throw std::runtime_error("Failed to fetch " + url + ": " + curl_easy_strerror(res));
|
||||||
|
}
|
||||||
|
response << '\0';
|
||||||
|
return cache[url] = json::parse(response.str());
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
fetch_json = [](const std::string &) {
|
||||||
|
_errors.push_back("Fetching external refs not supported, please recompile with CURL support.");
|
||||||
|
return json::object();
|
||||||
|
};
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string _generate_constant_rule(const json & value) {
|
std::string _generate_constant_rule(const json & value) {
|
||||||
|
@ -1001,7 +1045,7 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// todo warning
|
_warnings.push_back("Unsupported allOf schema");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
for (auto & t : schema["allOf"]) {
|
for (auto & t : schema["allOf"]) {
|
||||||
|
@ -1050,53 +1094,8 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static size_t json_schema_ref_curl_write_callback(char *ptr, size_t size, size_t nmemb, void *data) {
|
|
||||||
auto &response = *static_cast<std::ostringstream *>(data);
|
|
||||||
response.write((char *)ptr, size * nmemb);
|
|
||||||
return size * nmemb;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string json_schema_to_grammar(const json & schema) {
|
std::string json_schema_to_grammar(const json & schema) {
|
||||||
std::function<json(const std::string &)> fetch_json = [](const std::string &) { return json::object(); };
|
SchemaConverter converter(/* dotall= */ false);
|
||||||
|
|
||||||
#if defined(LLAMA_USE_CURL)
|
|
||||||
// TODO: implement HTTP caching semantics.
|
|
||||||
std::unordered_map<std::string, json> cache;
|
|
||||||
|
|
||||||
fetch_json = [&](const std::string & url) {
|
|
||||||
auto it = cache.find(url);
|
|
||||||
if (it != cache.end()) {
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
std::unique_ptr<CURL, decltype(&curl_easy_cleanup)> curl(curl_easy_init(), &curl_easy_cleanup);
|
|
||||||
if (!curl) {
|
|
||||||
fprintf(stderr, "%s: error initializing libcurl\n", __func__);
|
|
||||||
return json::object();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ostringstream response;
|
|
||||||
curl_easy_setopt(curl.get(), CURLOPT_URL, url.c_str());
|
|
||||||
curl_easy_setopt(curl.get(), CURLOPT_FOLLOWLOCATION, 1L);
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
// CURLSSLOPT_NATIVE_CA tells libcurl to use standard certificate store of
|
|
||||||
// operating system. Currently implemented under MS-Windows.
|
|
||||||
curl_easy_setopt(curl.get(), CURLOPT_SSL_OPTIONS, CURLSSLOPT_NATIVE_CA);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
curl_easy_setopt(curl.get(), CURLOPT_NOPROGRESS, 1L); // hide head request progress
|
|
||||||
curl_easy_setopt(curl.get(), CURLOPT_WRITEFUNCTION, &json_schema_ref_curl_write_callback);
|
|
||||||
curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, &response);
|
|
||||||
CURLcode res = curl_easy_perform(curl.get());
|
|
||||||
if (res != CURLE_OK) {
|
|
||||||
throw std::runtime_error("Failed to fetch " + url + ": " + curl_easy_strerror(res));
|
|
||||||
}
|
|
||||||
response << '\0';
|
|
||||||
return cache[url] = json::parse(response.str());
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SchemaConverter converter(fetch_json, /* dotall= */ false);
|
|
||||||
auto copy = schema;
|
auto copy = schema;
|
||||||
converter.visit(copy, "");
|
converter.visit(copy, "");
|
||||||
converter.check_errors();
|
converter.check_errors();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue