IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ticket #364: psMetadata.c

File psMetadata.c, 22.6 KB (added by eugene, 21 years ago)

modified psMetadata.c

Line 
1/** @file psMetadata.c
2*
3*
4* @brief Contains metadata structures, enumerations and functions prototypes.
5*
6* This file defines metadata item, metadata type, metadata flags, metadata containers, and function
7* prototypes necessary creating psLib metadata APIs
8*
9* @ingroup Metadata
10*
11* @author Robert DeSonia, MHPCC
12* @author Ross Harman, MHPCC
13*
14* @version $Revision: 1.57 $ $Name: rel5_0 $
15* @date $Date: 2005/03/29 21:31:54 $
16*
17* Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
18*/
19
20/******************************************************************************/
21/* INCLUDE FILES */
22/******************************************************************************/
23#include<stdio.h>
24#include<stdarg.h>
25#include<string.h>
26
27#include "fitsio.h"
28#include "psType.h"
29#include "psMemory.h"
30#include "psError.h"
31#include "psAbort.h"
32#include "psList.h"
33#include "psHash.h"
34#include "psVector.h"
35#include "psMetadata.h"
36#include "psLookupTable.h"
37#include "psString.h"
38#include "psAstronomyErrors.h"
39#include "psConstants.h"
40
41/******************************************************************************/
42/* DEFINE STATEMENTS */
43/******************************************************************************/
44
45/** Maximum size of a string */
46#define MAX_STRING_LENGTH 1024
47
48/******************************************************************************/
49/* TYPE DEFINITIONS */
50/******************************************************************************/
51
52// None
53
54/*****************************************************************************/
55/* GLOBAL VARIABLES */
56/*****************************************************************************/
57
58// None
59
60/*****************************************************************************/
61/* FILE STATIC VARIABLES */
62/*****************************************************************************/
63
64static psS32 metadataId = 0;
65
66/*****************************************************************************/
67/* FUNCTION IMPLEMENTATION - LOCAL */
68/*****************************************************************************/
69
70# if (0)
71static psMetadataItem* makeMetaMulti(psHash* table, const char* key, psMetadataItem* existing)
72{
73
74 if (existing != NULL && existing->type == PS_META_MULTI) {
75 return existing;
76 }
77
78 // move any existing entry into a psList
79 psList* newList = psListAlloc(existing);
80
81 psMetadataItem* item = psMetadataItemAlloc(key,
82 PS_META_MULTI,
83 "",
84 newList);
85
86 if (existing != NULL) {
87 psHashRemove(table,key); // take out the old entry
88 }
89
90 psHashAdd(table, key, item); // put in the new entry
91
92 // free local references of newly allocated items.
93 psFree(newList);
94 psFree(item);
95
96 return item;
97}
98# endif
99
100static void metadataItemFree(psMetadataItem* metadataItem)
101{
102 psMetadataType type;
103
104 type = metadataItem->type;
105
106 if (metadataItem == NULL) {
107 return;
108 }
109
110 psFree(metadataItem->name);
111 psFree(metadataItem->comment);
112 if (! PS_META_IS_PRIMITIVE(type)) {
113 psFree(metadataItem->data.V);
114 }
115}
116
117static void metadataIteratorFree(psMetadataIterator* iter)
118{
119 if (iter == NULL) {
120 return;
121 }
122 psFree(iter->iter);
123
124 if (iter->preg != NULL) {
125 regfree(iter->preg);
126 }
127}
128
129static void metadataFree(psMetadata* metadata)
130{
131 if (metadata == NULL) {
132 return;
133 }
134 psFree(metadata->list);
135 psFree(metadata->table);
136}
137
138/*****************************************************************************/
139/* FUNCTION IMPLEMENTATION - PUBLIC */
140/*****************************************************************************/
141
142psMetadataItem* psMetadataItemAlloc(const char *name, psMetadataType type,
143 const char *comment, ...)
144{
145 va_list argPtr;
146 psMetadataItem* metadataItem = NULL;
147
148 // Get the variable list parameters to pass to allocation function
149 va_start(argPtr, comment);
150
151 // Call metadata item allocation
152 metadataItem = psMetadataItemAllocV(name, type, comment, argPtr);
153
154 // Clean up stack after variable arguement has been used
155 va_end(argPtr);
156
157 return metadataItem;
158}
159
160#define METADATAITEM_ALLOC_TYPE(NAME,TYPE,METATYPE) \
161psMetadataItem* psMetadataItemAlloc##NAME(const char* name, \
162 const char* comment, \
163 TYPE value) \
164{ \
165 return psMetadataItemAlloc(name, METATYPE, comment, value); \
166}
167
168METADATAITEM_ALLOC_TYPE(Str,const char*,PS_META_STR)
169METADATAITEM_ALLOC_TYPE(F32,psF32,PS_META_F32)
170METADATAITEM_ALLOC_TYPE(F64,psF64,PS_META_F64)
171METADATAITEM_ALLOC_TYPE(S32,psS32,PS_META_S32)
172METADATAITEM_ALLOC_TYPE(Bool,psBool,PS_META_BOOL)
173
174psMetadataItem* psMetadataItemAllocV(const char *name, psMetadataType type,
175 const char *comment, va_list argPtr)
176{
177 psMetadataItem* metadataItem = NULL;
178 char tmp;
179 int Nbyte;
180
181 PS_PTR_CHECK_NULL(name,NULL);
182
183 // Allocate metadata item
184 metadataItem = (psMetadataItem*) psAlloc(sizeof(psMetadataItem));
185 metadataItem->data.V = NULL;
186
187 // Set deallocator
188 p_psMemSetDeallocator(metadataItem, (psFreeFcn) metadataItemFree);
189
190 // set metadata item comment
191 if (comment == NULL) {
192 // Per SDRS, null isn't allowed, must use "" instead
193 metadataItem->comment = psStringCopy ("");
194 } else {
195 metadataItem->comment = psStringCopy (comment);
196 }
197
198 // Set metadata item unique id
199 *(psS32 *)(&metadataItem->id) = ++metadataId;
200
201 // Set metadata item type
202 metadataItem->type = type & PS_METADATA_TYPE_MASK;
203
204 // Allocate and set metadata item name
205 Nbyte = vsnprintf(&tmp, 0, name, argPtr) + 1;
206 metadataItem->name = (char *)psAlloc(sizeof(char) * Nbyte);
207 vsprintf(metadataItem->name, name, argPtr);
208
209 // Set metadata item value
210 switch(metadataItem->type) {
211 case PS_META_BOOL:
212 metadataItem->data.B = (psBool)va_arg(argPtr, psS32);
213 break;
214 case PS_META_S32:
215 metadataItem->data.S32 = (psS32)va_arg(argPtr, psS32);
216 break;
217 case PS_META_F32:
218 metadataItem->data.F32 = (psF32)va_arg(argPtr, psF64);
219 break;
220 case PS_META_F64:
221 metadataItem->data.F64 = (psF64)va_arg(argPtr, psF64);
222 break;
223 case PS_META_STR:
224 // Perform copy of input strings
225 metadataItem->data.V = psStringCopy(va_arg(argPtr, char *));
226 break;
227 case PS_META_LIST:
228 case PS_META_VEC:
229 case PS_META_HASH:
230 case PS_META_LOOKUPTABLE:
231 case PS_META_JPEG:
232 case PS_META_PNG:
233 case PS_META_ASTROM:
234 case PS_META_UNKNOWN:
235 // Copy of input data not performed due to variability of data types
236 metadataItem->data.V = psMemIncrRefCounter(va_arg(argPtr, psPtr));
237 break;
238 case PS_META_MULTI:
239 // MULTI needs to create a psList entry, value must be NULL
240 metadataItem->data.list = psListAlloc(NULL);
241 break;
242 default:
243 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psMetadata_METATYPE_INVALID, type);
244 psFree(metadataItem);
245 metadataItem = NULL;
246 }
247 return metadataItem;
248}
249
250psMetadata* psMetadataAlloc(void)
251{
252 psList* list = NULL;
253 psHash* table = NULL;
254 psMetadata* metadata = NULL;
255
256 // Allocate metadata
257 metadata = (psMetadata*) psAlloc(sizeof(psMetadata));
258 // Set deallocator
259 p_psMemSetDeallocator(metadata, (psFreeFcn) metadataFree);
260
261 // Allocate metadata's internal containers
262 list = (psList*) psListAlloc(NULL);
263 table = (psHash*) psHashAlloc(10);
264
265 metadata->list = list;
266 metadata->table = table;
267
268 return metadata;
269}
270
271psBool MetadataAddNewItem (psMetadata *md, psMetadataItem *metadataItem, psS32 location) {
272
273 char * key = NULL;
274 psHash *mdTable = NULL;
275 psList *mdList = NULL;
276
277 mdTable = md->table;
278 mdList = md->list;
279 key = metadataItem->name;
280
281 // OK, this is a new item.
282 // Add new metadata item to metadata collection's hash
283 if(!psHashAdd(mdTable, key, metadataItem)) {
284 psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_TABLE_FAILED,key);
285 return false;
286 }
287
288 // Add new metadata item to metadata collection's list
289 if(!psListAdd(mdList, location, metadataItem)) {
290 psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_COLLECTION_FAILED,key);
291 return false;
292 }
293 // Success
294 return true;
295}
296
297psBool psMetadataAddItem(psMetadata *md, psMetadataItem *metadataItem, psS32 location, psS32 flags)
298{
299 char * key = NULL;
300 psHash *mdTable = NULL;
301 psList *mdList = NULL;
302 psMetadataItem *existingEntry = NULL;
303
304 PS_PTR_CHECK_NULL(md,NULL);
305 PS_PTR_CHECK_NULL(md->table,NULL);
306 PS_PTR_CHECK_NULL(md->list,NULL);
307 PS_PTR_CHECK_NULL(metadataItem,NULL);
308 PS_PTR_CHECK_NULL(metadataItem->name,NULL);
309
310 mdTable = md->table;
311 mdList = md->list;
312 key = metadataItem->name;
313
314 // See if key is already in table
315 existingEntry = psMetadataLookup(md, key);
316
317 if (existingEntry == NULL) {
318 MetadataAddNewItem (md, metadataItem, location);
319 return true;
320 }
321
322 // if existing entry is MULTI, add the new entry to that list
323 // XXX does this behave correctly for adding a MULTI node to an exiting MULTI node?
324 if (existingEntry->type == PS_META_MULTI) {
325 PS_PTR_CHECK_NULL(existingEntry->data.list,NULL);
326
327 // Add new metadata item to multi entry's list (XXX is TAIL correct, or location?)
328 if(!psListAdd(existingEntry->data.list, PS_LIST_TAIL, metadataItem)) {
329 psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_COLLECTION_FAILED,key);
330 return false;
331 }
332
333 // Add new metadata item to metadata collection's list
334 if(!psListAdd(mdList, location, metadataItem)) {
335 psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_COLLECTION_FAILED,key);
336 return false;
337 }
338 return true;
339 }
340
341 // if existing entry is NOT MULTI, we have several choices:
342 // - new entry is MULTI: move existing entry to new MULTI list
343 // - DUPLICATE_OK: create a new MULTI and add both old and new to it
344 // - REPLACE : replace the existing entry with the new entry
345 // - raise an error
346
347 // incoming entry is PS_META_MULTI (DUPLICATE_OK is redundant, REPLACE is non-sequitor)
348 if (metadataItem->type == PS_META_MULTI) {
349
350 // replace hash entry with points to existingEntry with new entry
351 psHashAdd (mdTable, key, metadataItem);
352
353 // move the existing hash entry to a node of the new entry
354 psListAdd (metadataItem->data.list, PS_LIST_TAIL, existingEntry);
355
356 return true; // all done.
357 }
358
359 // duplicate entries allowed - create a MULTI with name and add both to it
360 if (flags & PS_META_DUPLICATE_OK) {
361
362 psMetadataItem *multi;
363
364 multi = psMetadataItemAlloc (key, PS_META_MULTI, "multi container", NULL);
365
366 // replace hash entry with points to existingEntry with new multi
367 psHashAdd (mdTable, key, multi);
368
369 // move the existing hash entry to a node of the new entry
370 psListAdd (multi->data.list, PS_LIST_TAIL, existingEntry);
371
372 // move the existing hash entry to a node of the new entry
373 psListAdd (multi->data.list, PS_LIST_TAIL, metadataItem);
374
375 // move the existing hash entry to a node of the new entry
376 psListAdd (mdList, PS_LIST_TAIL, metadataItem);
377
378 return true;
379 }
380
381 if (flags & PS_META_REPLACE) {
382 // replace entry instead of creating a duplicate entry.
383
384 // remove the existing entry from metadata
385 psMetadataRemove(md,0,key);
386
387 // treat as if new (added to list below)
388 MetadataAddNewItem (md, metadataItem, location);
389 return true;
390 }
391
392 // default is to error on duplicate entry.
393 psError(PS_ERR_BAD_PARAMETER_VALUE, true,
394 PS_ERRORTEXT_psMetadata_DUPLICATE_NOT_ALLOWED);
395 return false;
396}
397
398psBool psMetadataAdd(psMetadata *md, psS32 location, const char *name,
399 psS32 type, const char *comment, ...)
400{
401 va_list argPtr;
402
403 va_start(argPtr, comment);
404 psBool result = psMetadataAddV(md,location,name,type,comment,argPtr);
405 va_end(argPtr);
406
407 return result;
408}
409
410psBool psMetadataAddV(psMetadata *md, psS32 location, const char *name,
411 psS32 type, const char *comment, va_list list)
412{
413 psMetadataItem* metadataItem = NULL;
414
415 metadataItem = psMetadataItemAllocV(name, type & PS_METADATA_TYPE_MASK, comment, list);
416
417 if (!psMetadataAddItem(md, metadataItem, location, type & PS_METADATA_FLAGS_MASK)) {
418 psError(PS_ERR_UNKNOWN,false,PS_ERRORTEXT_psMetadata_ADD_FAILED);
419 psFree(metadataItem);
420 return false;
421 }
422 // Decrement reference count, since the metadata item is now in metadata collection and no longer needed
423 psFree(metadataItem);
424
425 return true;
426}
427
428#define METADATA_ADD_TYPE(NAME,TYPE,METATYPE) \
429psBool psMetadataAdd##NAME(psMetadata* md, psS32 where, const char* name, \
430 const char* comment, TYPE value) { \
431 return psMetadataAdd(md,where,name, METATYPE,comment,value); \
432}
433
434METADATA_ADD_TYPE(S32,psS32,PS_META_S32)
435METADATA_ADD_TYPE(F32,psF32,PS_META_F32)
436METADATA_ADD_TYPE(F64,psF64,PS_META_F64)
437METADATA_ADD_TYPE(List,psList*,PS_META_LIST)
438METADATA_ADD_TYPE(Str,const char*,PS_META_STR)
439METADATA_ADD_TYPE(Vector,psVector*,PS_META_VEC)
440METADATA_ADD_TYPE(Image,psImage*,PS_META_IMG)
441METADATA_ADD_TYPE(Hash,psHash*,PS_META_HASH)
442METADATA_ADD_TYPE(LookupTable,psLookupTable*,PS_META_LOOKUPTABLE)
443METADATA_ADD_TYPE(Unknown,void*,PS_META_UNKNOWN)
444
445psBool psMetadataRemove(psMetadata *md, psS32 where, const char *key)
446{
447 PS_PTR_CHECK_NULL(md,NULL);
448
449 PS_PTR_CHECK_NULL(md->list,NULL);
450 psList* mdList = md->list;
451
452 PS_PTR_CHECK_NULL(md->table,NULL);
453 psHash* mdTable = md->table;
454
455 // Select removal by key or index
456 if (key != NULL) {
457 // Remove by key name
458 psMetadataItem* entry = psHashLookup(mdTable,key);
459 if (entry == NULL) {
460 psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psMetadata_REMOVE_TABLE_FAILED, key);
461 return false;
462 }
463 if (entry->type == PS_META_MULTI) {
464 psMetadataItem* listItem;
465 psListIterator* iter = psListIteratorAlloc(
466 entry->data.list,
467 PS_LIST_HEAD,true);
468 while ((listItem=psListGetAndIncrement(iter)) != NULL) {
469 psListRemoveData(mdList, listItem);
470 }
471 psFree(iter);
472 psHashRemove(mdTable,key);
473
474 } else {
475 psListRemoveData(mdList, entry);
476 psHashRemove(mdTable, key);
477 }
478 } else {
479 // Remove by index
480 psMetadataItem* entry = psListGet(mdList, where);
481 if (entry == NULL) {
482 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psMetadata_FIND_INDEX_FAILED, where);
483 return false;
484 }
485 key = entry->name;
486
487 if (key == NULL) {
488 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psMetadata_REMOVE_LIST_INDEX_FAILED, where);
489 return false;
490 }
491
492 psMetadataItem* tableItem = psHashLookup(mdTable, key);
493 if (tableItem == NULL) {
494 psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psMetadata_REMOVE_TABLE_FAILED, key);
495 return false;
496 }
497
498 if (tableItem->type == PS_META_MULTI) {
499 // multiple entries with same key, remove just the specified one
500 psListRemoveData(tableItem->data.list, entry);
501 } else {
502 if (!psHashRemove(mdTable, key)) {
503 psError(PS_ERR_UNKNOWN, false, PS_ERRORTEXT_psMetadata_REMOVE_TABLE_FAILED, key);
504 return false;
505 }
506 }
507 psListRemove(mdList, where);
508 }
509
510 return true;
511}
512
513psMetadataItem* psMetadataLookup(psMetadata *md, const char *key)
514{
515 psHash* mdTable = NULL;
516 psMetadataItem* entry = NULL;
517
518
519 PS_PTR_CHECK_NULL(md,NULL);
520 PS_PTR_CHECK_NULL(md->table,NULL);
521 PS_PTR_CHECK_NULL(key,NULL);
522
523 mdTable = md->table;
524 entry = (psMetadataItem*)psHashLookup(mdTable, key);
525
526 return entry;
527}
528
529void* psMetadataLookupPtr(psBool *status, psMetadata *md, const char *key)
530{
531 psMetadataItem *metadataItem = NULL;
532
533 if (status) {
534 *status = true;
535 }
536
537 metadataItem = psMetadataLookup(md, key);
538 if(metadataItem == NULL) {
539 if (status) {
540 *status = false;
541 }
542 return NULL;
543 }
544 if (metadataItem->type == PS_META_MULTI) {
545 // if multiple keys found, use the first.
546 metadataItem = (psMetadataItem*)((metadataItem->data.list)->head);
547 }
548
549 if(PS_META_IS_PRIMITIVE(metadataItem->type)) {
550 if (status) {
551 *status = false;
552 }
553 psError(PS_ERR_BAD_PARAMETER_VALUE, true,
554 PS_ERRORTEXT_psMetadata_METATYPE_INVALID,
555 metadataItem->type);
556 return NULL;
557 } else {
558 return metadataItem->data.V;
559 }
560}
561
562#define psMetadataLookupNumTYPE(TYPE) \
563ps##TYPE psMetadataLookup##TYPE(psBool *status, psMetadata *md, const char *key) \
564{ \
565 psMetadataItem *metadataItem = NULL; \
566 ps##TYPE value = 0; \
567 \
568 if (status) { \
569 *status = true; \
570 } \
571 \
572 metadataItem = psMetadataLookup(md, key); \
573 if(metadataItem == NULL) { \
574 if (status) { \
575 *status = false; \
576 } \
577 return 0; \
578 } \
579 if (metadataItem->type == PS_META_MULTI) { \
580 /* if multiple keys found, use the first. */ \
581 metadataItem = (psMetadataItem*)((metadataItem->data.list)->head); \
582 } \
583 \
584 switch (metadataItem->type) { \
585 case PS_META_S32: \
586 value = (ps##TYPE)metadataItem->data.S32; \
587 break; \
588 case PS_META_F32: \
589 value = (ps##TYPE)metadataItem->data.F32; \
590 break; \
591 case PS_META_F64: \
592 value = (ps##TYPE)metadataItem->data.F64; \
593 break; \
594 case PS_META_BOOL: \
595 if (metadataItem->data.B) { \
596 value = 1; \
597 } \
598 break; \
599 default: \
600 /* if you get to this point, the value is not a number. */ \
601 if (status) { \
602 *status = false; \
603 } \
604 break; \
605 } \
606 \
607 /* psFree(metadataItem); currently, the lookup doesn't increment the ref count */ \
608 return value; \
609}
610
611psMetadataLookupNumTYPE(F32)
612psMetadataLookupNumTYPE(F64)
613psMetadataLookupNumTYPE(S32)
614psMetadataLookupNumTYPE(Bool)
615
616psMetadataItem* psMetadataGet(psMetadata *md, psS32 where)
617{
618 psMetadataItem* entry = NULL;
619
620 PS_PTR_CHECK_NULL(md,NULL);
621 PS_PTR_CHECK_NULL(md->list,NULL);
622
623 entry = (psMetadataItem*) psListGet(md->list, where);
624 if (entry == NULL) {
625 psError(PS_ERR_BAD_PARAMETER_VALUE, true, PS_ERRORTEXT_psMetadata_FIND_INDEX_FAILED, where);
626 return NULL;
627 }
628
629 return entry;
630}
631
632psMetadataIterator* psMetadataIteratorAlloc(psMetadata* md,
633 int location,
634 const char* regex)
635{
636 PS_PTR_CHECK_NULL(md,NULL);
637 PS_PTR_CHECK_NULL(md->list,NULL);
638
639 psMetadataIterator* newIter = psAlloc(sizeof(psMetadataIterator));
640 newIter->preg = NULL;
641 newIter->iter = NULL;
642
643 // Set deallocator
644 p_psMemSetDeallocator(newIter, (psFreeFcn) metadataIteratorFree);
645
646 if (regex == NULL) {
647 newIter->iter = psListIteratorAlloc(md->list, location, false);
648 return newIter;
649 } else {
650 int regRtn = regcomp(newIter->preg,regex,0);
651 if (regRtn != 0) {
652 char errMsg[256];
653 regerror(regRtn, newIter->preg, errMsg, 256);
654 regfree(newIter->preg);
655 psError(PS_ERR_BAD_PARAMETER_VALUE, true,
656 PS_ERRORTEXT_psMetadata_REGEX_INVALID,
657 errMsg);
658 psFree(newIter);
659 return NULL;
660 }
661 }
662
663 psMetadataIteratorSet(newIter, location); // XXX: do we error if no match is found?
664
665 return newIter;
666}
667
668psBool psMetadataIteratorSet(psMetadataIterator* iterator,
669 int location)
670{
671 int match;
672 psMetadataItem* cursor;
673
674 PS_PTR_CHECK_NULL(iterator,NULL);
675
676 psListIterator* iter = iterator->iter;
677 PS_PTR_CHECK_NULL(iterator->iter,NULL);
678
679 regex_t* preg = iterator->preg;
680
681 // handle trivial case where no regex subsetting is required.
682 if (preg == NULL) {
683 return psListIteratorSet(iter,location);
684 }
685
686 if (location < 0) {
687 // match from the tail
688 match = 0;
689 psListIteratorSet(iter,PS_LIST_TAIL);
690 while ( (cursor=(psMetadataItem*)iter->cursor) != NULL) {
691 if (regexec(preg, cursor->name, 0, NULL, 0) == 0) {
692 // this key is a match
693 match--;
694 if (match == location) {
695 break;
696 }
697 }
698 (void)psListGetAndDecrement(iter);
699 }
700 return (match == location);
701 }
702
703 // find the n-th match from the head
704 match = -1;
705 psListIteratorSet(iter,PS_LIST_HEAD);
706 while ( (cursor=(psMetadataItem*)iter->cursor) != NULL) {
707 if (regexec(preg, cursor->name, 0, NULL, 0) == 0) {
708 // this key is a match
709 match++;
710 if (match == location) {
711 break;
712 }
713 }
714 (void)psListGetAndIncrement(iter);
715 }
716 return (match == location);
717}
718
719psMetadataItem* psMetadataGetAndIncrement(psMetadataIterator* iterator)
720{
721 psMetadataItem* oldValue;
722
723 PS_PTR_CHECK_NULL(iterator,NULL);
724
725 psListIterator* iter = iterator->iter;
726 PS_PTR_CHECK_NULL(iterator->iter,NULL);
727
728 regex_t* preg = iterator->preg;
729
730 // handle trivial case where no regex subsetting is required.
731 if (preg == NULL) {
732 return (psMetadataItem*)psListGetAndIncrement(iter);
733 }
734
735 oldValue = (psMetadataItem*)iter->cursor;
736
737 while (psListGetAndIncrement(iter) != NULL) {
738 if (iter->cursor != NULL &&
739 regexec(preg, ((psMetadataItem*)iter->cursor)->name, 0, NULL, 0) == 0) {
740 // this key is a match
741 break;
742 }
743 }
744 return oldValue;
745}
746
747psMetadataItem* psMetadataGetAndDecrement(psMetadataIterator* iterator)
748{
749 psMetadataItem* oldValue;
750
751 PS_PTR_CHECK_NULL(iterator,NULL);
752
753 psListIterator* iter = iterator->iter;
754 PS_PTR_CHECK_NULL(iterator->iter,NULL);
755
756 regex_t* preg = iterator->preg;
757
758 // handle trivial case where no regex subsetting is required.
759 if (preg == NULL) {
760 return (psMetadataItem*)psListGetAndDecrement(iter);
761 }
762
763 oldValue = (psMetadataItem*)iter->cursor;
764
765 while (psListGetAndDecrement(iter) != NULL) {
766 if (iter->cursor != NULL &&
767 regexec(preg, ((psMetadataItem*)iter->cursor)->name, 0, NULL, 0) == 0) {
768 // this key is a match
769 break;
770 }
771 }
772 return oldValue;
773}