Version 6.3
Copyright © 2005 - 2012 Lowell D. Thomas
APG
  … ABNF Parser Generator
All Data Structures Files Functions Variables Typedefs Macros Pages
Vector.c
Go to the documentation of this file.
1 /*******************************************************************************
2  APG Version 6.3
3  Copyright (C) 2005 - 2012 Lowell D. Thomas, all rights reserved
4 
5  author: Lowell D. Thomas
6  email: lowell@coasttocoastresearch.com
7  website: http://www.coasttocoastresearch.com
8 
9  This program is free software: you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 2 of the License, or
12  (at your option) any later version.
13 
14  This program is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU General Public License for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with this program. If not, see
21  <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>
22  or write to the Free Software Foundation, Inc.,
23  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 *******************************************************************************/
44 #include "Apg.h"
45 #include "Private.h"
46 
48 // VECTOR COMPONENT FUNCTIONS
50 
51 // private vector instance context
52 typedef struct
53 {
54  void* vpMemCtx; // context to the underlying memory component
55  char* cpData; // pointer to the vector's data buffer
56  apg_uint uiElementSize; // number of bytes in one element
57  apg_uint uiReserved; // number of elements that have been reserved on the buffer
58  apg_uint uiUsed; // number of the reserved elements that have been used
59  apg_uint uiReallocations; // statistics - number buffer reallocations done
60  void* vpValidate; // must be equal to the struct address
61 } APG_VECTOR_CTX;
62 
63 typedef struct
64 {
65  apg_uint uiElementSize;
66  apg_uint uiElements;
67  apg_uint uiValidator;
68 } APG_VECTOR_EXPORT_HDR;
71 static apg_uint uiGrow(APG_VECTOR_CTX* spCtx, apg_uint uiElements);
72 
81 void* vpVecCtor(void* vpMemCtx, apg_uint uiElementSize, apg_uint uiInitialAlloc)
82 {
83  void* vpReturn = NULL;
84  APG_VECTOR_CTX* spCtx;
85  while(APG_TRUE){
86  if(!vpMemCtx){break;}
87  if(!uiMemValidate(vpMemCtx)){break;}
88  if(uiElementSize == 0){uiElementSize = APG_VEC_ELEMENT;}
89  if(uiInitialAlloc == 0){uiInitialAlloc = APG_VEC_ALLOC;}
90 
91  // allocate the vector context
92  spCtx = (APG_VECTOR_CTX*)vpMemAlloc(vpMemCtx, sizeof(APG_VECTOR_CTX));
93  if(!spCtx){break;}
94 
95  // allocate the initial vector buffer
96  memset((void*)spCtx, 0, sizeof(*spCtx));
97  spCtx->vpMemCtx = vpMemCtx;
98  spCtx->cpData = (char*)vpMemAlloc(vpMemCtx, uiElementSize * uiInitialAlloc);
99  if(!spCtx->cpData)
100  {
101  // free the context and return failure
102  vMemFree(vpMemCtx, (void*)spCtx);
103  break;
104  }
105 
106  // initialize the context
107  spCtx->vpMemCtx = vpMemCtx;
108  spCtx->uiElementSize = uiElementSize;
109  spCtx->uiReserved = uiInitialAlloc;
110 
111  // success
112  spCtx->vpValidate = (void*)spCtx;
113  vpReturn = (void*)spCtx;
114  break;
115  }
116  return vpReturn;
117 }
118 
123 void vVecDtor(void* vpCtx)
124 {
125  APG_VECTOR_CTX* spCtx = (APG_VECTOR_CTX*)vpCtx;
126  // no error and no action if vpCtx = NULL
127  if(vpCtx && (spCtx->vpValidate == (void*)spCtx))
128  {
129  // delete the data buffer & context
130  spCtx->vpValidate = NULL;
131  vMemFree(spCtx->vpMemCtx, (void*)spCtx->cpData);
132  vMemFree(spCtx->vpMemCtx, (void*)spCtx);
133  }
134  return;
135 }
136 
142 apg_uint uiVecValidate(void* vpCtx){
143  APG_VECTOR_CTX* spCtx = (APG_VECTOR_CTX*)vpCtx;
144  return (spCtx && spCtx->vpValidate == (void*)spCtx);
145 }
146 
152 apg_uint uiVecBytes(void* vpCtx)
153 {
154  apg_uint uiRet = 0;
155  APG_VECTOR_CTX* spCtx = (APG_VECTOR_CTX*)vpCtx;
156  if(spCtx && spCtx->vpValidate == (void*)spCtx){
157  uiRet = spCtx->uiUsed * spCtx->uiElementSize;
158  }
159  return uiRet;
160 }
161 
167 apg_uint uiVecSize(void* vpCtx)
168 {
169  apg_uint uiRet = 0;
170  APG_VECTOR_CTX* spCtx = (APG_VECTOR_CTX*)vpCtx;
171  if(spCtx && spCtx->vpValidate == (void*)spCtx){
172  uiRet = spCtx->uiUsed;
173  }
174  return uiRet;
175 }
176 
186 {
187  apg_uint uiRet = 0;
188  APG_VECTOR_CTX* spCtx = (APG_VECTOR_CTX*)vpCtx;
189  if(spCtx && spCtx->vpValidate == (void*)spCtx){
190  uiRet = spCtx->uiElementSize;
191  }
192  return uiRet;
193 }
194 
201 {
202  apg_uint uiRet = 0;
203  APG_VECTOR_CTX* spCtx = (APG_VECTOR_CTX*)vpCtx;
204  if(spCtx && spCtx->vpValidate == (void*)spCtx){
205  uiRet = spCtx->uiReallocations;
206  }
207  return uiRet;
208 }
209 
218 void vVecClear(void* vpCtx)
219 {
220  APG_VECTOR_CTX* spCtx = (APG_VECTOR_CTX*)vpCtx;
221  if(vpCtx && (spCtx->vpValidate == (void*)spCtx))
222  {
223  spCtx->uiUsed = 0;
224  }
225  return;
226 }
227 
238 void* vpVecPush(void* vpCtx, void* vpElement)
239 {
240  void* vpReturn = NULL;
241  apg_uint uiTest = APG_TRUE;
242  APG_VECTOR_CTX* spCtx = (APG_VECTOR_CTX*)vpCtx;
243  while(APG_TRUE){
244  if(!(spCtx && spCtx->vpValidate == (void*)spCtx)){break;}
245  if(spCtx->uiUsed >= spCtx->uiReserved)
246  {
247  uiTest = uiGrow(spCtx, 1);
248  if(!uiTest){break;}
249  }
250 
251  vpReturn = (void*)(spCtx->cpData + (spCtx->uiUsed * spCtx->uiElementSize));
252  if(vpElement)
253  {
254  // copy new element to vector
255  memcpy(vpReturn, vpElement, spCtx->uiElementSize);
256  }
257 
258  // success, return a pointer to the new element
259  ++spCtx->uiUsed;
260  break;
261  }
262  return vpReturn;
263 }
264 
276 void* vpVecPushn(void* vpCtx, void* vpElement, apg_uint uiCount)
277 {
278  void* vpReturn = NULL;
279  apg_uint uiTest = APG_TRUE;
280  APG_VECTOR_CTX* spCtx = (APG_VECTOR_CTX*)vpCtx;
281  while(APG_TRUE){
282  if(!(spCtx && spCtx->vpValidate == (void*)spCtx)){break;}
283 
284  if(uiCount)
285  {
286  // check allocation
287  if((spCtx->uiUsed + uiCount) > spCtx->uiReserved)
288  {
289  uiTest = uiGrow(spCtx, uiCount);
290  if(!uiTest){break;}
291  }
292 
293  vpReturn = (void*)(spCtx->cpData + (spCtx->uiUsed * spCtx->uiElementSize));
294  if(vpElement)
295  {
296  // copy new elements to vector
297  memcpy(vpReturn, vpElement, uiCount * spCtx->uiElementSize);
298  }
299  spCtx->uiUsed += uiCount;
300  }
301  break;
302  }
303  return vpReturn;
304 }
305 
315 void* vpVecPop(void* vpCtx)
316 {
317  void* vpReturn = NULL;
318  APG_VECTOR_CTX* spCtx = (APG_VECTOR_CTX*)vpCtx;
319  if(spCtx && spCtx->vpValidate == (void*)spCtx){
320  if(spCtx->uiUsed)
321  {
322  // pop one element
323  --spCtx->uiUsed;
324  vpReturn = (void*)(spCtx->cpData + (spCtx->uiUsed * spCtx->uiElementSize));
325  }
326  }
327  // return a pointer to the popped element
328  return vpReturn;
329 }
330 
341 void* vpVecPopn(void* vpCtx, apg_uint uiCount)
342 {
343  void* vpReturn = NULL;
344  APG_VECTOR_CTX* spCtx = (APG_VECTOR_CTX*)vpCtx;
345  if(spCtx && spCtx->vpValidate == (void*)spCtx){
346  if(uiCount > 0){
347  if(spCtx->uiUsed > 0){
348  if(spCtx->uiUsed > uiCount)
349  {
350  // pop uiCount elements
351  spCtx->uiUsed -= uiCount;
352  vpReturn = (void*)(spCtx->cpData + (spCtx->uiUsed * spCtx->uiElementSize));
353  }
354  else
355  {
356  // pop all remaining elements
357  spCtx->uiUsed = 0;
358  vpReturn = spCtx->cpData;
359  }
360  }
361  }
362  }
363  return vpReturn;
364 }
365 
376 void* vpVecPopTo(void* vpCtx, apg_uint uiIndex)
377 {
378  void* vpReturn = NULL;
379  APG_VECTOR_CTX* spCtx = (APG_VECTOR_CTX*)vpCtx;
380  if(spCtx && spCtx->vpValidate == (void*)spCtx){
381  if(!(spCtx->uiUsed == 0 || uiIndex >= spCtx->uiUsed)){
382 
383  // success
384  spCtx->uiUsed = uiIndex;
385  vpReturn = (void*)(spCtx->cpData + uiIndex);
386  }
387  }
388  return vpReturn;
389 }
390 
396 void* vpVecFront(void* vpCtx)
397 {
398  void* vpReturn = NULL;
399  APG_VECTOR_CTX* spCtx = (APG_VECTOR_CTX*)vpCtx;
400  if(spCtx && spCtx->vpValidate == (void*)spCtx){
401  if(spCtx->uiUsed)
402  {
403  vpReturn = (void*)spCtx->cpData;
404  }
405  }
406  return vpReturn;
407 }
408 
414 void* vpVecBack(void* vpCtx)
415 {
416  void* vpReturn = NULL;
417  APG_VECTOR_CTX* spCtx = (APG_VECTOR_CTX*)vpCtx;
418  if(spCtx && spCtx->vpValidate == (void*)spCtx){
419  if(spCtx->uiUsed)
420  {
421  vpReturn = (void*)(spCtx->cpData + (spCtx->uiUsed - 1) * spCtx->uiElementSize);
422  }
423  }
424  return vpReturn;
425 }
426 
433 void* vpVecAt(void* vpCtx, apg_uint uiIndex)
434 {
435  void* vpReturn = NULL;
436  APG_VECTOR_CTX* spCtx = (APG_VECTOR_CTX*)vpCtx;
437  if(spCtx && spCtx->vpValidate == (void*)spCtx){
438  if(uiIndex < spCtx->uiUsed)
439  {
440  vpReturn = (void*)(spCtx->cpData + (uiIndex * spCtx->uiElementSize));
441  }
442  }
443  return vpReturn;
444 }
445 
447 // DESCRIPTION: reallocate the buffer
448 // - increase the buffer size to double the previous space plus
449 // specified number of elements
450 // - copy existing data to the new buffer
451 //
452 // FUNCTION: static apg_uint uiGrow
453 //
454 // ARG: 1) APG_VECTOR_CTX* spCtx
455 // : pointer to a valid vector context previously returned
456 // from vpVecCtor()
457 //
458 // ARG: 2) apg_uint uiElements
459 // : minimum number of elements to make additional room for
460 //
461 // RETURN: true on success, false on failure
462 //
464 static apg_uint uiGrow(APG_VECTOR_CTX* spCtx, apg_uint uiElements)
465 {
466  apg_uint uiReturn = APG_FALSE;
467  void* vpNewData;
468  apg_uint uiReserved;
469 
470  // allocate new space
471  uiReserved = 2 * (spCtx->uiReserved + uiElements);
472  vpNewData = vpMemRealloc(spCtx->vpMemCtx, (void*)spCtx->cpData, spCtx->uiElementSize * uiReserved);
473  if(vpNewData){
474  // success
475  spCtx->cpData = (char*)vpNewData;
476  spCtx->uiReserved = uiReserved;
477  ++spCtx->uiReallocations;
478  uiReturn = APG_TRUE;
479  }
480  return uiReturn;
481 }
vVecClear
void vVecClear(void *vpCtx)
Definition: Vector.c:218
vVecDtor
void vVecDtor(void *vpCtx)
Definition: Vector.c:123
uiVecReallocations
apg_uint uiVecReallocations(void *vpCtx)
Definition: Vector.c:200
vpMemRealloc
void * vpMemRealloc(void *vpCtx, void *vpData, apg_uint uiBytes)
Definition: Memory.c:182
uiVecBytes
apg_uint uiVecBytes(void *vpCtx)
Definition: Vector.c:152
apg_uint
unsigned int apg_uint
Definition: Apg.h:169
vpVecAt
void * vpVecAt(void *vpCtx, apg_uint uiIndex)
Definition: Vector.c:433
APG_VEC_ELEMENT
#define APG_VEC_ELEMENT
Definition: Apg.h:261
uiVecValidate
apg_uint uiVecValidate(void *vpCtx)
Definition: Vector.c:142
vpVecPop
void * vpVecPop(void *vpCtx)
Definition: Vector.c:315
vMemFree
void vMemFree(void *vpCtx, void *vpData)
Definition: Memory.c:157
vpMemAlloc
void * vpMemAlloc(void *vpCtx, apg_uint uiBytes)
Definition: Memory.c:130
APG_VEC_ALLOC
#define APG_VEC_ALLOC
Definition: Apg.h:265
vpVecPopTo
void * vpVecPopTo(void *vpCtx, apg_uint uiIndex)
Definition: Vector.c:376
Apg.h
Required header file for all APG-generated parsers. Contains important configuration macros and decla...
vpVecBack
void * vpVecBack(void *vpCtx)
Definition: Vector.c:414
APG_TRUE
#define APG_TRUE
Definition: Apg.h:187
uiVecElementSize
apg_uint uiVecElementSize(void *vpCtx)
Definition: Vector.c:185
vpVecCtor
void * vpVecCtor(void *vpMemCtx, apg_uint uiElementSize, apg_uint uiInitialAlloc)
Definition: Vector.c:81
vpVecPopn
void * vpVecPopn(void *vpCtx, apg_uint uiCount)
Definition: Vector.c:341
vpVecFront
void * vpVecFront(void *vpCtx)
Definition: Vector.c:396
vpVecPushn
void * vpVecPushn(void *vpCtx, void *vpElement, apg_uint uiCount)
Definition: Vector.c:276
APG_FALSE
#define APG_FALSE
Definition: Apg.h:190
vpVecPush
void * vpVecPush(void *vpCtx, void *vpElement)
Definition: Vector.c:238
uiVecSize
apg_uint uiVecSize(void *vpCtx)
Definition: Vector.c:167
uiMemValidate
apg_uint uiMemValidate(void *vpCtx)
Definition: Memory.c:115
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/licenses.html or write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.