prism 1.9.0 → 2.0.0.rc2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +88 -0
- data/CODE_OF_CONDUCT.md +1 -1
- data/LICENSE.md +1 -1
- data/Makefile +41 -12
- data/README.md +35 -97
- data/config.yml +174 -161
- data/docs/build_system.md +2 -2
- data/docs/configuration.md +5 -4
- data/docs/encoding.md +2 -2
- data/docs/fuzzing.md +4 -11
- data/docs/javascript.md +19 -4
- data/docs/mapping.md +1 -1
- data/docs/releasing.md +77 -5
- data/docs/relocation.md +2 -4
- data/docs/serialization.md +22 -24
- data/docs/testing.md +46 -29
- data/ext/prism/api_node.c +1461 -1401
- data/ext/prism/extconf.rb +3 -4
- data/ext/prism/extension.c +796 -422
- data/ext/prism/extension.h +3 -3
- data/include/prism/arena.h +37 -0
- data/include/prism/ast.h +2727 -610
- data/include/prism/buffer.h +52 -0
- data/include/prism/comments.h +55 -0
- data/include/prism/compiler/accel.h +26 -0
- data/include/prism/compiler/align.h +36 -0
- data/include/prism/compiler/assume.h +25 -0
- data/include/prism/compiler/bswap.h +46 -0
- data/include/prism/compiler/endianness.h +34 -0
- data/include/prism/compiler/exported.h +24 -0
- data/include/prism/compiler/fallthrough.h +22 -0
- data/include/prism/compiler/filesystem.h +32 -0
- data/include/prism/compiler/flex_array.h +19 -0
- data/include/prism/compiler/force_inline.h +21 -0
- data/include/prism/compiler/format.h +25 -0
- data/include/prism/compiler/inline.h +17 -0
- data/include/prism/compiler/nodiscard.h +22 -0
- data/include/prism/compiler/nonnull.h +18 -0
- data/include/prism/compiler/unused.h +18 -0
- data/include/prism/constant_pool.h +81 -0
- data/include/prism/diagnostic.h +38 -403
- data/include/prism/errors_format.h +53 -0
- data/include/prism/excludes.h +29 -0
- data/include/prism/integer.h +41 -0
- data/include/prism/internal/allocator.h +68 -0
- data/include/prism/internal/allocator_debug.h +88 -0
- data/include/prism/internal/arena.h +108 -0
- data/include/prism/internal/bit.h +42 -0
- data/include/prism/internal/buffer.h +94 -0
- data/include/prism/internal/char.h +145 -0
- data/include/prism/internal/comments.h +53 -0
- data/include/prism/internal/constant_pool.h +152 -0
- data/include/prism/internal/diagnostic.h +389 -0
- data/include/prism/{encoding.h → internal/encoding.h} +27 -68
- data/include/prism/internal/integer.h +68 -0
- data/include/prism/internal/isinf.h +16 -0
- data/include/prism/internal/line_offset_list.h +34 -0
- data/include/prism/{util/pm_list.h → internal/list.h} +11 -52
- data/include/prism/internal/magic_comments.h +23 -0
- data/include/prism/internal/memchr.h +15 -0
- data/include/prism/internal/node.h +38 -0
- data/include/prism/internal/options.h +232 -0
- data/include/prism/internal/parser.h +1004 -0
- data/include/prism/internal/regexp.h +26 -0
- data/include/prism/internal/serialize.h +39 -0
- data/include/prism/internal/source.h +72 -0
- data/include/prism/{static_literals.h → internal/static_literals.h} +26 -47
- data/include/prism/internal/stringy.h +35 -0
- data/include/prism/{util/pm_strncasecmp.h → internal/strncasecmp.h} +3 -17
- data/include/prism/{util/pm_strpbrk.h → internal/strpbrk.h} +7 -20
- data/include/prism/internal/tokens.h +11 -0
- data/include/prism/internal/xxh3.h +16 -0
- data/include/prism/json.h +32 -0
- data/include/prism/line_offset_list.h +61 -0
- data/include/prism/magic_comments.h +35 -0
- data/include/prism/node.h +18 -53
- data/include/prism/options.h +146 -280
- data/include/prism/parser.h +356 -867
- data/include/prism/prettyprint.h +6 -9
- data/include/prism/serialize.h +115 -0
- data/include/prism/source.h +155 -0
- data/include/prism/stream.h +28 -0
- data/include/prism/string_query.h +74 -0
- data/include/prism/stringy.h +72 -0
- data/include/prism/version.h +12 -3
- data/include/prism.h +43 -320
- data/lib/prism/compiler.rb +319 -305
- data/lib/prism/desugar_compiler.rb +105 -34
- data/lib/prism/dispatcher.rb +646 -473
- data/lib/prism/dot_visitor.rb +592 -511
- data/lib/prism/dsl.rb +391 -25
- data/lib/prism/ffi.rb +258 -90
- data/lib/prism/inspect_visitor.rb +357 -325
- data/lib/prism/lex_compat.rb +254 -212
- data/lib/prism/mutation_compiler.rb +313 -305
- data/lib/prism/node.rb +20966 -6992
- data/lib/prism/node_ext.rb +180 -187
- data/lib/prism/node_find.rb +215 -0
- data/lib/prism/parse_result/errors.rb +7 -1
- data/lib/prism/parse_result/newlines.rb +276 -8
- data/lib/prism/parse_result.rb +468 -139
- data/lib/prism/pattern.rb +65 -20
- data/lib/prism/reflection.rb +23 -12
- data/lib/prism/relocation.rb +149 -87
- data/lib/prism/serialize.rb +3460 -539
- data/lib/prism/string_query.rb +24 -1
- data/lib/prism/translation/parser/builder.rb +10 -2
- data/lib/prism/translation/parser/compiler.rb +44 -52
- data/lib/prism/translation/parser/lexer.rb +41 -92
- data/lib/prism/translation/parser.rb +1 -1
- data/lib/prism/translation/parser_current.rb +1 -1
- data/lib/prism/translation/ripper/lexer.rb +8 -10
- data/lib/prism/translation/ripper/sexp.rb +2 -10
- data/lib/prism/translation/ripper/shim.rb +2 -0
- data/lib/prism/translation/ripper.rb +967 -209
- data/lib/prism/translation/ruby_parser.rb +73 -316
- data/lib/prism/translation.rb +2 -0
- data/lib/prism/visitor.rb +632 -5
- data/lib/prism.rb +79 -9
- data/prism.gemspec +128 -62
- data/rbi/generated/prism/compiler.rbi +489 -0
- data/rbi/generated/prism/desugar_compiler.rbi +306 -0
- data/rbi/generated/prism/dispatcher.rbi +1138 -0
- data/rbi/generated/prism/dot_visitor.rbi +618 -0
- data/rbi/generated/prism/dsl.rbi +751 -0
- data/rbi/generated/prism/inspect_visitor.rbi +503 -0
- data/rbi/generated/prism/lex_compat.rbi +162 -0
- data/rbi/generated/prism/mutation_compiler.rbi +464 -0
- data/rbi/generated/prism/node.rbi +14407 -0
- data/rbi/generated/prism/node_ext.rbi +259 -0
- data/rbi/generated/prism/node_find.rbi +79 -0
- data/rbi/generated/prism/parse_result/errors.rbi +21 -0
- data/rbi/generated/prism/parse_result/newlines.rbi +208 -0
- data/rbi/generated/prism/parse_result.rbi +776 -0
- data/rbi/generated/prism/pattern.rbi +134 -0
- data/rbi/generated/prism/reflection.rbi +89 -0
- data/rbi/generated/prism/relocation.rbi +329 -0
- data/rbi/generated/prism/serialize.rbi +184 -0
- data/rbi/generated/prism/string_query.rbi +43 -0
- data/rbi/generated/prism/translation.rbi +7 -0
- data/rbi/generated/prism/visitor.rbi +650 -0
- data/rbi/generated/prism.rbi +86 -0
- data/rbi/prism/translation/parser_versions.rbi +5 -0
- data/rbi/rubyvm/node_find.rbi +14 -0
- data/sig/generated/prism/compiler.rbs +492 -0
- data/sig/generated/prism/desugar_compiler.rbs +305 -0
- data/sig/generated/prism/dispatcher.rbs +1292 -0
- data/sig/generated/prism/dot_visitor.rbs +635 -0
- data/sig/generated/prism/dsl.rbs +928 -0
- data/sig/generated/prism/inspect_visitor.rbs +509 -0
- data/sig/generated/prism/lex_compat.rbs +166 -0
- data/sig/{prism → generated/prism}/mutation_compiler.rbs +309 -4
- data/sig/generated/prism/node.rbs +20896 -0
- data/sig/generated/prism/node_ext.rbs +290 -0
- data/sig/generated/prism/node_find.rbs +90 -0
- data/sig/generated/prism/parse_result/errors.rbs +22 -0
- data/sig/generated/prism/parse_result/newlines.rbs +223 -0
- data/sig/generated/prism/parse_result.rbs +871 -0
- data/sig/generated/prism/pattern.rbs +156 -0
- data/sig/generated/prism/reflection.rbs +101 -0
- data/sig/generated/prism/relocation.rbs +428 -0
- data/sig/generated/prism/serialize.rbs +198 -0
- data/sig/generated/prism/string_query.rbs +43 -0
- data/sig/generated/prism/translation.rbs +8 -0
- data/sig/generated/prism/visitor.rbs +1111 -0
- data/sig/generated/prism.rbs +84 -0
- data/sig/manifest.yaml +2 -0
- data/src/arena.c +117 -0
- data/src/{util/pm_buffer.c → buffer.c} +53 -21
- data/src/{util/pm_char.c → char.c} +28 -57
- data/src/comments.c +454 -0
- data/src/constant_pool.c +406 -0
- data/src/diagnostic.c +97 -65
- data/src/encoding.c +8 -3
- data/src/errors_format.c +519 -0
- data/src/{util/pm_integer.c → integer.c} +33 -22
- data/src/json.c +5733 -0
- data/src/line_offset_list.c +100 -0
- data/src/list.c +24 -0
- data/src/{util/pm_memchr.c → memchr.c} +8 -6
- data/src/node.c +3504 -7674
- data/src/options.c +162 -49
- data/src/parser.c +367 -0
- data/src/prettyprint.c +421 -354
- data/src/prism.c +8402 -7161
- data/src/regexp.c +961 -45
- data/src/serialize.c +460 -424
- data/src/source.c +518 -0
- data/src/static_literals.c +111 -43
- data/src/string_query.c +180 -0
- data/src/stringy.c +91 -0
- data/src/{util/pm_strncasecmp.c → strncasecmp.c} +5 -4
- data/src/strpbrk.c +447 -0
- data/src/{token_type.c → tokens.c} +39 -18
- data/src/xxh3.c +292 -0
- metadata +128 -63
- data/ext/prism/api_pack.c +0 -276
- data/include/prism/defines.h +0 -260
- data/include/prism/pack.h +0 -163
- data/include/prism/regexp.h +0 -43
- data/include/prism/util/pm_buffer.h +0 -236
- data/include/prism/util/pm_char.h +0 -204
- data/include/prism/util/pm_constant_pool.h +0 -218
- data/include/prism/util/pm_integer.h +0 -130
- data/include/prism/util/pm_memchr.h +0 -29
- data/include/prism/util/pm_newline_list.h +0 -113
- data/include/prism/util/pm_string.h +0 -200
- data/lib/prism/pack.rb +0 -230
- data/lib/prism/parse_result/comments.rb +0 -188
- data/rbi/prism/compiler.rbi +0 -12
- data/rbi/prism/dsl.rbi +0 -524
- data/rbi/prism/inspect_visitor.rbi +0 -12
- data/rbi/prism/node.rbi +0 -8750
- data/rbi/prism/node_ext.rbi +0 -107
- data/rbi/prism/parse_result.rbi +0 -404
- data/rbi/prism/reflection.rbi +0 -58
- data/rbi/prism/string_query.rbi +0 -12
- data/rbi/prism/visitor.rbi +0 -473
- data/rbi/prism.rbi +0 -63
- data/sig/prism/compiler.rbs +0 -9
- data/sig/prism/dispatcher.rbs +0 -19
- data/sig/prism/dot_visitor.rbs +0 -6
- data/sig/prism/dsl.rbs +0 -351
- data/sig/prism/inspect_visitor.rbs +0 -22
- data/sig/prism/lex_compat.rbs +0 -10
- data/sig/prism/node.rbs +0 -4042
- data/sig/prism/node_ext.rbs +0 -149
- data/sig/prism/pack.rbs +0 -43
- data/sig/prism/parse_result/comments.rbs +0 -38
- data/sig/prism/parse_result.rbs +0 -197
- data/sig/prism/pattern.rbs +0 -13
- data/sig/prism/reflection.rbs +0 -50
- data/sig/prism/relocation.rbs +0 -185
- data/sig/prism/serialize.rbs +0 -8
- data/sig/prism/string_query.rbs +0 -11
- data/sig/prism/visitor.rbs +0 -169
- data/sig/prism.rbs +0 -272
- data/src/pack.c +0 -509
- data/src/util/pm_constant_pool.c +0 -342
- data/src/util/pm_list.c +0 -49
- data/src/util/pm_newline_list.c +0 -125
- data/src/util/pm_string.c +0 -381
- data/src/util/pm_strpbrk.c +0 -206
data/src/static_literals.c
CHANGED
|
@@ -1,4 +1,19 @@
|
|
|
1
|
-
#include "prism/static_literals.h"
|
|
1
|
+
#include "prism/internal/static_literals.h"
|
|
2
|
+
|
|
3
|
+
#include "prism/compiler/inline.h"
|
|
4
|
+
#include "prism/compiler/unused.h"
|
|
5
|
+
|
|
6
|
+
#include "prism/internal/allocator.h"
|
|
7
|
+
#include "prism/internal/buffer.h"
|
|
8
|
+
#include "prism/internal/integer.h"
|
|
9
|
+
#include "prism/internal/isinf.h"
|
|
10
|
+
#include "prism/internal/stringy.h"
|
|
11
|
+
|
|
12
|
+
#include <assert.h>
|
|
13
|
+
#include <math.h>
|
|
14
|
+
#include <stdio.h>
|
|
15
|
+
#include <stdlib.h>
|
|
16
|
+
#include <string.h>
|
|
2
17
|
|
|
3
18
|
/**
|
|
4
19
|
* A small struct used for passing around a subset of the information that is
|
|
@@ -7,16 +22,19 @@
|
|
|
7
22
|
*/
|
|
8
23
|
typedef struct {
|
|
9
24
|
/** The list of newline offsets to use to calculate line numbers. */
|
|
10
|
-
const
|
|
25
|
+
const pm_line_offset_list_t *line_offsets;
|
|
26
|
+
|
|
27
|
+
/** The start of the source being parsed. */
|
|
28
|
+
const uint8_t *start;
|
|
11
29
|
|
|
12
30
|
/** The line number that the parser starts on. */
|
|
13
31
|
int32_t start_line;
|
|
14
32
|
|
|
15
|
-
/** The
|
|
16
|
-
const
|
|
33
|
+
/** The encoding that the parser is using. */
|
|
34
|
+
const pm_encoding_t *encoding;
|
|
17
35
|
} pm_static_literals_metadata_t;
|
|
18
36
|
|
|
19
|
-
static
|
|
37
|
+
static PRISM_INLINE uint32_t
|
|
20
38
|
murmur_scramble(uint32_t value) {
|
|
21
39
|
value *= 0xcc9e2d51;
|
|
22
40
|
value = (value << 15) | (value >> 17);
|
|
@@ -77,6 +95,39 @@ integer_hash(const pm_integer_t *integer) {
|
|
|
77
95
|
return hash;
|
|
78
96
|
}
|
|
79
97
|
|
|
98
|
+
/**
|
|
99
|
+
* Return the flags of the given node that determine the encoding of its string.
|
|
100
|
+
*
|
|
101
|
+
* The FORCED_* flags record how a literal was written. An escape that locks the
|
|
102
|
+
* encoding to UTF-8 (a `\u` escape above U+007F, or any `\u` in a character
|
|
103
|
+
* literal) sets FORCED_UTF8 whether or not the file is already UTF-8. So in a
|
|
104
|
+
* UTF-8 file a `\u00E9` escape and a literal e-acute carry different flags
|
|
105
|
+
* while being the same string, and the flag has to be dropped for them to
|
|
106
|
+
* compare equally.
|
|
107
|
+
*/
|
|
108
|
+
static pm_node_flags_t
|
|
109
|
+
node_encoding_flags(const pm_static_literals_metadata_t *metadata, const pm_node_t *node) {
|
|
110
|
+
switch (PM_NODE_TYPE(node)) {
|
|
111
|
+
case PM_STRING_NODE: {
|
|
112
|
+
pm_node_flags_t mask = PM_STRING_FLAGS_FORCED_BINARY_ENCODING;
|
|
113
|
+
if (metadata->encoding != PM_ENCODING_UTF_8_ENTRY) mask |= PM_STRING_FLAGS_FORCED_UTF8_ENCODING;
|
|
114
|
+
return node->flags & mask;
|
|
115
|
+
}
|
|
116
|
+
case PM_SYMBOL_NODE: {
|
|
117
|
+
pm_node_flags_t mask = PM_SYMBOL_FLAGS_FORCED_BINARY_ENCODING | PM_SYMBOL_FLAGS_FORCED_US_ASCII_ENCODING;
|
|
118
|
+
if (metadata->encoding != PM_ENCODING_UTF_8_ENTRY) mask |= PM_SYMBOL_FLAGS_FORCED_UTF8_ENCODING;
|
|
119
|
+
return node->flags & mask;
|
|
120
|
+
}
|
|
121
|
+
case PM_SOURCE_FILE_NODE:
|
|
122
|
+
/* __FILE__ takes the encoding of the filepath, and every instance
|
|
123
|
+
* of it in a parse resolves the same way. */
|
|
124
|
+
return 0;
|
|
125
|
+
default:
|
|
126
|
+
assert(false && "unreachable");
|
|
127
|
+
return 0;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
80
131
|
/**
|
|
81
132
|
* Return the hash of the given node. It is important that nodes that have
|
|
82
133
|
* equivalent static literal values have the same hash. This is because we use
|
|
@@ -92,7 +143,7 @@ node_hash(const pm_static_literals_metadata_t *metadata, const pm_node_t *node)
|
|
|
92
143
|
}
|
|
93
144
|
case PM_SOURCE_LINE_NODE: {
|
|
94
145
|
// Source lines hash their line number.
|
|
95
|
-
const pm_line_column_t line_column =
|
|
146
|
+
const pm_line_column_t line_column = pm_line_offset_list_line_column(metadata->line_offsets, node->location.start, metadata->start_line);
|
|
96
147
|
const int32_t *value = &line_column.line;
|
|
97
148
|
return murmur_hash((const uint8_t *) value, sizeof(int32_t));
|
|
98
149
|
}
|
|
@@ -117,11 +168,7 @@ node_hash(const pm_static_literals_metadata_t *metadata, const pm_node_t *node)
|
|
|
117
168
|
// Strings hash their value and mix in their flags so that different
|
|
118
169
|
// encodings are not considered equal.
|
|
119
170
|
const pm_string_t *value = &((const pm_string_node_t *) node)->unescaped;
|
|
120
|
-
|
|
121
|
-
pm_node_flags_t flags = node->flags;
|
|
122
|
-
flags &= (PM_STRING_FLAGS_FORCED_BINARY_ENCODING | PM_STRING_FLAGS_FORCED_UTF8_ENCODING);
|
|
123
|
-
|
|
124
|
-
return murmur_hash(pm_string_source(value), pm_string_length(value) * sizeof(uint8_t)) ^ murmur_scramble((uint32_t) flags);
|
|
171
|
+
return murmur_hash(pm_string_source(value), pm_string_length(value) * sizeof(uint8_t)) ^ murmur_scramble((uint32_t) node_encoding_flags(metadata, node));
|
|
125
172
|
}
|
|
126
173
|
case PM_SOURCE_FILE_NODE: {
|
|
127
174
|
// Source files hash their value and mix in their flags so that
|
|
@@ -139,7 +186,7 @@ node_hash(const pm_static_literals_metadata_t *metadata, const pm_node_t *node)
|
|
|
139
186
|
// Symbols hash their value and mix in their flags so that different
|
|
140
187
|
// encodings are not considered equal.
|
|
141
188
|
const pm_string_t *value = &((const pm_symbol_node_t *) node)->unescaped;
|
|
142
|
-
return murmur_hash(pm_string_source(value), pm_string_length(value) * sizeof(uint8_t)) ^ murmur_scramble((uint32_t) node
|
|
189
|
+
return murmur_hash(pm_string_source(value), pm_string_length(value) * sizeof(uint8_t)) ^ murmur_scramble((uint32_t) node_encoding_flags(metadata, node));
|
|
143
190
|
}
|
|
144
191
|
default:
|
|
145
192
|
assert(false && "unreachable");
|
|
@@ -161,7 +208,7 @@ pm_node_hash_insert(pm_node_hash_t *hash, const pm_static_literals_metadata_t *m
|
|
|
161
208
|
// First, allocate space for the new node list.
|
|
162
209
|
uint32_t new_capacity = hash->capacity == 0 ? 4 : hash->capacity * 2;
|
|
163
210
|
pm_node_t **new_nodes = xcalloc(new_capacity, sizeof(pm_node_t *));
|
|
164
|
-
if (new_nodes == NULL)
|
|
211
|
+
if (new_nodes == NULL) abort();
|
|
165
212
|
|
|
166
213
|
// It turns out to be more efficient to mask the hash value than to use
|
|
167
214
|
// the modulo operator. Because our capacities are always powers of two,
|
|
@@ -174,13 +221,16 @@ pm_node_hash_insert(pm_node_hash_t *hash, const pm_static_literals_metadata_t *m
|
|
|
174
221
|
pm_node_t *node = hash->nodes[index];
|
|
175
222
|
|
|
176
223
|
if (node != NULL) {
|
|
177
|
-
uint32_t
|
|
178
|
-
new_nodes[
|
|
224
|
+
uint32_t new_index = node_hash(metadata, node) & mask;
|
|
225
|
+
while (new_nodes[new_index] != NULL) {
|
|
226
|
+
new_index = (new_index + 1) & mask;
|
|
227
|
+
}
|
|
228
|
+
new_nodes[new_index] = node;
|
|
179
229
|
}
|
|
180
230
|
}
|
|
181
231
|
|
|
182
232
|
// Finally, free the old node list and update the hash.
|
|
183
|
-
|
|
233
|
+
xfree_sized(hash->nodes, hash->capacity * sizeof(pm_node_t *));
|
|
184
234
|
hash->nodes = new_nodes;
|
|
185
235
|
hash->capacity = new_capacity;
|
|
186
236
|
}
|
|
@@ -218,7 +268,7 @@ pm_node_hash_insert(pm_node_hash_t *hash, const pm_static_literals_metadata_t *m
|
|
|
218
268
|
*/
|
|
219
269
|
static void
|
|
220
270
|
pm_node_hash_free(pm_node_hash_t *hash) {
|
|
221
|
-
if (hash->capacity > 0)
|
|
271
|
+
if (hash->capacity > 0) xfree_sized(hash->nodes, hash->capacity * sizeof(pm_node_t *));
|
|
222
272
|
}
|
|
223
273
|
|
|
224
274
|
/**
|
|
@@ -240,7 +290,7 @@ pm_int64_value(const pm_static_literals_metadata_t *metadata, const pm_node_t *n
|
|
|
240
290
|
return integer->negative ? -value : value;
|
|
241
291
|
}
|
|
242
292
|
case PM_SOURCE_LINE_NODE:
|
|
243
|
-
return (int64_t)
|
|
293
|
+
return (int64_t) pm_line_offset_list_line_column(metadata->line_offsets, node->location.start, metadata->start_line).line;
|
|
244
294
|
default:
|
|
245
295
|
assert(false && "unreachable");
|
|
246
296
|
return 0;
|
|
@@ -268,7 +318,7 @@ pm_compare_integer_nodes(const pm_static_literals_metadata_t *metadata, const pm
|
|
|
268
318
|
* A comparison function for comparing two FloatNode instances.
|
|
269
319
|
*/
|
|
270
320
|
static int
|
|
271
|
-
pm_compare_float_nodes(
|
|
321
|
+
pm_compare_float_nodes(PRISM_UNUSED const pm_static_literals_metadata_t *metadata, const pm_node_t *left, const pm_node_t *right) {
|
|
272
322
|
const double left_value = ((const pm_float_node_t *) left)->value;
|
|
273
323
|
const double right_value = ((const pm_float_node_t *) right)->value;
|
|
274
324
|
return PM_NUMERIC_COMPARISON(left_value, right_value);
|
|
@@ -327,17 +377,28 @@ pm_string_value(const pm_node_t *node) {
|
|
|
327
377
|
* A comparison function for comparing two nodes that have attached strings.
|
|
328
378
|
*/
|
|
329
379
|
static int
|
|
330
|
-
pm_compare_string_nodes(
|
|
380
|
+
pm_compare_string_nodes(const pm_static_literals_metadata_t *metadata, const pm_node_t *left, const pm_node_t *right) {
|
|
331
381
|
const pm_string_t *left_string = pm_string_value(left);
|
|
332
382
|
const pm_string_t *right_string = pm_string_value(right);
|
|
333
|
-
|
|
383
|
+
|
|
384
|
+
int result = pm_string_compare(left_string, right_string);
|
|
385
|
+
if (result != 0) return result;
|
|
386
|
+
|
|
387
|
+
/*
|
|
388
|
+
* Equal bytes are not enough. In a binary source file the two bytes written
|
|
389
|
+
* as `"\xC3\xA9"` stay BINARY while a `"\u00E9"` escape is forced to UTF-8,
|
|
390
|
+
* so those are distinct keys even though the bytes match.
|
|
391
|
+
*/
|
|
392
|
+
pm_node_flags_t left_flags = node_encoding_flags(metadata, left);
|
|
393
|
+
pm_node_flags_t right_flags = node_encoding_flags(metadata, right);
|
|
394
|
+
return PM_NUMERIC_COMPARISON(left_flags, right_flags);
|
|
334
395
|
}
|
|
335
396
|
|
|
336
397
|
/**
|
|
337
398
|
* A comparison function for comparing two RegularExpressionNode instances.
|
|
338
399
|
*/
|
|
339
400
|
static int
|
|
340
|
-
pm_compare_regular_expression_nodes(
|
|
401
|
+
pm_compare_regular_expression_nodes(PRISM_UNUSED const pm_static_literals_metadata_t *metadata, const pm_node_t *left, const pm_node_t *right) {
|
|
341
402
|
const pm_regular_expression_node_t *left_regexp = (const pm_regular_expression_node_t *) left;
|
|
342
403
|
const pm_regular_expression_node_t *right_regexp = (const pm_regular_expression_node_t *) right;
|
|
343
404
|
|
|
@@ -353,16 +414,17 @@ pm_compare_regular_expression_nodes(PRISM_ATTRIBUTE_UNUSED const pm_static_liter
|
|
|
353
414
|
* Add a node to the set of static literals.
|
|
354
415
|
*/
|
|
355
416
|
pm_node_t *
|
|
356
|
-
pm_static_literals_add(const
|
|
417
|
+
pm_static_literals_add(const pm_line_offset_list_t *line_offsets, const uint8_t *start, int32_t start_line, const pm_encoding_t *encoding, pm_static_literals_t *literals, pm_node_t *node, bool replace) {
|
|
357
418
|
switch (PM_NODE_TYPE(node)) {
|
|
358
419
|
case PM_INTEGER_NODE:
|
|
359
420
|
case PM_SOURCE_LINE_NODE:
|
|
360
421
|
return pm_node_hash_insert(
|
|
361
422
|
&literals->integer_nodes,
|
|
362
423
|
&(pm_static_literals_metadata_t) {
|
|
363
|
-
.
|
|
424
|
+
.line_offsets = line_offsets,
|
|
425
|
+
.start = start,
|
|
364
426
|
.start_line = start_line,
|
|
365
|
-
.
|
|
427
|
+
.encoding = encoding
|
|
366
428
|
},
|
|
367
429
|
node,
|
|
368
430
|
replace,
|
|
@@ -372,9 +434,10 @@ pm_static_literals_add(const pm_newline_list_t *newline_list, int32_t start_line
|
|
|
372
434
|
return pm_node_hash_insert(
|
|
373
435
|
&literals->float_nodes,
|
|
374
436
|
&(pm_static_literals_metadata_t) {
|
|
375
|
-
.
|
|
437
|
+
.line_offsets = line_offsets,
|
|
438
|
+
.start = start,
|
|
376
439
|
.start_line = start_line,
|
|
377
|
-
.
|
|
440
|
+
.encoding = encoding
|
|
378
441
|
},
|
|
379
442
|
node,
|
|
380
443
|
replace,
|
|
@@ -385,9 +448,10 @@ pm_static_literals_add(const pm_newline_list_t *newline_list, int32_t start_line
|
|
|
385
448
|
return pm_node_hash_insert(
|
|
386
449
|
&literals->number_nodes,
|
|
387
450
|
&(pm_static_literals_metadata_t) {
|
|
388
|
-
.
|
|
451
|
+
.line_offsets = line_offsets,
|
|
452
|
+
.start = start,
|
|
389
453
|
.start_line = start_line,
|
|
390
|
-
.
|
|
454
|
+
.encoding = encoding
|
|
391
455
|
},
|
|
392
456
|
node,
|
|
393
457
|
replace,
|
|
@@ -398,9 +462,10 @@ pm_static_literals_add(const pm_newline_list_t *newline_list, int32_t start_line
|
|
|
398
462
|
return pm_node_hash_insert(
|
|
399
463
|
&literals->string_nodes,
|
|
400
464
|
&(pm_static_literals_metadata_t) {
|
|
401
|
-
.
|
|
465
|
+
.line_offsets = line_offsets,
|
|
466
|
+
.start = start,
|
|
402
467
|
.start_line = start_line,
|
|
403
|
-
.
|
|
468
|
+
.encoding = encoding
|
|
404
469
|
},
|
|
405
470
|
node,
|
|
406
471
|
replace,
|
|
@@ -410,9 +475,10 @@ pm_static_literals_add(const pm_newline_list_t *newline_list, int32_t start_line
|
|
|
410
475
|
return pm_node_hash_insert(
|
|
411
476
|
&literals->regexp_nodes,
|
|
412
477
|
&(pm_static_literals_metadata_t) {
|
|
413
|
-
.
|
|
478
|
+
.line_offsets = line_offsets,
|
|
479
|
+
.start = start,
|
|
414
480
|
.start_line = start_line,
|
|
415
|
-
.
|
|
481
|
+
.encoding = encoding
|
|
416
482
|
},
|
|
417
483
|
node,
|
|
418
484
|
replace,
|
|
@@ -422,9 +488,10 @@ pm_static_literals_add(const pm_newline_list_t *newline_list, int32_t start_line
|
|
|
422
488
|
return pm_node_hash_insert(
|
|
423
489
|
&literals->symbol_nodes,
|
|
424
490
|
&(pm_static_literals_metadata_t) {
|
|
425
|
-
.
|
|
491
|
+
.line_offsets = line_offsets,
|
|
492
|
+
.start = start,
|
|
426
493
|
.start_line = start_line,
|
|
427
|
-
.
|
|
494
|
+
.encoding = encoding
|
|
428
495
|
},
|
|
429
496
|
node,
|
|
430
497
|
replace,
|
|
@@ -492,7 +559,7 @@ pm_static_literal_positive_p(const pm_node_t *node) {
|
|
|
492
559
|
/**
|
|
493
560
|
* Create a string-based representation of the given static literal.
|
|
494
561
|
*/
|
|
495
|
-
static
|
|
562
|
+
static PRISM_INLINE void
|
|
496
563
|
pm_static_literal_inspect_node(pm_buffer_t *buffer, const pm_static_literals_metadata_t *metadata, const pm_node_t *node) {
|
|
497
564
|
switch (PM_NODE_TYPE(node)) {
|
|
498
565
|
case PM_FALSE_NODE:
|
|
@@ -502,12 +569,12 @@ pm_static_literal_inspect_node(pm_buffer_t *buffer, const pm_static_literals_met
|
|
|
502
569
|
const double value = ((const pm_float_node_t *) node)->value;
|
|
503
570
|
|
|
504
571
|
if (PRISM_ISINF(value)) {
|
|
505
|
-
if (
|
|
572
|
+
if (metadata->start[node->location.start] == '-') {
|
|
506
573
|
pm_buffer_append_byte(buffer, '-');
|
|
507
574
|
}
|
|
508
575
|
pm_buffer_append_string(buffer, "Infinity", 8);
|
|
509
576
|
} else if (value == 0.0) {
|
|
510
|
-
if (
|
|
577
|
+
if (metadata->start[node->location.start] == '-') {
|
|
511
578
|
pm_buffer_append_byte(buffer, '-');
|
|
512
579
|
}
|
|
513
580
|
pm_buffer_append_string(buffer, "0.0", 3);
|
|
@@ -566,7 +633,7 @@ pm_static_literal_inspect_node(pm_buffer_t *buffer, const pm_static_literals_met
|
|
|
566
633
|
break;
|
|
567
634
|
}
|
|
568
635
|
case PM_SOURCE_ENCODING_NODE:
|
|
569
|
-
pm_buffer_append_format(buffer, "#<Encoding:%s>", metadata->
|
|
636
|
+
pm_buffer_append_format(buffer, "#<Encoding:%s>", metadata->encoding->name);
|
|
570
637
|
break;
|
|
571
638
|
case PM_SOURCE_FILE_NODE: {
|
|
572
639
|
const pm_string_t *filepath = &((const pm_source_file_node_t *) node)->filepath;
|
|
@@ -576,7 +643,7 @@ pm_static_literal_inspect_node(pm_buffer_t *buffer, const pm_static_literals_met
|
|
|
576
643
|
break;
|
|
577
644
|
}
|
|
578
645
|
case PM_SOURCE_LINE_NODE:
|
|
579
|
-
pm_buffer_append_format(buffer, "%d",
|
|
646
|
+
pm_buffer_append_format(buffer, "%d", pm_line_offset_list_line_column(metadata->line_offsets, node->location.start, metadata->start_line).line);
|
|
580
647
|
break;
|
|
581
648
|
case PM_STRING_NODE: {
|
|
582
649
|
const pm_string_t *unescaped = &((const pm_string_node_t *) node)->unescaped;
|
|
@@ -604,13 +671,14 @@ pm_static_literal_inspect_node(pm_buffer_t *buffer, const pm_static_literals_met
|
|
|
604
671
|
* Create a string-based representation of the given static literal.
|
|
605
672
|
*/
|
|
606
673
|
void
|
|
607
|
-
pm_static_literal_inspect(pm_buffer_t *buffer, const
|
|
674
|
+
pm_static_literal_inspect(pm_buffer_t *buffer, const pm_line_offset_list_t *line_offsets, const uint8_t *start, int32_t start_line, const pm_encoding_t *encoding, const pm_node_t *node) {
|
|
608
675
|
pm_static_literal_inspect_node(
|
|
609
676
|
buffer,
|
|
610
677
|
&(pm_static_literals_metadata_t) {
|
|
611
|
-
.
|
|
678
|
+
.line_offsets = line_offsets,
|
|
679
|
+
.start = start,
|
|
612
680
|
.start_line = start_line,
|
|
613
|
-
.
|
|
681
|
+
.encoding = encoding
|
|
614
682
|
},
|
|
615
683
|
node
|
|
616
684
|
);
|
data/src/string_query.c
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
#include "prism/string_query.h"
|
|
2
|
+
|
|
3
|
+
#include "prism/internal/char.h"
|
|
4
|
+
#include "prism/internal/encoding.h"
|
|
5
|
+
#include "prism/internal/parser.h"
|
|
6
|
+
|
|
7
|
+
#include <assert.h>
|
|
8
|
+
#include <string.h>
|
|
9
|
+
|
|
10
|
+
/** The category of slice returned from pm_slice_type. */
|
|
11
|
+
typedef enum {
|
|
12
|
+
/** Returned when the given encoding name is invalid. */
|
|
13
|
+
PM_SLICE_TYPE_ERROR = -1,
|
|
14
|
+
|
|
15
|
+
/** Returned when no other types apply to the slice. */
|
|
16
|
+
PM_SLICE_TYPE_NONE,
|
|
17
|
+
|
|
18
|
+
/** Returned when the slice is a valid local variable name. */
|
|
19
|
+
PM_SLICE_TYPE_LOCAL,
|
|
20
|
+
|
|
21
|
+
/** Returned when the slice is a valid constant name. */
|
|
22
|
+
PM_SLICE_TYPE_CONSTANT,
|
|
23
|
+
|
|
24
|
+
/** Returned when the slice is a valid method name. */
|
|
25
|
+
PM_SLICE_TYPE_METHOD_NAME
|
|
26
|
+
} pm_slice_type_t;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Check that the slice is a valid local variable name or constant.
|
|
30
|
+
*/
|
|
31
|
+
static pm_slice_type_t
|
|
32
|
+
pm_slice_type(const uint8_t *source, size_t length, const char *encoding_name) {
|
|
33
|
+
// first, get the right encoding object
|
|
34
|
+
const pm_encoding_t *encoding = pm_encoding_find((const uint8_t *) encoding_name, (const uint8_t *) (encoding_name + strlen(encoding_name)));
|
|
35
|
+
if (encoding == NULL) return PM_SLICE_TYPE_ERROR;
|
|
36
|
+
|
|
37
|
+
// check that there is at least one character
|
|
38
|
+
if (length == 0) return PM_SLICE_TYPE_NONE;
|
|
39
|
+
|
|
40
|
+
size_t width;
|
|
41
|
+
if ((width = encoding->alpha_char(source, (ptrdiff_t) length)) != 0) {
|
|
42
|
+
// valid because alphabetical
|
|
43
|
+
} else if (*source == '_') {
|
|
44
|
+
// valid because underscore
|
|
45
|
+
width = 1;
|
|
46
|
+
} else if ((*source >= 0x80) && ((width = encoding->char_width(source, (ptrdiff_t) length)) > 0)) {
|
|
47
|
+
// valid because multibyte
|
|
48
|
+
} else {
|
|
49
|
+
// invalid because no match
|
|
50
|
+
return PM_SLICE_TYPE_NONE;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// determine the type of the slice based on the first character
|
|
54
|
+
const uint8_t *end = source + length;
|
|
55
|
+
pm_slice_type_t result = encoding->isupper_char(source, end - source) ? PM_SLICE_TYPE_CONSTANT : PM_SLICE_TYPE_LOCAL;
|
|
56
|
+
|
|
57
|
+
// next, iterate through all of the bytes of the string to ensure that they
|
|
58
|
+
// are all valid identifier characters
|
|
59
|
+
source += width;
|
|
60
|
+
|
|
61
|
+
while (source < end) {
|
|
62
|
+
if ((width = encoding->alnum_char(source, end - source)) != 0) {
|
|
63
|
+
// valid because alphanumeric
|
|
64
|
+
source += width;
|
|
65
|
+
} else if (*source == '_') {
|
|
66
|
+
// valid because underscore
|
|
67
|
+
source++;
|
|
68
|
+
} else if ((*source >= 0x80) && ((width = encoding->char_width(source, end - source)) > 0)) {
|
|
69
|
+
// valid because multibyte
|
|
70
|
+
source += width;
|
|
71
|
+
} else {
|
|
72
|
+
// invalid because no match
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// accept a ! or ? at the end of the slice as a method name
|
|
78
|
+
if (*source == '!' || *source == '?' || *source == '=') {
|
|
79
|
+
source++;
|
|
80
|
+
result = PM_SLICE_TYPE_METHOD_NAME;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// valid if we are at the end of the slice
|
|
84
|
+
return source == end ? result : PM_SLICE_TYPE_NONE;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Check that the slice is a valid local variable name.
|
|
89
|
+
*/
|
|
90
|
+
pm_string_query_t
|
|
91
|
+
pm_string_query_local(const uint8_t *source, size_t length, const char *encoding_name) {
|
|
92
|
+
switch (pm_slice_type(source, length, encoding_name)) {
|
|
93
|
+
case PM_SLICE_TYPE_ERROR:
|
|
94
|
+
return PM_STRING_QUERY_ERROR;
|
|
95
|
+
case PM_SLICE_TYPE_NONE:
|
|
96
|
+
case PM_SLICE_TYPE_CONSTANT:
|
|
97
|
+
case PM_SLICE_TYPE_METHOD_NAME:
|
|
98
|
+
return PM_STRING_QUERY_FALSE;
|
|
99
|
+
case PM_SLICE_TYPE_LOCAL:
|
|
100
|
+
return PM_STRING_QUERY_TRUE;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
assert(false && "unreachable");
|
|
104
|
+
return PM_STRING_QUERY_FALSE;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Check that the slice is a valid constant name.
|
|
109
|
+
*/
|
|
110
|
+
pm_string_query_t
|
|
111
|
+
pm_string_query_constant(const uint8_t *source, size_t length, const char *encoding_name) {
|
|
112
|
+
switch (pm_slice_type(source, length, encoding_name)) {
|
|
113
|
+
case PM_SLICE_TYPE_ERROR:
|
|
114
|
+
return PM_STRING_QUERY_ERROR;
|
|
115
|
+
case PM_SLICE_TYPE_NONE:
|
|
116
|
+
case PM_SLICE_TYPE_LOCAL:
|
|
117
|
+
case PM_SLICE_TYPE_METHOD_NAME:
|
|
118
|
+
return PM_STRING_QUERY_FALSE;
|
|
119
|
+
case PM_SLICE_TYPE_CONSTANT:
|
|
120
|
+
return PM_STRING_QUERY_TRUE;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
assert(false && "unreachable");
|
|
124
|
+
return PM_STRING_QUERY_FALSE;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Check that the slice is a valid method name.
|
|
129
|
+
*/
|
|
130
|
+
pm_string_query_t
|
|
131
|
+
pm_string_query_method_name(const uint8_t *source, size_t length, const char *encoding_name) {
|
|
132
|
+
#define B(p) ((p) ? PM_STRING_QUERY_TRUE : PM_STRING_QUERY_FALSE)
|
|
133
|
+
#define C1(c) (*source == c)
|
|
134
|
+
#define C2(s) (memcmp(source, s, 2) == 0)
|
|
135
|
+
#define C3(s) (memcmp(source, s, 3) == 0)
|
|
136
|
+
|
|
137
|
+
switch (pm_slice_type(source, length, encoding_name)) {
|
|
138
|
+
case PM_SLICE_TYPE_ERROR:
|
|
139
|
+
return PM_STRING_QUERY_ERROR;
|
|
140
|
+
case PM_SLICE_TYPE_NONE:
|
|
141
|
+
break;
|
|
142
|
+
case PM_SLICE_TYPE_LOCAL:
|
|
143
|
+
// numbered parameters are not valid method names
|
|
144
|
+
return B((length != 2) || (source[0] != '_') || (source[1] == '0') || !pm_char_is_decimal_digit(source[1]));
|
|
145
|
+
case PM_SLICE_TYPE_CONSTANT:
|
|
146
|
+
// all constants are valid method names
|
|
147
|
+
case PM_SLICE_TYPE_METHOD_NAME:
|
|
148
|
+
// all method names are valid method names
|
|
149
|
+
return PM_STRING_QUERY_TRUE;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
switch (length) {
|
|
153
|
+
case 1:
|
|
154
|
+
return B(C1('&') || C1('`') || C1('!') || C1('^') || C1('>') || C1('<') || C1('-') || C1('%') || C1('|') || C1('+') || C1('/') || C1('*') || C1('~'));
|
|
155
|
+
case 2:
|
|
156
|
+
return B(C2("!=") || C2("!~") || C2("[]") || C2("==") || C2("=~") || C2(">=") || C2(">>") || C2("<=") || C2("<<") || C2("**"));
|
|
157
|
+
case 3:
|
|
158
|
+
return B(C3("===") || C3("<=>") || C3("[]="));
|
|
159
|
+
default:
|
|
160
|
+
return PM_STRING_QUERY_FALSE;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
#undef B
|
|
164
|
+
#undef C1
|
|
165
|
+
#undef C2
|
|
166
|
+
#undef C3
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Check that the slice is a keyword. Keywords are spelled in ASCII, so any
|
|
171
|
+
* ASCII-compatible encoding spells them with the same bytes.
|
|
172
|
+
*/
|
|
173
|
+
pm_string_query_t
|
|
174
|
+
pm_string_query_keyword(const uint8_t *source, size_t length, const char *encoding_name) {
|
|
175
|
+
if (pm_encoding_find((const uint8_t *) encoding_name, (const uint8_t *) (encoding_name + strlen(encoding_name))) == NULL) {
|
|
176
|
+
return PM_STRING_QUERY_ERROR;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return pm_keyword_p(source, source + length) ? PM_STRING_QUERY_TRUE : PM_STRING_QUERY_FALSE;
|
|
180
|
+
}
|
data/src/stringy.c
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
#include "prism/internal/stringy.h"
|
|
2
|
+
|
|
3
|
+
#include "prism/internal/allocator.h"
|
|
4
|
+
|
|
5
|
+
#include <assert.h>
|
|
6
|
+
#include <stdlib.h>
|
|
7
|
+
#include <string.h>
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Initialize a shared string that is based on initial input.
|
|
11
|
+
*/
|
|
12
|
+
void
|
|
13
|
+
pm_string_shared_init(pm_string_t *string, const uint8_t *start, const uint8_t *end) {
|
|
14
|
+
assert(start <= end);
|
|
15
|
+
|
|
16
|
+
*string = (pm_string_t) {
|
|
17
|
+
.type = PM_STRING_SHARED,
|
|
18
|
+
.source = start,
|
|
19
|
+
.length = (size_t) (end - start)
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Initialize an owned string that is responsible for freeing allocated memory.
|
|
25
|
+
*/
|
|
26
|
+
void
|
|
27
|
+
pm_string_owned_init(pm_string_t *string, uint8_t *source, size_t length) {
|
|
28
|
+
*string = (pm_string_t) {
|
|
29
|
+
.type = PM_STRING_OWNED,
|
|
30
|
+
.source = source,
|
|
31
|
+
.length = length
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Initialize a constant string that doesn't own its memory source.
|
|
37
|
+
*/
|
|
38
|
+
void
|
|
39
|
+
pm_string_constant_init(pm_string_t *string, const char *source, size_t length) {
|
|
40
|
+
*string = (pm_string_t) {
|
|
41
|
+
.type = PM_STRING_CONSTANT,
|
|
42
|
+
.source = (const uint8_t *) source,
|
|
43
|
+
.length = length
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Compare the underlying lengths and bytes of two strings. Returns 0 if the
|
|
49
|
+
* strings are equal, a negative number if the left string is less than the
|
|
50
|
+
* right string, and a positive number if the left string is greater than the
|
|
51
|
+
* right string.
|
|
52
|
+
*/
|
|
53
|
+
int
|
|
54
|
+
pm_string_compare(const pm_string_t *left, const pm_string_t *right) {
|
|
55
|
+
size_t left_length = pm_string_length(left);
|
|
56
|
+
size_t right_length = pm_string_length(right);
|
|
57
|
+
|
|
58
|
+
if (left_length < right_length) {
|
|
59
|
+
return -1;
|
|
60
|
+
} else if (left_length > right_length) {
|
|
61
|
+
return 1;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return memcmp(pm_string_source(left), pm_string_source(right), left_length);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Returns the length associated with the string.
|
|
69
|
+
*/
|
|
70
|
+
size_t
|
|
71
|
+
pm_string_length(const pm_string_t *string) {
|
|
72
|
+
return string->length;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Returns the start pointer associated with the string.
|
|
77
|
+
*/
|
|
78
|
+
const uint8_t *
|
|
79
|
+
pm_string_source(const pm_string_t *string) {
|
|
80
|
+
return string->source;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Free the associated memory of the given string.
|
|
85
|
+
*/
|
|
86
|
+
void
|
|
87
|
+
pm_string_cleanup(pm_string_t *string) {
|
|
88
|
+
if (string->type == PM_STRING_OWNED) {
|
|
89
|
+
xfree_sized((void *) string->source, string->length);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
#include "prism/
|
|
1
|
+
#include "prism/internal/strncasecmp.h"
|
|
2
|
+
|
|
3
|
+
#include "prism/compiler/inline.h"
|
|
2
4
|
|
|
3
5
|
/**
|
|
4
6
|
* A locale-insensitive version of `tolower(3)`
|
|
5
7
|
*/
|
|
6
|
-
static
|
|
7
|
-
pm_tolower(int c)
|
|
8
|
-
{
|
|
8
|
+
static PRISM_INLINE int
|
|
9
|
+
pm_tolower(int c) {
|
|
9
10
|
if ('A' <= c && c <= 'Z') {
|
|
10
11
|
return c | 0x20;
|
|
11
12
|
}
|