| /**************************************************************************** |
| * include/obstack.h |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. The |
| * ASF licenses this file to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance with the |
| * License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations |
| * under the License. |
| * |
| ****************************************************************************/ |
| |
| /* This is based on the GlibC API but the implementation is not exactly same. |
| * The major difference is how required memory is allocated. The GlibC |
| * implementation starts with 4KB of allocated space. That would make it |
| * impossible to use this on MCUs. This implementation rather tries to |
| * allocated only required amount of space and it won't allocate chunk unless |
| * grow functions are used and even then it uses realloc to release unused |
| * space. It also in default won't use 4KB per chunk but rather just BUFSIZ. |
| * |
| * Not implemented interface: |
| * obstack_alignment_mask: |
| * The current implementation does not provide any alignment guaranties. |
| * obstack_chunk_alloc and obstack_chunk_free: |
| * Internal implementation uses not only alloc and free but also realloc |
| * and thus standard implementations are used unconditionally instead of |
| * requiring users to provide declaration for these functions. |
| */ |
| |
| #ifndef __INCLUDE_OBSTACK_H |
| #define __INCLUDE_OBSTACK_H |
| |
| /**************************************************************************** |
| * Included Files |
| ****************************************************************************/ |
| |
| #include <stddef.h> |
| #include <stdarg.h> |
| |
| /**************************************************************************** |
| * Pre-processor Definitions |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Name: obstack_chunk_size |
| * |
| * Description: |
| * The access to the obstack configuration specifying the size of the |
| * single chunk used when growing object. |
| * It is documented t hat this is macro and that it is possible to use |
| * assignment to change the chunk size (eq.: obstack_chunk_size(h) = 1024). |
| * |
| * The default chunk size is set to BUFSIZ. |
| * |
| * The chunks size has to be always power of two due to the limitations of |
| * the obstack_make_room implementation! |
| * |
| * Input Parameters: |
| * h: pointer to the handle used to grow the object. |
| * |
| * Returned Value: |
| * Size of the single chunk. |
| * |
| ****************************************************************************/ |
| |
| #define obstack_chunk_size(h) ((h)->chunk_size) |
| |
| /**************************************************************************** |
| * Name: obstack_base |
| * |
| * Description: |
| * Provides access to the tentative starting address of the |
| * currently growing object. |
| * |
| * Input Parameters: |
| * h: pointer to the handle used to grow the object. |
| * |
| * Returned Value: |
| * Tentative starting address of the currently growing object. |
| * |
| ****************************************************************************/ |
| |
| #define obstack_base(h) ((h)->object_base) |
| |
| /**************************************************************************** |
| * Name: obstack_next_free |
| * |
| * Description: |
| * Provides access to the tentative address just after the end of the |
| * currently growing object. |
| * |
| * Input Parameters: |
| * h: pointer to the handle used to grow the object. |
| * |
| * Returned Value: |
| * Address just after the end of the currently growing object. |
| * |
| ****************************************************************************/ |
| |
| #define obstack_next_free(h) ((h)->next_free) |
| |
| /**************************************************************************** |
| * Name: obstack_blank_fast |
| * |
| * Description: |
| * Moves the end of the currently growing object by given size and thus |
| * adding given number of uninitialized bytes to the growing object. |
| * There is no check if there is enough room and thus it is easy to cause |
| * buffer overrun. Use only when you are sure that there is enough room! |
| * |
| * Input Parameters: |
| * h: pointer to the handle used to grow the object. |
| * size: number of bytes |
| * |
| ****************************************************************************/ |
| |
| #define obstack_blank_fast(h, size) ((void)((h)->next_free += (size))) |
| |
| /**************************************************************************** |
| * Name: obstack_1grow_fast |
| * |
| * Description: |
| * Adds one byte to the currently growing object. |
| * There is no check if there is enough room and thus it is easy to cause |
| * buffer overrun. Use only when you are sure that there is enough room! |
| * |
| * Input Parameters: |
| * h: pointer to the handle used to grow the object. |
| * data: byte to be added |
| * |
| ****************************************************************************/ |
| |
| #define obstack_1grow_fast(h, data) ((void)(*((h)->next_free++) = (data))) |
| |
| /**************************************************************************** |
| * Name: obstack_ptr_grow_fast |
| * |
| * Description: |
| * Adds one pointer to the currently growing object. |
| * There is no check if there is enough room and thus it is easy to cause |
| * buffer overrun. Use only when you are sure that there is enough room! |
| * |
| * Input Parameters: |
| * h: pointer to the handle used to grow the object. |
| * ptr: pointer to be added |
| * |
| ****************************************************************************/ |
| |
| #define obstack_ptr_grow_fast(h, ptr) \ |
| do { \ |
| FAR struct obstack *__o = (h); \ |
| *(const void **)__o->next_free = (ptr); \ |
| __o->next_free += sizeof(const void*); \ |
| } while (0) |
| |
| /**************************************************************************** |
| * Name: obstack_int_grow_fast |
| * |
| * Description: |
| * Adds one integer to the currently growing object. |
| * There is no check if there is enough room and thus it is easy to cause |
| * buffer overrun. Use only when you are sure that there is enough room! |
| * |
| * Input Parameters: |
| * h: pointer to the handle used to grow the object. |
| * data: integer to be added |
| * |
| ****************************************************************************/ |
| |
| #define obstack_int_grow_fast(h, data) \ |
| do { \ |
| FAR struct obstack *__o = (h); \ |
| *(int*)__o->next_free = (data); \ |
| __o->next_free += sizeof(const void*); \ |
| } while (0) |
| |
| /**************************************************************************** |
| * Public Type Definitions |
| ****************************************************************************/ |
| |
| struct _obstack_chunk /* Chunk head. */ |
| { |
| FAR char *limit; /* Address of char after this chunk */ |
| FAR struct _obstack_chunk *prev; /* Address of prior chunk or NULL */ |
| }; |
| |
| struct obstack |
| { |
| size_t chunk_size; /* Preferred size to allocate chunks in */ |
| FAR struct _obstack_chunk *chunk; /* Address of current struct _obstack_chunk */ |
| FAR char *object_base; /* Address of object we are building */ |
| FAR char *next_free; /* Where to add next char to current object */ |
| }; |
| |
| /**************************************************************************** |
| * Public Function Prototypes |
| ****************************************************************************/ |
| |
| #undef EXTERN |
| #if defined(__cplusplus) |
| #define EXTERN extern "C" |
| extern "C" |
| { |
| #else |
| #define EXTERN extern |
| #endif |
| |
| /**************************************************************************** |
| * Name: obstack_init |
| * |
| * Description: |
| * Initialize obstack for allocation of objects. |
| * Compared to the GlibC version this won't initialize a first chunk. |
| * |
| * Input Parameters: |
| * h: pointer to the handle to initialize |
| * |
| ****************************************************************************/ |
| |
| void obstack_init(FAR struct obstack *h); |
| |
| /**************************************************************************** |
| * Name: obstack_alloc |
| * |
| * Description: |
| * Allocate an object of given size with uninitialized bytes. |
| * Compared to the GlibC version this uses malloc to allocate exactly |
| * required space (plus overhead) and nothing more. |
| * |
| * Input Parameters: |
| * h: pointer to the handle to allocate an object in |
| * size: number of bytes to allocate |
| * |
| ****************************************************************************/ |
| |
| FAR void *obstack_alloc(FAR struct obstack *h, size_t size); |
| |
| /**************************************************************************** |
| * Name: obstack_copy |
| * |
| * Description: |
| * Allocate an object of given size with contents copied from address. |
| * The same remarks regarding the allocation apply here as for |
| * obstack_alloc. |
| * |
| * Input Parameters: |
| * h: pointer to the handle to allocate an object in |
| * address: pointer to the bytes to be used to initialize new object |
| * size: number of bytes to allocate |
| * |
| ****************************************************************************/ |
| |
| FAR void *obstack_copy(FAR struct obstack *h, |
| FAR const void *address, size_t size); |
| |
| /**************************************************************************** |
| * Name: obstack_copy0 |
| * |
| * Description: |
| * Allocate an object of given size+1 with contents copied from address and |
| * append null byte at the end. |
| * The same remarks regarding the allocation apply here as for |
| * obstack_alloc. |
| * |
| * Input Parameters: |
| * h: pointer to the handle to allocate an object in |
| * address: pointer to the bytes to be used to initialize new object |
| * size: number of bytes to allocate (excluding the null byte) |
| * |
| ****************************************************************************/ |
| |
| FAR void *obstack_copy0(FAR struct obstack *h, |
| FAR const void *address, size_t size); |
| |
| /**************************************************************************** |
| * Name: obstack_free |
| * |
| * Description: |
| * Free objects (and everything allocated in the specified obstack more |
| * recently than object). You can pass NULL to free everything. |
| * The buffer the allocated object was preset is kept and thus can be |
| * immediately reused for growing. The only exception for this is when NULL |
| * is passed as in such case even the last buffer is freed. |
| * |
| * Input Parameters: |
| * h: pointer to the handle object belongs to |
| * object: the pointer to the object or NULL |
| * |
| ****************************************************************************/ |
| |
| void obstack_free(FAR struct obstack *h, FAR void *object); |
| |
| /**************************************************************************** |
| * Name: obstack_make_room |
| * |
| * Description: |
| * This is non-standard function that is probably available only on NuttX! |
| * Make sure that there is room in the buffer to fit object with given |
| * size. The allocation performed is in multiples of chunk_size specified |
| * for the obstack. |
| * |
| * Input Parameters: |
| * h: pointer to the handle where room should be made |
| * size: number of bytes to be free for growth |
| * |
| * Assumptions/Limitations: |
| * The obstack's chunk_size is expected to be power of two. This helps to |
| * eliminate division that might not be implemented in the HW and thus |
| * inefficient. |
| * |
| ****************************************************************************/ |
| |
| void obstack_make_room(struct obstack *h, size_t size); |
| |
| /**************************************************************************** |
| * Name: obstack_blank |
| * |
| * Description: |
| * Grow object by given size. The bytes are uninitialized. |
| * |
| * Input Parameters: |
| * h: pointer to the handle to allocated object to |
| * size: number of bytes to grow object |
| * |
| ****************************************************************************/ |
| |
| void obstack_blank(FAR struct obstack *h, size_t size); |
| |
| /**************************************************************************** |
| * Name: obstack_grow |
| * |
| * Description: |
| * Grow object by given size and allocated it with bytes from address. |
| * |
| * Input Parameters: |
| * h: pointer to the handle to allocated object to |
| * address: pointer to the bytes to be used to initialize the new object |
| * size: number of bytes to grow object |
| * |
| ****************************************************************************/ |
| |
| void obstack_grow(FAR struct obstack *h, |
| FAR const void *address, size_t size); |
| |
| /**************************************************************************** |
| * Name: obstack_grow0 |
| * |
| * Description: |
| * Grow object by given size+1 and allocated it with bytes from address |
| * plus null byte at the end. |
| * |
| * Input Parameters: |
| * h: pointer to the handle to allocated object to |
| * address: pointer to the bytes to be used to initialize the new object |
| * size: number of bytes to grow object (excluding the null byte) |
| * |
| ****************************************************************************/ |
| |
| void obstack_grow0(FAR struct obstack *h, |
| FAR const void *address, size_t size); |
| |
| /**************************************************************************** |
| * Name: obstack_1grow |
| * |
| * Description: |
| * Grow object by single data byte. |
| * |
| * Input Parameters: |
| * h: pointer to the handle to allocated object to |
| * data: byte to be added to the growing object |
| * |
| ****************************************************************************/ |
| |
| void obstack_1grow(FAR struct obstack *h, char data); |
| |
| /**************************************************************************** |
| * Name: obstack_ptr_grow |
| * |
| * Description: |
| * Grow object by one pointer. |
| * |
| * Input Parameters: |
| * h: pointer to the handle to allocated object to |
| * ptr: pointer to be added to the growing object |
| * |
| ****************************************************************************/ |
| |
| void obstack_ptr_grow(FAR struct obstack *h, const void *ptr); |
| |
| /**************************************************************************** |
| * Name: obstack_int_grow |
| * |
| * Description: |
| * Grow object by one integer. |
| * |
| * Input Parameters: |
| * h: pointer to the handle to allocated object to |
| * data: integer to be added to the growing object |
| * |
| ****************************************************************************/ |
| |
| void obstack_int_grow(FAR struct obstack *h, int data); |
| |
| /**************************************************************************** |
| * Name: obstack_finish |
| * |
| * Description: |
| * Finish growing object and receive address to it. |
| * Compared to the GlibC version this uses realloc to reduce buffer size to |
| * only allocated amount. The non-standard obstack_finish_norealloc can be |
| * used if you want the standard behavior for ever reason. |
| * |
| * Input Parameters: |
| * h: pointer to the handle used to grow the object. |
| * |
| * Returned Value: |
| * Permanent address to the object. |
| * |
| ****************************************************************************/ |
| |
| FAR void *obstack_finish(FAR struct obstack *h); |
| |
| /**************************************************************************** |
| * Name: obstack_finish_norealloc |
| * |
| * Description: |
| * Finish growing object and receive address to it without reallocating |
| * buffer to fit the object (keeping space for more growth). |
| * |
| * Input Parameters: |
| * h: pointer to the handle used to grow the object. |
| * |
| * Returned Value: |
| * Permanent address to the object. |
| * |
| ****************************************************************************/ |
| |
| FAR void *obstack_finish_norealloc(FAR struct obstack *h); |
| |
| /**************************************************************************** |
| * Name: obstack_object_size |
| * |
| * Description: |
| * Calculate the size of the currently growing object. |
| * |
| * Input Parameters: |
| * h: pointer to the handle used to grow the object. |
| * |
| * Returned Value: |
| * Size of the object. |
| * |
| ****************************************************************************/ |
| |
| size_t obstack_object_size(FAR struct obstack *h); |
| |
| /**************************************************************************** |
| * Name: obstack_room |
| * |
| * Description: |
| * Calculate the number of bytes available for growth before reallocation |
| * is required. |
| * |
| * Input Parameters: |
| * h: pointer to the handle used to grow the object. |
| * |
| * Returned Value: |
| * Number of free bytes. |
| * |
| ****************************************************************************/ |
| |
| size_t obstack_room(FAR struct obstack *h); |
| |
| /**************************************************************************** |
| * Name: obstack_printf |
| * |
| * Description: |
| * This is similar to the asprintf except it uses obstack to allocate |
| * string on. The characters are written onto the end of the currently |
| * growing object and terminated by null byte. |
| * |
| * This function is defined in stdio.h in GlibC. There is no definition |
| * that would be in stdio.h required for these here and thus it is easier |
| * to just keep these functions here as user has to include obstack anyway |
| * to get the full functionality. |
| * |
| * Input Parameters: |
| * h: pointer to the handle used to grow the object. |
| * fmt: format string with its format inputs followed. |
| * |
| * Returned Value: |
| * Number of characters added to the obstack excluding the null byte. |
| * |
| ****************************************************************************/ |
| |
| int obstack_printf(FAR struct obstack *h, FAR const char *fmt, ...) |
| printf_like(2, 3); |
| |
| /**************************************************************************** |
| * Name: obstack_vprintf |
| * |
| * Description: |
| * This is similar to the vasprintf except it uses obstack to allocate |
| * string on. The characters are written onto the end of the currently |
| * growing object and terminated by null byte. |
| * |
| * The same remarks are applied here as for obstack_printf regarding the |
| * definition location in GlibC. |
| * |
| * Input Parameters: |
| * h: pointer to the handle used to grow the object. |
| * fmt: format string |
| * ap: format string input as a variable argument list |
| * |
| * Returned Value: |
| * Number of characters added to the obstack excluding the null byte. |
| * |
| ****************************************************************************/ |
| |
| int obstack_vprintf(FAR struct obstack *h, FAR const char *fmt, va_list ap) |
| printf_like(2, 0); |
| |
| /**************************************************************************** |
| * Name: obstack_alloc_failed_handler |
| * |
| * Description: |
| * Error handler called when 'obstack_chunk_alloc' failed to allocate more |
| * memory. This can be set to a user defined function which should either |
| * abort gracefully or use longjump - but shouldn't return. The default |
| * action is to print a message and abort. |
| * |
| ****************************************************************************/ |
| |
| extern void (*obstack_alloc_failed_handler) (void); |
| |
| #undef EXTERN |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif /* __INCLUDE_OBSTACK_H */ |