libs/libc: add obstack

This commit is contained in:
Karel Kočí 2022-08-31 16:23:48 +02:00 committed by Xiang Xiao
parent 739210708a
commit 61b1791584
17 changed files with 1521 additions and 0 deletions

479
include/obstack.h Normal file
View File

@ -0,0 +1,479 @@
/****************************************************************************
* 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
*
* Returned Value:
* The new address just after the end of the currently growing object.
*
****************************************************************************/
#define obstack_blank_fast(h, size) ((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
*
* Returned Value:
* Added byte.
*
****************************************************************************/
#define obstack_1grow_fast(h, data) (*((h)->next_free++) = (data))
/****************************************************************************
* 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_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, ...)
printflike(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)
printflike(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 */

View File

@ -42,6 +42,7 @@ include misc/Make.defs
include modlib/Make.defs
include net/Make.defs
include netdb/Make.defs
include obstack/Make.defs
include pthread/Make.defs
include pwd/Make.defs
include queue/Make.defs

View File

@ -0,0 +1,29 @@
############################################################################
# libs/libc/obstack/Make.defs
#
# 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.
#
############################################################################
CSRCS += lib_obstack_init.c lib_obstack_alloc.c lib_obstack_copy.c
CSRCS += lib_obstack_free.c lib_obstack_make_room.c lib_obstack_blank.c
CSRCS += lib_obstack_grow.c lib_obstack_finish.c
CSRCS += lib_obstack_object_size.c lib_obstack_room.c
CSRCS += lib_obstack_printf.c lib_obstack_vprintf.c
CSRCS += lib_obstack_malloc.c
DEPPATH += --dep-path obstack
VPATH += :obstack

View File

@ -0,0 +1,68 @@
/****************************************************************************
* libs/libc/obstack/lib_obstack_alloc.c
*
* 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <obstack.h>
#include "lib_obstack_malloc.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* 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)
{
FAR struct _obstack_chunk *prev;
FAR void *res;
if (h->chunk == NULL || (h->chunk->limit - h->object_base) < size)
{
/* TODO: could we just expand current allocation? */
prev = h->chunk;
h->chunk = lib_obstack_malloc(size + sizeof(struct _obstack_chunk));
h->chunk->limit =
(FAR char *)h->chunk + sizeof(struct _obstack_chunk) + size;
h->chunk->prev = prev;
h->object_base = (FAR char *)h->chunk + sizeof(struct _obstack_chunk);
}
res = h->object_base;
h->object_base += size;
h->next_free = h->object_base;
return res;
}

View File

@ -0,0 +1,47 @@
/****************************************************************************
* libs/libc/obstack/lib_obstack_blank.c
*
* 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <obstack.h>
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* 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)
{
obstack_make_room(h, size);
obstack_blank_fast(h, size);
}

View File

@ -0,0 +1,78 @@
/****************************************************************************
* libs/libc/obstack/lib_obstack_copy.c
*
* 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <obstack.h>
#include <string.h>
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* 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)
{
FAR void *res = obstack_alloc(h, size);
memcpy(res, address, size);
return res;
}
/****************************************************************************
* 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)
{
FAR char *res = obstack_alloc(h, size + 1);
memcpy(res, address, size);
res[size] = '\0';
return res;
}

View File

@ -0,0 +1,98 @@
/****************************************************************************
* libs/libc/obstack/lib_obstack_finish.c
*
* 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <obstack.h>
#include <assert.h>
#include "lib_obstack_malloc.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* 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)
{
size_t chsize;
void *chbase;
/* To reduce memory used by allocation we reallocate the chunk to fit
* exactly data it contains.
* This can be performed only if there is no other object preset in the
* chunk already as we can't ensure that realloc won't move the data and
* thus invalidate already returned address to the existing object.
* The object can be there if called uses obstack_finish alongside with
* obstack_finish_norealloc.
*/
chbase = (FAR char *)h->chunk + sizeof(struct _obstack_chunk);
if (chbase == h->object_base)
{
chsize = h->next_free - (FAR char *)h->chunk;
h->chunk = lib_obstack_realloc(h->chunk, chsize);
h->chunk->limit = (FAR void *)h->chunk + chsize;
h->object_base = h->chunk->limit;
h->next_free = h->chunk->limit;
return (FAR void *)h->chunk + sizeof(struct _obstack_chunk);
}
return obstack_finish_norealloc(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)
{
FAR char *res = h->object_base;
h->object_base = h->next_free;
return res;
}

