2 * Copyright 2010 Jerome Glisse <glisse@freedesktop.org>
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
34 static int bof_entry_grow(bof_t *bof)
38 if (bof->array_size < bof->nentry)
40 array = realloc(bof->array, (bof->nentry + 16) * sizeof(void*));
51 bof_t *bof_object(void)
55 object = calloc(1, sizeof(bof_t));
59 object->type = BOF_TYPE_OBJECT;
64 bof_t *bof_object_get(bof_t *object, const char *keyname)
68 for (i = 0; i < object->array_size; i += 2) {
69 if (!strcmp(object->array[i]->value, keyname)) {
70 return object->array[i + 1];
76 int bof_object_set(bof_t *object, const char *keyname, bof_t *value)
81 if (object->type != BOF_TYPE_OBJECT)
83 r = bof_entry_grow(object);
86 key = bof_string(keyname);
89 object->array[object->array_size++] = key;
90 object->array[object->array_size++] = value;
91 object->size += value->size;
92 object->size += key->size;
100 bof_t *bof_array(void)
102 bof_t *array = bof_object();
106 array->type = BOF_TYPE_ARRAY;
111 int bof_array_append(bof_t *array, bof_t *value)
114 if (array->type != BOF_TYPE_ARRAY)
116 r = bof_entry_grow(array);
119 array->array[array->array_size++] = value;
120 array->size += value->size;
125 bof_t *bof_array_get(bof_t *bof, unsigned i)
127 if (!bof_is_array(bof) || i >= bof->array_size)
129 return bof->array[i];
132 unsigned bof_array_size(bof_t *bof)
134 if (!bof_is_array(bof))
136 return bof->array_size;
142 bof_t *bof_blob(unsigned size, void *value)
144 bof_t *blob = bof_object();
148 blob->type = BOF_TYPE_BLOB;
149 blob->value = calloc(1, size);
150 if (blob->value == NULL) {
155 memcpy(blob->value, value, size);
160 unsigned bof_blob_size(bof_t *bof)
162 if (!bof_is_blob(bof))
164 return bof->size - 12;
167 void *bof_blob_value(bof_t *bof)
169 if (!bof_is_blob(bof))
177 bof_t *bof_string(const char *value)
179 bof_t *string = bof_object();
183 string->type = BOF_TYPE_STRING;
184 string->size = strlen(value) + 1;
185 string->value = calloc(1, string->size);
186 if (string->value == NULL) {
190 strcpy(string->value, value);
198 bof_t *bof_int32(int32_t value)
200 bof_t *int32 = bof_object();
204 int32->type = BOF_TYPE_INT32;
206 int32->value = calloc(1, int32->size);
207 if (int32->value == NULL) {
211 memcpy(int32->value, &value, 4);
216 int32_t bof_int32_value(bof_t *bof)
218 return *((uint32_t*)bof->value);
224 static void bof_indent(int level)
228 for (i = 0; i < level; i++)
229 fprintf(stderr, " ");
232 static void bof_print_bof(bof_t *bof, int level, int entry)
236 fprintf(stderr, "--NULL-- for entry %d\n", entry);
240 case BOF_TYPE_STRING:
241 fprintf(stderr, "%p string [%s %d]\n", bof, (char*)bof->value, bof->size);
244 fprintf(stderr, "%p int32 [%d %d]\n", bof, *(int*)bof->value, bof->size);
247 fprintf(stderr, "%p blob [%d]\n", bof, bof->size);
250 fprintf(stderr, "%p null [%d]\n", bof, bof->size);
252 case BOF_TYPE_OBJECT:
253 fprintf(stderr, "%p object [%d %d]\n", bof, bof->array_size / 2, bof->size);
256 fprintf(stderr, "%p array [%d %d]\n", bof, bof->array_size, bof->size);
259 fprintf(stderr, "%p unknown [%d]\n", bof, bof->type);
264 static void bof_print_rec(bof_t *bof, int level, int entry)
268 bof_print_bof(bof, level, entry);
269 for (i = 0; i < bof->array_size; i++) {
270 bof_print_rec(bof->array[i], level + 2, i);
274 void bof_print(bof_t *bof)
276 bof_print_rec(bof, 0, 0);
279 static int bof_read(bof_t *root, FILE *file, long end, int level)
284 if (ftell(file) >= end) {
287 r = bof_entry_grow(root);
293 bof->offset = ftell(file);
294 r = fread(&bof->type, 4, 1, file);
297 r = fread(&bof->size, 4, 1, file);
300 r = fread(&bof->array_size, 4, 1, file);
304 case BOF_TYPE_STRING:
307 bof->value = calloc(1, bof->size - 12);
308 if (bof->value == NULL) {
311 r = fread(bof->value, bof->size - 12, 1, file);
313 fprintf(stderr, "error reading %d\n", bof->size - 12);
319 case BOF_TYPE_OBJECT:
321 r = bof_read(bof, file, bof->offset + bof->size, level + 2);
326 fprintf(stderr, "invalid type %d\n", bof->type);
329 root->array[root->centry++] = bof;
330 return bof_read(root, file, end, level);
336 bof_t *bof_load_file(const char *filename)
338 bof_t *root = bof_object();
342 fprintf(stderr, "%s failed to create root object\n", __func__);
345 root->file = fopen(filename, "r");
346 if (root->file == NULL)
348 r = fseek(root->file, 0L, SEEK_SET);
350 fprintf(stderr, "%s failed to seek into file %s\n", __func__, filename);
353 root->offset = ftell(root->file);
354 r = fread(&root->type, 4, 1, root->file);
357 r = fread(&root->size, 4, 1, root->file);
360 r = fread(&root->array_size, 4, 1, root->file);
363 r = bof_read(root, root->file, root->offset + root->size, 2);
372 void bof_incref(bof_t *bof)
377 void bof_decref(bof_t *bof)
383 if (--bof->refcount > 0)
385 for (i = 0; i < bof->array_size; i++) {
386 bof_decref(bof->array[i]);
387 bof->array[i] = NULL;
399 static int bof_file_write(bof_t *bof, FILE *file)
404 r = fwrite(&bof->type, 4, 1, file);
407 r = fwrite(&bof->size, 4, 1, file);
410 r = fwrite(&bof->array_size, 4, 1, file);
418 case BOF_TYPE_STRING:
421 r = fwrite(bof->value, bof->size - 12, 1, file);
425 case BOF_TYPE_OBJECT:
427 for (i = 0; i < bof->array_size; i++) {
428 r = bof_file_write(bof->array[i], file);
439 int bof_dump_file(bof_t *bof, const char *filename)
448 bof->file = fopen(filename, "w");
449 if (bof->file == NULL) {
450 fprintf(stderr, "%s failed to open file %s\n", __func__, filename);
454 r = fseek(bof->file, 0L, SEEK_SET);
456 fprintf(stderr, "%s failed to seek into file %s\n", __func__, filename);
459 r = fwrite(&bof->type, 4, 1, bof->file);
462 r = fwrite(&bof->size, 4, 1, bof->file);
465 r = fwrite(&bof->array_size, 4, 1, bof->file);
468 for (i = 0; i < bof->array_size; i++) {
469 r = bof_file_write(bof->array[i], bof->file);