Add Dqn_String and update some arenas to allocators

This commit is contained in:
doyle 2020-02-08 18:47:48 +11:00
parent cd9ccfebe2
commit 65cbe4b493
2 changed files with 143 additions and 108 deletions

View File

@ -599,7 +599,7 @@ enum struct Dqn_Allocator_Type
XHeap, // Malloc realloc, free, crash on failure
Arena,
Custom,
NullAllocator,
Null,
};
#define DQN_ALLOCATOR_ALLOCATE_PROC(name) void *name(Dqn_usize size)
@ -667,8 +667,8 @@ struct Dqn_MemArenaScopedRegion
#define DQN_DEBUG_PARAMS
#endif
#define DQN_MEM_ARENA_INIT_WITH_ALLOCATOR(arena, allocator, size) Dqn_MemArena_InitWithAllocator(arena, allocator, size DQN_DEBUG_PARAMS)
#define DQN_MEM_ARENA_INIT_MEMORY(arena, src, size) Dqn_MemArena_InitMemory(arena, src, size DQN_DEBUG_PARAMS)
#define DQN_MEM_ARENA_INIT_WITH_ALLOCATOR(allocator, size) Dqn_MemArena_InitWithAllocator(allocator, size DQN_DEBUG_PARAMS)
#define DQN_MEM_ARENA_INIT_MEMORY(src, size) Dqn_MemArena_InitMemory(src, size DQN_DEBUG_PARAMS)
#define DQN_MEM_ARENA_ALLOC(arena, size) Dqn_MemArena_Alloc(arena, size DQN_DEBUG_PARAMS)
#define DQN_MEM_ARENA_ALLOC_ARRAY(arena, T, num) (T *)Dqn_MemArena_Alloc(arena, sizeof(T) * num DQN_DEBUG_PARAMS)
#define DQN_MEM_ARENA_ALLOC_STRUCT(arena, T) (T *)Dqn_MemArena_Alloc(arena, sizeof(T) DQN_DEBUG_PARAMS)
@ -681,28 +681,28 @@ DQN_HEADER_COPY_END
// @ NOTE: Dqn_Allocator
// @
// @ -------------------------------------------------------------------------------------------------
DQN_HEADER_COPY_PROTOTYPE(Dqn_Allocator, inline Dqn_Allocator_NullAllocator())
DQN_HEADER_COPY_PROTOTYPE(Dqn_Allocator, inline Dqn_Allocator_Null())
{
Dqn_Allocator result = {};
result.type = Dqn_Allocator_Type::NullAllocator;
result.type = Dqn_Allocator_Type::Null;
return result;
}
DQN_HEADER_COPY_PROTOTYPE(Dqn_Allocator, inline Dqn_Allocator_HeapAllocator())
DQN_HEADER_COPY_PROTOTYPE(Dqn_Allocator, inline Dqn_Allocator_Heap())
{
Dqn_Allocator result = {};
result.type = Dqn_Allocator_Type::Heap;
return result;
}
DQN_HEADER_COPY_PROTOTYPE(Dqn_Allocator, inline Dqn_Allocator_XHeapAllocator())
DQN_HEADER_COPY_PROTOTYPE(Dqn_Allocator, inline Dqn_Allocator_XHeap())
{
Dqn_Allocator result = {};
result.type = Dqn_Allocator_Type::XHeap;
return result;
}
DQN_HEADER_COPY_PROTOTYPE(Dqn_Allocator, inline Dqn_Allocator_ArenaAllocator(Dqn_MemArena *arena))
DQN_HEADER_COPY_PROTOTYPE(Dqn_Allocator, inline Dqn_Allocator_Arena(Dqn_MemArena *arena))
{
Dqn_Allocator result = {};
result.type = Dqn_Allocator_Type::Arena;
@ -710,6 +710,24 @@ DQN_HEADER_COPY_PROTOTYPE(Dqn_Allocator, inline Dqn_Allocator_ArenaAllocator(Dqn
return result;
}
// @ -------------------------------------------------------------------------------------------------
// @
// @ NOTE: String
// @
// @ -------------------------------------------------------------------------------------------------
DQN_HEADER_COPY_BEGIN
struct Dqn_String
{
char *str;
Dqn_isize len;
char const *begin() const { return str; }
char const *end () const { return str + len; }
char *begin() { return str; }
char *end () { return str + len; }
};
#define DQN_STRING_LITERAL(string) {string, Dqn_CharCountI(string)}
DQN_HEADER_COPY_END
// @ -------------------------------------------------------------------------------------------------
// @
// @ NOTE: String Builder
@ -833,22 +851,19 @@ DQN_HEADER_COPY_PROTOTYPE(template <Dqn_usize N> void, Dqn_StringBuilder_BuildIn
Dqn_StringBuilder__BuildOutput(builder, dest, dest_size);
}
DQN_HEADER_COPY_PROTOTYPE(template <Dqn_usize N> char *, Dqn_StringBuilder_BuildFromMalloc(Dqn_StringBuilder<N> *builder, Dqn_isize *len = nullptr))
DQN_HEADER_COPY_PROTOTYPE(template <Dqn_usize N> char *, Dqn_StringBuilder_Build(Dqn_StringBuilder<N> *builder, Dqn_Allocator *allocator, Dqn_isize *len = nullptr))
{
Dqn_isize len_w_null_terminator = Dqn_StringBuilder_BuildLen(builder);
auto *result = static_cast<char *>(malloc(len_w_null_terminator));
auto *result = DQN_CAST(char *)Dqn_Allocator_Allocate(allocator, sizeof(char) * len_w_null_terminator);
if (len) *len = len_w_null_terminator;
Dqn_StringBuilder__BuildOutput(builder, result, len_w_null_terminator);
return result;
}
void *Dqn_MemArena_Alloc(Dqn_MemArena *arena, Dqn_usize size DQN_DEBUG_ARGS);
DQN_HEADER_COPY_PROTOTYPE(template <Dqn_usize N> char *, Dqn_StringBuilder_BuildFromArena(Dqn_StringBuilder<N> *builder, Dqn_MemArena *arena, Dqn_isize *len = nullptr))
DQN_HEADER_COPY_PROTOTYPE(template <Dqn_usize N> Dqn_String, Dqn_StringBuilder_BuildString(Dqn_StringBuilder<N> *builder, Dqn_Allocator *allocator))
{
Dqn_isize len_w_null_terminator = Dqn_StringBuilder_BuildLen(builder);
char *result = DQN_MEM_ARENA_ALLOC_ARRAY(arena, char, len_w_null_terminator);
if (len) *len = len_w_null_terminator;
Dqn_StringBuilder__BuildOutput(builder, result, len_w_null_terminator);
Dqn_String result = {};
result.str = Dqn_StringBuilder_Build(builder, allocator, &result.len);
return result;
}
@ -912,11 +927,8 @@ DQN_HEADER_COPY_PROTOTYPE(template <Dqn_usize N> void, Dqn_StringBuilder_Free(Dq
template <typename T>
struct Dqn_Slice
{
union { T *data; T *buf; T *str; };
union { Dqn_isize size; Dqn_isize len; };
Dqn_Slice() = default;
Dqn_Slice(T *str, Dqn_isize len) { this->str = str; this->len = len; }
T *data;
Dqn_isize len;
T const &operator[] (Dqn_isize i) const { DQN_ASSERT_MSG(i >= 0 && i < len, "%d >= 0 && %d < %d", i, len); return data[i]; }
T &operator[] (Dqn_isize i) { DQN_ASSERT_MSG(i >= 0 && i < len, "%d >= 0 && %d < %d", i, len); return data[i]; }
@ -927,7 +939,6 @@ struct Dqn_Slice
T const *operator+ (Dqn_isize i) const { DQN_ASSERT_MSG(i >= 0 && i < len, "%d >= 0 && %d < %d", i, len); return data + i; }
T *operator+ (Dqn_isize i) { DQN_ASSERT_MSG(i >= 0 && i < len, "%d >= 0 && %d < %d", i, len); return data + i; }
};
#define SLICE_LITERAL(string) Dqn_Slice<char const>(DQN_STR_AND_LEN(string))
DQN_HEADER_COPY_PROTOTYPE(template <typename T> inline Dqn_Slice<T>, Dqn_Slice_CopyNullTerminated(Dqn_MemArena *arena, T const *src, Dqn_isize len))
{
@ -968,51 +979,6 @@ DQN_HEADER_COPY_PROTOTYPE(template <typename T> inline bool, Dqn_Slice_Equals(Dq
return result;
}
// @ -------------------------------------------------------------------------------------------------
// @
// @ NOTE: Dqn_Asprintf (Allocate Sprintf)
// @
// @ -------------------------------------------------------------------------------------------------
int Dqn_Safe_TruncateISizeToInt(Dqn_isize val);
DQN_HEADER_COPY_PROTOTYPE(template <typename T> Dqn_Slice<char>, Dqn_AsprintfSlice(T *arena, char const *fmt, va_list va))
{
Dqn_Slice<char> result = {};
result.len = stbsp_vsnprintf(nullptr, 0, fmt, va) + 1;
result.buf = DQN_MEM_ARENA_ALLOC_ARRAY(arena, char, result.len);
stbsp_vsnprintf(result.buf, Dqn_Safe_TruncateISizeToInt(result.len), fmt, va);
result.buf[result.len - 1] = 0;
return result;
}
DQN_HEADER_COPY_PROTOTYPE(template <typename T> Dqn_Slice<char>, Dqn_AsprintfSlice(T *arena, char const *fmt, ...))
{
va_list va;
va_start(va, fmt);
Dqn_Slice<char> result = Dqn_AsprintfSlice(arena, fmt, va);
va_end(va);
return result;
}
DQN_HEADER_COPY_PROTOTYPE(template <typename T> char *, Dqn_Asprintf(T *arena, int *len, char const *fmt, ...))
{
va_list va;
va_start(va, fmt);
Dqn_Slice<char> result = Dqn_AsprintfSlice(arena, fmt, va);
va_end(va);
if (len) *len = result.len;
return result.str;
}
DQN_HEADER_COPY_PROTOTYPE(template <typename T> char *, Dqn_Asprintf(T *arena, char const *fmt, ...))
{
va_list va;
va_start(va, fmt);
Dqn_Slice<char> result = Dqn_AsprintfSlice(arena, fmt, va);
va_end(va);
return result.str;
}
// @ -------------------------------------------------------------------------------------------------
// @
// @ NOTE: Dqn_FixedArray
@ -1181,7 +1147,7 @@ DQN_HEADER_COPY_END
DQN_HEADER_COPY_PROTOTYPE(template <typename T> Dqn_Array<T>, Dqn_Array_InitMemory(T *memory, Dqn_isize max, Dqn_isize len = 0))
{
Dqn_Array<T> result = {};
result.allocator = Dqn_Allocator_NullAllocator();
result.allocator = Dqn_Allocator_Null();
result.data = memory;
result.len = len;
result.max = max;
@ -1457,18 +1423,20 @@ DQN_HEADER_COPY_PROTOTYPE(Dqn_b32, Dqn_Log(Dqn_LogType type, char const *file, D
return true;
}
void * Dqn_MemArena_Alloc(Dqn_MemArena *arena, Dqn_usize size DQN_DEBUG_ARGS);
Dqn_b32 Dqn_MemArena_Reserve(Dqn_MemArena *arena, Dqn_usize size DQN_DEBUG_ARGS);
DQN_HEADER_COPY_PROTOTYPE(void *, Dqn_Allocator_Allocate(Dqn_Allocator *allocator, Dqn_usize size))
{
void *result = nullptr;
switch (allocator->type)
{
case Dqn_Allocator_Type::NullAllocator:
case Dqn_Allocator_Type::Null:
default: break;
case Dqn_Allocator_Type::Heap:
case Dqn_Allocator_Type::XHeap:
{
result = malloc(size);
result = calloc(1, size);
if (!result && allocator->type == Dqn_Allocator_Type::XHeap)
{
DQN_ASSERT(result);
@ -1494,7 +1462,6 @@ DQN_HEADER_COPY_PROTOTYPE(void *, Dqn_Allocator_Allocate(Dqn_Allocator *allocato
return result;
}
Dqn_b32 Dqn_MemArena_Reserve(Dqn_MemArena *arena, Dqn_usize size DQN_DEBUG_ARGS);
DQN_HEADER_COPY_PROTOTYPE(void *, Dqn_Allocator_Realloc(Dqn_Allocator *allocator, void *old_ptr, Dqn_isize old_size, Dqn_isize new_size))
{
DQN_IF_ASSERT(old_size >= 0) old_size = 0;
@ -1503,7 +1470,7 @@ DQN_HEADER_COPY_PROTOTYPE(void *, Dqn_Allocator_Realloc(Dqn_Allocator *allocator
void *result = nullptr;
switch (allocator->type)
{
case Dqn_Allocator_Type::NullAllocator:
case Dqn_Allocator_Type::Null:
default: break;
case Dqn_Allocator_Type::Heap:
@ -1543,7 +1510,7 @@ DQN_HEADER_COPY_PROTOTYPE(void, Dqn_Allocator_Free(Dqn_Allocator *allocator, voi
{
switch (allocator->type)
{
case Dqn_Allocator_Type::NullAllocator:
case Dqn_Allocator_Type::Null:
default: break;
case Dqn_Allocator_Type::Heap:
@ -1681,31 +1648,33 @@ DQN_HEADER_COPY_PROTOTYPE(Dqn_b32, Dqn_MemArena_Reserve(Dqn_MemArena *arena, Dqn
return true;
}
DQN_HEADER_COPY_PROTOTYPE(void, Dqn_MemArena_InitWithAllocator(Dqn_MemArena *arena, Dqn_Allocator allocator, Dqn_usize size DQN_DEBUG_ARGS))
DQN_HEADER_COPY_PROTOTYPE(Dqn_MemArena, Dqn_MemArena_InitWithAllocator(Dqn_Allocator allocator, Dqn_usize size DQN_DEBUG_ARGS))
{
#if defined(DQN_DEBUG_DQN_MEM_ARENA_LOGGING)
(void)file; (void)file_len; (void)func; (void)func_len; (void)line;
#endif
DQN_ASSERT_MSG(size >= sizeof(*arena->curr_mem_block), "(%zu >= %zu) There needs to be enough space to encode the Dqn_MemBlock struct into the memory buffer", size, sizeof(*arena->curr_mem_block));
*arena = {};
arena->allocator = allocator;
Dqn_MemBlock *mem_block = Dqn_MemArena__AllocateBlock(arena, size);
Dqn_MemArena__AttachBlock(arena, mem_block);
Dqn_MemArena result = {};
DQN_ASSERT_MSG(size >= sizeof(*result.curr_mem_block), "(%zu >= %zu) There needs to be enough space to encode the Dqn_MemBlock struct into the memory buffer", size, sizeof(*result.curr_mem_block));
result.allocator = allocator;
Dqn_MemBlock *mem_block = Dqn_MemArena__AllocateBlock(&result, size);
Dqn_MemArena__AttachBlock(&result, mem_block);
return result;
}
DQN_HEADER_COPY_PROTOTYPE(void, Dqn_MemArena_InitMemory(Dqn_MemArena *arena, void *memory, Dqn_usize size DQN_DEBUG_ARGS))
DQN_HEADER_COPY_PROTOTYPE(Dqn_MemArena, Dqn_MemArena_InitMemory(void *memory, Dqn_usize size DQN_DEBUG_ARGS))
{
#if defined(DQN_DEBUG_DQN_MEM_ARENA_LOGGING)
(void)file; (void)file_len; (void)func; (void)func_len; (void)line;
#endif
DQN_ASSERT_MSG(size >= sizeof(*arena->curr_mem_block), "(%zu >= %zu) There needs to be enough space to encode the Dqn_MemBlock struct into the memory buffer", size, sizeof(*arena->curr_mem_block));
*arena = {};
arena->allocator = Dqn_Allocator_NullAllocator();
Dqn_MemArena result = {};
DQN_ASSERT_MSG(size >= sizeof(*result.curr_mem_block), "(%zu >= %zu) There needs to be enough space to encode the Dqn_MemBlock struct into the memory buffer", size, sizeof(*result.curr_mem_block));
result.allocator = Dqn_Allocator_Null();
auto *mem_block = DQN_CAST(Dqn_MemBlock *) memory;
*mem_block = {};
mem_block->memory = DQN_CAST(Dqn_u8 *) memory + sizeof(*mem_block);
mem_block->size = size - sizeof(*mem_block);
Dqn_MemArena__AttachBlock(arena, mem_block);
Dqn_MemArena__AttachBlock(&result, mem_block);
return result;
}
DQN_HEADER_COPY_PROTOTYPE(void, Dqn_MemArena_ResetUsage(Dqn_MemArena *arena, Dqn_ZeroMem zero_mem))
@ -1749,6 +1718,31 @@ Dqn_MemArenaScopedRegion::~Dqn_MemArenaScopedRegion()
this->arena->curr_mem_block->used = this->curr_mem_block_used;
}
// @ -------------------------------------------------------------------------------------------------
// @
// @ NOTE: Dqn_Asprintf (Allocate Sprintf)
// @
// @ -------------------------------------------------------------------------------------------------
int Dqn_Safe_TruncateISizeToInt(Dqn_isize val);
DQN_HEADER_COPY_PROTOTYPE(Dqn_String, Dqn_Asprintf(Dqn_Allocator *allocator, char const *fmt, va_list va))
{
Dqn_String result = {};
result.len = stbsp_vsnprintf(nullptr, 0, fmt, va) + 1;
result.str = DQN_CAST(char *)Dqn_Allocator_Allocate(allocator, sizeof(char) * result.len);
stbsp_vsnprintf(result.str, Dqn_Safe_TruncateISizeToInt(result.len), fmt, va);
result.str[result.len - 1] = 0;
return result;
}
DQN_HEADER_COPY_PROTOTYPE(Dqn_String, Dqn_Asprintf(Dqn_Allocator *allocator, char const *fmt, ...))
{
va_list va;
va_start(va, fmt);
Dqn_String result = Dqn_Asprintf(allocator, fmt, va);
va_end(va);
return result;
}
// @ -------------------------------------------------------------------------------------------------
// @
// @ NOTE: Vectors
@ -2124,7 +2118,7 @@ DQN_HEADER_COPY_PROTOTYPE(int, Dqn_Safe_TruncateUSizeToInt(Dqn_usize val))
DQN_HEADER_COPY_PROTOTYPE(Dqn_isize, Dqn_Safe_TruncateUSizeToISize(Dqn_usize val))
{
DQN_ASSERT_MSG(val <= CAST(Dqn_usize)ISIZE_MAX, "%zu <= %zu", val, CAST(Dqn_usize)ISIZE_MAX);
DQN_ASSERT_MSG(val <= DQN_CAST(Dqn_usize)DQN_ISIZE_MAX, "%zu <= %zu", val, DQN_CAST(Dqn_usize)DQN_ISIZE_MAX);
auto result = DQN_CAST(Dqn_isize)val;
return result;
}
@ -2141,7 +2135,6 @@ DQN_HEADER_COPY_PROTOTYPE(Dqn_b32, Dqn_Char_IsAlpha(char ch))
return result;
}
DQN_HEADER_COPY_PROTOTYPE(Dqn_b32, Dqn_Char_IsDigit(char ch))
{
Dqn_b32 result = (ch >= '0' && ch <= '9');
@ -2162,6 +2155,14 @@ DQN_HEADER_COPY_PROTOTYPE(Dqn_b32, Dqn_Char_IsWhitespace(char ch))
return result;
}
DQN_HEADER_COPY_PROTOTYPE(char, Dqn_Char_ToLower(char ch))
{
char result = ch;
if (result >= 'A' && result <= 'Z')
result = 'a' - 'A';
return result;
}
// @ -------------------------------------------------------------------------------------------------
// @
// @ NOTE: String Helpers
@ -2382,6 +2383,39 @@ DQN_HEADER_COPY_PROTOTYPE(Dqn_i64, Dqn_Str_ToI64(char const *buf, int len = -1))
return result;
}
// @ -------------------------------------------------------------------------------------------------
// @
// @ NOTE: Dqn_String
// @
// @ -------------------------------------------------------------------------------------------------
DQN_HEADER_COPY_PROTOTYPE(Dqn_b32, Dqn_String_Compare(Dqn_String const lhs, Dqn_String const rhs))
{
Dqn_b32 result = false;
if (lhs.len == rhs.len)
result = (memcmp(lhs.str, rhs.str, lhs.len) == 0);
return result;
}
DQN_HEADER_COPY_PROTOTYPE(Dqn_b32, Dqn_String_CompareCaseInsensitive(Dqn_String const lhs, Dqn_String const rhs))
{
Dqn_b32 result = (lhs.len == rhs.len);
if (result)
{
for (Dqn_isize index = 0; index < lhs.len && result; index++)
result = (Dqn_Char_ToLower(lhs.str[index]) == Dqn_Char_ToLower(rhs.str[index]));
}
return result;
}
DQN_HEADER_COPY_PROTOTYPE(Dqn_String, Dqn_String_Copy(Dqn_Allocator *allocator, Dqn_String const src))
{
Dqn_String result = src;
result.str = DQN_CAST(decltype(result.str))Dqn_Allocator_Allocate(allocator, sizeof(*result.str) * result.len);
memcpy(result.str, src.str, result.len);
return result;
}
// @ -------------------------------------------------------------------------------------------------
// @
// @ NOTE: File

View File

@ -146,12 +146,12 @@ struct HeaderEntry
{
struct
{
Dqn_Slice<char> return_val;
Dqn_Slice<char> name_and_args;
Dqn_String return_val;
Dqn_String name_and_args;
} function_decl;
Dqn_Slice<char> comment;
Dqn_Slice<char> copy_range;
Dqn_String comment;
Dqn_String copy_range;
};
};
@ -229,8 +229,9 @@ int main(int argc, char *argv[])
isize func_name_len = 0;
char const *func_name = ParseFunctionNameAndParameters(ptr, &func_name_len);
entry->function_decl.return_val = Dqn_AsprintfSlice(&arena, "%.*s", func_type_len, func_type);
entry->function_decl.name_and_args = Dqn_AsprintfSlice(&arena, "%.*s", func_name_len, func_name);
Dqn_Allocator allocator = Dqn_Allocator_Arena(&arena);
entry->function_decl.return_val = Dqn_Asprintf(&allocator, "%.*s", func_type_len, func_type);
entry->function_decl.name_and_args = Dqn_Asprintf(&allocator, "%.*s", func_name_len, func_name);
ptr = func_name + func_name_len + 1; // Ptr is at macro closing paren, skip the paren
max_prototype_return_val = DQN_MAX(max_prototype_return_val, func_type_len);
@ -243,7 +244,7 @@ int main(int argc, char *argv[])
ptr++;
isize comment_len = ptr - comment_start;
entry->comment.buf = DQN_MEM_ARENA_ALLOC_ARRAY(&arena, char, comment_len);
entry->comment.str = DQN_MEM_ARENA_ALLOC_ARRAY(&arena, char, comment_len);
DQN_FOR_EACH(comment_index, comment_len)
{
// NOTE: We capture "// @", and we want to skip the @ symbol, its ugly which is at the index 3
@ -251,10 +252,10 @@ int main(int argc, char *argv[])
char ch = comment_start[comment_index];
if (comment_index == 3 && ch == '@') continue;
if (comment_index == 4 && ch == ' ') continue;
entry->comment.buf[entry->comment.len++] = ch;
entry->comment.str[entry->comment.len++] = ch;
}
while (entry->comment.len > 0 && Dqn_Char_IsWhitespace(entry->comment.buf[entry->comment.len - 1]))
while (entry->comment.len > 0 && Dqn_Char_IsWhitespace(entry->comment.str[entry->comment.len - 1]))
entry->comment.len--;
ptr = comment_start + comment_len;
}
@ -271,12 +272,12 @@ int main(int argc, char *argv[])
}
isize copy_len = copy_end - copy_start;
entry->copy_range.buf = (char *)DQN_MEM_ARENA_ALLOC(&arena, copy_len);
entry->copy_range.str = (char *)DQN_MEM_ARENA_ALLOC(&arena, copy_len);
DQN_FOR_EACH(copy_index, copy_len)
{
char ch = copy_start[copy_index];
if (ch == '\r') continue;
entry->copy_range.buf[entry->copy_range.len++] = ch;
entry->copy_range.str[entry->copy_range.len++] = ch;
}
ptr = copy_end;
}
@ -301,13 +302,13 @@ int main(int argc, char *argv[])
case HeaderEntryType::Comment:
{
fprintf(stdout, "%.*s\n", (int)entry->comment.len, entry->comment.buf);
fprintf(stdout, "%.*s\n", (int)entry->comment.len, entry->comment.str);
}
break;
case HeaderEntryType::CopyBegin:
{
fprintf(stdout, "%.*s\n", (int)entry->copy_range.len, entry->copy_range.buf);
fprintf(stdout, "%.*s\n", (int)entry->copy_range.len, entry->copy_range.str);
}
break;
}