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
);