Skip to content

Commit

Permalink
Fix internal terminoligy
Browse files Browse the repository at this point in the history
  • Loading branch information
P-p-H-d committed Jul 26, 2024
1 parent 847f52f commit 341d145
Showing 1 changed file with 36 additions and 35 deletions.
71 changes: 36 additions & 35 deletions m-string.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ typedef struct m_str1ng_heap_s {

/* Define the union between a heap allocated string and its inline representation
If buffer[sizeof(m_str1ng_heap_ct)-2] == 0 then
It is a stack based string where buffer is the string, with a maximum allocation of 15 bytes
It is a embedded based string where buffer is the string, with a maximum allocation of 15 bytes
In this case buffer[sizeof(m_str1ng_heap_ct)-1] is the size of the string
Otherwise it is a heap representation then
ptr is the pointer to the data, size its size, and alloc a representation of the capacity:
Expand Down Expand Up @@ -153,13 +153,14 @@ typedef struct m_string_it_s {
m_string_: public methods
*/

/* Internal method to test if the string is stack based or heap based
Stack representation ensures that the penultimate byte is 0.
/* Internal method to test if the characters of the string are fully embedded in the struct,
or if the characters are allocated on the heap.
Embedded representation ensures that the penultimate byte is 0.
By encoding, we ensure that the penultimate byte of 'alloc' (of the heap representation)
cannot be 0.
*/
M_INLINE bool
m_str1ng_stack_p(const m_string_t s)
m_str1ng_embedded_p(const m_string_t s)
{
// Function can be called when contract is not fulfilled
return (s->u.buffer[sizeof(m_str1ng_heap_ct)-2] == 0);
Expand All @@ -170,7 +171,7 @@ M_INLINE void
m_str1ng_set_size(m_string_t s, size_t size)
{
// Function can be called when contract is not fulfilled
if (m_str1ng_stack_p(s)) {
if (m_str1ng_embedded_p(s)) {
M_ASSERT (size < sizeof (m_str1ng_heap_ct) - 1);
// The size of the string is stored as the last char of the buffer.
s->u.buffer[sizeof(m_str1ng_heap_ct)-1] = (char) size;
Expand All @@ -185,19 +186,19 @@ M_INLINE size_t
m_string_size(const m_string_t s)
{
// Function can be called when contract is not fulfilled
const size_t s_stack = (size_t) s->u.buffer[sizeof(m_str1ng_heap_ct)-1];
const size_t s_embed = (size_t) s->u.buffer[sizeof(m_str1ng_heap_ct)-1];
const size_t s_heap = s->u.heap.size;
return m_str1ng_stack_p(s) ? s_stack : s_heap;
return m_str1ng_embedded_p(s) ? s_embed : s_heap;
}

/* Return the capacity of the string (including the final nul char) */
M_INLINE size_t
m_string_capacity(const m_string_t s)
{
// Function can be called when contract is not fulfilled
const size_t c_stack = sizeof (m_str1ng_heap_ct) - 1;
const size_t c_embed = sizeof (m_str1ng_heap_ct) - 1;
const size_t c_heap = (m_str1ng_size_t) s->u.heap.alloc[sizeof (m_str1ng_size_t)-2] << s->u.heap.alloc[sizeof (m_str1ng_size_t)-1];
return m_str1ng_stack_p(s) ? c_stack : c_heap;
return m_str1ng_embedded_p(s) ? c_embed : c_heap;
}

/* Internal function to round up the allocation size to the next allowed representation
Expand Down Expand Up @@ -254,9 +255,9 @@ M_INLINE char*
m_str1ng_get_cstr(m_string_t v)
{
// Function can be called when contract is not fulfilled
char *const ptr_stack = &v->u.buffer[0];
char *const ptr_embed = &v->u.buffer[0];
char *const ptr_heap = v->u.heap.ptr;
return m_str1ng_stack_p(v) ? ptr_stack : ptr_heap;
return m_str1ng_embedded_p(v) ? ptr_embed : ptr_heap;
}

/* Return the string view a classic C string (const char *) */
Expand All @@ -265,9 +266,9 @@ m_string_get_cstr(const m_string_t v)
{
// Function cannot be called when contract is not fulfilled
// but it is called by contract (so no contract check to avoid infinite recursion).
const char *const ptr_stack = &v->u.buffer[0];
const char *const ptr_embed = &v->u.buffer[0];
const char *const ptr_heap = v->u.heap.ptr;
return m_str1ng_stack_p(v) ? ptr_stack : ptr_heap;
return m_str1ng_embedded_p(v) ? ptr_embed : ptr_heap;
}

/* Initialize the dynamic string (constructor)
Expand All @@ -284,7 +285,7 @@ M_INLINE void
m_string_clear(m_string_t v)
{
M_STR1NG_CONTRACT(v);
if (!m_str1ng_stack_p(v)) {
if (!m_str1ng_embedded_p(v)) {
M_MEMORY_FREE(v->u.heap.ptr);
v->u.heap.ptr = NULL;
}
Expand All @@ -305,8 +306,8 @@ m_string_clear_get_cstr(m_string_t v)
{
M_STR1NG_CONTRACT(v);
char *p = v->u.heap.ptr;
if (m_str1ng_stack_p(v)) {
// The string was stack allocated.
if (m_str1ng_embedded_p(v)) {
// The characters are embedded in the string.
p = &v->u.buffer[0];
// Need to allocate a heap string to return the copy.
size_t alloc = m_string_size(v)+1;
Expand Down Expand Up @@ -363,7 +364,7 @@ m_string_empty_p(const m_string_t v)
/* Internal method to fit the string to the given size
Ensures that the string capacity is greater than size_alloc
(size_alloc shall include the final null char).
It may move the string from stack based to heap based.
It may transform the string from embedded based to heap based.
The string 'v' no longer has a working size field.
Return a pointer to the writable string.
*/
Expand All @@ -390,23 +391,23 @@ m_str1ng_fit2size (m_string_t v, size_t size_alloc)
abort();
return NULL;
}
char *ptr = m_str1ng_stack_p(v) ? NULL : v->u.heap.ptr;
char *ptr = m_str1ng_embedded_p(v) ? NULL : v->u.heap.ptr;
ptr = M_MEMORY_REALLOC (char, ptr, alloc);
if (M_UNLIKELY_NOMEM (ptr == NULL)) {
M_MEMORY_FULL(sizeof (char) * alloc);
// NOTE: Return is currently broken.
abort();
return NULL;
}
// The pointer cannot be the stack buffer of the string as it is heap allocated
// The pointer cannot be the embedded buffer of the string as it is heap allocated
M_ASSERT(ptr != &v->u.buffer[0]);
if (m_str1ng_stack_p(v)) {
// The string was stack allocated.
/* Copy the stack allocation into the new heap allocation */
if (m_str1ng_embedded_p(v)) {
// The string was fully embedded.
/* Copy the embedded characters into the new heap allocation */
const size_t size = (size_t) v->u.buffer[sizeof(m_str1ng_heap_ct) - 1];
memcpy(ptr, &v->u.buffer[0], size+1);
}
// The string cannot be stack allocated anymore.
// The string cannot be fully embedded anymore.
v->u.heap.ptr = ptr;
m_str1ng_set_capacity(v, m, e);
// Size is not set as the function is called in context
Expand All @@ -431,37 +432,37 @@ m_string_reserve(m_string_t v, size_t alloc)
}
M_ASSERT (alloc > 0);
if (alloc < sizeof (m_str1ng_heap_ct)) {
// Allocation can fit in the stack space
if (!m_str1ng_stack_p(v)) {
/* Transform Heap Allocate to Stack Allocate */
// All characters can fit in am embedded structure
if (!m_str1ng_embedded_p(v)) {
/* Move the characters from the heap to within the structure */
char *ptr = &v->u.buffer[0];
char *oldptr = v->u.heap.ptr;
memcpy(ptr, oldptr, size+1);
// Free the allocated memory on the heap
M_MEMORY_FREE(oldptr);
v->u.buffer[sizeof(m_string_t)-2] = 0;
v->u.buffer[sizeof(m_string_t)-1] = (char) size;
} else {
/* Already a stack based alloc: nothing to do */
/* Already a fully embedded based type: nothing to do */
}
} else {
// Allocation cannot fit in the stack space
// Allocation cannot fit in the embedded structure space
// Need to allocate in heap space
unsigned char m, e;
size_t r_alloc = m_str1ng_round_capacity(&m, &e, (m_str1ng_size_t) alloc);
if (M_UNLIKELY_NOMEM (alloc > r_alloc)) {
M_MEMORY_FULL(sizeof (char) * alloc);
return;
}
char *ptr = m_str1ng_stack_p(v) ? NULL : v->u.heap.ptr;
char *ptr = m_str1ng_embedded_p(v) ? NULL : v->u.heap.ptr;
ptr = M_MEMORY_REALLOC (char, ptr, r_alloc);
if (M_UNLIKELY_NOMEM (ptr == NULL) ) {
M_MEMORY_FULL(sizeof (char) * alloc);
return;
}
if (m_str1ng_stack_p(v)) {
// Copy from stack space to heap space the string
char *ptr_stack = &v->u.buffer[0];
memcpy(ptr, ptr_stack, size+1);
if (m_str1ng_embedded_p(v)) {
// Copy the characters embedded in the structure to the allocated heap space
memcpy(ptr, &v->u.buffer[0], size+1);
M_ASSERT(size == (m_str1ng_size_t) size);
v->u.heap.size = (m_str1ng_size_t) size;
}
Expand Down Expand Up @@ -675,7 +676,7 @@ m_string_equal_p(const m_string_t v1, const m_string_t v2)
{
/* m_string_equal_p can be called with (at most) one string which is an OOR value.
In case of OOR value, .ptr is NULL and .alloc is the maximum or the maximum-1.
As it will detect a stack based string, it will read the size from the alloc fied
As it will detect a full embedded based string, it will read the size from the alloc fied
as 0xFF or 0xFE. In both cases, the size cannot be equal to a normal string
so the test m_string_size(v1) == m_string_size(v2) is false in this case.
*/
Expand Down Expand Up @@ -1283,7 +1284,7 @@ m_string_fgets(m_string_t v, FILE *f, m_string_fgets_t arg)
M_IF_EXCEPTION( m_str1ng_get_cstr(v)[size] = 0 );
/* The string buffer is not big enough:
increase it and continue reading */
/* v cannot be stack alloc */
/* v cannot be a full embedded type */
ptr = m_str1ng_fit2size (v, alloc + alloc/2);
alloc = m_string_capacity(v);
}
Expand Down

0 comments on commit 341d145

Please sign in to comment.