gwenhywfar  5.10.1
simpleptrlist.c
Go to the documentation of this file.
1 /***************************************************************************
2  begin : Fri Dec 06 2019
3  copyright : (C) 2019 by Martin Preuss
4  email : martin@libchipcard.de
5 
6  ***************************************************************************
7  * *
8  * This library is free software; you can redistribute it and/or *
9  * modify it under the terms of the GNU Lesser General Public *
10  * License as published by the Free Software Foundation; either *
11  * version 2.1 of the License, or (at your option) any later version. *
12  * *
13  * This library is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
16  * Lesser General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU Lesser General Public *
19  * License along with this library; if not, write to the Free Software *
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21  * MA 02111-1307 USA *
22  * *
23  ***************************************************************************/
24 
25 #ifdef HAVE_CONFIG_H
26 # include <config.h>
27 #endif
28 
29 #define DISABLE_DEBUGLOG
30 
31 
32 #include "simpleptrlist_p.h"
33 #include <gwenhywfar/debug.h>
34 
35 
36 #include <stdlib.h>
37 #include <assert.h>
38 #include <string.h>
39 
40 
41 
42 /* ------------------------------------------------------------------------------------------------
43  * forward declarations
44  * ------------------------------------------------------------------------------------------------
45  */
46 
47 static void _attachToObject(GWEN_SIMPLEPTRLIST *pl, void *p);
48 static void _detachFromObject(GWEN_SIMPLEPTRLIST *pl, void *p);
51 
52 static INTERNAL_PTRLIST *_mallocPtrList(uint64_t totalEntries);
53 static void _attachToPtrList(INTERNAL_PTRLIST *entries);
54 static void _freePtrList(INTERNAL_PTRLIST *entries);
55 static INTERNAL_PTRLIST *_reallocPtrList(INTERNAL_PTRLIST *oldEntries, uint64_t totalEntries);
56 static INTERNAL_PTRLIST *_copyPtrList(const INTERNAL_PTRLIST *oldEntries, uint64_t totalEntries);
57 
58 
59 
60 /* ------------------------------------------------------------------------------------------------
61  * implementations
62  * ------------------------------------------------------------------------------------------------
63  */
64 
65 
67 
68 
69 
70 
71 GWEN_SIMPLEPTRLIST *GWEN_SimplePtrList_new(uint64_t startEntries, uint64_t steps)
72 {
74 
76  pl->refCount=1;
78 
79  pl->entryList=_mallocPtrList(startEntries);
80  pl->maxEntries=startEntries;
81  pl->steps=steps;
82  pl->usedEntries=0;
83  return pl;
84 }
85 
86 
87 
89 {
91 
93  pl->refCount=1;
95 
96  pl->entryList=oldList->entryList;
97  _attachToPtrList(pl->entryList);
98 
99  pl->maxEntries=oldList->maxEntries;
100  pl->steps=oldList->steps;
101  pl->usedEntries=oldList->usedEntries;
102  pl->attachObjectFn=oldList->attachObjectFn;
103  pl->freeObjectFn=oldList->freeObjectFn;
104  pl->userIntData=oldList->userIntData;
105  pl->flags=oldList->flags | GWEN_SIMPLEPTRLIST_FLAGS_COPYONWRITE;
106  /* set copyOnWrite flag also on old list to keep lists separate even when changes to old lists are made */
107  oldList->flags|=GWEN_SIMPLEPTRLIST_FLAGS_COPYONWRITE;
108  return pl;
109 }
110 
111 
112 
114 {
115  assert(pl);
116  assert(pl->refCount);
117  pl->refCount++;
118 }
119 
120 
121 
123 {
124  if (pl) {
125  assert(pl->refCount);
126  if (pl->refCount==1) {
128  if (pl->flags & GWEN_SIMPLEPTRLIST_FLAGS_DETACHFROMOBJECTS && pl->entryList->refCounter==1) {
129  DBG_VERBOUS(GWEN_LOGDOMAIN, "Entries no longer needed, detaching from its objects");
131  }
132  _freePtrList(pl->entryList);
133  pl->entryList=NULL;
134  pl->maxEntries=0;
135  pl->refCount--;
136  GWEN_FREE_OBJECT(pl);
137  }
138  else
139  pl->refCount--;
140  }
141 }
142 
143 
144 
146 {
147  uint64_t i;
148  void **ptr;
149 
150  assert(pl);
151  assert(pl->refCount);
152 
155 
156  ptr=pl->entryList->entries;
157  for (i=0; i<pl->usedEntries; i++)
158  *(ptr++)=NULL;
159 }
160 
161 
162 
164 {
165  assert(pl);
166  assert(pl->refCount);
167  return pl->userIntData;
168 }
169 
170 
171 
173 {
174  assert(pl);
175  assert(pl->refCount);
176  pl->userIntData=i;
177 }
178 
179 
180 
182 {
183  assert(pl);
184  assert(pl->refCount);
185  pl->userCounter=i;
186 }
187 
188 
189 
191 {
192  assert(pl);
193  assert(pl->refCount);
194  return pl->userCounter;
195 }
196 
197 
198 
200 {
201  assert(pl);
202  assert(pl->refCount);
203  pl->userCounter++;
204 }
205 
206 
207 
209 {
210  assert(pl);
211  assert(pl->refCount);
212  if (pl->userCounter) {
213  pl->userCounter--;
214  return 0;
215  }
216  else
217  return GWEN_ERROR_INVALID; /* counter already is 0 */
218 }
219 
220 
221 
222 
223 
224 
225 void *GWEN_SimplePtrList_GetPtrAt(const GWEN_SIMPLEPTRLIST *pl, uint64_t idx)
226 {
227  assert(pl);
228  assert(pl->refCount);
229  if (idx<pl->usedEntries) {
230  return pl->entryList->entries[idx];
231  }
232  else {
234  "Index outside boundaries (%lu >= %lu)",
235  (unsigned long) idx,
236  (unsigned long)(pl->usedEntries));
237  }
238  return NULL;
239 }
240 
241 
242 
243 int GWEN_SimplePtrList_SetPtrAt(GWEN_SIMPLEPTRLIST *pl, uint64_t idx, void *p)
244 {
245  assert(pl);
246  assert(pl->refCount);
247 
248  if (idx<pl->usedEntries) {
249  int rv;
250  void *oldPtr;
251 
252  /* copy on write, if needed */
254  if (rv<0) {
255  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
256  return rv;
257  }
258 
259  oldPtr=pl->entryList->entries[idx];
260  pl->entryList->entries[idx]=p;
261  if (p && (pl->flags & GWEN_SIMPLEPTRLIST_FLAGS_ATTACHTOOBJECTS))
262  _attachToObject(pl, p);
263  if (oldPtr && (pl->flags & GWEN_SIMPLEPTRLIST_FLAGS_DETACHFROMOBJECTS))
264  _detachFromObject(pl, oldPtr);
265  }
266  else {
267  DBG_ERROR(GWEN_LOGDOMAIN, "Bad index");
269  }
270 
271  return 0;
272 }
273 
274 
275 
277 {
278  int rv;
279 
280  assert(pl);
281  assert(pl->refCount);
282 
284  if (rv<0) {
285  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
286  return rv;
287  }
288 
289  if (pl->usedEntries >= pl->maxEntries) {
290  uint64_t num;
291 
292  num=pl->maxEntries+pl->steps;
293  if (num>pl->maxEntries) {
294  INTERNAL_PTRLIST *entryList;
295 
296  /* resize current list */
297  entryList=_reallocPtrList(pl->entryList, num);
298  if (entryList==NULL) {
299  DBG_ERROR(GWEN_LOGDOMAIN, "Memory full.");
300  return GWEN_ERROR_MEMORY_FULL;
301  }
302  pl->entryList=entryList;
303  pl->maxEntries=num;
304  }
305  else {
306  DBG_ERROR(GWEN_LOGDOMAIN, "Table full (step size==0).");
307  return GWEN_ERROR_MEMORY_FULL;
308  }
309  }
310 
311  /* add entry */
312  pl->entryList->entries[pl->usedEntries]=p;
313  if (p && (pl->flags & GWEN_SIMPLEPTRLIST_FLAGS_ATTACHTOOBJECTS))
314  _attachToObject(pl, p);
315  pl->usedEntries++;
316  return pl->usedEntries-1;
317 }
318 
319 
320 
322 {
323  assert(pl);
324  assert(pl->refCount);
325  return pl->steps;
326 }
327 
328 
329 
331 {
332  assert(pl);
333  assert(pl->refCount);
334  pl->steps=steps;
335 }
336 
337 
338 
340 {
341  assert(pl);
342  assert(pl->refCount);
343  return pl->maxEntries;
344 }
345 
346 
347 
349 {
350  assert(pl);
351  assert(pl->refCount);
352  return pl->usedEntries;
353 }
354 
355 
356 
358 {
359  assert(pl);
360  assert(pl->refCount);
361  return pl->entryList->entries;
362 }
363 
364 
365 
367 {
368  assert(pl);
369  assert(pl->refCount);
370  return pl->flags;
371 }
372 
373 
374 
376 {
377  assert(pl);
378  assert(pl->refCount);
379  pl->flags=f;
380 }
381 
382 
383 
385 {
386  assert(pl);
387  assert(pl->refCount);
388  pl->flags|=f;
389 }
390 
391 
392 
394 {
395  assert(pl);
396  assert(pl->refCount);
397  pl->flags&=~f;
398 }
399 
400 
401 
404 {
406 
407  assert(pl);
408  assert(pl->refCount);
409 
410  oldFn=pl->attachObjectFn;
411  pl->attachObjectFn=fn;
412  return oldFn;
413 }
414 
415 
416 
419 {
421 
422  assert(pl);
423  assert(pl->refCount);
424 
425  oldFn=pl->freeObjectFn;
426  pl->freeObjectFn=fn;
427  return oldFn;
428 }
429 
430 
431 
433 {
434  if (pl->attachObjectFn)
435  pl->attachObjectFn(pl, p);
436 }
437 
438 
439 
441 {
442  if (pl->freeObjectFn)
443  pl->freeObjectFn(pl, p);
444 }
445 
446 
447 
449 {
450  if (pl->attachObjectFn) {
451  uint64_t i;
452  void **ptr;
453 
454  DBG_VERBOUS(GWEN_LOGDOMAIN, "Attaching to objects");
455  ptr=pl->entryList->entries;
456  for (i=0; i<pl->usedEntries; i++) {
457  if (*ptr!=NULL)
458  _attachToObject(pl, *ptr);
459  ptr++;
460  }
461  }
462  else {
463  DBG_ERROR(GWEN_LOGDOMAIN, "No attachObjectFn set");
464  }
465 }
466 
467 
468 
470 {
471  if (pl->freeObjectFn) {
472  uint64_t i;
473  void **ptr;
474 
475  DBG_VERBOUS(GWEN_LOGDOMAIN, "Detaching from objects");
476  ptr=pl->entryList->entries;
477  for (i=0; i<pl->usedEntries; i++) {
478  if (*ptr!=NULL)
479  _detachFromObject(pl, *ptr);
480  ptr++;
481  }
482  }
483  else {
484  DBG_ERROR(GWEN_LOGDOMAIN, "No attachObjectFn set");
485  }
486 }
487 
488 
489 
490 
491 
492 
493 INTERNAL_PTRLIST *_mallocPtrList(uint64_t totalEntries)
494 {
495  INTERNAL_PTRLIST *entries;
496  size_t objectSize;
497 
498  DBG_VERBOUS(GWEN_LOGDOMAIN, "Malloc entries");
499  objectSize=sizeof(INTERNAL_PTRLIST) + (totalEntries*sizeof(void *));
500  entries=(INTERNAL_PTRLIST *) malloc(objectSize);
501  if (entries==NULL) {
502  DBG_ERROR(GWEN_LOGDOMAIN, "Memory full.");
503  return NULL;
504  }
505  memset((void *)entries, 0, objectSize);
506  entries->refCounter=1;
507  entries->storedEntries=totalEntries;
508  return entries;
509 }
510 
511 
512 
513 void _attachToPtrList(INTERNAL_PTRLIST *entries)
514 {
515  assert(entries && entries->refCounter>0);
516  if (entries && entries->refCounter>0) {
517  DBG_VERBOUS(GWEN_LOGDOMAIN, "Attaching to entries");
518  entries->refCounter++;
519  }
520  else {
521  DBG_ERROR(GWEN_LOGDOMAIN, "Null pointer or already freed");
522  }
523 }
524 
525 
526 
527 void _freePtrList(INTERNAL_PTRLIST *entries)
528 {
529  if (entries && entries->refCounter>0) {
530  if (entries->refCounter==1) {
531  DBG_VERBOUS(GWEN_LOGDOMAIN, "Freeing entries");
532  entries->refCounter=0;
533  free(entries);
534  }
535  else {
536  entries->refCounter--;
537  }
538  }
539 }
540 
541 
542 
543 INTERNAL_PTRLIST *_reallocPtrList(INTERNAL_PTRLIST *entries, uint64_t totalEntries)
544 {
545  assert(entries && entries->refCounter>0);
546  if (entries && entries->refCounter>0) {
547  size_t newSize;
548  uint64_t diffEntries;
549 
550  DBG_VERBOUS(GWEN_LOGDOMAIN, "Resizing entries");
551  if (totalEntries<entries->storedEntries) {
552  DBG_INFO(GWEN_LOGDOMAIN, "Will not decrease size (for now)");
553  return entries;
554  }
555 
556  diffEntries=totalEntries-(entries->storedEntries);
557  newSize=sizeof(INTERNAL_PTRLIST)+totalEntries*sizeof(void *);
558 
559  entries=(INTERNAL_PTRLIST *) realloc(entries, newSize);
560  if (entries==NULL) {
561  DBG_ERROR(GWEN_LOGDOMAIN, "Memory full.");
562  return NULL;
563  }
564 
565  /* preset new entries */
566  if (diffEntries)
567  memset((void *) &(entries->entries[entries->storedEntries]), 0, diffEntries*sizeof(void *));
568  entries->storedEntries=totalEntries;
569  return entries;
570  }
571  else {
572  DBG_ERROR(GWEN_LOGDOMAIN, "Null pointer or already freed");
573  return NULL;
574  }
575 }
576 
577 
578 
579 INTERNAL_PTRLIST *_copyPtrList(const INTERNAL_PTRLIST *oldEntries, uint64_t totalEntries)
580 {
581  assert(oldEntries && oldEntries->refCounter>0);
582  if (oldEntries && oldEntries->refCounter>0) {
583  INTERNAL_PTRLIST *entries;
584  size_t oldSize;
585  size_t newSize;
586  uint64_t diffEntries;
587 
588  DBG_VERBOUS(GWEN_LOGDOMAIN, "Copying entries");
589  if (totalEntries<oldEntries->storedEntries)
590  totalEntries=oldEntries->storedEntries;
591 
592  diffEntries=totalEntries-(oldEntries->storedEntries);
593  oldSize=sizeof(INTERNAL_PTRLIST)+((oldEntries->storedEntries)*sizeof(void *));
594  newSize=sizeof(INTERNAL_PTRLIST)+totalEntries*sizeof(void *);
595 
596  entries=(INTERNAL_PTRLIST *) malloc(newSize);
597  if (entries==NULL) {
598  DBG_ERROR(GWEN_LOGDOMAIN, "Memory full.");
599  return NULL;
600  }
601 
602  /* copy old struct */
603  memmove(entries, oldEntries, oldSize);
604 
605  /* preset new entries */
606  if (diffEntries)
607  memset((void *) &(entries->entries[entries->storedEntries]), 0, diffEntries*sizeof(void *));
608 
609  /* setup rest of the fields */
610  entries->refCounter=1;
611  entries->storedEntries=totalEntries;
612  return entries;
613  }
614  else {
615  DBG_ERROR(GWEN_LOGDOMAIN, "Null pointer or already freed");
616  return NULL;
617  }
618 }
619 
620 
621 
623 {
624  assert(pl && pl->refCount);
625 
626  if (pl->flags & GWEN_SIMPLEPTRLIST_FLAGS_COPYONWRITE) {
627  INTERNAL_PTRLIST *entryList;
628  uint64_t num;
629 
630  num=pl->maxEntries+pl->steps;
631 
632  DBG_VERBOUS(GWEN_LOGDOMAIN, "Copying entries");
633 
634  /* make new entries pointer a copy of the old one */
635  entryList=_copyPtrList(pl->entryList, num);
636  if (entryList==NULL) {
637  DBG_ERROR(GWEN_LOGDOMAIN, "Memory full.");
638  return GWEN_ERROR_MEMORY_FULL;
639  }
640 
641  _freePtrList(pl->entryList);
642  pl->entryList=entryList;
643  pl->maxEntries=num;
644  /* this is a copy, attach to objs */
646  DBG_VERBOUS(GWEN_LOGDOMAIN, "Attaching to objects");
648  }
649  /* clear copy-on-write flag */
650  pl->flags&=~GWEN_SIMPLEPTRLIST_FLAGS_COPYONWRITE;
651  }
652 
653  return 0;
654 }
655 
656 
657 
658 /* include tests */
659 #include "simpleptrlist-t.c"
660 
uint64_t GWEN_SimplePtrList_GetMaxEntries(const GWEN_SIMPLEPTRLIST *pl)
void * GWEN_SimplePtrList_GetPtrAt(const GWEN_SIMPLEPTRLIST *pl, uint64_t idx)
int GWEN_SimplePtrList_DecUserCounter(GWEN_SIMPLEPTRLIST *pl)
#define GWEN_INHERIT_FINI(t, element)
Definition: inherit.h:238
#define GWEN_ERROR_INVALID
Definition: error.h:67
GWENHYWFAR_CB void(* GWEN_SIMPLEPTRLIST_ATTACHOBJECT_FN)(GWEN_SIMPLEPTRLIST *pl, void *p)
Definition: simpleptrlist.h:43
void GWEN_SimplePtrList_SetUserCounter(GWEN_SIMPLEPTRLIST *pl, uint64_t i)
void GWEN_SimplePtrList_IncUserCounter(GWEN_SIMPLEPTRLIST *pl)
GWENHYWFAR_CB void(* GWEN_SIMPLEPTRLIST_FREEOBJECT_FN)(GWEN_SIMPLEPTRLIST *pl, void *p)
Definition: simpleptrlist.h:44
uint32_t GWEN_SimplePtrList_GetFlags(const GWEN_SIMPLEPTRLIST *pl)
#define GWEN_FREE_OBJECT(varname)
Definition: memory.h:61
#define NULL
Definition: binreloc.c:300
#define DBG_VERBOUS(dbg_logger, format, args...)
Definition: debug.h:224
static void _attachToAllObjects(GWEN_SIMPLEPTRLIST *pl)
#define GWEN_LOGDOMAIN
Definition: logger.h:35
static void _detachFromAllObjects(GWEN_SIMPLEPTRLIST *pl)
#define GWEN_ERROR_BUFFER_OVERFLOW
Definition: error.h:79
static INTERNAL_PTRLIST * _reallocPtrList(INTERNAL_PTRLIST *oldEntries, uint64_t totalEntries)
int GWEN_SimplePtrList_SetPtrAt(GWEN_SIMPLEPTRLIST *pl, uint64_t idx, void *p)
void GWEN_SimplePtrList_SetSteps(GWEN_SIMPLEPTRLIST *pl, uint64_t steps)
uint64_t GWEN_SimplePtrList_GetUserCounter(const GWEN_SIMPLEPTRLIST *pl)
#define GWEN_NEW_OBJECT(typ, varname)
Definition: memory.h:55
static void _attachToObject(GWEN_SIMPLEPTRLIST *pl, void *p)
static INTERNAL_PTRLIST * _copyPtrList(const INTERNAL_PTRLIST *oldEntries, uint64_t totalEntries)
GWEN_SIMPLEPTRLIST * GWEN_SimplePtrList_LazyCopy(GWEN_SIMPLEPTRLIST *oldList)
Definition: simpleptrlist.c:88
void GWEN_SimplePtrList_Clear(GWEN_SIMPLEPTRLIST *pl)
void * GWEN_SimplePtrList_GetEntries(const GWEN_SIMPLEPTRLIST *pl)
#define GWEN_INHERIT_INIT(t, element)
Definition: inherit.h:223
struct GWEN_SIMPLEPTRLIST GWEN_SIMPLEPTRLIST
Definition: simpleptrlist.h:38
int GWEN_SimplePtrList_EnsureWritability(GWEN_SIMPLEPTRLIST *pl)
int GWEN_SimplePtrList_GetUserIntData(const GWEN_SIMPLEPTRLIST *pl)
#define GWEN_SIMPLEPTRLIST_FLAGS_ATTACHTOOBJECTS
Definition: simpleptrlist.h:33
static INTERNAL_PTRLIST * _mallocPtrList(uint64_t totalEntries)
static void _attachToPtrList(INTERNAL_PTRLIST *entries)
void GWEN_SimplePtrList_SubFlags(GWEN_SIMPLEPTRLIST *pl, uint32_t f)
void GWEN_SimplePtrList_Attach(GWEN_SIMPLEPTRLIST *pl)
#define DBG_ERROR(dbg_logger, format, args...)
Definition: debug.h:97
static void _detachFromObject(GWEN_SIMPLEPTRLIST *pl, void *p)
static void _freePtrList(INTERNAL_PTRLIST *entries)
void GWEN_SimplePtrList_SetUserIntData(GWEN_SIMPLEPTRLIST *pl, int i)
void GWEN_SimplePtrList_AddFlags(GWEN_SIMPLEPTRLIST *pl, uint32_t f)
void GWEN_SimplePtrList_SetFlags(GWEN_SIMPLEPTRLIST *pl, uint32_t f)
GWEN_SIMPLEPTRLIST * GWEN_SimplePtrList_new(uint64_t startEntries, uint64_t steps)
Definition: simpleptrlist.c:71
GWEN_SIMPLEPTRLIST_FREEOBJECT_FN GWEN_SimplePtrList_SetFreeObjectFn(GWEN_SIMPLEPTRLIST *pl, GWEN_SIMPLEPTRLIST_FREEOBJECT_FN fn)
#define DBG_INFO(dbg_logger, format, args...)
Definition: debug.h:181
uint64_t GWEN_SimplePtrList_GetUsedEntries(const GWEN_SIMPLEPTRLIST *pl)
GWEN_SIMPLEPTRLIST_ATTACHOBJECT_FN GWEN_SimplePtrList_SetAttachObjectFn(GWEN_SIMPLEPTRLIST *pl, GWEN_SIMPLEPTRLIST_ATTACHOBJECT_FN fn)
uint64_t GWEN_SimplePtrList_GetSteps(const GWEN_SIMPLEPTRLIST *pl)
int64_t GWEN_SimplePtrList_AddPtr(GWEN_SIMPLEPTRLIST *pl, void *p)
#define GWEN_SIMPLEPTRLIST_FLAGS_DETACHFROMOBJECTS
Definition: simpleptrlist.h:34
#define GWEN_INHERIT_FUNCTIONS(t)
Definition: inherit.h:163
#define GWEN_ERROR_MEMORY_FULL
Definition: error.h:77
void GWEN_SimplePtrList_free(GWEN_SIMPLEPTRLIST *pl)