diff options
author | Kevin Newton <[email protected]> | 2023-11-02 14:01:20 -0400 |
---|---|---|
committer | Kevin Newton <[email protected]> | 2023-11-03 10:13:49 -0400 |
commit | 05f5c545d232554b6ffb183d6948ad37f46df53b (patch) | |
tree | 43ab5b181b7fb31e5421a9adda59f822e0d65c45 /prism/options.c | |
parent | ca7297efd389eca792c706326d1af138acf5a4f6 (diff) |
[ruby/prism] Wire up options through the FFI API
https://github.com/ruby/prism/commit/f0aa8ad93b
Diffstat (limited to 'prism/options.c')
-rw-r--r-- | prism/options.c | 78 |
1 files changed, 76 insertions, 2 deletions
diff --git a/prism/options.c b/prism/options.c index 7f45c2026c..84c1fcbb39 100644 --- a/prism/options.c +++ b/prism/options.c @@ -5,7 +5,7 @@ */ PRISM_EXPORTED_FUNCTION void pm_options_filepath_set(pm_options_t *options, const char *filepath) { - options->filepath = filepath; + pm_string_constant_init(&options->filepath, filepath, strlen(filepath)); } /** @@ -13,7 +13,7 @@ pm_options_filepath_set(pm_options_t *options, const char *filepath) { */ PRISM_EXPORTED_FUNCTION void pm_options_encoding_set(pm_options_t *options, const char *encoding) { - options->encoding = encoding; + pm_string_constant_init(&options->encoding, encoding, strlen(encoding)); } /** @@ -82,6 +82,9 @@ pm_options_scope_local_get(const pm_options_scope_t *scope, size_t index) { */ PRISM_EXPORTED_FUNCTION void pm_options_free(pm_options_t *options) { + pm_string_free(&options->filepath); + pm_string_free(&options->encoding); + for (size_t scope_index = 0; scope_index < options->scopes_count; scope_index++) { pm_options_scope_t *scope = &options->scopes[scope_index]; @@ -94,3 +97,74 @@ pm_options_free(pm_options_t *options) { free(options->scopes); } + +/** + * Read a 32-bit unsigned integer from a pointer. This function is used to read + * the options that are passed into the parser from the Ruby implementation. It + * handles aligned and unaligned reads. + */ +static uint32_t +pm_options_read_u32(const char *data) { + if (((uintptr_t) data) % sizeof(uint32_t) == 0) { + return *((uint32_t *) data); + } else { + uint32_t value; + memcpy(&value, data, sizeof(uint32_t)); + return value; + } +} + +/** + * Deserialize an options struct from the given binary string. This is used to + * pass options to the parser from an FFI call so that consumers of the library + * from an FFI perspective don't have to worry about the structure of our + * options structs. Since the source of these calls will be from Ruby + * implementation internals we assume it is from a trusted source. + */ +void +pm_options_read(pm_options_t *options, const char *data) { + uint32_t filepath_length = pm_options_read_u32(data); + data += 4; + + if (filepath_length > 0) { + pm_string_constant_init(&options->filepath, data, filepath_length); + data += filepath_length; + } + + options->line = pm_options_read_u32(data); + data += 4; + + uint32_t encoding_length = pm_options_read_u32(data); + data += 4; + + if (encoding_length > 0) { + pm_string_constant_init(&options->encoding, data, encoding_length); + data += encoding_length; + } + + options->frozen_string_literal = *data++; + options->suppress_warnings = *data++; + + uint32_t scopes_count = pm_options_read_u32(data); + data += 4; + + if (scopes_count > 0) { + pm_options_scopes_init(options, scopes_count); + + for (size_t scope_index = 0; scope_index < scopes_count; scope_index++) { + uint32_t locals_count = pm_options_read_u32(data); + data += 4; + + pm_options_scope_t *scope = &options->scopes[scope_index]; + pm_options_scope_init(scope, locals_count); + + for (size_t local_index = 0; local_index < locals_count; local_index++) { + uint32_t local_length = pm_options_read_u32(data); + data += 4; + + pm_string_constant_init(&scope->locals[local_index], data, local_length); + data += local_length; + } + } + } +} |