Changeset 156
- Timestamp:
- Mar 9, 2004, 12:50:03 PM (22 years ago)
- Location:
- trunk/archive/pslib/src/Metadata
- Files:
-
- 2 edited
-
metadata.c (modified) (7 diffs)
-
psMetaData.h (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/archive/pslib/src/Metadata/metadata.c
r141 r156 8 8 #include "psUtils.h" 9 9 #include "psMetaData.h" 10 /* 11 * Return a properly filled-out psMetaData 10 11 /*****************************************************************************/ 12 /* 13 * Handle sets of metadata 14 */ 15 psMetaDataSet *psMetaDataSetNew(void) // make a new set of metadata 16 { 17 psMetaDataSet *ms = psAlloc(sizeof(psMetaDataSet)); 18 19 ms->list = psDlistNew(NULL); // list of metadata 20 ms->table = psHashNew(128); // hash table 21 22 return ms; 23 } 24 25 void psMetaDataSetDel(psMetaDataSet *ms) // destroy a set of metadata 26 { 27 if (ms == NULL) { 28 return; 29 } 30 31 psDlistDel(ms->list, (void (*)(void *))NULL); 32 psHashDel(ms->table, (void (*)(void *))psMetaDataItemDel); 33 34 psFree(ms); 35 } 36 37 /*****************************************************************************/ 38 /* 39 * Return a properly filled-out psMetaDataItem 12 40 * 13 41 * N.b. For types PS_META_FLOAT, PS_META_INT, and PS_META_STR, a COPY 14 42 * of the data will be kept. In all other cases, only a POINTER 15 43 * to the data will be kept. 16 * 17 * An unused argument, copy, is provided to handle this better 18 * once we have copy constructors available. 19 */ 20 psMetaData *psMetaDataNew( 21 const char *name, // name of new item of metadata 22 psMetaDataType type, // type of this piece of metadata 44 */ 45 psMetaDataItem *psMetaDataItemNew( 46 int typeFlags, // type of this piece of metadata + flags 23 47 const void *data, // value of new item 24 const char *comment, // comment associated with item; 25 // may be NULL 26 int copy) // always copy data; NOTUSED 27 { 48 const char *comment, // comment associated with item; may be NULL 49 const char *name, // name of new item of metadata (may be an sprintf format) 50 ... // possible arguments for name format 51 ) 52 { 53 const psMetaDataType type = typeFlags & PS_META_TYPE_MASK; // the type part of typeFlags 54 const long flags = typeFlags & ~PS_META_TYPE_MASK; // the flags part of typeFlags 28 55 static int id = 0; // unique ID for an item of metadata 29 psMetaData *ms = psAlloc(sizeof(psMetaData));56 psMetaDataItem *ms = psAlloc(sizeof(psMetaDataItem)); 30 57 31 58 *(int *)&ms->id = id++; // need to cast away const 59 60 assert ((PS_META_NTYPE & PS_META_TYPE_MASK) == PS_META_NTYPE); // we have enough type names available 61 if (flags & PS_META_NON_UNIQUE) { 62 if (flags & PS_META_UNIQUE) { 63 psTrace("metadata.name", 1, 64 "Keyword \"%s\" was specified as both UNIQUE and NON_UNIQUE; adopting UNIQUE\n", name); 65 flags &= ~PS_META_NON_UNIQUE; 66 } 67 } else { 68 flags |= PS_META_UNIQUE; 69 } 70 32 71 ms->type = type; 72 ms->flags = flags; 73 ms->items = NULL; 33 74 34 75 assert (name != NULL); 35 ms->name = psAlloc(strlen(name) + 1); 36 strcpy(ms->name, name); 37 38 if(comment == NULL) { 39 comment = ""; 40 } 41 ms->comment = psAlloc(strlen(comment) + 1); 42 strcpy(ms->comment, comment); 76 if (strchr(name, '%') != NULL) { 77 static char tmp[201]; // should be enough; we won't overflow even if it isn't 78 79 va_list ap; 80 va_start(ap, name); 81 if(vsnprintf(tmp, sizeof(tmp), name, ap) > sizeof(tmp) - 1) { 82 psTrace("metadata.name", 1, "Keyword \"%s\" was truncated to \"%s\" upon expansion\n", name, tmp); 83 } 84 va_end(ap); 85 86 name = tmp; 87 } 88 ms->name = psStringCopy(name); 89 90 ms->comment = psStringCopy(comment == NULL ? "" : comment); 43 91 44 92 assert (type >= 0 && type < PS_META_NTYPE); 45 93 switch (type) { 94 case PS_META_ITEM_SET: 95 *(void **)&ms->val.v = NULL; 96 ms->items = psDlistNew(NULL); 97 break; 98 46 99 case PS_META_FLOAT: 47 100 *(float *)&ms->val.f = *(float *)data; … … 62 115 case PS_META_ASTROM: 63 116 case PS_META_UNKNOWN: 64 *(void **) ms->val.v = (void *)data;117 *(void **)&ms->val.v = (void *)data; 65 118 break; 66 119 case PS_META_NTYPE: … … 72 125 } 73 126 74 void psMetaData Del(psMetaData*ms) // piece of metadata to destroy127 void psMetaDataItemDel(psMetaDataItem *ms) // piece of metadata to destroy 75 128 { 76 129 if(ms == NULL) { … … 83 136 assert (ms->type >= 0 && ms->type < PS_META_NTYPE); 84 137 switch (ms->type) { 138 case PS_META_ITEM_SET: 139 psDlistDel(ms->items, (void (*)(void *))NULL); // they're still in the hash table 140 ms->items = NULL; 141 break; 85 142 case PS_META_FLOAT: 86 143 case PS_META_INT: 87 144 break; // nothing to do 88 89 145 case PS_META_STR: 90 146 psFree(ms->val.v); … … 107 163 108 164 /*****************************************************************************/ 109 110 void psMetaDataPrint(FILE *fd, // file descriptor to write to 111 const psMetaData *ms) // item of metadata to print 165 /* 166 * Add an new psMetaDataItem to a psMetaDataSet 167 */ 168 psMetaDataItem *psMetaDataAppend(psMetaDataSet *restrict ms, psMetaDataItem *restrict item) 169 { 170 psMetaDataItem *meta = NULL; // an item of metadata 171 assert (ms != NULL && ms->list != NULL && ms->table != NULL); 172 173 // Have we already seen this item? 174 meta = psHashLookup(ms->table, item->name); 175 176 if (item->flags & PS_META_NON_UNIQUE) { 177 psMetaDataItem *head = meta; 178 if (head == NULL) { // this is the first item of this name 179 head = psMetaDataAppend(ms, psMetaDataItemNew(PS_META_ITEM_SET, NULL, NULL, item->name)); 180 } 181 182 psDlistSetIterator(head->items, PS_DLIST_TAIL, 0); 183 meta = psDlistGetPrev(head->items, 0); 184 185 int i = 0; // index of this instance of name 186 if (meta != NULL) { // no items of this name 187 char *ptr = strrchr(meta->name, '.'); 188 assert (ptr != NULL); 189 i = atoi(ptr + 1) + 1; // next value 190 } 191 192 char newname[strlen(item->name) + 2 + 1]; 193 sprintf(newname, "%s.%d", item->name, i); 194 195 assert (psHashLookup(ms->table, newname) == NULL); // name isn't in use 196 197 psFree(item->name); 198 item->name = psStringCopy(newname); 199 200 psDlistAppend(head->items, item); 201 psHashInsert(ms->table, item->name, item, (void (*)(void *))psMetaDataItemDel); 202 203 return item; 204 } else if (meta != NULL) { 205 psError(__func__, "Key \"%s\" is already present in the metaDataSet 0x%x", item->name, ms); 206 //psMetaDataItemDel(item); 207 208 return NULL; 209 } 210 211 psDlistAppend(ms->list, item); 212 psHashInsert(ms->table, item->name, item, (void (*)(void *))psMetaDataItemDel); 213 214 return item; 215 } 216 217 /*****************************************************************************/ 218 /* 219 * Remove and return an item of metadata from a set 220 */ 221 psMetaDataItem *psMetaDataRemove(psMetaDataSet *restrict ms, const char *restrict key) 222 { 223 assert (ms != NULL && ms->list != NULL && ms->table != NULL); 224 225 void *data = psHashRemove(ms->table, key); 226 227 if (data == NULL) { 228 return NULL; 229 } else { 230 return psDlistRemove(ms->list, data, PS_DLIST_UNKNOWN); 231 } 232 } 233 234 /*****************************************************************************/ 235 /* 236 * Iterators for the psDlist representation of the metadata 237 */ 238 void psMetaDataSetIterator(psMetaDataSet *ms) 239 { 240 assert (ms != NULL); 241 psDlistSetIterator(ms->list, PS_DLIST_HEAD, 0); 242 } 243 244 psMetaDataItem *psMetaDataGetNext(psMetaDataSet *restrict ms, 245 const char *restrict match) 246 { 247 assert (ms != NULL); 248 psMetaDataItem *meta = psDlistGetNext(ms->list, 0); 249 250 if (match == NULL || meta == NULL) { 251 return meta; 252 } else { 253 if (strncmp(meta->name, match, strlen(match)) == 0) { // a match 254 return meta; 255 } else { 256 return psMetaDataGetNext(ms, match); 257 } 258 } 259 } 260 261 /*****************************************************************************/ 262 /* 263 * Access using the hash table 264 */ 265 psMetaDataItem *psMetaDataLookup(const psMetaDataSet *restrict ms, 266 const char *restrict key) 267 { 268 assert (ms != NULL); 269 270 return psHashLookup(ms->table, key); 271 } 272 273 /*****************************************************************************/ 274 void psMetaDataItemPrint(FILE *fd, // file descriptor to write to 275 const psMetaDataItem *restrict ms, // item of metadata to print 276 const char *prefix) // print this at the beginning of each line 112 277 { 113 278 if(ms == NULL) { … … 115 280 } 116 281 117 fprintf(fd, " Name: %-40s (ID: %d)\n", ms->name, ms->id);282 fprintf(fd, "%sName: %-40s (ID: %d)\n", prefix, ms->name, ms->id); 118 283 if (*ms->comment != '\0') { 119 fprintf(fd, " Comment: %s\n", ms->comment);120 } 121 fprintf(fd, " Value: ");284 fprintf(fd, "%sComment: %s\n", prefix, ms->comment); 285 } 286 fprintf(fd, "%sValue: ", prefix); 122 287 123 288 assert (ms->type >= 0 && ms->type < PS_META_NTYPE); 289 fprintf(fd, "%s", prefix); 124 290 switch (ms->type) { 291 case PS_META_ITEM_SET: 292 { // gcc 3.3 doesn't allow a declaration here 293 psMetaDataItem *meta = NULL; 294 295 fprintf(fd, "\n"); 296 psDlistSetIterator(ms->items, PS_DLIST_HEAD, 0); 297 while ((meta = psDlistGetNext(ms->items, 0)) != NULL) { 298 psMetaDataItemPrint(fd, meta, "\t"); 299 } 300 } 301 302 break; 125 303 case PS_META_FLOAT: 126 304 fprintf(fd, "%g\n", ms->val.f); 127 305 break; 128 129 306 case PS_META_INT: 130 307 fprintf(fd, "%d\n", ms->val.i); 131 308 break; 132 133 309 case PS_META_STR: 134 310 fprintf(fd, "%s\n", (char *)ms->val.v); 135 311 break; 136 137 312 case PS_META_IMG: 138 313 fprintf(fd, "(IMG)\n"); 139 314 break; 140 141 315 case PS_META_JPEG: 142 316 fprintf(fd, "(JPG)\n"); 143 317 break; 144 145 318 case PS_META_PNG: 146 319 fprintf(fd, "(PNG)\n"); 147 320 break; 148 149 321 case PS_META_ASTROM: 150 322 fprintf(fd, "(ASTROM)\n"); 151 323 break; 152 153 324 case PS_META_UNKNOWN: 154 325 fprintf(fd, "(UNKNOWN)\n"); 155 326 break; 156 157 327 case PS_META_NTYPE: 158 328 psAbort(__FILE__, "You cannot get here (%d)\n", __LINE__); … … 170 340 int main(void) 171 341 { 172 psDlist *list = psDlistNew(NULL); // list of metadata 173 174 const int ten = 10; 175 psDlistAppend(list, psMetaDataNew("const.ten", PS_META_INT, &ten, NULL,0)); 176 const float sqrt2 = sqrt(2); 177 psDlistAppend(list, psMetaDataNew("const.sqrt2", PS_META_FLOAT, &sqrt2, 178 "square root of two", 0)); 179 psDlistAppend(list, psMetaDataNew("lang.hello", PS_META_STR, "Bonjour", 180 "French", 0)); 181 /* 182 * Print that data 183 */ 184 for (psDlistElem *ptr = list->head; ptr != NULL; ptr = ptr->next) { 185 psMetaDataPrint(stdout, ptr->data); 186 } 187 342 psSetTraceLevel("metadata", 1); // turn on tracing 343 psSetLogFormat("NM"); // suppress some of the psLogMsg verbosity 344 345 psMetaDataSet *ms = psMetaDataSetNew(); // set of metadata 346 psMetaDataItem *meta = NULL; // used to traverse a set of metadata 347 348 for (int i = 0; i < 10; i += 5) { 349 float sqrti = sqrt(i); 350 psMetaDataAppend(ms, psMetaDataItemNew(PS_META_INT, &i, NULL, "const.%d", i)); 351 psMetaDataAppend(ms, psMetaDataItemNew(PS_META_FLOAT, &sqrti, "square root", "const.sqrt%d", i)); 352 } 353 psMetaDataAppend(ms, psMetaDataItemNew(PS_META_STR | PS_META_NON_UNIQUE, 354 "Bonjour", "French", "lang.hello")); 355 psMetaDataAppend(ms, psMetaDataItemNew(PS_META_STR | PS_META_NON_UNIQUE, 356 "Aloha", "Hawaiian", "lang.hello")); 357 psMetaDataAppend(ms, psMetaDataItemNew(PS_META_STR | PS_META_NON_UNIQUE, 358 "Good Morning", "English", "lang.hello")); 359 /* 360 * Print all metadata starting "lang" 361 */ 362 psMetaDataSetIterator(ms); 363 while ((meta = psMetaDataGetNext(ms, "lang")) != NULL) { 364 psMetaDataItemPrint(stdout, meta, ""); 365 } 366 /* 367 * Remove a key 368 */ 369 psMetaDataItemDel(psMetaDataRemove(ms, "lang.hello")); 370 /* 371 * Print all metadata 372 */ 188 373 fprintf(stdout, "------\n"); 189 /* 190 * Print it again 191 */ 192 (void)psDlistGet(list, PS_DLIST_TAIL); // initialise iterator 193 psMetaData *ms = NULL; 194 while ((ms = psDlistGet(list, PS_DLIST_PREV)) != NULL) { 195 psMetaDataPrint(stdout, ms); 374 psMetaDataSetIterator(ms); 375 while ((meta = psMetaDataGetNext(ms, NULL)) != NULL) { 376 psMetaDataItemPrint(stdout, meta, ""); 377 } 378 /* 379 * Look up a key by name 380 */ 381 fprintf(stdout, "------\n"); 382 fprintf(stdout, "Looking up by name:\n"); 383 meta = psMetaDataLookup(ms, "const.5"); 384 if (meta != NULL) { 385 psMetaDataItemPrint(stdout, meta, ""); 196 386 } 197 387 /* 198 388 * Clean up 199 389 */ 200 ps DlistDel(list, (void (*)(void *))psMetaDataDel);390 psMetaDataSetDel(ms); 201 391 /* 202 392 * Check for memory leaks 203 393 */ 204 394 fprintf(stderr,"Checking for memory leaks:\n"); 395 psTraceReset(); 205 396 psMemCheckLeaks(0, NULL, stderr); 206 397 -
trunk/archive/pslib/src/Metadata/psMetaData.h
r141 r156 8 8 */ 9 9 typedef enum { // type of val is: 10 PS_META_FLOAT = 0, // float (.f) 10 PS_META_ITEM_SET = 0, // NULL; metadata is in psMetaDataType.items 11 PS_META_FLOAT, // float (.f) 11 12 PS_META_INT, // int (.i) 12 13 PS_META_STR, // string (.v) … … 19 20 } psMetaDataType; 20 21 22 enum { 23 PS_META_TYPE_MASK = 0xffff, // the type enum must fit in this mask 24 PS_META_UNIQUE = 0x10000, // the name must be unique (default) 25 PS_META_NON_UNIQUE = 0x20000, // the name may be repeated, and should be disambiguated for us 26 }; 27 21 28 /* 22 29 * A struct to define a single item of metadata … … 25 32 const int id; // unique ID for this item 26 33 27 char * name;// Name of item34 char *restrict name; // Name of item 28 35 psMetaDataType type; // type of this item 36 int flags; // flags associated with this item 29 37 const union { 30 38 float f; // floating value … … 33 41 } val; // value of metadata 34 42 char *comment; // optional comment ("", not NULL) 35 } psMetaData; 43 psDlist *restrict items; // list of psMetaDataItems with the same name 44 } psMetaDataItem; 45 46 /* 47 * A set of metadata 48 */ 49 typedef struct { 50 psDlist *restrict list; // list of psMetaDataItem 51 psHash *restrict table; // hash table of the same metadata 52 } psMetaDataSet; 36 53 37 54 /*****************************************************************************/ … … 39 56 * Constructors and destructors 40 57 */ 41 psMetaData *psMetaDataNew( 42 const char *name, // name of new item of metadata 43 psMetaDataType type, // type of this piece of metadata 58 psMetaDataItem *psMetaDataItemNew( 59 int typeFlags, // type of this piece of metadata + flags 44 60 const void *val, // value of new item 45 61 // N.b. a pointer even if the item 46 62 // is of type e.g. int 47 63 const char *comment, // comment associated with item 48 int copy); // always copy data; NOTUSED 64 const char *name, // name of new item of metadata (may be an sprintf format) 65 ...); // possible arguments for name format 49 66 50 void psMetaDataDel(psMetaData *ms); // piece of metadata to destroy 67 void psMetaDataItemDel(psMetaDataItem *ms); // piece of metadata to destroy 68 69 psMetaDataSet *psMetaDataSetNew(void); // make a new set of metadata 70 void psMetaDataSetDel(psMetaDataSet *ms); // destroy a set of metadata 51 71 52 72 /*****************************************************************************/ … … 54 74 * Utilities 55 75 */ 56 void psMetaDataPrint(FILE *fd, // file descriptor to write to 57 const psMetaData *ms); // item of metadata to print 76 psMetaDataItem *psMetaDataAppend(psMetaDataSet *restrict ms, psMetaDataItem *restrict item); 77 psMetaDataItem *psMetaDataRemove(psMetaDataSet *restrict ms, const char *restrict key); 58 78 79 void psMetaDataSetIterator(psMetaDataSet *ms); 80 psMetaDataItem *psMetaDataGetNext(psMetaDataSet *restrict ms, const char *restrict match); 81 psMetaDataItem *psMetaDataLookup(const psMetaDataSet *restrict ms, const char *restrict key); 59 82 83 void psMetaDataItemPrint(FILE *fd, // file descriptor to write to 84 const psMetaDataItem *restrict ms, // item of metadata to print 85 const char *prefix); // print this at the beginning of each line 60 86 #endif
Note:
See TracChangeset
for help on using the changeset viewer.
