7pm_buffer_sizeof(
void) {
15pm_buffer_init_capacity(
pm_buffer_t *buffer,
size_t capacity) {
20 return buffer->
value != NULL;
28 return pm_buffer_init_capacity(buffer, 1024);
51pm_buffer_append_length(
pm_buffer_t *buffer,
size_t length) {
52 size_t next_length = buffer->
length + length;
53 const size_t original_capacity = buffer->
capacity;
55 if (next_length > buffer->
capacity) {
60 while (next_length > buffer->
capacity) {
65 if (buffer->
value == NULL)
return false;
68 buffer->
length = next_length;
76pm_buffer_append(
pm_buffer_t *buffer,
const void *source,
size_t length) {
77 size_t cursor = buffer->
length;
78 if (pm_buffer_append_length(buffer, length)) {
79 memcpy(buffer->
value + cursor, source, length);
88 size_t cursor = buffer->
length;
89 if (pm_buffer_append_length(buffer, length)) {
90 memset(buffer->
value + cursor, 0, length);
98pm_buffer_append_format(
pm_buffer_t *buffer,
const char *format, ...) {
100 va_start(arguments, format);
101 int result = vsnprintf(NULL, 0, format, arguments);
104 if (result < 0)
return;
105 size_t length = (size_t) (result + 1);
107 size_t cursor = buffer->
length;
108 if (pm_buffer_append_length(buffer, length)) {
109 va_start(arguments, format);
110 vsnprintf(buffer->
value + cursor, length, format, arguments);
120pm_buffer_append_string(
pm_buffer_t *buffer,
const char *value,
size_t length) {
121 pm_buffer_append(buffer, value, length);
128pm_buffer_append_bytes(
pm_buffer_t *buffer,
const uint8_t *value,
size_t length) {
129 pm_buffer_append(buffer, (
const char *) value, length);
137 const void *source = &value;
138 pm_buffer_append(buffer, source,
sizeof(uint8_t));
147 pm_buffer_append_byte(buffer, (uint8_t) value);
151 pm_buffer_append_byte(buffer, (uint8_t) (n | 128));
154 pm_buffer_append_byte(buffer, (uint8_t) n);
163 uint32_t unsigned_int = ((uint32_t)(value) << 1) ^ ((uint32_t)(value >> 31));
164 pm_buffer_append_varuint(buffer, unsigned_int);
172 const void *source = &value;
173 pm_buffer_append(buffer, source,
sizeof(
double));
180pm_buffer_append_unicode_codepoint(
pm_buffer_t *buffer, uint32_t value) {
182 pm_buffer_append_byte(buffer, (uint8_t) value);
184 }
else if (value <= 0x7FF) {
186 (uint8_t) (0xC0 | ((value >> 6) & 0x3F)),
187 (uint8_t) (0x80 | (value & 0x3F))
190 pm_buffer_append_bytes(buffer, bytes, 2);
192 }
else if (value <= 0xFFFF) {
194 (uint8_t) (0xE0 | ((value >> 12) & 0x3F)),
195 (uint8_t) (0x80 | ((value >> 6) & 0x3F)),
196 (uint8_t) (0x80 | (value & 0x3F))
199 pm_buffer_append_bytes(buffer, bytes, 3);
201 }
else if (value <= 0x10FFFF) {
203 (uint8_t) (0xF0 | ((value >> 18) & 0x3F)),
204 (uint8_t) (0x80 | ((value >> 12) & 0x3F)),
205 (uint8_t) (0x80 | ((value >> 6) & 0x3F)),
206 (uint8_t) (0x80 | (value & 0x3F))
209 pm_buffer_append_bytes(buffer, bytes, 4);
221 for (
size_t index = 0; index < length; index++) {
222 const uint8_t
byte = source[index];
224 if ((
byte <= 0x06) || (
byte >= 0x0E &&
byte <= 0x1F) || (
byte >= 0x7F)) {
225 if (escaping == PM_BUFFER_ESCAPING_RUBY) {
226 pm_buffer_append_format(buffer,
"\\x%02X",
byte);
228 pm_buffer_append_format(buffer,
"\\u%04X",
byte);
233 if (escaping == PM_BUFFER_ESCAPING_RUBY) {
234 pm_buffer_append_string(buffer,
"\\a", 2);
236 pm_buffer_append_format(buffer,
"\\u%04X",
byte);
240 pm_buffer_append_string(buffer,
"\\b", 2);
243 pm_buffer_append_string(buffer,
"\\t", 2);
246 pm_buffer_append_string(buffer,
"\\n", 2);
249 if (escaping == PM_BUFFER_ESCAPING_RUBY) {
250 pm_buffer_append_string(buffer,
"\\v", 2);
252 pm_buffer_append_format(buffer,
"\\u%04X",
byte);
256 pm_buffer_append_string(buffer,
"\\f", 2);
259 pm_buffer_append_string(buffer,
"\\r", 2);
262 pm_buffer_append_string(buffer,
"\\\"", 2);
265 if (escaping == PM_BUFFER_ESCAPING_RUBY && index + 1 < length) {
266 const uint8_t next_byte = source[index + 1];
267 if (next_byte ==
'{' || next_byte ==
'@' || next_byte ==
'$') {
268 pm_buffer_append_byte(buffer,
'\\');
272 pm_buffer_append_byte(buffer,
'#');
276 pm_buffer_append_string(buffer,
"\\\\", 2);
279 pm_buffer_append_byte(buffer,
byte);
290pm_buffer_prepend_string(
pm_buffer_t *buffer,
const char *value,
size_t length) {
291 size_t cursor = buffer->
length;
292 if (pm_buffer_append_length(buffer, length)) {
293 memmove(buffer->
value + length, buffer->
value, cursor);
294 memcpy(buffer->
value, value, length);
304 pm_buffer_append(destination, source->
value, source->
length);
332 const char *first = memchr(buffer->
value, value, buffer->
length);
333 return (first == NULL) ? SIZE_MAX : (size_t) (first - buffer->
value);
340pm_buffer_insert(
pm_buffer_t *buffer,
size_t index,
const char *value,
size_t length) {
341 assert(index <= buffer->length);
343 if (index == buffer->
length) {
344 pm_buffer_append_string(buffer, value, length);
346 pm_buffer_append_zeroes(buffer, length);
347 memmove(buffer->
value + index + length, buffer->
value + index, buffer->
length - length - index);
348 memcpy(buffer->
value + index, value, length);
#define xmalloc
Old name of ruby_xmalloc.
void pm_buffer_free(pm_buffer_t *buffer)
Free the memory associated with the buffer.
bool pm_buffer_init(pm_buffer_t *buffer)
Initialize a pm_buffer_t with its default values.
size_t pm_buffer_length(const pm_buffer_t *buffer)
Return the length of the buffer.
char * pm_buffer_value(const pm_buffer_t *buffer)
Return the value of the buffer.
A wrapper around a contiguous block of allocated memory.
pm_buffer_escaping_t
The different types of escaping that can be performed by the buffer when appending a slice of Ruby so...
static PRISM_FORCE_INLINE bool pm_char_is_whitespace(const uint8_t b)
Returns true if the given character is a whitespace character.
A pm_buffer_t is a simple memory buffer that stores data in a contiguous block of memory.
size_t capacity
The capacity of the buffer in bytes that has been allocated.
size_t length
The length of the buffer in bytes.
char * value
A pointer to the start of the buffer.