| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- #include <limits>
- #include "../../state/activity/defaults/activity_defaults_validation.h"
- #include "../../state/entitlements/validation.h"
- #include "parser.h"
- namespace sunrise::core::settings::parser {
- /** @param input Complete JSON text, borrowed and never changed. */
- Parser::Parser(std::string_view input) noexcept : input_(input) {}
- /** Parses the supported root object and skips unknown top-level values. */
- bool Parser::parse_root(Settings& output) noexcept {
- if (!consume('{')) {
- return false;
- }
- if (consume('}')) {
- return at_end();
- }
- bool hasVersion = false;
- bool hasCore = false;
- bool hasClient = false;
- bool hasServer = false;
- bool hasSteam = false;
- bool hasState = false;
- for (;;) {
- std::string_view key;
- if (!string(key) || !consume(':')) {
- return false;
- }
- if (key == "version") {
- std::uint64_t value{};
- if (hasVersion || !unsigned_integer(value)
- || value > (std::numeric_limits<std::uint32_t>::max)()) {
- return false;
- }
- output.version = static_cast<std::uint32_t>(value);
- hasVersion = true;
- } else if (key == "core") {
- if (hasCore || !core(output)) {
- return false;
- }
- hasCore = true;
- } else if (key == "client") {
- if (hasClient || !client_settings(output.client)) {
- return false;
- }
- hasClient = true;
- } else if (key == "server") {
- if (hasServer || !server_settings(output.server)) {
- return false;
- }
- hasServer = true;
- } else if (key == "steam") {
- if (hasSteam || !steam_settings(output.steam)) {
- return false;
- }
- hasSteam = true;
- } else if (key == "state") {
- if (hasState || !state_settings(output)) {
- return false;
- }
- hasState = true;
- } else if (!skip_value(0)) {
- return false;
- }
- if (consume('}')) {
- return at_end();
- }
- if (!consume(',')) {
- return false;
- }
- }
- }
- /** Parses the supported Core settings object. */
- bool Parser::core(Settings& output) noexcept {
- if (!consume('{')) {
- return false;
- }
- if (consume('}')) {
- return true;
- }
- bool hasLogging = false;
- bool hasActivitySdkGeneration = false;
- for (;;) {
- std::string_view key;
- if (!string(key) || !consume(':')) {
- return false;
- }
- if (key == "logging") {
- if (hasLogging || !logging(output.logging)) {
- return false;
- }
- hasLogging = true;
- } else if (key == "activity_sdk_generation") {
- if (hasActivitySdkGeneration
- || !activity_sdk_generation_settings(output.activitySdkGeneration)) {
- return false;
- }
- hasActivitySdkGeneration = true;
- } else if (!skip_value(0)) {
- return false;
- }
- if (consume('}')) {
- return true;
- }
- if (!consume(',')) {
- return false;
- }
- }
- }
- /** Parses the Core-owned activity SDK generation gate. Omitted members keep their defaults. */
- bool Parser::activity_sdk_generation_settings(ActivitySdkGenerationSettings& output) noexcept {
- if (!consume('{')) {
- return false;
- }
- ActivitySdkGenerationSettings candidate{};
- if (consume('}')) {
- output = candidate;
- return true;
- }
- bool hasEnabled = false;
- bool hasLuaDeclarations = false;
- for (;;) {
- std::string_view key;
- if (!string(key) || !consume(':')) {
- return false;
- }
- if (key == "enabled") {
- if (hasEnabled || !boolean(candidate.enabled)) {
- return false;
- }
- hasEnabled = true;
- } else if (key == "lua_declarations") {
- if (hasLuaDeclarations || !boolean(candidate.luaDeclarations)) {
- return false;
- }
- hasLuaDeclarations = true;
- } else if (!skip_value(0)) {
- return false;
- }
- if (consume('}')) {
- output = candidate;
- return true;
- }
- if (!consume(',')) {
- return false;
- }
- }
- }
- /** Parses logging sinks and channel levels. */
- bool Parser::logging(log::Settings& output) noexcept {
- if (!consume('{')) {
- return false;
- }
- if (consume('}')) {
- return true;
- }
- for (;;) {
- std::string_view key;
- if (!string(key) || !consume(':')) {
- return false;
- }
- if (key == "debugger_sink") {
- if (!boolean(output.debuggerSink)) {
- return false;
- }
- } else if (key == "file_sink") {
- if (!boolean(output.fileSink)) {
- return false;
- }
- } else if (key == "levels") {
- if (!levels(output)) {
- return false;
- }
- } else if (!skip_value(0)) {
- return false;
- }
- if (consume('}')) {
- return true;
- }
- if (!consume(',')) {
- return false;
- }
- }
- }
- /** Parses named channel levels and ignores unknown channels. */
- bool Parser::levels(log::Settings& output) noexcept {
- if (!consume('{')) {
- return false;
- }
- if (consume('}')) {
- return true;
- }
- for (;;) {
- std::string_view channelName;
- std::string_view levelName;
- if (!string(channelName) || !consume(':') || !string(levelName)) {
- return false;
- }
- log::Level level{};
- if (!level_value(levelName, level)) {
- return false;
- }
- const std::size_t index = channel_index(channelName);
- if (index < output.levels.size()) {
- output.levels[index] = level;
- }
- if (consume('}')) {
- return true;
- }
- if (!consume(',')) {
- return false;
- }
- }
- }
- } // namespace sunrise::core::settings::parser
- namespace sunrise::core::settings {
- /** @return Default Core settings, with the default logging levels. */
- Settings defaults() noexcept {
- // Named members, so adding one to Settings cannot silently shift the rest.
- return Settings{
- .version = kSettingsVersion,
- .completeExoticCatalysts = true,
- .logging = log::defaults(),
- .activitySdkGeneration = {},
- .server = server::Settings{state::entitlements::authored()},
- .initialActivityDefaults = state::activity::defaults::authored(),
- };
- }
- /** Parses the supported settings from complete JSON text. */
- bool parse(std::string_view json, Settings& output) noexcept {
- Settings parsed = defaults();
- parser::Parser parser(json);
- if (!parser.parse_root(parsed)) {
- return false;
- }
- output = parsed;
- return true;
- }
- } // namespace sunrise::core::settings
|