yarp 0.7.0 → 0.9.0
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 +54 -2
- data/Makefile +2 -0
- data/README.md +9 -5
- data/config.yml +160 -93
- data/docs/configuration.md +1 -0
- data/docs/ruby_api.md +2 -0
- data/docs/serialization.md +1 -1
- data/docs/testing.md +2 -2
- data/ext/yarp/api_node.c +361 -238
- data/ext/yarp/extension.c +75 -26
- data/ext/yarp/extension.h +2 -2
- data/include/yarp/ast.h +226 -175
- data/include/yarp/defines.h +5 -0
- data/include/yarp/node.h +10 -0
- data/include/yarp/unescape.h +4 -2
- data/include/yarp/util/yp_buffer.h +9 -1
- data/include/yarp/util/yp_constant_pool.h +3 -0
- data/include/yarp/util/yp_list.h +7 -7
- data/include/yarp/util/yp_newline_list.h +7 -0
- data/include/yarp/util/yp_state_stack.h +1 -1
- data/include/yarp/version.h +2 -2
- data/include/yarp.h +10 -0
- data/lib/yarp/desugar_visitor.rb +267 -0
- data/lib/yarp/ffi.rb +89 -48
- data/lib/yarp/lex_compat.rb +93 -25
- data/lib/yarp/mutation_visitor.rb +683 -0
- data/lib/yarp/node.rb +2061 -422
- data/lib/yarp/serialize.rb +162 -120
- data/lib/yarp.rb +54 -8
- data/src/node.c +360 -304
- data/src/prettyprint.c +190 -152
- data/src/serialize.c +382 -340
- data/src/token_type.c +2 -2
- data/src/unescape.c +89 -77
- data/src/util/yp_buffer.c +18 -0
- data/src/util/yp_list.c +7 -16
- data/src/util/yp_newline_list.c +10 -0
- data/src/util/yp_state_stack.c +0 -6
- data/src/yarp.c +941 -596
- data/yarp.gemspec +3 -1
- metadata +4 -2
data/src/token_type.c
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/******************************************************************************/
|
2
|
-
/* This file is generated by the
|
3
|
-
/* modified manually. See
|
2
|
+
/* This file is generated by the templates/template.rb script and should not */
|
3
|
+
/* be modified manually. See */
|
4
4
|
/* templates/src/token_type.c.erb */
|
5
5
|
/* if you are looking to modify the */
|
6
6
|
/* template */
|
data/src/unescape.c
CHANGED
@@ -14,6 +14,20 @@ yp_char_is_hexadecimal_digits(const char *c, size_t length) {
|
|
14
14
|
return true;
|
15
15
|
}
|
16
16
|
|
17
|
+
// We don't call the char_width function unless we have to because it's
|
18
|
+
// expensive to go through the indirection of the function pointer. Instead we
|
19
|
+
// provide a fast path that will check if we can just return 1.
|
20
|
+
static inline size_t
|
21
|
+
yp_char_width(yp_parser_t *parser, const char *start, const char *end) {
|
22
|
+
const unsigned char *uc = (const unsigned char *) start;
|
23
|
+
|
24
|
+
if (parser->encoding_changed || (*uc >= 0x80)) {
|
25
|
+
return parser->encoding.char_width(start, end - start);
|
26
|
+
} else {
|
27
|
+
return 1;
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
17
31
|
/******************************************************************************/
|
18
32
|
/* Lookup tables for characters */
|
19
33
|
/******************************************************************************/
|
@@ -178,24 +192,8 @@ unescape_char(const unsigned char value, const unsigned char flags) {
|
|
178
192
|
|
179
193
|
// Read a specific escape sequence into the given destination.
|
180
194
|
static const char *
|
181
|
-
unescape(char *dest, size_t *dest_length, const char *backslash, const char *end,
|
195
|
+
unescape(yp_parser_t *parser, char *dest, size_t *dest_length, const char *backslash, const char *end, const unsigned char flags, bool write_to_str) {
|
182
196
|
switch (backslash[1]) {
|
183
|
-
// \a \b \e \f \n \r \s \t \v
|
184
|
-
case '\r': {
|
185
|
-
// if this is an \r\n we need to escape both
|
186
|
-
if (write_to_str) {
|
187
|
-
dest[(*dest_length)++] = (char) unescape_char(unescape_chars[(unsigned char) backslash[1]], flags);
|
188
|
-
}
|
189
|
-
|
190
|
-
if (backslash + 2 < end && backslash[2] == '\n') {
|
191
|
-
if (write_to_str) {
|
192
|
-
dest[(*dest_length)++] = (char) unescape_char(unescape_chars[(unsigned char) backslash[2]], flags);
|
193
|
-
}
|
194
|
-
return backslash + 3;
|
195
|
-
}
|
196
|
-
|
197
|
-
return backslash + 2;
|
198
|
-
}
|
199
197
|
case 'a':
|
200
198
|
case 'b':
|
201
199
|
case 'e':
|
@@ -234,7 +232,7 @@ unescape(char *dest, size_t *dest_length, const char *backslash, const char *end
|
|
234
232
|
// \unnnn Unicode character, where nnnn is exactly 4 hexadecimal digits ([0-9a-fA-F])
|
235
233
|
case 'u': {
|
236
234
|
if ((flags & YP_UNESCAPE_FLAG_CONTROL) | (flags & YP_UNESCAPE_FLAG_META)) {
|
237
|
-
yp_diagnostic_list_append(error_list, backslash, backslash + 2, "Unicode escape sequence cannot be used with control or meta flags.");
|
235
|
+
yp_diagnostic_list_append(&parser->error_list, backslash, backslash + 2, "Unicode escape sequence cannot be used with control or meta flags.");
|
238
236
|
return backslash + 2;
|
239
237
|
}
|
240
238
|
|
@@ -251,11 +249,11 @@ unescape(char *dest, size_t *dest_length, const char *backslash, const char *end
|
|
251
249
|
|
252
250
|
// \u{nnnn} character literal allows only 1-6 hexadecimal digits
|
253
251
|
if (hexadecimal_length > 6)
|
254
|
-
yp_diagnostic_list_append(error_list, unicode_cursor, unicode_cursor + hexadecimal_length, "invalid Unicode escape.");
|
252
|
+
yp_diagnostic_list_append(&parser->error_list, unicode_cursor, unicode_cursor + hexadecimal_length, "invalid Unicode escape.");
|
255
253
|
|
256
254
|
// there are not hexadecimal characters
|
257
255
|
if (hexadecimal_length == 0) {
|
258
|
-
yp_diagnostic_list_append(error_list, unicode_cursor, unicode_cursor + hexadecimal_length, "unterminated Unicode escape");
|
256
|
+
yp_diagnostic_list_append(&parser->error_list, unicode_cursor, unicode_cursor + hexadecimal_length, "unterminated Unicode escape");
|
259
257
|
return unicode_cursor;
|
260
258
|
}
|
261
259
|
|
@@ -268,7 +266,7 @@ unescape(char *dest, size_t *dest_length, const char *backslash, const char *end
|
|
268
266
|
uint32_t value;
|
269
267
|
unescape_unicode(unicode_start, (size_t) (unicode_cursor - unicode_start), &value);
|
270
268
|
if (write_to_str) {
|
271
|
-
*dest_length += unescape_unicode_write(dest + *dest_length, value, unicode_start, unicode_cursor, error_list);
|
269
|
+
*dest_length += unescape_unicode_write(dest + *dest_length, value, unicode_start, unicode_cursor, &parser->error_list);
|
272
270
|
}
|
273
271
|
|
274
272
|
unicode_cursor += yp_strspn_whitespace(unicode_cursor, end - unicode_cursor);
|
@@ -276,7 +274,7 @@ unescape(char *dest, size_t *dest_length, const char *backslash, const char *end
|
|
276
274
|
|
277
275
|
// ?\u{nnnn} character literal should contain only one codepoint and cannot be like ?\u{nnnn mmmm}
|
278
276
|
if (flags & YP_UNESCAPE_FLAG_EXPECT_SINGLE && codepoints_count > 1)
|
279
|
-
yp_diagnostic_list_append(error_list, extra_codepoints_start, unicode_cursor - 1, "Multiple codepoints at single character literal");
|
277
|
+
yp_diagnostic_list_append(&parser->error_list, extra_codepoints_start, unicode_cursor - 1, "Multiple codepoints at single character literal");
|
280
278
|
|
281
279
|
return unicode_cursor + 1;
|
282
280
|
}
|
@@ -286,12 +284,12 @@ unescape(char *dest, size_t *dest_length, const char *backslash, const char *end
|
|
286
284
|
unescape_unicode(backslash + 2, 4, &value);
|
287
285
|
|
288
286
|
if (write_to_str) {
|
289
|
-
*dest_length += unescape_unicode_write(dest + *dest_length, value, backslash + 2, backslash + 6, error_list);
|
287
|
+
*dest_length += unescape_unicode_write(dest + *dest_length, value, backslash + 2, backslash + 6, &parser->error_list);
|
290
288
|
}
|
291
289
|
return backslash + 6;
|
292
290
|
}
|
293
291
|
|
294
|
-
yp_diagnostic_list_append(error_list, backslash, backslash + 2, "Invalid Unicode escape sequence");
|
292
|
+
yp_diagnostic_list_append(&parser->error_list, backslash, backslash + 2, "Invalid Unicode escape sequence");
|
295
293
|
return backslash + 2;
|
296
294
|
}
|
297
295
|
// \c\M-x meta control character, where x is an ASCII printable character
|
@@ -299,18 +297,18 @@ unescape(char *dest, size_t *dest_length, const char *backslash, const char *end
|
|
299
297
|
// \cx control character, where x is an ASCII printable character
|
300
298
|
case 'c':
|
301
299
|
if (backslash + 2 >= end) {
|
302
|
-
yp_diagnostic_list_append(error_list, backslash, backslash + 1, "Invalid control escape sequence");
|
300
|
+
yp_diagnostic_list_append(&parser->error_list, backslash, backslash + 1, "Invalid control escape sequence");
|
303
301
|
return end;
|
304
302
|
}
|
305
303
|
|
306
304
|
if (flags & YP_UNESCAPE_FLAG_CONTROL) {
|
307
|
-
yp_diagnostic_list_append(error_list, backslash, backslash + 1, "Control escape sequence cannot be doubled.");
|
305
|
+
yp_diagnostic_list_append(&parser->error_list, backslash, backslash + 1, "Control escape sequence cannot be doubled.");
|
308
306
|
return backslash + 2;
|
309
307
|
}
|
310
308
|
|
311
309
|
switch (backslash[2]) {
|
312
310
|
case '\\':
|
313
|
-
return unescape(dest, dest_length, backslash + 2, end,
|
311
|
+
return unescape(parser, dest, dest_length, backslash + 2, end, flags | YP_UNESCAPE_FLAG_CONTROL, write_to_str);
|
314
312
|
case '?':
|
315
313
|
if (write_to_str) {
|
316
314
|
dest[(*dest_length)++] = (char) unescape_char(0x7f, flags);
|
@@ -318,7 +316,7 @@ unescape(char *dest, size_t *dest_length, const char *backslash, const char *end
|
|
318
316
|
return backslash + 3;
|
319
317
|
default: {
|
320
318
|
if (!char_is_ascii_printable(backslash[2])) {
|
321
|
-
yp_diagnostic_list_append(error_list, backslash, backslash + 1, "Invalid control escape sequence");
|
319
|
+
yp_diagnostic_list_append(&parser->error_list, backslash, backslash + 1, "Invalid control escape sequence");
|
322
320
|
return backslash + 2;
|
323
321
|
}
|
324
322
|
|
@@ -332,23 +330,23 @@ unescape(char *dest, size_t *dest_length, const char *backslash, const char *end
|
|
332
330
|
// \C-? delete, ASCII 7Fh (DEL)
|
333
331
|
case 'C':
|
334
332
|
if (backslash + 3 >= end) {
|
335
|
-
yp_diagnostic_list_append(error_list, backslash, backslash + 1, "Invalid control escape sequence");
|
333
|
+
yp_diagnostic_list_append(&parser->error_list, backslash, backslash + 1, "Invalid control escape sequence");
|
336
334
|
return end;
|
337
335
|
}
|
338
336
|
|
339
337
|
if (flags & YP_UNESCAPE_FLAG_CONTROL) {
|
340
|
-
yp_diagnostic_list_append(error_list, backslash, backslash + 1, "Control escape sequence cannot be doubled.");
|
338
|
+
yp_diagnostic_list_append(&parser->error_list, backslash, backslash + 1, "Control escape sequence cannot be doubled.");
|
341
339
|
return backslash + 2;
|
342
340
|
}
|
343
341
|
|
344
342
|
if (backslash[2] != '-') {
|
345
|
-
yp_diagnostic_list_append(error_list, backslash, backslash + 1, "Invalid control escape sequence");
|
343
|
+
yp_diagnostic_list_append(&parser->error_list, backslash, backslash + 1, "Invalid control escape sequence");
|
346
344
|
return backslash + 2;
|
347
345
|
}
|
348
346
|
|
349
347
|
switch (backslash[3]) {
|
350
348
|
case '\\':
|
351
|
-
return unescape(dest, dest_length, backslash + 3, end,
|
349
|
+
return unescape(parser, dest, dest_length, backslash + 3, end, flags | YP_UNESCAPE_FLAG_CONTROL, write_to_str);
|
352
350
|
case '?':
|
353
351
|
if (write_to_str) {
|
354
352
|
dest[(*dest_length)++] = (char) unescape_char(0x7f, flags);
|
@@ -356,7 +354,7 @@ unescape(char *dest, size_t *dest_length, const char *backslash, const char *end
|
|
356
354
|
return backslash + 4;
|
357
355
|
default:
|
358
356
|
if (!char_is_ascii_printable(backslash[3])) {
|
359
|
-
yp_diagnostic_list_append(error_list, backslash, backslash + 2, "Invalid control escape sequence");
|
357
|
+
yp_diagnostic_list_append(&parser->error_list, backslash, backslash + 2, "Invalid control escape sequence");
|
360
358
|
return backslash + 2;
|
361
359
|
}
|
362
360
|
|
@@ -370,22 +368,22 @@ unescape(char *dest, size_t *dest_length, const char *backslash, const char *end
|
|
370
368
|
// \M-x meta character, where x is an ASCII printable character
|
371
369
|
case 'M': {
|
372
370
|
if (backslash + 3 >= end) {
|
373
|
-
yp_diagnostic_list_append(error_list, backslash, backslash + 1, "Invalid control escape sequence");
|
371
|
+
yp_diagnostic_list_append(&parser->error_list, backslash, backslash + 1, "Invalid control escape sequence");
|
374
372
|
return end;
|
375
373
|
}
|
376
374
|
|
377
375
|
if (flags & YP_UNESCAPE_FLAG_META) {
|
378
|
-
yp_diagnostic_list_append(error_list, backslash, backslash + 2, "Meta escape sequence cannot be doubled.");
|
376
|
+
yp_diagnostic_list_append(&parser->error_list, backslash, backslash + 2, "Meta escape sequence cannot be doubled.");
|
379
377
|
return backslash + 2;
|
380
378
|
}
|
381
379
|
|
382
380
|
if (backslash[2] != '-') {
|
383
|
-
yp_diagnostic_list_append(error_list, backslash, backslash + 2, "Invalid meta escape sequence");
|
381
|
+
yp_diagnostic_list_append(&parser->error_list, backslash, backslash + 2, "Invalid meta escape sequence");
|
384
382
|
return backslash + 2;
|
385
383
|
}
|
386
384
|
|
387
385
|
if (backslash[3] == '\\') {
|
388
|
-
return unescape(dest, dest_length, backslash + 3, end,
|
386
|
+
return unescape(parser, dest, dest_length, backslash + 3, end, flags | YP_UNESCAPE_FLAG_META, write_to_str);
|
389
387
|
}
|
390
388
|
|
391
389
|
if (char_is_ascii_printable(backslash[3])) {
|
@@ -395,17 +393,29 @@ unescape(char *dest, size_t *dest_length, const char *backslash, const char *end
|
|
395
393
|
return backslash + 4;
|
396
394
|
}
|
397
395
|
|
398
|
-
yp_diagnostic_list_append(error_list, backslash, backslash + 2, "Invalid meta escape sequence");
|
396
|
+
yp_diagnostic_list_append(&parser->error_list, backslash, backslash + 2, "Invalid meta escape sequence");
|
399
397
|
return backslash + 3;
|
400
398
|
}
|
399
|
+
// \n
|
400
|
+
case '\n':
|
401
|
+
return backslash + 2;
|
402
|
+
// \r
|
403
|
+
case '\r':
|
404
|
+
if (backslash + 2 < end && backslash[2] == '\n') {
|
405
|
+
return backslash + 3;
|
406
|
+
}
|
407
|
+
/* fallthrough */
|
401
408
|
// In this case we're escaping something that doesn't need escaping.
|
402
|
-
default:
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
409
|
+
default: {
|
410
|
+
size_t width = yp_char_width(parser, backslash + 1, end);
|
411
|
+
|
412
|
+
if (write_to_str) {
|
413
|
+
memcpy(dest + *dest_length, backslash + 1, width);
|
414
|
+
*dest_length += width;
|
408
415
|
}
|
416
|
+
|
417
|
+
return backslash + 1 + width;
|
418
|
+
}
|
409
419
|
}
|
410
420
|
}
|
411
421
|
|
@@ -438,26 +448,24 @@ unescape(char *dest, size_t *dest_length, const char *backslash, const char *end
|
|
438
448
|
// \c? or \C-? delete, ASCII 7Fh (DEL)
|
439
449
|
//
|
440
450
|
YP_EXPORTED_FUNCTION void
|
441
|
-
yp_unescape_manipulate_string(yp_parser_t *parser,
|
451
|
+
yp_unescape_manipulate_string(yp_parser_t *parser, yp_string_t *string, yp_unescape_type_t unescape_type) {
|
442
452
|
if (unescape_type == YP_UNESCAPE_NONE) {
|
443
453
|
// If we're not unescaping then we can reference the source directly.
|
444
|
-
yp_string_shared_init(string, value, value + length);
|
445
454
|
return;
|
446
455
|
}
|
447
456
|
|
448
|
-
const char *backslash = yp_memchr(
|
457
|
+
const char *backslash = yp_memchr(string->source, '\\', string->length, parser->encoding_changed, &parser->encoding);
|
449
458
|
|
450
459
|
if (backslash == NULL) {
|
451
460
|
// Here there are no escapes, so we can reference the source directly.
|
452
|
-
yp_string_shared_init(string, value, value + length);
|
453
461
|
return;
|
454
462
|
}
|
455
463
|
|
456
464
|
// Here we have found an escape character, so we need to handle all escapes
|
457
465
|
// within the string.
|
458
|
-
char *allocated = malloc(length);
|
466
|
+
char *allocated = malloc(string->length);
|
459
467
|
if (allocated == NULL) {
|
460
|
-
yp_diagnostic_list_append(error_list,
|
468
|
+
yp_diagnostic_list_append(&parser->error_list, string->source, string->source + string->length, "Failed to allocate memory for unescaping.");
|
461
469
|
return;
|
462
470
|
}
|
463
471
|
|
@@ -468,13 +476,13 @@ yp_unescape_manipulate_string(yp_parser_t *parser, const char *value, size_t len
|
|
468
476
|
// This is the current position in the source string that we're looking at.
|
469
477
|
// It's going to move along behind the backslash so that we can copy each
|
470
478
|
// segment of the string that doesn't contain an escape.
|
471
|
-
const char *cursor =
|
472
|
-
const char *end =
|
479
|
+
const char *cursor = string->source;
|
480
|
+
const char *end = string->source + string->length;
|
473
481
|
|
474
482
|
// For each escape found in the source string, we will handle it and update
|
475
483
|
// the moving cursor->backslash window.
|
476
484
|
while (backslash != NULL && backslash + 1 < end) {
|
477
|
-
assert(dest_length < length);
|
485
|
+
assert(dest_length < string->length);
|
478
486
|
|
479
487
|
// This is the size of the segment of the string from the previous escape
|
480
488
|
// or the start of the string to the current escape.
|
@@ -502,7 +510,7 @@ yp_unescape_manipulate_string(yp_parser_t *parser, const char *value, size_t len
|
|
502
510
|
// This is the only type of unescaping left. In this case we need to
|
503
511
|
// handle all of the different unescapes.
|
504
512
|
assert(unescape_type == YP_UNESCAPE_ALL);
|
505
|
-
cursor = unescape(dest, &dest_length, backslash, end,
|
513
|
+
cursor = unescape(parser, dest, &dest_length, backslash, end, YP_UNESCAPE_FLAG_NONE, true);
|
506
514
|
break;
|
507
515
|
}
|
508
516
|
|
@@ -520,36 +528,21 @@ yp_unescape_manipulate_string(yp_parser_t *parser, const char *value, size_t len
|
|
520
528
|
cursor = end;
|
521
529
|
}
|
522
530
|
|
531
|
+
// If the string was already allocated, then we need to free that memory
|
532
|
+
// here. That's because we're about to override it with the escaped string.
|
533
|
+
yp_string_free(string);
|
534
|
+
|
523
535
|
// We also need to update the length at the end. This is because every escape
|
524
536
|
// reduces the length of the final string, and we don't want garbage at the
|
525
537
|
// end.
|
526
538
|
yp_string_owned_init(string, allocated, dest_length + ((size_t) (end - cursor)));
|
527
539
|
}
|
528
540
|
|
529
|
-
YP_EXPORTED_FUNCTION bool
|
530
|
-
yp_unescape_string(const char *start, size_t length, yp_unescape_type_t unescape_type, yp_string_t *result) {
|
531
|
-
bool success;
|
532
|
-
|
533
|
-
yp_list_t error_list;
|
534
|
-
yp_list_init(&error_list);
|
535
|
-
|
536
|
-
yp_parser_t parser;
|
537
|
-
yp_parser_init(&parser, start, length, "");
|
538
|
-
|
539
|
-
yp_unescape_manipulate_string(&parser, start, length, result, unescape_type, &error_list);
|
540
|
-
success = yp_list_empty_p(&error_list);
|
541
|
-
|
542
|
-
yp_list_free(&error_list);
|
543
|
-
yp_parser_free(&parser);
|
544
|
-
|
545
|
-
return success;
|
546
|
-
}
|
547
|
-
|
548
541
|
// This function is similar to yp_unescape_manipulate_string, except it doesn't
|
549
542
|
// actually perform any string manipulations. Instead, it calculates how long
|
550
543
|
// the unescaped character is, and returns that value
|
551
|
-
|
552
|
-
yp_unescape_calculate_difference(
|
544
|
+
size_t
|
545
|
+
yp_unescape_calculate_difference(yp_parser_t *parser, const char *backslash, yp_unescape_type_t unescape_type, bool expect_single_codepoint) {
|
553
546
|
assert(unescape_type != YP_UNESCAPE_NONE);
|
554
547
|
|
555
548
|
switch (backslash[1]) {
|
@@ -557,7 +550,9 @@ yp_unescape_calculate_difference(const char *backslash, const char *end, yp_unes
|
|
557
550
|
case '\'':
|
558
551
|
return 2;
|
559
552
|
default: {
|
560
|
-
if (unescape_type == YP_UNESCAPE_MINIMAL)
|
553
|
+
if (unescape_type == YP_UNESCAPE_MINIMAL) {
|
554
|
+
return 1 + yp_char_width(parser, backslash + 1, parser->end);
|
555
|
+
}
|
561
556
|
|
562
557
|
// This is the only type of unescaping left. In this case we need to
|
563
558
|
// handle all of the different unescapes.
|
@@ -567,10 +562,27 @@ yp_unescape_calculate_difference(const char *backslash, const char *end, yp_unes
|
|
567
562
|
if (expect_single_codepoint)
|
568
563
|
flags |= YP_UNESCAPE_FLAG_EXPECT_SINGLE;
|
569
564
|
|
570
|
-
const char *cursor = unescape(NULL, 0, backslash, end,
|
565
|
+
const char *cursor = unescape(parser, NULL, 0, backslash, parser->end, flags, false);
|
571
566
|
assert(cursor > backslash);
|
572
567
|
|
573
568
|
return (size_t) (cursor - backslash);
|
574
569
|
}
|
575
570
|
}
|
576
571
|
}
|
572
|
+
|
573
|
+
// This is one of the main entry points into the extension. It accepts a source
|
574
|
+
// string, a type of unescaping, and a pointer to a result string. It returns a
|
575
|
+
// boolean indicating whether or not the unescaping was successful.
|
576
|
+
YP_EXPORTED_FUNCTION bool
|
577
|
+
yp_unescape_string(const char *start, size_t length, yp_unescape_type_t unescape_type, yp_string_t *result) {
|
578
|
+
yp_parser_t parser;
|
579
|
+
yp_parser_init(&parser, start, length, NULL);
|
580
|
+
|
581
|
+
yp_string_shared_init(result, start, start + length);
|
582
|
+
yp_unescape_manipulate_string(&parser, result, unescape_type);
|
583
|
+
|
584
|
+
bool success = yp_list_empty_p(&parser.error_list);
|
585
|
+
yp_parser_free(&parser);
|
586
|
+
|
587
|
+
return success;
|
588
|
+
}
|
data/src/util/yp_buffer.c
CHANGED
@@ -2,6 +2,12 @@
|
|
2
2
|
|
3
3
|
#define YP_BUFFER_INITIAL_SIZE 1024
|
4
4
|
|
5
|
+
// Return the size of the yp_buffer_t struct.
|
6
|
+
size_t
|
7
|
+
yp_buffer_sizeof(void) {
|
8
|
+
return sizeof(yp_buffer_t);
|
9
|
+
}
|
10
|
+
|
5
11
|
// Initialize a yp_buffer_t with its default values.
|
6
12
|
bool
|
7
13
|
yp_buffer_init(yp_buffer_t *buffer) {
|
@@ -12,6 +18,18 @@ yp_buffer_init(yp_buffer_t *buffer) {
|
|
12
18
|
return buffer->value != NULL;
|
13
19
|
}
|
14
20
|
|
21
|
+
// Return the value of the buffer.
|
22
|
+
char *
|
23
|
+
yp_buffer_value(yp_buffer_t *buffer) {
|
24
|
+
return buffer->value;
|
25
|
+
}
|
26
|
+
|
27
|
+
// Return the length of the buffer.
|
28
|
+
size_t
|
29
|
+
yp_buffer_length(yp_buffer_t *buffer) {
|
30
|
+
return buffer->length;
|
31
|
+
}
|
32
|
+
|
15
33
|
// Append the given amount of space to the buffer.
|
16
34
|
static inline void
|
17
35
|
yp_buffer_append_length(yp_buffer_t *buffer, size_t length) {
|
data/src/util/yp_list.c
CHANGED
@@ -1,28 +1,15 @@
|
|
1
1
|
#include "yarp/util/yp_list.h"
|
2
2
|
|
3
|
-
// Initializes a new list.
|
4
|
-
YP_EXPORTED_FUNCTION void
|
5
|
-
yp_list_init(yp_list_t *list) {
|
6
|
-
*list = (yp_list_t) { .head = NULL, .tail = NULL };
|
7
|
-
}
|
8
|
-
|
9
3
|
// Returns true if the given list is empty.
|
10
4
|
YP_EXPORTED_FUNCTION bool
|
11
5
|
yp_list_empty_p(yp_list_t *list) {
|
12
6
|
return list->head == NULL;
|
13
7
|
}
|
14
8
|
|
15
|
-
|
9
|
+
// Returns the size of the list.
|
10
|
+
YP_EXPORTED_FUNCTION size_t
|
16
11
|
yp_list_size(yp_list_t *list) {
|
17
|
-
|
18
|
-
uint32_t length = 0;
|
19
|
-
|
20
|
-
while (node != NULL) {
|
21
|
-
length++;
|
22
|
-
node = node->next;
|
23
|
-
}
|
24
|
-
|
25
|
-
return length;
|
12
|
+
return list->size;
|
26
13
|
}
|
27
14
|
|
28
15
|
// Append a node to the given list.
|
@@ -33,7 +20,9 @@ yp_list_append(yp_list_t *list, yp_list_node_t *node) {
|
|
33
20
|
} else {
|
34
21
|
list->tail->next = node;
|
35
22
|
}
|
23
|
+
|
36
24
|
list->tail = node;
|
25
|
+
list->size++;
|
37
26
|
}
|
38
27
|
|
39
28
|
// Deallocate the internal state of the given list.
|
@@ -47,4 +36,6 @@ yp_list_free(yp_list_t *list) {
|
|
47
36
|
free(node);
|
48
37
|
node = next;
|
49
38
|
}
|
39
|
+
|
40
|
+
list->size = 0;
|
50
41
|
}
|
data/src/util/yp_newline_list.c
CHANGED
@@ -30,6 +30,7 @@ yp_newline_list_append(yp_newline_list_t *list, const char *cursor) {
|
|
30
30
|
if (list->offsets == NULL) return false;
|
31
31
|
}
|
32
32
|
|
33
|
+
assert(*cursor == '\n');
|
33
34
|
assert(cursor >= list->start);
|
34
35
|
size_t newline_offset = (size_t) (cursor - list->start + 1);
|
35
36
|
assert(list->size == 0 || newline_offset > list->offsets[list->size - 1]);
|
@@ -38,6 +39,15 @@ yp_newline_list_append(yp_newline_list_t *list, const char *cursor) {
|
|
38
39
|
return true;
|
39
40
|
}
|
40
41
|
|
42
|
+
// Conditionally append a new offset to the newline list, if the value passed in is a newline.
|
43
|
+
bool
|
44
|
+
yp_newline_list_check_append(yp_newline_list_t *list, const char *cursor) {
|
45
|
+
if (*cursor != '\n') {
|
46
|
+
return true;
|
47
|
+
}
|
48
|
+
return yp_newline_list_append(list, cursor);
|
49
|
+
}
|
50
|
+
|
41
51
|
// Returns the line and column of the given offset, assuming we don't have any
|
42
52
|
// information about the previous index that we found.
|
43
53
|
static yp_line_column_t
|
data/src/util/yp_state_stack.c
CHANGED
@@ -1,11 +1,5 @@
|
|
1
1
|
#include "yarp/util/yp_state_stack.h"
|
2
2
|
|
3
|
-
// Initializes the state stack to an empty stack.
|
4
|
-
void
|
5
|
-
yp_state_stack_init(yp_state_stack_t *stack) {
|
6
|
-
*stack = 0;
|
7
|
-
}
|
8
|
-
|
9
3
|
// Pushes a value onto the stack.
|
10
4
|
void
|
11
5
|
yp_state_stack_push(yp_state_stack_t *stack, bool value) {
|