View File

@ -0,0 +1,76 @@
/****************************************************************************
* libs/libc/obstack/lib_obstack_free.c
*
* 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <obstack.h>
#include <nuttx/lib/lib.h>
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* 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)
{
FAR struct _obstack_chunk *prev;
while (h->chunk)
{
if (object >= (FAR void *)&h->chunk + sizeof(struct _obstack_chunk)
&& object < (FAR void *)h->chunk->limit)
{
/* The object is in this chunk so just move object base.
* Note: this keeps the last chunk allocated. This is desirable
* behavior as we can decide if we want to reuse it by either
* passing NULL to free everything or the first returned object to
* keep the chunk allocated.
*/
h->object_base = object;
h->next_free = object;
return;
}
prev = h->chunk->prev;
lib_free(h->chunk);
h->chunk = prev;
}
h->object_base = NULL;
h->next_free = NULL;
}

View File

@ -0,0 +1,93 @@
/****************************************************************************
* libs/libc/obstack/lib_obstack_grow.c
*
* 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <obstack.h>
#include <string.h>
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* 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)
{
obstack_make_room(h, size);
memcpy(h->next_free, address, size);
h->next_free += 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)
{
obstack_make_room(h, size + 1);
memcpy(h->next_free, address, size);
h->next_free += size;
*h->next_free = '\0';
h->next_free++;
}
/****************************************************************************
* 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)
{
obstack_make_room(h, 1);
obstack_1grow_fast(h, data);
}

View File

@ -0,0 +1,53 @@
/****************************************************************************
* libs/libc/obstack/lib_obstack_init.c
*
* 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <obstack.h>
#include <stdio.h>
#include <assert.h>
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* 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)
{
DEBUGASSERT(h != NULL);
h->chunk_size = BUFSIZ;
h->chunk = NULL;
h->object_base = NULL;
h->next_free = NULL;
}

View File

@ -0,0 +1,105 @@
/****************************************************************************
* libs/libc/obstack/lib_obstack_make_room.c
*
* 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <obstack.h>
#include <assert.h>
#include <string.h>
#include "lib_obstack_malloc.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* 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(FAR struct obstack *h, size_t size)
{
unsigned i;
size_t mask;
DEBUGASSERT(h);
if (obstack_room(h) >= size)
{
return; /* No need to allocate anything */
}
size_t object_size = obstack_object_size(h);
size += object_size + sizeof(struct _obstack_chunk);
/* Note: this is rounding up to the multiple of chunk size that is power of
* two. Thus this creates limitation that chunks can be only power of two.
*/
mask = h->chunk_size;
for (i = 1; i < sizeof(size_t); i <<= 1)
mask |= mask >> i;
size = (size + mask) & ~mask;
if (h->chunk == NULL ||
h->object_base != (FAR char *)h->chunk + sizeof(struct _obstack_chunk))
{
/* Allocate new chunk if there is something in the chunk already or if
* there is no chunk yet.
*/
FAR struct _obstack_chunk *prev = h->chunk;
h->chunk = lib_obstack_malloc(size);
h->chunk->prev = prev;
/* Move growing object to the new chunk */
memcpy((FAR char *)h->chunk + sizeof(struct _obstack_chunk),
h->object_base, object_size);
}
else
{
h->chunk = lib_obstack_realloc(h->chunk, size);
}
h->chunk->limit =
(FAR char *)h->chunk + sizeof(struct _obstack_chunk) + size;
h->object_base = (FAR char *)h->chunk + sizeof(struct _obstack_chunk);
h->next_free = h->object_base + object_size;
}

