|
1 | 1 | #include <sourcemeta/core/io.h> |
2 | 2 | #include <sourcemeta/core/json.h> |
3 | 3 | #include <sourcemeta/core/jsonschema.h> |
| 4 | +#include <sourcemeta/core/regex.h> |
4 | 5 | #include <sourcemeta/core/yaml.h> |
5 | 6 |
|
6 | 7 | #include <sourcemeta/blaze/compiler.h> |
7 | 8 |
|
8 | | -#include <iostream> // std::cerr, std::cout |
| 9 | +#include <algorithm> // std::transform |
| 10 | +#include <cctype> // std::toupper |
| 11 | +#include <iomanip> // std::hex, std::setw, std::setfill |
| 12 | +#include <iostream> // std::cerr, std::cout |
| 13 | +#include <sstream> // std::ostringstream |
9 | 14 |
|
10 | 15 | #include "command.h" |
11 | 16 | #include "configuration.h" |
@@ -62,11 +67,67 @@ auto sourcemeta::jsonschema::compile(const sourcemeta::core::Options &options) |
62 | 67 | } |
63 | 68 |
|
64 | 69 | const auto template_json{sourcemeta::blaze::to_json(schema_template)}; |
65 | | - if (options.contains("minify")) { |
| 70 | + |
| 71 | + if (options.contains("include") && !options.at("include").empty()) { |
| 72 | + std::string name{options.at("include").front()}; |
| 73 | + |
| 74 | + static const auto IDENTIFIER_PATTERN{ |
| 75 | + sourcemeta::core::to_regex("^[A-Za-z_][A-Za-z0-9_]*$")}; |
| 76 | + if (!IDENTIFIER_PATTERN.has_value() || |
| 77 | + !sourcemeta::core::matches(IDENTIFIER_PATTERN.value(), name)) { |
| 78 | + throw InvalidIncludeIdentifier{name}; |
| 79 | + } |
| 80 | + |
| 81 | + std::transform(name.begin(), name.end(), name.begin(), |
| 82 | + [](unsigned char character) -> unsigned char { |
| 83 | + return static_cast<unsigned char>(std::toupper(character)); |
| 84 | + }); |
| 85 | + |
| 86 | + std::ostringstream json_stream; |
| 87 | + sourcemeta::core::stringify(template_json, json_stream); |
| 88 | + const auto json_data{std::move(json_stream).str()}; |
| 89 | + |
| 90 | + constexpr auto BYTES_PER_LINE{16}; |
| 91 | + |
| 92 | + std::cout << "#ifndef SOURCEMETA_JSONSCHEMA_INCLUDE_" << name << "_H_\n"; |
| 93 | + std::cout << "#define SOURCEMETA_JSONSCHEMA_INCLUDE_" << name << "_H_\n"; |
| 94 | + std::cout << "\n"; |
| 95 | + std::cout << "#ifdef __cplusplus\n"; |
| 96 | + std::cout << "#include <string_view>\n"; |
| 97 | + std::cout << "#endif\n"; |
| 98 | + std::cout << "\n"; |
| 99 | + std::cout << "static const char " << name << "_DATA[] ="; |
| 100 | + |
| 101 | + for (std::size_t index = 0; index < json_data.size(); ++index) { |
| 102 | + if (index % BYTES_PER_LINE == 0) { |
| 103 | + std::cout << "\n \""; |
| 104 | + } |
| 105 | + |
| 106 | + std::cout << "\\x" << std::hex << std::setw(2) << std::setfill('0') |
| 107 | + << (static_cast<unsigned int>( |
| 108 | + static_cast<unsigned char>(json_data[index]))); |
| 109 | + |
| 110 | + if ((index + 1) % BYTES_PER_LINE == 0 || index + 1 == json_data.size()) { |
| 111 | + std::cout << "\""; |
| 112 | + } |
| 113 | + } |
| 114 | + |
| 115 | + std::cout << ";\n"; |
| 116 | + std::cout << std::dec; |
| 117 | + std::cout << "static const unsigned int " << name |
| 118 | + << "_LENGTH = " << json_data.size() << ";\n"; |
| 119 | + std::cout << "\n"; |
| 120 | + std::cout << "#ifdef __cplusplus\n"; |
| 121 | + std::cout << "static constexpr std::string_view " << name << "{" << name |
| 122 | + << "_DATA, " << name << "_LENGTH};\n"; |
| 123 | + std::cout << "#endif\n"; |
| 124 | + std::cout << "\n"; |
| 125 | + std::cout << "#endif\n"; |
| 126 | + } else if (options.contains("minify")) { |
66 | 127 | sourcemeta::core::stringify(template_json, std::cout); |
| 128 | + std::cout << "\n"; |
67 | 129 | } else { |
68 | 130 | sourcemeta::core::prettify(template_json, std::cout); |
| 131 | + std::cout << "\n"; |
69 | 132 | } |
70 | | - |
71 | | - std::cout << "\n"; |
72 | 133 | } |
0 commit comments