Skip to content

Commit 7dc41ee

Browse files
committed
Use common fields for yp_string_t
* Otherwise it is undefined behavior to access the field of another `.as`. * Accessing the right `.as` field according mode would be extra overhead.
1 parent c603bba commit 7dc41ee

File tree

4 files changed

+28
-63
lines changed

4 files changed

+28
-63
lines changed

include/yarp/util/yp_string.h

Lines changed: 5 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include "yarp/defines.h"
55

6+
#include <assert.h>
67
#include <stdbool.h>
78
#include <stddef.h>
89
#include <stdlib.h>
@@ -11,30 +12,12 @@
1112
// This struct represents a string value.
1213
typedef struct {
1314
enum { YP_STRING_SHARED, YP_STRING_OWNED, YP_STRING_CONSTANT, YP_STRING_MAPPED } type;
14-
15-
union {
16-
struct {
17-
const char *start;
18-
const char *end;
19-
} shared;
20-
21-
struct {
22-
char *source;
23-
size_t length;
24-
} owned;
25-
26-
struct {
27-
const char *source;
28-
size_t length;
29-
} constant;
30-
31-
struct {
32-
char *source;
33-
size_t length;
34-
} mapped;
35-
} as;
15+
char *source;
16+
size_t length;
3617
} yp_string_t;
3718

19+
#define YP_EMPTY_STRING ((yp_string_t) { .type = YP_STRING_CONSTANT, .source = NULL, .length = 0 })
20+
3821
// Initialize a shared string that is based on initial input.
3922
void yp_string_shared_init(yp_string_t *string, const char *start, const char *end);
4023

src/unescape.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -461,10 +461,8 @@ yp_unescape_manipulate_string(yp_parser_t *parser, const char *value, size_t len
461461
return;
462462
}
463463

464-
yp_string_owned_init(string, allocated, length);
465-
466464
// This is the memory address where we're putting the unescaped string.
467-
char *dest = string->as.owned.source;
465+
char *dest = allocated;
468466
size_t dest_length = 0;
469467

470468
// This is the current position in the source string that we're looking at.
@@ -525,7 +523,7 @@ yp_unescape_manipulate_string(yp_parser_t *parser, const char *value, size_t len
525523
// We also need to update the length at the end. This is because every escape
526524
// reduces the length of the final string, and we don't want garbage at the
527525
// end.
528-
string->as.owned.length = dest_length + ((size_t) (end - cursor));
526+
yp_string_owned_init(string, allocated, dest_length + ((size_t) (end - cursor)));
529527
}
530528

531529
YP_EXPORTED_FUNCTION bool

src/util/yp_string.c

Lines changed: 17 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,11 @@
1313
// Initialize a shared string that is based on initial input.
1414
void
1515
yp_string_shared_init(yp_string_t *string, const char *start, const char *end) {
16+
assert(start <= end);
1617
*string = (yp_string_t) {
1718
.type = YP_STRING_SHARED,
18-
.as.shared = {
19-
.start = start,
20-
.end = end
21-
}
19+
.source = (char*) start,
20+
.length = (size_t) (end - start)
2221
};
2322
}
2423

@@ -27,10 +26,8 @@ void
2726
yp_string_owned_init(yp_string_t *string, char *source, size_t length) {
2827
*string = (yp_string_t) {
2928
.type = YP_STRING_OWNED,
30-
.as.owned = {
31-
.source = source,
32-
.length = length
33-
}
29+
.source = source,
30+
.length = length
3431
};
3532
}
3633

@@ -39,21 +36,17 @@ void
3936
yp_string_constant_init(yp_string_t *string, const char *source, size_t length) {
4037
*string = (yp_string_t) {
4138
.type = YP_STRING_CONSTANT,
42-
.as.constant = {
43-
.source = source,
44-
.length = length
45-
}
39+
.source = (char*) source,
40+
.length = length
4641
};
4742
}
4843

4944
static void
5045
yp_string_mapped_init_internal(yp_string_t *string, char *source, size_t length) {
5146
*string = (yp_string_t) {
5247
.type = YP_STRING_MAPPED,
53-
.as.mapped = {
54-
.source = source,
55-
.length = length
56-
}
48+
.source = source,
49+
.length = length
5750
};
5851
}
5952

