[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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
yp_string_owned_init(string, allocated, length);
|
|
||||||
|
|
||||||
// This is the memory address where we're putting the unescaped string.
|
// 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;
|
size_t dest_length = 0;
|
||||||
|
|
||||||
// This is the current position in the source string that we're looking at.
|
// 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
|
// 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
|
// reduces the length of the final string, and we don't want garbage at the
|
||||||
// end.
|
// 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
|
YP_EXPORTED_FUNCTION bool
|
||||||
|
@ -13,12 +13,11 @@
|
|||||||
// Initialize a shared string that is based on initial input.
|
// Initialize a shared string that is based on initial input.
|
||||||
void
|
void
|
||||||
yp_string_shared_init(yp_string_t *string, const char *start, const char *end) {
|
yp_string_shared_init(yp_string_t *string, const char *start, const char *end) {
|
||||||
|
assert(start <= end);
|
||||||
*string = (yp_string_t) {
|
*string = (yp_string_t) {
|
||||||
.type = YP_STRING_SHARED,
|
.type = YP_STRING_SHARED,
|
||||||
.as.shared = {
|
.source = (char*) start,
|
||||||
.start = start,
|
.length = (size_t) (end - start)
|
||||||
.end = end
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,10 +26,8 @@ void
|
|||||||
yp_string_owned_init(yp_string_t *string, char *source, size_t length) {
|
yp_string_owned_init(yp_string_t *string, char *source, size_t length) {
|
||||||
*string = (yp_string_t) {
|
*string = (yp_string_t) {
|
||||||
.type = YP_STRING_OWNED,
|
.type = YP_STRING_OWNED,
|
||||||
.as.owned = {
|
.source = source,
|
||||||
.source = source,
|
.length = length
|
||||||
.length = length
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,10 +36,8 @@ void
|
|||||||
yp_string_constant_init(yp_string_t *string, const char *source, size_t length) {
|
yp_string_constant_init(yp_string_t *string, const char *source, size_t length) {
|
||||||
*string = (yp_string_t) {
|
*string = (yp_string_t) {
|
||||||
.type = YP_STRING_CONSTANT,
|
.type = YP_STRING_CONSTANT,
|
||||||
.as.constant = {
|
.source = (char*) source,
|
||||||
.source = source,
|
.length = length
|
||||||
.length = length
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,10 +45,8 @@ static void
|
|||||||
yp_string_mapped_init_internal(yp_string_t *string, char *source, size_t length) {
|
yp_string_mapped_init_internal(yp_string_t *string, char *source, size_t length) {
|
||||||
*string = (yp_string_t) {
|
*string = (yp_string_t) {
|
||||||
.type = YP_STRING_MAPPED,
|
.type = YP_STRING_MAPPED,
|
||||||
.as.mapped = {
|
.source = source,
|
||||||
.source = source,
|
.length = length
|
||||||
.length = length
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +55,7 @@ size_t
|
|||||||
yp_string_memsize(const yp_string_t *string) {
|
yp_string_memsize(const yp_string_t *string) {
|
||||||
size_t size = sizeof(yp_string_t);
|
size_t size = sizeof(yp_string_t);
|
||||||
if (string->type == YP_STRING_OWNED) {
|
if (string->type == YP_STRING_OWNED) {
|
||||||
size += string->as.owned.length;
|
size += string->length;
|
||||||
}
|
}
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
@ -77,40 +70,32 @@ yp_string_ensure_owned(yp_string_t *string) {
|
|||||||
const char *source = yp_string_source(string);
|
const char *source = yp_string_source(string);
|
||||||
|
|
||||||
yp_string_owned_init(string, malloc(length), length);
|
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.
|
// Returns the length associated with the string.
|
||||||
YP_EXPORTED_FUNCTION size_t
|
YP_EXPORTED_FUNCTION size_t
|
||||||
yp_string_length(const yp_string_t *string) {
|
yp_string_length(const yp_string_t *string) {
|
||||||
if (string->type == YP_STRING_SHARED) {
|
return string->length;
|
||||||
return (size_t) (string->as.shared.end - string->as.shared.start);
|
|
||||||
} else {
|
|
||||||
return string->as.owned.length;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the start pointer associated with the string.
|
// Returns the start pointer associated with the string.
|
||||||
YP_EXPORTED_FUNCTION const char *
|
YP_EXPORTED_FUNCTION const char *
|
||||||
yp_string_source(const yp_string_t *string) {
|
yp_string_source(const yp_string_t *string) {
|
||||||
if (string->type == YP_STRING_SHARED) {
|
return string->source;
|
||||||
return string->as.shared.start;
|
|
||||||
} else {
|
|
||||||
return string->as.owned.source;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free the associated memory of the given string.
|
// Free the associated memory of the given string.
|
||||||
YP_EXPORTED_FUNCTION void
|
YP_EXPORTED_FUNCTION void
|
||||||
yp_string_free(yp_string_t *string) {
|
yp_string_free(yp_string_t *string) {
|
||||||
if (string->type == YP_STRING_OWNED) {
|
if (string->type == YP_STRING_OWNED) {
|
||||||
free(string->as.owned.source);
|
free(string->source);
|
||||||
} else if (string->type == YP_STRING_MAPPED && string->as.mapped.length) {
|
} else if (string->type == YP_STRING_MAPPED && string->length) {
|
||||||
void *memory = (void *) string->as.mapped.source;
|
void *memory = (void *) string->source;
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
UnmapViewOfFile(memory);
|
UnmapViewOfFile(memory);
|
||||||
#elif defined(HAVE_MMAP)
|
#elif defined(HAVE_MMAP)
|
||||||
munmap(memory, string->as.mapped.length);
|
munmap(memory, string->length);
|
||||||
#else
|
#else
|
||||||
free(memory);
|
free(memory);
|
||||||
#endif
|
#endif
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "yarp/defines.h"
|
#include "yarp/defines.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -11,30 +12,12 @@
|
|||||||
// This struct represents a string value.
|
// This struct represents a string value.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
enum { YP_STRING_SHARED, YP_STRING_OWNED, YP_STRING_CONSTANT, YP_STRING_MAPPED } type;
|
enum { YP_STRING_SHARED, YP_STRING_OWNED, YP_STRING_CONSTANT, YP_STRING_MAPPED } type;
|
||||||
|
char *source;
|
||||||
union {
|
size_t length;
|
||||||
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;
|
} 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.
|
// 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);
|
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 };
|
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_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_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 })
|
#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
|
// 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
|
// destination to move bytes into. We'll also use it for bounds checking
|
||||||
// since we don't require that these strings be null terminated.
|
// since we don't require that these strings be null terminated.
|
||||||
size_t dest_length = string->as.owned.length;
|
size_t dest_length = yp_string_length(string);
|
||||||
char *source_start = string->as.owned.source;
|
char *source_start = string->source;
|
||||||
|
|
||||||
const char *source_cursor = source_start;
|
const char *source_cursor = source_start;
|
||||||
const char *source_end = source_cursor + dest_length;
|
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;
|
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];
|
yp_string_t *name = &named_captures.strings[index];
|
||||||
assert(name->type == YP_STRING_SHARED);
|
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