-
-
Notifications
You must be signed in to change notification settings - Fork 454
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
#124 add ringbuf and strbuf from flecs.util
- Loading branch information
1 parent
92c50b8
commit f47d3f8
Showing
5 changed files
with
768 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
|
||
|
||
#ifndef FLECS_RINGBUF_H_ | ||
#define FLECS_RINGBUF_H_ | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
typedef struct ecs_ringbuf_t ecs_ringbuf_t; | ||
|
||
FLECS_EXPORT | ||
ecs_ringbuf_t* _ecs_ringbuf_new( | ||
size_t elem_size, | ||
int32_t elem_count); | ||
|
||
#define ecs_ringbuf_new(T, elem_count)\ | ||
_ecs_ringbuf_new(sizeof(T), elem_count) | ||
|
||
FLECS_EXPORT | ||
void* _ecs_ringbuf_push( | ||
ecs_ringbuf_t *buffer, | ||
size_t elem_size); | ||
|
||
#define ecs_ringbuf_push(buffer, T)\ | ||
(T*)_ecs_ringbuf_push(buffer, sizeof(T)) | ||
|
||
FLECS_EXPORT | ||
void* _ecs_ringbuf_get( | ||
ecs_ringbuf_t *buffer, | ||
size_t elem_size, | ||
int32_t index); | ||
|
||
#define ecs_ringbuf_get(buffer, T, index)\ | ||
(T*)_ecs_ringbuf_get(buffer, sizeof(T), index) | ||
|
||
FLECS_EXPORT | ||
void* _ecs_ringbuf_last( | ||
ecs_ringbuf_t *buffer, | ||
size_t elem_size); | ||
|
||
#define ecs_ringbuf_last(buffer, T)\ | ||
(T*)_ecs_ringbuf_last(buffer, elem_size) | ||
|
||
FLECS_EXPORT | ||
int32_t ecs_ringbuf_index( | ||
ecs_ringbuf_t *buffer); | ||
|
||
FLECS_EXPORT | ||
int32_t ecs_ringbuf_count( | ||
ecs_ringbuf_t *buffer); | ||
|
||
FLECS_EXPORT | ||
void ecs_ringbuf_free( | ||
ecs_ringbuf_t *buffer); | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
#ifndef FLECS_STRBUF_H_ | ||
#define FLECS_STRBUF_H_ | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
#define ECS_STRBUF_INIT (ecs_strbuf_t){0} | ||
#define ECS_STRBUF_ELEMENT_SIZE (511) | ||
#define ECS_STRBUF_MAX_LIST_DEPTH (32) | ||
|
||
/* A buffer builds up a list of elements which individually can be up to N bytes | ||
* large. While appending, data is added to these elements. More elements are | ||
* added on the fly when needed. When an application calls ecs_strbuf_get, all | ||
* elements are combined in one string and the element administration is freed. | ||
* | ||
* This approach prevents reallocs of large blocks of memory, and therefore | ||
* copying large blocks of memory when appending to a large buffer. A buffer | ||
* preallocates some memory for the element overhead so that for small strings | ||
* there is hardly any overhead, while for large strings the overhead is offset | ||
* by the reduced time spent on copying memory. | ||
*/ | ||
|
||
typedef struct ecs_strbuf_element { | ||
bool buffer_embedded; | ||
uint32_t pos; | ||
char *buf; | ||
struct ecs_strbuf_element *next; | ||
} ecs_strbuf_element; | ||
|
||
typedef struct ecs_strbuf_element_embedded { | ||
ecs_strbuf_element super; | ||
char buf[ECS_STRBUF_ELEMENT_SIZE + 1]; | ||
} ecs_strbuf_element_embedded; | ||
|
||
typedef struct ecs_strbuf_element_str { | ||
ecs_strbuf_element super; | ||
char *alloc_str; | ||
} ecs_strbuf_element_str; | ||
|
||
typedef struct ecs_strbuf_list_elem { | ||
uint32_t count; | ||
const char *separator; | ||
} ecs_strbuf_list_elem; | ||
|
||
typedef struct ecs_strbuf_t { | ||
/* When set by an application, append will write to this buffer */ | ||
char *buf; | ||
|
||
/* The maximum number of characters that may be printed */ | ||
uint32_t max; | ||
|
||
/* Size of elements minus current element */ | ||
uint32_t size; | ||
|
||
/* The number of elements in use */ | ||
uint32_t elementCount; | ||
|
||
/* Always allocate at least one element */ | ||
ecs_strbuf_element_embedded firstElement; | ||
|
||
/* The current element being appended to */ | ||
ecs_strbuf_element *current; | ||
|
||
/* Stack that keeps track of number of list elements, used for conditionally | ||
* inserting a separator */ | ||
ecs_strbuf_list_elem list_stack[ECS_STRBUF_MAX_LIST_DEPTH]; | ||
uint32_t list_sp; | ||
} ecs_strbuf_t; | ||
|
||
/* Append format string to a buffer. | ||
* Returns false when max is reached, true when there is still space */ | ||
FLECS_EXPORT | ||
bool ecs_strbuf_append( | ||
ecs_strbuf_t *buffer, | ||
const char *fmt, | ||
...); | ||
|
||
/* Append format string with argument list to a buffer. | ||
* Returns false when max is reached, true when there is still space */ | ||
FLECS_EXPORT | ||
bool ecs_strbuf_vappend( | ||
ecs_strbuf_t *buffer, | ||
const char *fmt, | ||
va_list args); | ||
|
||
/* Append string to buffer. | ||
* Returns false when max is reached, true when there is still space */ | ||
FLECS_EXPORT | ||
bool ecs_strbuf_appendstr( | ||
ecs_strbuf_t *buffer, | ||
const char *str); | ||
|
||
/* Append source buffer to destination buffer. | ||
* Returns false when max is reached, true when there is still space */ | ||
FLECS_EXPORT | ||
bool ecs_strbuf_mergebuff( | ||
ecs_strbuf_t *dst_buffer, | ||
ecs_strbuf_t *src_buffer); | ||
|
||
/* Append string to buffer, transfer ownership to buffer. | ||
* Returns false when max is reached, true when there is still space */ | ||
FLECS_EXPORT | ||
bool ecs_strbuf_appendstr_zerocpy( | ||
ecs_strbuf_t *buffer, | ||
char *str); | ||
|
||
/* Append string to buffer, do not free/modify string. | ||
* Returns false when max is reached, true when there is still space */ | ||
FLECS_EXPORT | ||
bool ecs_strbuf_appendstr_zerocpy_const( | ||
ecs_strbuf_t *buffer, | ||
const char *str); | ||
|
||
/* Append n characters to buffer. | ||
* Returns false when max is reached, true when there is still space */ | ||
FLECS_EXPORT | ||
bool ecs_strbuf_appendstrn( | ||
ecs_strbuf_t *buffer, | ||
const char *str, | ||
uint32_t n); | ||
|
||
/* Return result string (also resets buffer) */ | ||
FLECS_EXPORT | ||
char *ecs_strbuf_get( | ||
ecs_strbuf_t *buffer); | ||
|
||
/* Reset buffer without returning a string */ | ||
FLECS_EXPORT | ||
void ecs_strbuf_reset( | ||
ecs_strbuf_t *buffer); | ||
|
||
/* Push a list */ | ||
FLECS_EXPORT | ||
void ecs_strbuf_list_push( | ||
ecs_strbuf_t *buffer, | ||
const char *list_open, | ||
const char *separator); | ||
|
||
/* Pop a new list */ | ||
FLECS_EXPORT | ||
void ecs_strbuf_list_pop( | ||
ecs_strbuf_t *buffer, | ||
const char *list_close); | ||
|
||
/* Insert a new element in list */ | ||
FLECS_EXPORT | ||
void ecs_strbuf_list_next( | ||
ecs_strbuf_t *buffer); | ||
|
||
/* Append formatted string as a new element in list */ | ||
FLECS_EXPORT | ||
bool ecs_strbuf_list_append( | ||
ecs_strbuf_t *buffer, | ||
const char *fmt, | ||
...); | ||
|
||
/* Append string as a new element in list */ | ||
FLECS_EXPORT | ||
bool ecs_strbuf_list_appendstr( | ||
ecs_strbuf_t *buffer, | ||
const char *str); | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
|
||
#include "flecs_private.h" | ||
|
||
struct ecs_ringbuf_t { | ||
ecs_vector_t *data; | ||
int32_t index; | ||
#ifndef NDEBUG | ||
size_t elem_size; | ||
#endif | ||
}; | ||
|
||
ecs_ringbuf_t* _ecs_ringbuf_new( | ||
size_t elem_size, | ||
int32_t elem_count) | ||
{ | ||
ecs_ringbuf_t *result = ecs_os_malloc(sizeof(ecs_ringbuf_t)); | ||
ecs_assert(result != NULL, ECS_OUT_OF_MEMORY, NULL); | ||
|
||
result->data = ecs_vector_new(elem_size, elem_count); | ||
result->index = 0; | ||
return result; | ||
} | ||
|
||
void* _ecs_ringbuf_push( | ||
ecs_ringbuf_t *buffer, | ||
size_t elem_size) | ||
{ | ||
ecs_assert(elem_size == buffer->elem_size, ECS_INVALID_PARAMETER, NULL); | ||
|
||
int32_t size = ecs_vector_size(buffer->data); | ||
int32_t count = ecs_vector_count(buffer->data); | ||
void *result; | ||
|
||
if (count == buffer->index) { | ||
result = _ecs_vector_add(&buffer->data, elem_size); | ||
} else { | ||
result = _ecs_vector_get(buffer->data, elem_size, buffer->index); | ||
} | ||
|
||
buffer->index = (buffer->index + 1) % size; | ||
|
||
return result; | ||
} | ||
|
||
void ecs_ringbuf_free( | ||
ecs_ringbuf_t *buffer) | ||
{ | ||
ecs_vector_free(buffer->data); | ||
ecs_os_free(buffer); | ||
} | ||
|
||
void* _ecs_ringbuf_get( | ||
ecs_ringbuf_t *buffer, | ||
size_t elem_size, | ||
int32_t index) | ||
{ | ||
int32_t count = ecs_vector_count(buffer->data); | ||
int32_t size = ecs_vector_size(buffer->data); | ||
index = ((buffer->index - count + size) + (int32_t)index) % size; | ||
return _ecs_vector_get(buffer->data, elem_size, index); | ||
} | ||
|
||
void* _ecs_ringbuf_last( | ||
ecs_ringbuf_t *buffer, | ||
size_t elem_size) | ||
{ | ||
int32_t index = buffer->index; | ||
if (!index) { | ||
index = ecs_vector_size(buffer->data); | ||
} | ||
|
||
return _ecs_vector_get(buffer->data, elem_size, index - 1); | ||
} | ||
|
||
int32_t ecs_ringbuf_index( | ||
ecs_ringbuf_t *buffer) | ||
{ | ||
return buffer->index; | ||
} | ||
|
||
int32_t ecs_ringbuf_count( | ||
ecs_ringbuf_t *buffer) | ||
{ | ||
return ecs_vector_count(buffer->data); | ||
} |
Oops, something went wrong.