@@ -62,7 +55,7 @@ size_t
6255
yp_string_memsize(const yp_string_t *string) {
6356
size_t size = sizeof(yp_string_t);
6457
if (string->type == YP_STRING_OWNED) {
65-
size += string->as.owned.length;
58+
size += string->length;
6659
}
6760
return size;
6861
}
@@ -77,40 +70,32 @@ yp_string_ensure_owned(yp_string_t *string) {
7770
const char *source = yp_string_source(string);
7871

7972
yp_string_owned_init(string, malloc(length), length);
80-
memcpy(string->as.owned.source, source, length);
73+
memcpy(string->source, source, length);
8174
}
8275

8376
// Returns the length associated with the string.
8477
YP_EXPORTED_FUNCTION size_t
8578
yp_string_length(const yp_string_t *string) {
86-
if (string->type == YP_STRING_SHARED) {
87-
return (size_t) (string->as.shared.end - string->as.shared.start);
88-
} else {
89-
return string->as.owned.length;
90-
}
79+
return string->length;
9180
}
9281

9382
// Returns the start pointer associated with the string.
9483
YP_EXPORTED_FUNCTION const char *
9584
yp_string_source(const yp_string_t *string) {
96-
if (string->type == YP_STRING_SHARED) {
97-
return string->as.shared.start;
98-
} else {
99-
return string->as.owned.source;
100-
}
85+
return string->source;
10186
}
10287

10388
// Free the associated memory of the given string.
10489
YP_EXPORTED_FUNCTION void
10590
yp_string_free(yp_string_t *string) {
10691
if (string->type == YP_STRING_OWNED) {
107-
free(string->as.owned.source);
108-
} else if (string->type == YP_STRING_MAPPED && string->as.mapped.length) {
109-
void *memory = (void *) string->as.mapped.source;
92+
free(string->source);
93+
} else if (string->type == YP_STRING_MAPPED && string->length) {
94+
void *memory = (void *) string->source;
11095
#if defined(_WIN32)
11196
UnmapViewOfFile(memory);
11297
#elif defined(HAVE_MMAP)
113-
munmap(memory, string->as.mapped.length);
98+
munmap(memory, string->length);
11499
#else
115100
free(memory);
116101
#endif

src/yarp.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,6 @@ not_provided(yp_parser_t *parser) {
445445
return (yp_token_t) { .type = YP_TOKEN_NOT_PROVIDED, .start = parser->start, .end = parser->start };
446446
}
447447

448-
#define YP_EMPTY_STRING ((yp_string_t) { .type = YP_STRING_SHARED, .as.shared.start = NULL, .as.shared.end = NULL })
449448
#define YP_LOCATION_NULL_VALUE(parser) ((yp_location_t) { .start = parser->start, .end = parser->start })
450449
#define YP_LOCATION_TOKEN_VALUE(token) ((yp_location_t) { .start = (token)->start, .end = (token)->end })
451450
#define YP_LOCATION_NODE_VALUE(node) ((yp_location_t) { .start = (node)->location.start, .end = (node)->location.end })
@@ -9385,8 +9384,8 @@ parse_heredoc_dedent(yp_parser_t *parser, yp_node_t *node, yp_heredoc_quote_t qu
93859384
// Now get the bounds of the existing string. We'll use this as a
93869385
// destination to move bytes into. We'll also use it for bounds checking
93879386
// since we don't require that these strings be null terminated.
9388-
size_t dest_length = string->as.owned.length;
9389-
char *source_start = string->as.owned.source;
9387+
size_t dest_length = yp_string_length(string);
9388+
char *source_start = string->source;
93909389

93919390
const char *source_cursor = source_start;
93929391
const char *source_end = source_cursor + dest_length;
@@ -9440,7 +9439,7 @@ parse_heredoc_dedent(yp_parser_t *parser, yp_node_t *node, yp_heredoc_quote_t qu
94409439
dedent_next = true;
94419440
}
94429441

9443-
string->as.owned.length = dest_length;
9442+
string->length = dest_length;
94449443
}
94459444
}
94469445

@@ -12491,7 +12490,7 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
1249112490
yp_string_t *name = &named_captures.strings[index];
1249212491
assert(name->type == YP_STRING_SHARED);
1249312492

12494-
yp_parser_local_add_location(parser, name->as.shared.start, name->as.shared.end);
12493+
yp_parser_local_add_location(parser, name->source, name->source + name->length);
1249512494
}
1249612495
}
1249712496

0 commit comments

Comments
 (0)