View File

@ -0,0 +1,81 @@
/****************************************************************************
* libs/libc/obstack/lib_obstack_malloc.c
*
* 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "lib_obstack_malloc.h"
#include <stdlib.h>
#include <nuttx/lib/lib.h>
#include <assert.h>
#include <debug.h>
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static void default_alloc_failed_handler(void);
/****************************************************************************
* Public Data
****************************************************************************/
void (*obstack_alloc_failed_handler)(void) = default_alloc_failed_handler;
/****************************************************************************
* Private Functions
****************************************************************************/
static void default_alloc_failed_handler(void)
{
lerr("Failed to allocate to grow obstack");
abort();
}
/****************************************************************************
* Public Functions
****************************************************************************/
FAR void *lib_obstack_malloc(size_t size)
{
FAR void *res;
res = lib_malloc(size);
if (res)
return res;
obstack_alloc_failed_handler();
PANIC();
}
FAR void *lib_obstack_realloc(FAR void *ptr, size_t size)
{
FAR void *res;
res = lib_realloc(ptr, size);
if (res)
return res;
obstack_alloc_failed_handler();
PANIC();
}

View File

@ -0,0 +1,53 @@
/****************************************************************************
* libs/libc/obstack/lib_obstack_malloc.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.
*
****************************************************************************/
#ifndef __LIBS_LIBC_OBSTACK_MALLOC_H
#define __LIBS_LIBC_OBSTACK_MALLOC_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/compiler.h>
#include <stddef.h>
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
FAR void *lib_obstack_malloc(size_t size);
FAR void *lib_obstack_realloc(FAR void *ptr, size_t size);
#undef EXTERN
#if defined(__cplusplus)
}
#endif
#endif /* __LIBS_LIBC_OBSTACK_MALLOC_H */

View File

@ -0,0 +1,48 @@
/****************************************************************************
* libs/libc/obstack/lib_obstack_object_size.c
*
* 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <obstack.h>
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* 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)
{
return h->next_free - h->object_base;
}

View File

@ -0,0 +1,64 @@
/****************************************************************************
* libs/libc/obstack/lib_obstack_printf.c
*
* 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <obstack.h>
#include <stdarg.h>
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* 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, ...)
{
int res;
va_list ap;
va_start(ap, fmt);
res = obstack_vprintf(h, fmt, ap);
va_end(ap);
return res;
}

View File

@ -0,0 +1,51 @@
/****************************************************************************
* libs/libc/obstack/lib_obstack_room.c
*
* 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <obstack.h>
#include <assert.h>
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* 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)
{
DEBUGASSERT(h);
return h->chunk != NULL ? h->chunk->limit - h->next_free : 0;
}

View File

@ -0,0 +1,97 @@
/****************************************************************************
* libs/libc/obstack/lib_obstack_vprintf.c
*
* 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <obstack.h>
#include <assert.h>
#include <nuttx/streams.h>
/****************************************************************************
* Private Types
****************************************************************************/
struct obstack_stream
{
struct lib_outstream_s public;
FAR struct obstack *h;
};
/****************************************************************************
* Private Functions
****************************************************************************/
static int obstack_puts(FAR struct lib_outstream_s *this,
FAR const void *buf, int len)
{
FAR struct obstack_stream *mthis = (FAR struct obstack_stream *)this;
DEBUGASSERT(this);
obstack_grow(mthis->h, buf, len);
return len;
}
static void obstack_putc(FAR struct lib_outstream_s *this, int ch)
{
char tmp = ch;
obstack_puts(this, &tmp, 1);
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* 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)
{
struct obstack_stream outstream;
outstream.public.put = obstack_putc;
outstream.public.puts = obstack_puts;
outstream.public.flush = lib_noflush;
outstream.public.nput = 0;
outstream.h = h;
return lib_vsprintf(&outstream.public, fmt, ap);
}