Home | History | Annotate | Download | only in radeon
      1 /*
      2  * Copyright 2010 Jerome Glisse <glisse (at) freedesktop.org>
      3  *
      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:
     10  *
     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
     13  * Software.
     14  *
     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.
     22  *
     23  * Authors:
     24  *      Jerome Glisse
     25  */
     26 #include <errno.h>
     27 #include <stdlib.h>
     28 #include <string.h>
     29 #include "bof.h"
     30 
     31 /*
     32  * helpers
     33  */
     34 static int bof_entry_grow(bof_t *bof)
     35 {
     36 	bof_t **array;
     37 
     38 	if (bof->array_size < bof->nentry)
     39 		return 0;
     40 	array = realloc(bof->array, (bof->nentry + 16) * sizeof(void*));
     41 	if (array == NULL)
     42 		return -ENOMEM;
     43 	bof->array = array;
     44 	bof->nentry += 16;
     45 	return 0;
     46 }
     47 
     48 /*
     49  * object
     50  */
     51 bof_t *bof_object(void)
     52 {
     53 	bof_t *object;
     54 
     55 	object = calloc(1, sizeof(bof_t));
     56 	if (object == NULL)
     57 		return NULL;
     58 	object->refcount = 1;
     59 	object->type = BOF_TYPE_OBJECT;
     60 	object->size = 12;
     61 	return object;
     62 }
     63 
     64 bof_t *bof_object_get(bof_t *object, const char *keyname)
     65 {
     66 	unsigned i;
     67 
     68 	for (i = 0; i < object->array_size; i += 2) {
     69 		if (!strcmp(object->array[i]->value, keyname)) {
     70 			return object->array[i + 1];
     71 		}
     72 	}
     73 	return NULL;
     74 }
     75 
     76 int bof_object_set(bof_t *object, const char *keyname, bof_t *value)
     77 {
     78 	bof_t *key;
     79 	int r;
     80 
     81 	if (object->type != BOF_TYPE_OBJECT)
     82 		return -EINVAL;
     83 	r = bof_entry_grow(object);
     84 	if (r)
     85 		return r;
     86 	key = bof_string(keyname);
     87 	if (key == NULL)
     88 		return -ENOMEM;
     89 	object->array[object->array_size++] = key;
     90 	object->array[object->array_size++] = value;
     91 	object->size += value->size;
     92 	object->size += key->size;
     93 	bof_incref(value);
     94 	return 0;
     95 }
     96 
     97 /*
     98  * array
     99  */
    100 bof_t *bof_array(void)
    101 {
    102 	bof_t *array = bof_object();
    103 
    104 	if (array == NULL)
    105 		return NULL;
    106 	array->type = BOF_TYPE_ARRAY;
    107 	array->size = 12;
    108 	return array;
    109 }
    110 
    111 int bof_array_append(bof_t *array, bof_t *value)
    112 {
    113 	int r;
    114 	if (array->type != BOF_TYPE_ARRAY)
    115 		return -EINVAL;
    116 	r = bof_entry_grow(array);
    117 	if (r)
    118 		return r;
    119 	array->array[array->array_size++] = value;
    120 	array->size += value->size;
    121 	bof_incref(value);
    122 	return 0;
    123 }
    124 
    125 bof_t *bof_array_get(bof_t *bof, unsigned i)
    126 {
    127 	if (!bof_is_array(bof) || i >= bof->array_size)
    128 		return NULL;
    129 	return bof->array[i];
    130 }
    131 
    132 unsigned bof_array_size(bof_t *bof)
    133 {
    134 	if (!bof_is_array(bof))
    135 		return 0;
    136 	return bof->array_size;
    137 }
    138 
    139 /*
    140  * blob
    141  */
    142 bof_t *bof_blob(unsigned size, void *value)
    143 {
    144 	bof_t *blob = bof_object();
    145 
    146 	if (blob == NULL)
    147 		return NULL;
    148 	blob->type = BOF_TYPE_BLOB;
    149 	blob->value = calloc(1, size);
    150 	if (blob->value == NULL) {
    151 		bof_decref(blob);
    152 		return NULL;
    153 	}
    154 	blob->size = size;
    155 	memcpy(blob->value, value, size);
    156 	blob->size += 12;
    157 	return blob;
    158 }
    159 
    160 unsigned bof_blob_size(bof_t *bof)
    161 {
    162 	if (!bof_is_blob(bof))
    163 		return 0;
    164 	return bof->size - 12;
    165 }
    166 
    167 void *bof_blob_value(bof_t *bof)
    168 {
    169 	if (!bof_is_blob(bof))
    170 		return NULL;
    171 	return bof->value;
    172 }
    173 
    174 /*
    175  * string
    176  */
    177 bof_t *bof_string(const char *value)
    178 {
    179 	bof_t *string = bof_object();
    180 
    181 	if (string == NULL)
    182 		return NULL;
    183 	string->type = BOF_TYPE_STRING;
    184 	string->size = strlen(value) + 1;
    185 	string->value = calloc(1, string->size);
    186 	if (string->value == NULL) {
    187 		bof_decref(string);
    188 		return NULL;
    189 	}
    190 	strcpy(string->value, value);
    191 	string->size += 12;
    192 	return string;
    193 }
    194 
    195 /*
    196  *  int32
    197  */
    198 bof_t *bof_int32(int32_t value)
    199 {
    200 	bof_t *int32 = bof_object();
    201 
    202 	if (int32 == NULL)
    203 		return NULL;
    204 	int32->type = BOF_TYPE_INT32;
    205 	int32->size = 4;
    206 	int32->value = calloc(1, int32->size);
    207 	if (int32->value == NULL) {
    208 		bof_decref(int32);
    209 		return NULL;
    210 	}
    211 	memcpy(int32->value, &value, 4);
    212 	int32->size += 12;
    213 	return int32;
    214 }
    215 
    216 int32_t bof_int32_value(bof_t *bof)
    217 {
    218 	return *((uint32_t*)bof->value);
    219 }
    220 
    221 /*
    222  *  common
    223  */
    224 static void bof_indent(int level)
    225 {
    226 	int i;
    227 
    228 	for (i = 0; i < level; i++)
    229 		fprintf(stderr, " ");
    230 }
    231 
    232 static void bof_print_bof(bof_t *bof, int level, int entry)
    233 {
    234 	bof_indent(level);
    235 	if (bof == NULL) {
    236 		fprintf(stderr, "--NULL-- for entry %d\n", entry);
    237 		return;
    238 	}
    239 	switch (bof->type) {
    240 	case BOF_TYPE_STRING:
    241 		fprintf(stderr, "%p string [%s %d]\n", bof, (char*)bof->value, bof->size);
    242 		break;
    243 	case BOF_TYPE_INT32:
    244 		fprintf(stderr, "%p int32 [%d %d]\n", bof, *(int*)bof->value, bof->size);
    245 		break;
    246 	case BOF_TYPE_BLOB:
    247 		fprintf(stderr, "%p blob [%d]\n", bof, bof->size);
    248 		break;
    249 	case BOF_TYPE_NULL:
    250 		fprintf(stderr, "%p null [%d]\n", bof, bof->size);
    251 		break;
    252 	case BOF_TYPE_OBJECT:
    253 		fprintf(stderr, "%p object [%d %d]\n", bof, bof->array_size / 2, bof->size);
    254 		break;
    255 	case BOF_TYPE_ARRAY:
    256 		fprintf(stderr, "%p array [%d %d]\n", bof, bof->array_size, bof->size);
    257 		break;
    258 	default:
    259 		fprintf(stderr, "%p unknown [%d]\n", bof, bof->type);
    260 		return;
    261 	}
    262 }
    263 
    264 static void bof_print_rec(bof_t *bof, int level, int entry)
    265 {
    266 	unsigned i;
    267 
    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);
    271 	}
    272 }
    273 
    274 void bof_print(bof_t *bof)
    275 {
    276 	bof_print_rec(bof, 0, 0);
    277 }
    278 
    279 static int bof_read(bof_t *root, FILE *file, long end, int level)
    280 {
    281 	bof_t *bof = NULL;
    282 	int r;
    283 
    284 	if (ftell(file) >= end) {
    285 		return 0;
    286 	}
    287 	r = bof_entry_grow(root);
    288 	if (r)
    289 		return r;
    290 	bof = bof_object();
    291 	if (bof == NULL)
    292 		return -ENOMEM;
    293 	bof->offset = ftell(file);
    294 	r = fread(&bof->type, 4, 1, file);
    295 	if (r != 1)
    296 		goto out_err;
    297 	r = fread(&bof->size, 4, 1, file);
    298 	if (r != 1)
    299 		goto out_err;
    300 	r = fread(&bof->array_size, 4, 1, file);
    301 	if (r != 1)
    302 		goto out_err;
    303 	switch (bof->type) {
    304 	case BOF_TYPE_STRING:
    305 	case BOF_TYPE_INT32:
    306 	case BOF_TYPE_BLOB:
    307 		bof->value = calloc(1, bof->size - 12);
    308 		if (bof->value == NULL) {
    309 			goto out_err;
    310 		}
    311 		r = fread(bof->value, bof->size - 12, 1, file);
    312 		if (r != 1) {
    313 			fprintf(stderr, "error reading %d\n", bof->size - 12);
    314 			goto out_err;
    315 		}
    316 		break;
    317 	case BOF_TYPE_NULL:
    318 		return 0;
    319 	case BOF_TYPE_OBJECT:
    320 	case BOF_TYPE_ARRAY:
    321 		r = bof_read(bof, file, bof->offset + bof->size, level + 2);
    322 		if (r)
    323 			goto out_err;
    324 		break;
    325 	default:
    326 		fprintf(stderr, "invalid type %d\n", bof->type);
    327 		goto out_err;
    328 	}
    329 	root->array[root->centry++] = bof;
    330 	return bof_read(root, file, end, level);
    331 out_err:
    332 	bof_decref(bof);
    333 	return -EINVAL;
    334 }
    335 
    336 bof_t *bof_load_file(const char *filename)
    337 {
    338 	bof_t *root = bof_object();
    339 	int r;
    340 
    341 	if (root == NULL) {
    342 		fprintf(stderr, "%s failed to create root object\n", __func__);
    343 		return NULL;
    344 	}
    345 	root->file = fopen(filename, "r");
    346 	if (root->file == NULL)
    347 		goto out_err;
    348 	r = fseek(root->file, 0L, SEEK_SET);
    349 	if (r) {
    350 		fprintf(stderr, "%s failed to seek into file %s\n", __func__, filename);
    351 		goto out_err;
    352 	}
    353 	root->offset = ftell(root->file);
    354 	r = fread(&root->type, 4, 1, root->file);
    355 	if (r != 1)
    356 		goto out_err;
    357 	r = fread(&root->size, 4, 1, root->file);
    358 	if (r != 1)
    359 		goto out_err;
    360 	r = fread(&root->array_size, 4, 1, root->file);
    361 	if (r != 1)
    362 		goto out_err;
    363 	r = bof_read(root, root->file, root->offset + root->size, 2);
    364 	if (r)
    365 		goto out_err;
    366 	return root;
    367 out_err:
    368 	bof_decref(root);
    369 	return NULL;
    370 }
    371 
    372 void bof_incref(bof_t *bof)
    373 {
    374 	bof->refcount++;
    375 }
    376 
    377 void bof_decref(bof_t *bof)
    378 {
    379 	unsigned i;
    380 
    381 	if (bof == NULL)
    382 		return;
    383 	if (--bof->refcount > 0)
    384 		return;
    385 	for (i = 0; i < bof->array_size; i++) {
    386 		bof_decref(bof->array[i]);
    387 		bof->array[i] = NULL;
    388 	}
    389 	bof->array_size = 0;
    390 	if (bof->file) {
    391 		fclose(bof->file);
    392 		bof->file = NULL;
    393 	}
    394 	free(bof->array);
    395 	free(bof->value);
    396 	free(bof);
    397 }
    398 
    399 static int bof_file_write(bof_t *bof, FILE *file)
    400 {
    401 	unsigned i;
    402 	int r;
    403 
    404 	r = fwrite(&bof->type, 4, 1, file);
    405 	if (r != 1)
    406 		return -EINVAL;
    407 	r = fwrite(&bof->size, 4, 1, file);
    408 	if (r != 1)
    409 		return -EINVAL;
    410 	r = fwrite(&bof->array_size, 4, 1, file);
    411 	if (r != 1)
    412 		return -EINVAL;
    413 	switch (bof->type) {
    414 	case BOF_TYPE_NULL:
    415 		if (bof->size)
    416 			return -EINVAL;
    417 		break;
    418 	case BOF_TYPE_STRING:
    419 	case BOF_TYPE_INT32:
    420 	case BOF_TYPE_BLOB:
    421 		r = fwrite(bof->value, bof->size - 12, 1, file);
    422 		if (r != 1)
    423 			return -EINVAL;
    424 		break;
    425 	case BOF_TYPE_OBJECT:
    426 	case BOF_TYPE_ARRAY:
    427 		for (i = 0; i < bof->array_size; i++) {
    428 			r = bof_file_write(bof->array[i], file);
    429 			if (r)
    430 				return r;
    431 		}
    432 		break;
    433 	default:
    434 		return -EINVAL;
    435 	}
    436 	return 0;
    437 }
    438 
    439 int bof_dump_file(bof_t *bof, const char *filename)
    440 {
    441 	unsigned i;
    442 	int r = 0;
    443 
    444 	if (bof->file) {
    445 		fclose(bof->file);
    446 		bof->file = NULL;
    447 	}
    448 	bof->file = fopen(filename, "w");
    449 	if (bof->file == NULL) {
    450 		fprintf(stderr, "%s failed to open file %s\n", __func__, filename);
    451 		r = -EINVAL;
    452 		goto out_err;
    453 	}
    454 	r = fseek(bof->file, 0L, SEEK_SET);
    455 	if (r) {
    456 		fprintf(stderr, "%s failed to seek into file %s\n", __func__, filename);
    457 		goto out_err;
    458 	}
    459 	r = fwrite(&bof->type, 4, 1, bof->file);
    460 	if (r != 1)
    461 		goto out_err;
    462 	r = fwrite(&bof->size, 4, 1, bof->file);
    463 	if (r != 1)
    464 		goto out_err;
    465 	r = fwrite(&bof->array_size, 4, 1, bof->file);
    466 	if (r != 1)
    467 		goto out_err;
    468 	for (i = 0; i < bof->array_size; i++) {
    469 		r = bof_file_write(bof->array[i], bof->file);
    470 		if (r)
    471 			return r;
    472 	}
    473 out_err:
    474 	fclose(bof->file);
    475 	bof->file = NULL;
    476 	return r;
    477 }
    478