[ruby/yarp] 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. https://github.com/ruby/yarp/commit/7dc41ee803
This commit is contained in:
parent
ab2f638a27
commit
b6f26c2e4a
Notes:
git
2023-08-17 00:48:10 +00:00
@ -461,10 +461,8 @@ yp_unescape_manipulate_string(yp_parser_t *parser, const char *value, size_t len
|
||||
return;
|
||||
}
|
||||
|
||||
yp_string_owned_init(string, allocated, length);
|
||||
|
||||
// This is the memory address where we're putting the unescaped string.
|
||||
char *dest = string->as.owned.source;
|
||||
char *dest = allocated;
|
||||
size_t dest_length = 0;
|
||||
|
||||
// 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
|
||||
// We also need to update the length at the end. This is because every escape
|
||||
// reduces the length of the final string, and we don't want garbage at the
|
||||
// end.
|
||||
string->as.owned.length = dest_length + ((size_t) (end - cursor));
|
||||
yp_string_owned_init(string, allocated, dest_length + ((size_t) (end - cursor)));
|
||||
}
|
||||
|
||||
YP_EXPORTED_FUNCTION bool
|
||||
|
@ -13,12 +13,11 @@
|
||||
// Initialize a shared string that is based on initial input.
|
||||
void
|
||||
yp_string_shared_init(yp_string_t *string, const char *start, const char *end) {
|
||||
assert(start <= end);
|
||||
*string = (yp_string_t) {
|
||||
.type = YP_STRING_SHARED,
|
||||
.as.shared = {
|
||||
.start = start,
|
||||
.end = end
|
||||
}
|
||||
.source = (char*) start,
|
||||
.length = (size_t) (end - start)
|
||||
};
|
||||
}
|
||||
|
||||
@ -27,10 +26,8 @@ void
|
||||
yp_string_owned_init(yp_string_t *string, char *source, size_t length) {
|
||||
*string = (yp_string_t) {
|
||||
.type = YP_STRING_OWNED,
|
||||
.as.owned = {
|
||||
.source = source,
|
||||
.length = length
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -39,10 +36,8 @@ void
|
||||
yp_string_constant_init(yp_string_t *string, const char *source, size_t length) {
|
||||
*string = (yp_string_t) {
|
||||
.type = YP_STRING_CONSTANT,
|
||||
.as.constant = {
|
||||
.source = source,
|
||||
.source = (char*) source,
|
||||
.length = length
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -50,10 +45,8 @@ static void
|
||||
yp_string_mapped_init_internal(yp_string_t *string, char *source, size_t length) {
|
||||
*string = (yp_string_t) {
|
||||
.type = YP_STRING_MAPPED,
|
||||
.as.mapped = {
|
||||
.source = source,
|
||||
.length = length
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -62,7 +55,7 @@ size_t
|
||||
yp_string_memsize(const yp_string_t *string) {
|
||||
size_t size = sizeof(yp_string_t);
|
||||
if (string->type == YP_STRING_OWNED) {
|
||||
size += string->as.owned.length;
|
||||
size += string->length;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
@ -77,40 +70,32 @@ yp_string_ensure_owned(yp_string_t *string) {
|
||||
const char *source = yp_string_source(string);
|
||||
|
||||
yp_string_owned_init(string, malloc(length), length);
|
||||
memcpy(string->as.owned.source, source, length);
|
||||
memcpy(string->source, source, length);
|
||||
}
|
||||
|
||||
// Returns the length associated with the string.
|
||||
YP_EXPORTED_FUNCTION size_t
|
||||
yp_string_length(const yp_string_t *string) {
|
||||
if (string->type == YP_STRING_SHARED) {
|
||||
return (size_t) (string->as.shared.end - string->as.shared.start);
|
||||
} else {
|
||||
return string->as.owned.length;
|
||||
}
|
||||
return string->length;
|
||||
}
|
||||
|
||||
// Returns the start pointer associated with the string.
|
||||
YP_EXPORTED_FUNCTION const char *
|
||||
yp_string_source(const yp_string_t *string) {
|
||||
if (string->type == YP_STRING_SHARED) {
|
||||
return string->as.shared.start;
|
||||
} else {
|
||||
return string->as.owned.source;
|
||||
}
|
||||
return string->source;
|
||||
}
|
||||
|
||||
// Free the associated memory of the given string.
|
||||
YP_EXPORTED_FUNCTION void
|
||||
yp_string_free(yp_string_t *string) {
|
||||
if (string->type == YP_STRING_OWNED) {
|
||||
free(string->as.owned.source);
|
||||
} else if (string->type == YP_STRING_MAPPED && string->as.mapped.length) {
|
||||
void *memory = (void *) string->as.mapped.source;
|
||||
free(string->source);
|
||||
} else if (string->type == YP_STRING_MAPPED && string->length) {
|
||||
void *memory = (void *) string->source;
|
||||
#if defined(_WIN32)
|
||||
UnmapViewOfFile(memory);
|
||||
#elif defined(HAVE_MMAP)
|
||||
munmap(memory, string->as.mapped.length);
|
||||
munmap(memory, string->length);
|
||||
#else
|
||||
free(memory);
|
||||
#endif
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include "yarp/defines.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
@ -11,30 +12,12 @@
|
||||
// This struct represents a string value.
|
||||
typedef struct {
|
||||
enum { YP_STRING_SHARED, YP_STRING_OWNED, YP_STRING_CONSTANT, YP_STRING_MAPPED } type;
|
||||
|
||||
union {
|
||||
struct {
|
||||
const char *start;
|
||||
const char *end;
|
||||
} shared;
|
||||
|
||||
struct {
|
||||
char *source;
|
||||
size_t length;
|
||||
} owned;
|
||||
|
||||
struct {
|
||||
const char *source;
|
||||
size_t length;
|
||||
} constant;
|
||||
|
||||
struct {
|
||||
char *source;
|
||||
size_t length;
|
||||
} mapped;
|
||||
} as;
|
||||
} yp_string_t;
|
||||
|
||||
#define YP_EMPTY_STRING ((yp_string_t) { .type = YP_STRING_CONSTANT, .source = NULL, .length = 0 })
|
||||
|
||||
// Initialize a shared string that is based on initial input.
|
||||
void yp_string_shared_init(yp_string_t *string, const char *start, const char *end);
|
||||
|
||||
|
@ -445,7 +445,6 @@ not_provided(yp_parser_t *parser) {
|
||||
return (yp_token_t) { .type = YP_TOKEN_NOT_PROVIDED, .start = parser->start, .end = parser->start };
|
||||
}
|
||||
|
||||
#define YP_EMPTY_STRING ((yp_string_t) { .type = YP_STRING_SHARED, .as.shared.start = NULL, .as.shared.end = NULL })
|
||||
#define YP_LOCATION_NULL_VALUE(parser) ((yp_location_t) { .start = parser->start, .end = parser->start })
|
||||
#define YP_LOCATION_TOKEN_VALUE(token) ((yp_location_t) { .start = (token)->start, .end = (token)->end })
|
||||
#define YP_LOCATION_NODE_VALUE(node) ((yp_location_t) { .start = (node)->location.start, .end = (node)->location.end })
|
||||
@ -9345,8 +9344,8 @@ parse_heredoc_dedent(yp_parser_t *parser, yp_node_t *node, yp_heredoc_quote_t qu
|
||||
// Now get the bounds of the existing string. We'll use this as a
|
||||
// destination to move bytes into. We'll also use it for bounds checking
|
||||
// since we don't require that these strings be null terminated.
|
||||
size_t dest_length = string->as.owned.length;
|
||||
char *source_start = string->as.owned.source;
|
||||
size_t dest_length = yp_string_length(string);
|
||||
char *source_start = string->source;
|
||||
|
||||
const char *source_cursor = source_start;
|
||||
const char *source_end = source_cursor + dest_length;
|
||||
@ -9400,7 +9399,7 @@ parse_heredoc_dedent(yp_parser_t *parser, yp_node_t *node, yp_heredoc_quote_t qu
|
||||
dedent_next = true;
|
||||
}
|
||||
|
||||
string->as.owned.length = dest_length;
|
||||
string->length = dest_length;
|
||||
}
|
||||
}
|
||||
|
||||
@ -12450,7 +12449,7 @@ parse_expression_infix(yp_parser_t *parser, yp_node_t *node, yp_binding_power_t
|
||||
yp_string_t *name = &named_captures.strings[index];
|
||||
assert(name->type == YP_STRING_SHARED);
|
||||
|
||||
yp_parser_local_add_location(parser, name->as.shared.start, name->as.shared.end);
|
||||
yp_parser_local_add_location(parser, name->source, name->source + name->length);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user