@@ -89,7 +89,6 @@ int elf_data_start;
8989
9090/**
9191 * arena_block_create() - Creates a new arena block with given capacity.
92- * The created arena block is guaranteed to be zero-initialized.
9392 * @capacity: The capacity of the arena block. Must be positive.
9493 *
9594 * Return: The pointer of created arena block. NULL if failed to allocate.
@@ -99,14 +98,14 @@ arena_block_t *arena_block_create(int capacity)
9998 arena_block_t * block = malloc (sizeof (arena_block_t ));
10099
101100 if (!block ) {
102- printf ("Failed to allocate memory for arena block\n" );
101+ printf ("Failed to allocate memory for arena block structure \n" );
103102 exit (1 );
104103 }
105104
106- block -> memory = calloc (capacity , sizeof (char ));
105+ block -> memory = malloc (capacity * sizeof (char ));
107106
108107 if (!block -> memory ) {
109- printf ("Failed to allocate memory for arena block\n" );
108+ printf ("Failed to allocate memory for arena block buffer \n" );
110109 free (block );
111110 exit (1 );
112111 }
@@ -117,6 +116,16 @@ arena_block_t *arena_block_create(int capacity)
117116 return block ;
118117}
119118
119+ /**
120+ * arena_block_free() - Free a single arena block and its memory buffer.
121+ * @block: Pointer to the arena_block_t to free. Must not be NULL.
122+ */
123+ void arena_block_free (arena_block_t * block )
124+ {
125+ free (block -> memory );
126+ free (block );
127+ }
128+
120129/**
121130 * arena_init() - Initializes the given arena with initial capacity.
122131 * @initial_capacity: The initial capacity of the arena. Must be positive.
@@ -126,6 +135,10 @@ arena_block_t *arena_block_create(int capacity)
126135arena_t * arena_init (int initial_capacity )
127136{
128137 arena_t * arena = malloc (sizeof (arena_t ));
138+ if (!arena ) {
139+ printf ("Failed to allocate memory for arena structure\n" );
140+ exit (1 );
141+ }
129142 arena -> head = arena_block_create (initial_capacity );
130143 return arena ;
131144}
@@ -141,47 +154,123 @@ arena_t *arena_init(int initial_capacity)
141154 */
142155void * arena_alloc (arena_t * arena , int size )
143156{
144- char * ptr ;
145- arena_block_t * block = arena -> head ;
146-
147- while (block ) {
148- if (block -> offset + size <= block -> capacity ) {
149- ptr = block -> memory + block -> offset ;
150- block -> offset += size ;
151- return ptr ;
152- }
153- if (!block -> next )
154- break ;
155- block = block -> next ;
157+ if (size <= 0 ) {
158+ printf ("arena_alloc: size must be positive" );
159+ exit (1 );
156160 }
157161
158- /* If no space is available, create a new block
159- * Allocate at least 256 KiB or the requested size
160- */
161- int new_capacity = size > DEFAULT_ARENA_SIZE ? size : DEFAULT_ARENA_SIZE ;
162- arena_block_t * new_block = arena_block_create (new_capacity );
162+ /* Align to PTR_SIZE bytes */
163+ size = (size + PTR_SIZE - 1 ) & ~(PTR_SIZE - 1 );
163164
164- if (!new_block )
165- return NULL ;
165+ if (!arena -> head || arena -> head -> offset + size > arena -> head -> capacity ) {
166+ /* Need a new block: choose capacity = max(DEFAULT_ARENA_SIZE, size) */
167+ int new_capacity =
168+ (size > DEFAULT_ARENA_SIZE ? size : DEFAULT_ARENA_SIZE );
169+ arena_block_t * new_block = arena_block_create (new_capacity );
170+ new_block -> next = arena -> head ;
171+ arena -> head = new_block ;
172+ }
166173
167- block -> next = new_block ;
168- ptr = new_block -> memory + new_block -> offset ;
169- new_block -> offset += size ;
174+ void * ptr = arena -> head -> memory + arena -> head -> offset ;
175+ arena -> head -> offset += size ;
170176 return ptr ;
171177}
172178
173179/**
174- * arena_reset() - Resets the given arena by resetting all blocks' offset to 0.
175- * @arena: The arena to reset. Must not be NULL.
180+ * arena_calloc() - arena_alloc() plus explicit zero‑initialization.
181+ * @arena: The arena to allocate memory from. Must not be NULL.
182+ * @n: Number of elements.
183+ * @size: Size of each element in bytes.
184+ *
185+ * Internally calls arena_alloc(n * size) and then fills the entire region
186+ * with zero bytes.
187+ *
188+ * Return: Pointer to zero-initialized memory.
176189 */
177- void arena_reset (arena_t * arena )
190+ void * arena_calloc (arena_t * arena , int n , int size )
178191{
179- arena_block_t * block = arena -> head ;
192+ int total = n * size ;
193+ void * ptr = arena_alloc (arena , total );
180194
181- while (block ) {
182- block -> offset = 0 ;
183- block = block -> next ;
195+ int * w_ptr = ptr ;
196+ int w_count = total >> 2 ;
197+ int b_index = w_count << 2 ;
198+
199+ for (int i = 0 ; i < w_count ; ++ i )
200+ w_ptr [i ] = 0 ;
201+
202+ char * b_ptr = ptr ;
203+ while (b_index < total )
204+ b_ptr [b_index ++ ] = 0 ;
205+
206+ return ptr ;
207+ }
208+
209+ /**
210+ * arena_realloc() - Reallocate a previously allocated region within the arena
211+ * to a different size.
212+ *
213+ * If existing region is the most recent allocation in the current block
214+ * and there is enough space to expand in place, simply extend the offset.
215+ * Otherwise, allocate a new region of the requested size and copy the old data.
216+ *
217+ * @arena: Pointer to the arena. Must not be NULL.
218+ * @oldptr: Pointer to the previously allocated memory in the arena.
219+ * @oldsz: Original size (in bytes) of that allocation.
220+ * @newsz: New desired size (in bytes).
221+ *
222+ * Return: Pointer to the reallocated (resized) memory region.
223+ */
224+ void * arena_realloc (arena_t * arena , char * oldptr , int oldsz , int newsz )
225+ {
226+ /* No need to grow; existing pointer is sufficient. */
227+ if (newsz <= oldsz )
228+ return oldptr ;
229+
230+ /* Check if oldptr is at the end of the current block's allocations */
231+ if (oldptr + oldsz == arena -> head -> memory + arena -> head -> offset &&
232+ arena -> head -> offset + (newsz - oldsz ) <= arena -> head -> capacity ) {
233+ /* Grow in place */
234+ arena -> head -> offset += (newsz - oldsz );
235+ return oldptr ;
184236 }
237+
238+ /* Otherwise, allocate new region and copy */
239+ void * newptr = arena_alloc (arena , newsz );
240+ memcpy (newptr , oldptr , oldsz );
241+ return newptr ;
242+ }
243+
244+ /**
245+ * arena_strdup() - Duplicate a NULL-terminated string into the arena.
246+ *
247+ * @arena: a Pointer to the arena. Must not be NULL.
248+ * @str: NULL-terminated input string to duplicate. Must not be NULL.
249+ *
250+ * Return: Pointer to the duplicated string stored in the arena.
251+ */
252+ char * arena_strdup (arena_t * arena , char * str )
253+ {
254+ int n = strlen (str );
255+ char * dup = arena_alloc (arena , n + 1 );
256+ memcpy (dup , str , n );
257+ dup [n ] = '\0' ;
258+ return dup ;
259+ }
260+
261+ /**
262+ * arena_memdup() - Duplicate a block of memory into the arena.
263+ * Allocates size bytes within the arena and copies data from the input pointer.
264+ *
265+ * @arena: a Pointer to the arena. Must not be NULL.
266+ * @data: data Pointer to the source memory. Must not be NULL.
267+ * @size: size Number of bytes to copy. Must be non-negative.
268+ *
269+ * Return: The pointer to the duplicated memory stored in the arena.
270+ */
271+ void * arena_memdup (arena_t * arena , void * data , int size )
272+ {
273+ return memcpy (arena_alloc (arena , size ), data , size );
185274}
186275
187276/**
@@ -194,8 +283,7 @@ void arena_free(arena_t *arena)
194283
195284 while (block ) {
196285 next = block -> next ;
197- free (block -> memory );
198- free (block );
286+ arena_block_free (block );
199287 block = next ;
200288 }
201289
0 commit comments