rbs 3.9.5 → 3.10.0.pre.1
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/.clang-format +74 -0
- data/.clangd +2 -0
- data/.github/workflows/c-check.yml +54 -0
- data/.github/workflows/comments.yml +3 -3
- data/.github/workflows/ruby.yml +34 -19
- data/.github/workflows/typecheck.yml +1 -1
- data/.github/workflows/windows.yml +1 -1
- data/.gitignore +4 -0
- data/README.md +38 -1
- data/Rakefile +152 -23
- data/config.yml +190 -62
- data/core/array.rbs +44 -43
- data/core/dir.rbs +2 -2
- data/core/encoding.rbs +3 -2
- data/core/enumerable.rbs +89 -2
- data/core/errno.rbs +8 -0
- data/core/errors.rbs +28 -1
- data/core/exception.rbs +2 -2
- data/core/fiber.rbs +3 -3
- data/core/file.rbs +26 -11
- data/core/float.rbs +1 -1
- data/core/gc.rbs +422 -281
- data/core/hash.rbs +1024 -727
- data/core/io/wait.rbs +11 -33
- data/core/io.rbs +6 -4
- data/core/kernel.rbs +49 -43
- data/core/marshal.rbs +1 -1
- data/core/match_data.rbs +1 -1
- data/core/math.rbs +42 -3
- data/core/method.rbs +14 -6
- data/core/module.rbs +71 -11
- data/core/nil_class.rbs +3 -3
- data/core/numeric.rbs +8 -8
- data/core/object.rbs +3 -3
- data/core/object_space.rbs +13 -0
- data/{stdlib/pathname/0 → core}/pathname.rbs +253 -352
- data/core/proc.rbs +15 -8
- data/core/process.rbs +2 -2
- data/core/ractor.rbs +278 -437
- data/core/range.rbs +6 -7
- data/core/rbs/unnamed/argf.rbs +1 -1
- data/core/rbs/unnamed/env_class.rbs +1 -1
- data/core/rbs/unnamed/random.rbs +4 -2
- data/core/regexp.rbs +22 -17
- data/core/ruby_vm.rbs +6 -4
- data/core/rubygems/errors.rbs +3 -70
- data/core/rubygems/rubygems.rbs +11 -79
- data/core/set.rbs +439 -332
- data/core/string.rbs +2897 -1117
- data/core/struct.rbs +1 -1
- data/core/symbol.rbs +4 -4
- data/core/thread.rbs +83 -20
- data/core/time.rbs +35 -9
- data/core/unbound_method.rbs +14 -6
- data/docs/aliases.md +79 -0
- data/docs/collection.md +2 -2
- data/docs/gem.md +0 -1
- data/docs/sigs.md +3 -3
- data/ext/rbs_extension/ast_translation.c +1016 -0
- data/ext/rbs_extension/ast_translation.h +37 -0
- data/ext/rbs_extension/class_constants.c +157 -0
- data/{include/rbs/constants.h → ext/rbs_extension/class_constants.h} +7 -1
- data/ext/rbs_extension/compat.h +10 -0
- data/ext/rbs_extension/extconf.rb +25 -1
- data/ext/rbs_extension/legacy_location.c +317 -0
- data/ext/rbs_extension/legacy_location.h +45 -0
- data/ext/rbs_extension/main.c +365 -14
- data/ext/rbs_extension/rbs_extension.h +6 -21
- data/ext/rbs_extension/rbs_string_bridging.c +9 -0
- data/ext/rbs_extension/rbs_string_bridging.h +24 -0
- data/include/rbs/ast.h +687 -0
- data/include/rbs/defines.h +86 -0
- data/include/rbs/lexer.h +199 -0
- data/include/rbs/location.h +59 -0
- data/include/rbs/parser.h +135 -0
- data/include/rbs/string.h +49 -0
- data/include/rbs/util/rbs_allocator.h +59 -0
- data/include/rbs/util/rbs_assert.h +20 -0
- data/include/rbs/util/rbs_buffer.h +83 -0
- data/include/rbs/util/rbs_constant_pool.h +6 -67
- data/include/rbs/util/rbs_encoding.h +282 -0
- data/include/rbs/util/rbs_unescape.h +23 -0
- data/include/rbs.h +1 -2
- data/lib/rbs/annotate/formatter.rb +3 -13
- data/lib/rbs/annotate/rdoc_annotator.rb +3 -1
- data/lib/rbs/annotate/rdoc_source.rb +1 -1
- data/lib/rbs/cli/validate.rb +2 -2
- data/lib/rbs/cli.rb +1 -1
- data/lib/rbs/collection/config/lockfile_generator.rb +1 -0
- data/lib/rbs/definition_builder/ancestor_builder.rb +5 -5
- data/lib/rbs/environment.rb +64 -59
- data/lib/rbs/environment_loader.rb +1 -1
- data/lib/rbs/errors.rb +1 -1
- data/lib/rbs/parser_aux.rb +5 -0
- data/lib/rbs/resolver/constant_resolver.rb +2 -2
- data/lib/rbs/resolver/type_name_resolver.rb +124 -38
- data/lib/rbs/test/type_check.rb +13 -0
- data/lib/rbs/types.rb +3 -1
- data/lib/rbs/version.rb +1 -1
- data/lib/rbs.rb +1 -1
- data/lib/rdoc/discover.rb +1 -1
- data/lib/rdoc_plugin/parser.rb +3 -3
- data/sig/annotate/formatter.rbs +2 -2
- data/sig/annotate/rdoc_annotater.rbs +1 -1
- data/sig/environment.rbs +57 -6
- data/sig/manifest.yaml +0 -1
- data/sig/parser.rbs +20 -0
- data/sig/resolver/type_name_resolver.rbs +38 -7
- data/sig/types.rbs +4 -1
- data/src/ast.c +1256 -0
- data/src/lexer.c +2956 -0
- data/src/lexer.re +147 -0
- data/src/lexstate.c +205 -0
- data/src/location.c +71 -0
- data/src/parser.c +3495 -0
- data/src/string.c +90 -0
- data/src/util/rbs_allocator.c +152 -0
- data/src/util/rbs_assert.c +21 -0
- data/src/util/rbs_buffer.c +54 -0
- data/src/util/rbs_constant_pool.c +16 -86
- data/src/util/rbs_encoding.c +21308 -0
- data/src/util/rbs_unescape.c +131 -0
- data/stdlib/cgi/0/core.rbs +2 -396
- data/stdlib/cgi/0/manifest.yaml +1 -0
- data/stdlib/cgi-escape/0/escape.rbs +153 -0
- data/stdlib/coverage/0/coverage.rbs +3 -1
- data/stdlib/delegate/0/delegator.rbs +10 -7
- data/stdlib/erb/0/erb.rbs +737 -347
- data/stdlib/fileutils/0/fileutils.rbs +18 -13
- data/stdlib/forwardable/0/forwardable.rbs +3 -0
- data/stdlib/json/0/json.rbs +67 -48
- data/stdlib/net-http/0/net-http.rbs +3 -0
- data/stdlib/objspace/0/objspace.rbs +8 -3
- data/stdlib/open-uri/0/open-uri.rbs +40 -0
- data/stdlib/openssl/0/openssl.rbs +182 -149
- data/stdlib/optparse/0/optparse.rbs +3 -3
- data/stdlib/rdoc/0/code_object.rbs +2 -2
- data/stdlib/rdoc/0/comment.rbs +2 -0
- data/stdlib/rdoc/0/options.rbs +76 -0
- data/stdlib/rdoc/0/rdoc.rbs +7 -5
- data/stdlib/rdoc/0/store.rbs +1 -1
- data/stdlib/resolv/0/resolv.rbs +25 -68
- data/stdlib/ripper/0/ripper.rbs +5 -2
- data/stdlib/singleton/0/singleton.rbs +3 -0
- data/stdlib/socket/0/socket.rbs +13 -1
- data/stdlib/socket/0/tcp_socket.rbs +10 -2
- data/stdlib/stringio/0/stringio.rbs +412 -80
- data/stdlib/strscan/0/string_scanner.rbs +31 -31
- data/stdlib/tempfile/0/tempfile.rbs +1 -1
- data/stdlib/tsort/0/cyclic.rbs +3 -0
- data/stdlib/uri/0/common.rbs +11 -2
- data/stdlib/uri/0/file.rbs +1 -1
- data/stdlib/uri/0/generic.rbs +16 -15
- data/stdlib/uri/0/rfc2396_parser.rbs +6 -7
- data/stdlib/zlib/0/zstream.rbs +1 -0
- metadata +41 -18
- data/ext/rbs_extension/lexer.c +0 -2728
- data/ext/rbs_extension/lexer.h +0 -179
- data/ext/rbs_extension/lexer.re +0 -147
- data/ext/rbs_extension/lexstate.c +0 -175
- data/ext/rbs_extension/location.c +0 -325
- data/ext/rbs_extension/location.h +0 -85
- data/ext/rbs_extension/parser.c +0 -2982
- data/ext/rbs_extension/parser.h +0 -18
- data/ext/rbs_extension/parserstate.c +0 -411
- data/ext/rbs_extension/parserstate.h +0 -163
- data/ext/rbs_extension/unescape.c +0 -32
- data/include/rbs/ruby_objs.h +0 -72
- data/src/constants.c +0 -153
- data/src/ruby_objs.c +0 -799
data/src/string.c
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#include "rbs/string.h"
|
|
2
|
+
#include "rbs/defines.h"
|
|
3
|
+
|
|
4
|
+
#include <stdlib.h>
|
|
5
|
+
#include <string.h>
|
|
6
|
+
#include <stdio.h>
|
|
7
|
+
#include <ctype.h>
|
|
8
|
+
|
|
9
|
+
unsigned int rbs_utf8_string_to_codepoint(const rbs_string_t string) {
|
|
10
|
+
unsigned int codepoint = 0;
|
|
11
|
+
int remaining_bytes = 0;
|
|
12
|
+
|
|
13
|
+
const char *s = string.start;
|
|
14
|
+
const char *end = string.end;
|
|
15
|
+
|
|
16
|
+
if (s >= end) return 0; // End of string
|
|
17
|
+
|
|
18
|
+
if (RBS_LIKELY((*s & 0x80) == 0)) {
|
|
19
|
+
// Single byte character (0xxxxxxx)
|
|
20
|
+
return *s;
|
|
21
|
+
} else if ((*s & 0xE0) == 0xC0) {
|
|
22
|
+
// Two byte character (110xxxxx 10xxxxxx)
|
|
23
|
+
codepoint = *s & 0x1F;
|
|
24
|
+
remaining_bytes = 1;
|
|
25
|
+
} else if ((*s & 0xF0) == 0xE0) {
|
|
26
|
+
// Three byte character (1110xxxx 10xxxxxx 10xxxxxx)
|
|
27
|
+
codepoint = *s & 0x0F;
|
|
28
|
+
remaining_bytes = 2;
|
|
29
|
+
} else if ((*s & 0xF8) == 0xF0) {
|
|
30
|
+
// Four byte character (11110xxx 10xxxxxx 10xxxxxx 10xxxxxx)
|
|
31
|
+
codepoint = *s & 0x07;
|
|
32
|
+
remaining_bytes = 3;
|
|
33
|
+
} else {
|
|
34
|
+
// Invalid UTF-8 sequence
|
|
35
|
+
return 0xFFFD; // Unicode replacement character
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
s++;
|
|
39
|
+
while (remaining_bytes > 0 && s < end) {
|
|
40
|
+
if ((*s & 0xC0) != 0x80) {
|
|
41
|
+
// Invalid continuation byte
|
|
42
|
+
return 0xFFFD;
|
|
43
|
+
}
|
|
44
|
+
codepoint = (codepoint << 6) | (*s & 0x3F);
|
|
45
|
+
s++;
|
|
46
|
+
remaining_bytes--;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (remaining_bytes > 0) {
|
|
50
|
+
// Incomplete sequence
|
|
51
|
+
return 0xFFFD;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return codepoint;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
rbs_string_t rbs_string_new(const char *start, const char *end) {
|
|
58
|
+
return (rbs_string_t) {
|
|
59
|
+
.start = start,
|
|
60
|
+
.end = end,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
rbs_string_t rbs_string_strip_whitespace(rbs_string_t *self) {
|
|
65
|
+
const char *new_start = self->start;
|
|
66
|
+
while (isspace(*new_start) && new_start < self->end) {
|
|
67
|
+
new_start++;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (new_start == self->end) { // Handle empty string case
|
|
71
|
+
return rbs_string_new(new_start, new_start);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const char *new_end = self->end - 1;
|
|
75
|
+
while (isspace(*new_end) && new_start < new_end) {
|
|
76
|
+
new_end--;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return rbs_string_new(new_start, new_end + 1);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
size_t rbs_string_len(const rbs_string_t self) {
|
|
83
|
+
return self.end - self.start;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
bool rbs_string_equal(const rbs_string_t lhs, const rbs_string_t rhs) {
|
|
87
|
+
if (lhs.start == rhs.start && lhs.end == rhs.end) return true;
|
|
88
|
+
if (rbs_string_len(lhs) != rbs_string_len(rhs)) return false;
|
|
89
|
+
return strncmp(lhs.start, rhs.start, rbs_string_len(lhs)) == 0;
|
|
90
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file rbs_allocator.c
|
|
3
|
+
*
|
|
4
|
+
* A simple arena allocator that can be freed all at once.
|
|
5
|
+
*
|
|
6
|
+
* This allocator maintains a linked list of pages, which come in two flavours:
|
|
7
|
+
* 1. Small allocation pages, which are the same size as the system page size.
|
|
8
|
+
* 2. Large allocation pages, which are the exact size requested, for sizes greater than the small page size.
|
|
9
|
+
*
|
|
10
|
+
* Small allocations always fit into the unused space at the end of the "head" page. If there isn't enough room, a new
|
|
11
|
+
* page is allocated, and the small allocation is placed at its start. This approach wastes that unused slack at the
|
|
12
|
+
* end of the previous page, but it means that allocations are instant and never scan the linked list to find a gap.
|
|
13
|
+
*
|
|
14
|
+
* This allocator doesn't support freeing individual allocations. Only the whole arena can be freed at once at the end.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
#include "rbs/util/rbs_allocator.h"
|
|
18
|
+
#include "rbs/util/rbs_assert.h"
|
|
19
|
+
|
|
20
|
+
#include <stdlib.h>
|
|
21
|
+
#include <string.h> // for memset()
|
|
22
|
+
#include <stdint.h>
|
|
23
|
+
#include <inttypes.h>
|
|
24
|
+
|
|
25
|
+
#ifdef _WIN32
|
|
26
|
+
#include <windows.h>
|
|
27
|
+
#else
|
|
28
|
+
#include <unistd.h>
|
|
29
|
+
#include <sys/types.h>
|
|
30
|
+
#include <sys/mman.h>
|
|
31
|
+
#include <fcntl.h>
|
|
32
|
+
#endif
|
|
33
|
+
|
|
34
|
+
typedef struct rbs_allocator_page {
|
|
35
|
+
// The previously allocated page, or NULL if this is the first page.
|
|
36
|
+
struct rbs_allocator_page *next;
|
|
37
|
+
|
|
38
|
+
// The size of the payload in bytes.
|
|
39
|
+
size_t size;
|
|
40
|
+
|
|
41
|
+
// The offset of the next available byte.
|
|
42
|
+
size_t used;
|
|
43
|
+
} rbs_allocator_page_t;
|
|
44
|
+
|
|
45
|
+
static size_t get_system_page_size(void) {
|
|
46
|
+
#ifdef _WIN32
|
|
47
|
+
SYSTEM_INFO si;
|
|
48
|
+
GetSystemInfo(&si);
|
|
49
|
+
return si.dwPageSize;
|
|
50
|
+
#else
|
|
51
|
+
long sz = sysconf(_SC_PAGESIZE);
|
|
52
|
+
if (sz == -1) return 4096; // Fallback to the common 4KB page size
|
|
53
|
+
return (size_t) sz;
|
|
54
|
+
#endif
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
static rbs_allocator_page_t *rbs_allocator_page_new(size_t payload_size) {
|
|
58
|
+
const size_t page_header_size = sizeof(rbs_allocator_page_t);
|
|
59
|
+
|
|
60
|
+
rbs_allocator_page_t *page = malloc(page_header_size + payload_size);
|
|
61
|
+
page->size = payload_size;
|
|
62
|
+
page->used = 0;
|
|
63
|
+
|
|
64
|
+
return page;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
rbs_allocator_t *rbs_allocator_init(void) {
|
|
68
|
+
rbs_allocator_t *allocator = malloc(sizeof(rbs_allocator_t));
|
|
69
|
+
|
|
70
|
+
const size_t system_page_size = get_system_page_size();
|
|
71
|
+
|
|
72
|
+
allocator->default_page_payload_size = system_page_size - sizeof(rbs_allocator_page_t);
|
|
73
|
+
|
|
74
|
+
allocator->page = rbs_allocator_page_new(allocator->default_page_payload_size);
|
|
75
|
+
allocator->page->next = NULL;
|
|
76
|
+
|
|
77
|
+
return allocator;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
void rbs_allocator_free(rbs_allocator_t *allocator) {
|
|
81
|
+
rbs_allocator_page_t *page = allocator->page;
|
|
82
|
+
while (page) {
|
|
83
|
+
rbs_allocator_page_t *next = page->next;
|
|
84
|
+
free(page);
|
|
85
|
+
page = next;
|
|
86
|
+
}
|
|
87
|
+
free(allocator);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Allocates `new_size` bytes from `allocator`, aligned to an `alignment`-byte boundary.
|
|
91
|
+
// Copies `old_size` bytes from `ptr` to the new allocation.
|
|
92
|
+
// It always reallocates the memory in new space and thus wastes the old space.
|
|
93
|
+
void *rbs_allocator_realloc_impl(rbs_allocator_t *allocator, void *ptr, size_t old_size, size_t new_size, size_t alignment) {
|
|
94
|
+
void *p = rbs_allocator_malloc_impl(allocator, new_size, alignment);
|
|
95
|
+
memcpy(p, ptr, old_size);
|
|
96
|
+
return p;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Allocates `size` bytes from `allocator`, aligned to an `alignment`-byte boundary.
|
|
100
|
+
void *rbs_allocator_malloc_impl(rbs_allocator_t *allocator, size_t size, size_t alignment) {
|
|
101
|
+
RBS_ASSERT(size % alignment == 0, "size must be a multiple of the alignment. size: %zu, alignment: %zu", size, alignment);
|
|
102
|
+
|
|
103
|
+
if (allocator->default_page_payload_size < size) { // Big allocation, give it its own page.
|
|
104
|
+
rbs_allocator_page_t *new_page = rbs_allocator_page_new(size);
|
|
105
|
+
|
|
106
|
+
// This simple allocator can only put small allocations into the head page.
|
|
107
|
+
// Naively prepending this large allocation page to the head of the allocator before the previous head page
|
|
108
|
+
// would waste the remaining space in the head page.
|
|
109
|
+
// So instead, we'll splice in the large page *after* the head page.
|
|
110
|
+
//
|
|
111
|
+
// +-------+ +-----------+ +-----------+
|
|
112
|
+
// | arena | | head page | | new_page |
|
|
113
|
+
// |-------| |-----------+ |-----------+
|
|
114
|
+
// | *page |--->| size | +--->| size | +---> ... previous tail
|
|
115
|
+
// +-------+ | offset | | | offset | |
|
|
116
|
+
// | *next ----+---+ | *next ----+---+
|
|
117
|
+
// | ... | | ... |
|
|
118
|
+
// +-----------+ +-----------+
|
|
119
|
+
//
|
|
120
|
+
new_page->next = allocator->page->next;
|
|
121
|
+
allocator->page->next = new_page;
|
|
122
|
+
|
|
123
|
+
uintptr_t pointer = (uintptr_t) new_page + sizeof(rbs_allocator_page_t);
|
|
124
|
+
return (void *) pointer;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
rbs_allocator_page_t *page = allocator->page;
|
|
128
|
+
if (page->used + size > page->size) {
|
|
129
|
+
// Not enough space. Allocate a new small page and prepend it to the allocator's linked list.
|
|
130
|
+
rbs_allocator_page_t *new_page = rbs_allocator_page_new(allocator->default_page_payload_size);
|
|
131
|
+
new_page->next = allocator->page;
|
|
132
|
+
allocator->page = new_page;
|
|
133
|
+
page = new_page;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
uintptr_t pointer = (uintptr_t) page + sizeof(rbs_allocator_page_t) + page->used;
|
|
137
|
+
page->used += size;
|
|
138
|
+
return (void *) pointer;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Note: This will eagerly fill with zeroes, unlike `calloc()` which can map a page in a page to be zeroed lazily.
|
|
142
|
+
// It's assumed that callers to this function will immediately write to the allocated memory, anyway.
|
|
143
|
+
void *rbs_allocator_calloc_impl(rbs_allocator_t *allocator, size_t count, size_t size, size_t alignment) {
|
|
144
|
+
void *p = rbs_allocator_malloc_many_impl(allocator, count, size, alignment);
|
|
145
|
+
memset(p, 0, count * size);
|
|
146
|
+
return p;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Similar to `rbs_allocator_malloc_impl()`, but allocates `count` instances of `size` bytes, aligned to an `alignment`-byte boundary.
|
|
150
|
+
void *rbs_allocator_malloc_many_impl(rbs_allocator_t *allocator, size_t count, size_t size, size_t alignment) {
|
|
151
|
+
return rbs_allocator_malloc_impl(allocator, count * size, alignment);
|
|
152
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#include "rbs/util/rbs_assert.h"
|
|
2
|
+
|
|
3
|
+
#include <stdarg.h>
|
|
4
|
+
#include <stdio.h>
|
|
5
|
+
#include <stdlib.h>
|
|
6
|
+
#include <stdbool.h>
|
|
7
|
+
|
|
8
|
+
void rbs_assert_impl(bool condition, const char *fmt, ...) {
|
|
9
|
+
printf("RBS_ASSERT called\n");
|
|
10
|
+
|
|
11
|
+
if (condition) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
va_list args;
|
|
16
|
+
va_start(args, fmt);
|
|
17
|
+
vfprintf(stderr, fmt, args);
|
|
18
|
+
va_end(args);
|
|
19
|
+
fprintf(stderr, "\n");
|
|
20
|
+
exit(EXIT_FAILURE);
|
|
21
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#include "rbs/util/rbs_buffer.h"
|
|
2
|
+
#include "rbs/util/rbs_assert.h"
|
|
3
|
+
|
|
4
|
+
bool rbs_buffer_init(rbs_allocator_t *allocator, rbs_buffer_t *buffer) {
|
|
5
|
+
size_t capacity = RBS_BUFFER_DEFAULT_CAPACITY;
|
|
6
|
+
|
|
7
|
+
buffer->length = 0;
|
|
8
|
+
buffer->capacity = capacity;
|
|
9
|
+
|
|
10
|
+
buffer->value = rbs_allocator_calloc(allocator, capacity, char);
|
|
11
|
+
return buffer->value != NULL;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
char *rbs_buffer_value(const rbs_buffer_t *buffer) {
|
|
15
|
+
return buffer->value;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
size_t rbs_buffer_length(const rbs_buffer_t *buffer) {
|
|
19
|
+
return buffer->length;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
void rbs_buffer_append_string(rbs_allocator_t *allocator, rbs_buffer_t *buffer, const char *source, size_t length) {
|
|
23
|
+
size_t next_length = buffer->length + length;
|
|
24
|
+
|
|
25
|
+
if (next_length > buffer->capacity) {
|
|
26
|
+
size_t old_capacity = buffer->capacity;
|
|
27
|
+
|
|
28
|
+
RBS_ASSERT(old_capacity != 0, "Precondition: capacity must be at least 1. Got %zu", old_capacity);
|
|
29
|
+
|
|
30
|
+
size_t new_capacity = buffer->capacity * 2;
|
|
31
|
+
|
|
32
|
+
while (next_length > new_capacity) {
|
|
33
|
+
new_capacity *= 2;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
char *new_value = rbs_allocator_realloc(allocator, buffer->value, old_capacity, new_capacity, char);
|
|
37
|
+
RBS_ASSERT(new_value != NULL, "Failed to append to buffer. Old capacity: %zu, new capacity: %zu", old_capacity, new_capacity);
|
|
38
|
+
|
|
39
|
+
buffer->value = new_value;
|
|
40
|
+
buffer->capacity = new_capacity;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
size_t cursor = buffer->length;
|
|
44
|
+
buffer->length = next_length;
|
|
45
|
+
memcpy(buffer->value + cursor, source, length);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
void rbs_buffer_append_cstr(rbs_allocator_t *allocator, rbs_buffer_t *buffer, const char *value) {
|
|
49
|
+
rbs_buffer_append_string(allocator, buffer, value, strlen(value));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
rbs_string_t rbs_buffer_to_string(rbs_buffer_t *buffer) {
|
|
53
|
+
return rbs_string_new(buffer->value, buffer->value + buffer->length);
|
|
54
|
+
}
|
|
@@ -1,75 +1,5 @@
|
|
|
1
1
|
#include "rbs/util/rbs_constant_pool.h"
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Initialize a list of constant ids.
|
|
5
|
-
*/
|
|
6
|
-
void
|
|
7
|
-
rbs_constant_id_list_init(rbs_constant_id_list_t *list) {
|
|
8
|
-
list->ids = NULL;
|
|
9
|
-
list->size = 0;
|
|
10
|
-
list->capacity = 0;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Initialize a list of constant ids with a given capacity.
|
|
15
|
-
*/
|
|
16
|
-
void
|
|
17
|
-
rbs_constant_id_list_init_capacity(rbs_constant_id_list_t *list, size_t capacity) {
|
|
18
|
-
list->ids = calloc(capacity, sizeof(rbs_constant_id_t));
|
|
19
|
-
if (list->ids == NULL) abort();
|
|
20
|
-
|
|
21
|
-
list->size = 0;
|
|
22
|
-
list->capacity = capacity;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Append a constant id to a list of constant ids. Returns false if any
|
|
27
|
-
* potential reallocations fail.
|
|
28
|
-
*/
|
|
29
|
-
bool
|
|
30
|
-
rbs_constant_id_list_append(rbs_constant_id_list_t *list, rbs_constant_id_t id) {
|
|
31
|
-
if (list->size >= list->capacity) {
|
|
32
|
-
list->capacity = list->capacity == 0 ? 8 : list->capacity * 2;
|
|
33
|
-
list->ids = (rbs_constant_id_t *) realloc(list->ids, sizeof(rbs_constant_id_t) * list->capacity);
|
|
34
|
-
if (list->ids == NULL) return false;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
list->ids[list->size++] = id;
|
|
38
|
-
return true;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Insert a constant id into a list of constant ids at the specified index.
|
|
43
|
-
*/
|
|
44
|
-
void
|
|
45
|
-
rbs_constant_id_list_insert(rbs_constant_id_list_t *list, size_t index, rbs_constant_id_t id) {
|
|
46
|
-
assert(index < list->capacity);
|
|
47
|
-
assert(list->ids[index] == RBS_CONSTANT_ID_UNSET);
|
|
48
|
-
|
|
49
|
-
list->ids[index] = id;
|
|
50
|
-
list->size++;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Checks if the current constant id list includes the given constant id.
|
|
55
|
-
*/
|
|
56
|
-
bool
|
|
57
|
-
rbs_constant_id_list_includes(rbs_constant_id_list_t *list, rbs_constant_id_t id) {
|
|
58
|
-
for (size_t index = 0; index < list->size; index++) {
|
|
59
|
-
if (list->ids[index] == id) return true;
|
|
60
|
-
}
|
|
61
|
-
return false;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Free the memory associated with a list of constant ids.
|
|
66
|
-
*/
|
|
67
|
-
void
|
|
68
|
-
rbs_constant_id_list_free(rbs_constant_id_list_t *list) {
|
|
69
|
-
if (list->ids != NULL) {
|
|
70
|
-
free(list->ids);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
2
|
+
#include "rbs/util/rbs_assert.h"
|
|
73
3
|
|
|
74
4
|
/**
|
|
75
5
|
* A relatively simple hash function (djb2) that is used to hash strings. We are
|
|
@@ -107,19 +37,16 @@ next_power_of_two(uint32_t v) {
|
|
|
107
37
|
return v;
|
|
108
38
|
}
|
|
109
39
|
|
|
110
|
-
|
|
111
|
-
static bool
|
|
112
|
-
is_power_of_two(uint32_t size) {
|
|
40
|
+
RBS_ATTRIBUTE_UNUSED static bool is_power_of_two(uint32_t size) {
|
|
113
41
|
return (size & (size - 1)) == 0;
|
|
114
42
|
}
|
|
115
|
-
#endif
|
|
116
43
|
|
|
117
44
|
/**
|
|
118
45
|
* Resize a constant pool to a given capacity.
|
|
119
46
|
*/
|
|
120
47
|
static inline bool
|
|
121
48
|
rbs_constant_pool_resize(rbs_constant_pool_t *pool) {
|
|
122
|
-
|
|
49
|
+
RBS_ASSERT(is_power_of_two(pool->capacity), "pool->capacity is not a power of two. Got %i", pool->capacity);
|
|
123
50
|
|
|
124
51
|
uint32_t next_capacity = pool->capacity * 2;
|
|
125
52
|
if (next_capacity < pool->capacity) return false;
|
|
@@ -131,7 +58,7 @@ rbs_constant_pool_resize(rbs_constant_pool_t *pool) {
|
|
|
131
58
|
if (next == NULL) return false;
|
|
132
59
|
|
|
133
60
|
rbs_constant_pool_bucket_t *next_buckets = next;
|
|
134
|
-
rbs_constant_t *next_constants = (void *)(((char *) next) + next_capacity * sizeof(rbs_constant_pool_bucket_t));
|
|
61
|
+
rbs_constant_t *next_constants = (void *) (((char *) next) + next_capacity * sizeof(rbs_constant_pool_bucket_t));
|
|
135
62
|
|
|
136
63
|
// For each bucket in the current constant pool, find the index in the
|
|
137
64
|
// next constant pool, and insert it.
|
|
@@ -175,8 +102,7 @@ rbs_constant_pool_t *RBS_GLOBAL_CONSTANT_POOL = &RBS_GLOBAL_CONSTANT_POOL_STORAG
|
|
|
175
102
|
/**
|
|
176
103
|
* Initialize a new constant pool with a given capacity.
|
|
177
104
|
*/
|
|
178
|
-
bool
|
|
179
|
-
rbs_constant_pool_init(rbs_constant_pool_t *pool, uint32_t capacity) {
|
|
105
|
+
bool rbs_constant_pool_init(rbs_constant_pool_t *pool, uint32_t capacity) {
|
|
180
106
|
const uint32_t maximum = (~((uint32_t) 0));
|
|
181
107
|
if (capacity >= ((maximum / 2) + 1)) return false;
|
|
182
108
|
|
|
@@ -186,7 +112,7 @@ rbs_constant_pool_init(rbs_constant_pool_t *pool, uint32_t capacity) {
|
|
|
186
112
|
if (memory == NULL) return false;
|
|
187
113
|
|
|
188
114
|
pool->buckets = memory;
|
|
189
|
-
pool->constants = (void *)(((char *)memory) + capacity * sizeof(rbs_constant_pool_bucket_t));
|
|
115
|
+
pool->constants = (void *) (((char *) memory) + capacity * sizeof(rbs_constant_pool_bucket_t));
|
|
190
116
|
pool->size = 0;
|
|
191
117
|
pool->capacity = capacity;
|
|
192
118
|
return true;
|
|
@@ -197,7 +123,7 @@ rbs_constant_pool_init(rbs_constant_pool_t *pool, uint32_t capacity) {
|
|
|
197
123
|
*/
|
|
198
124
|
rbs_constant_t *
|
|
199
125
|
rbs_constant_pool_id_to_constant(const rbs_constant_pool_t *pool, rbs_constant_id_t constant_id) {
|
|
200
|
-
|
|
126
|
+
RBS_ASSERT(constant_id != RBS_CONSTANT_ID_UNSET && constant_id <= pool->size, "constant_id is not valid. Got %i, pool->size: %i", constant_id, pool->size);
|
|
201
127
|
return &pool->constants[constant_id - 1];
|
|
202
128
|
}
|
|
203
129
|
|
|
@@ -207,7 +133,7 @@ rbs_constant_pool_id_to_constant(const rbs_constant_pool_t *pool, rbs_constant_i
|
|
|
207
133
|
*/
|
|
208
134
|
rbs_constant_id_t
|
|
209
135
|
rbs_constant_pool_find(const rbs_constant_pool_t *pool, const uint8_t *start, size_t length) {
|
|
210
|
-
|
|
136
|
+
RBS_ASSERT(is_power_of_two(pool->capacity), "pool->capacity is not a power of two. Got %i", pool->capacity);
|
|
211
137
|
const uint32_t mask = pool->capacity - 1;
|
|
212
138
|
|
|
213
139
|
uint32_t hash = rbs_constant_pool_hash(start, length);
|
|
@@ -235,7 +161,7 @@ rbs_constant_pool_insert(rbs_constant_pool_t *pool, const uint8_t *start, size_t
|
|
|
235
161
|
if (!rbs_constant_pool_resize(pool)) return RBS_CONSTANT_ID_UNSET;
|
|
236
162
|
}
|
|
237
163
|
|
|
238
|
-
|
|
164
|
+
RBS_ASSERT(is_power_of_two(pool->capacity), "pool->capacity is not a power of two. Got %i", pool->capacity);
|
|
239
165
|
const uint32_t mask = pool->capacity - 1;
|
|
240
166
|
|
|
241
167
|
uint32_t hash = rbs_constant_pool_hash(start, length);
|
|
@@ -276,7 +202,7 @@ rbs_constant_pool_insert(rbs_constant_pool_t *pool, const uint8_t *start, size_t
|
|
|
276
202
|
// IDs are allocated starting at 1, since the value 0 denotes a non-existent
|
|
277
203
|
// constant.
|
|
278
204
|
uint32_t id = ++pool->size;
|
|
279
|
-
|
|
205
|
+
RBS_ASSERT(pool->size < ((uint32_t) (1 << 30)), "pool->size is too large. Got %i", pool->size);
|
|
280
206
|
|
|
281
207
|
*bucket = (rbs_constant_pool_bucket_t) {
|
|
282
208
|
.id = (unsigned int) (id & 0x3fffffff),
|
|
@@ -301,6 +227,11 @@ rbs_constant_pool_insert_shared(rbs_constant_pool_t *pool, const uint8_t *start,
|
|
|
301
227
|
return rbs_constant_pool_insert(pool, start, length, RBS_CONSTANT_POOL_BUCKET_DEFAULT);
|
|
302
228
|
}
|
|
303
229
|
|
|
230
|
+
rbs_constant_id_t
|
|
231
|
+
rbs_constant_pool_insert_shared_with_encoding(rbs_constant_pool_t *pool, const uint8_t *start, size_t length, const rbs_encoding_t *encoding) {
|
|
232
|
+
return rbs_constant_pool_insert_shared(pool, start, length);
|
|
233
|
+
}
|
|
234
|
+
|
|
304
235
|
/**
|
|
305
236
|
* Insert a constant into a constant pool from memory that is now owned by the
|
|
306
237
|
* constant pool. Returns the id of the constant, or RBS_CONSTANT_ID_UNSET if any
|
|
@@ -324,8 +255,7 @@ rbs_constant_pool_insert_constant(rbs_constant_pool_t *pool, const uint8_t *star
|
|
|
324
255
|
/**
|
|
325
256
|
* Free the memory associated with a constant pool.
|
|
326
257
|
*/
|
|
327
|
-
void
|
|
328
|
-
rbs_constant_pool_free(rbs_constant_pool_t *pool) {
|
|
258
|
+
void rbs_constant_pool_free(rbs_constant_pool_t *pool) {
|
|
329
259
|
// For each constant in the current constant pool, free the contents if the
|
|
330
260
|
// contents are owned.
|
|
331
261
|
for (uint32_t index = 0; index < pool->capacity; index++) {
|