Back to index

libdrm  2.4.37
bof.c
Go to the documentation of this file.
00001 /*
00002  * Copyright 2010 Jerome Glisse <glisse@freedesktop.org>
00003  *
00004  * Permission is hereby granted, free of charge, to any person obtaining a
00005  * copy of this software and associated documentation files (the "Software"),
00006  * to deal in the Software without restriction, including without limitation
00007  * on the rights to use, copy, modify, merge, publish, distribute, sub
00008  * license, and/or sell copies of the Software, and to permit persons to whom
00009  * the Software is furnished to do so, subject to the following conditions:
00010  *
00011  * The above copyright notice and this permission notice (including the next
00012  * paragraph) shall be included in all copies or substantial portions of the
00013  * Software.
00014  *
00015  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00016  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00017  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
00018  * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
00019  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
00020  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
00021  * USE OR OTHER DEALINGS IN THE SOFTWARE.
00022  *
00023  * Authors:
00024  *      Jerome Glisse
00025  */
00026 #include <errno.h>
00027 #include <stdlib.h>
00028 #include <string.h>
00029 #include "bof.h"
00030 
00031 /*
00032  * helpers
00033  */
00034 static int bof_entry_grow(bof_t *bof)
00035 {
00036        bof_t **array;
00037 
00038        if (bof->array_size < bof->nentry)
00039               return 0;
00040        array = realloc(bof->array, (bof->nentry + 16) * sizeof(void*));
00041        if (array == NULL)
00042               return -ENOMEM;
00043        bof->array = array;
00044        bof->nentry += 16;
00045        return 0;
00046 }
00047 
00048 /*
00049  * object 
00050  */
00051 bof_t *bof_object(void)
00052 {
00053        bof_t *object;
00054 
00055        object = calloc(1, sizeof(bof_t));
00056        if (object == NULL)
00057               return NULL;
00058        object->refcount = 1;
00059        object->type = BOF_TYPE_OBJECT;
00060        object->size = 12;
00061        return object;
00062 }
00063 
00064 bof_t *bof_object_get(bof_t *object, const char *keyname)
00065 {
00066        unsigned i;
00067 
00068        for (i = 0; i < object->array_size; i += 2) {
00069               if (!strcmp(object->array[i]->value, keyname)) {
00070                      return object->array[i + 1];
00071               }
00072        }
00073        return NULL;
00074 }
00075 
00076 int bof_object_set(bof_t *object, const char *keyname, bof_t *value)
00077 {
00078        bof_t *key;
00079        int r;
00080 
00081        if (object->type != BOF_TYPE_OBJECT)
00082               return -EINVAL;
00083        r = bof_entry_grow(object);
00084        if (r)
00085               return r;
00086        key = bof_string(keyname);
00087        if (key == NULL)
00088               return -ENOMEM;
00089        object->array[object->array_size++] = key;
00090        object->array[object->array_size++] = value;
00091        object->size += value->size;
00092        object->size += key->size;
00093        bof_incref(value);
00094        return 0;
00095 }
00096 
00097 /*
00098  * array
00099  */
00100 bof_t *bof_array(void)
00101 {
00102        bof_t *array = bof_object();
00103 
00104        if (array == NULL)
00105               return NULL;
00106        array->type = BOF_TYPE_ARRAY;
00107        array->size = 12;
00108        return array;
00109 }
00110 
00111 int bof_array_append(bof_t *array, bof_t *value)
00112 {
00113        int r;
00114        if (array->type != BOF_TYPE_ARRAY)
00115               return -EINVAL;
00116        r = bof_entry_grow(array);
00117        if (r)
00118               return r;
00119        array->array[array->array_size++] = value;
00120        array->size += value->size;
00121        bof_incref(value);
00122        return 0;
00123 }
00124 
00125 bof_t *bof_array_get(bof_t *bof, unsigned i)
00126 {
00127        if (!bof_is_array(bof) || i >= bof->array_size)
00128               return NULL;
00129        return bof->array[i];
00130 }
00131 
00132 unsigned bof_array_size(bof_t *bof)
00133 {
00134        if (!bof_is_array(bof))
00135               return 0;
00136        return bof->array_size;
00137 }
00138 
00139 /*
00140  * blob
00141  */
00142 bof_t *bof_blob(unsigned size, void *value)
00143 {
00144        bof_t *blob = bof_object();
00145 
00146        if (blob == NULL)
00147               return NULL;
00148        blob->type = BOF_TYPE_BLOB;
00149        blob->value = calloc(1, size);
00150        if (blob->value == NULL) {
00151               bof_decref(blob);
00152               return NULL;
00153        }
00154        blob->size = size;
00155        memcpy(blob->value, value, size);
00156        blob->size += 12;
00157        return blob;
00158 }
00159 
00160 unsigned bof_blob_size(bof_t *bof)
00161 {
00162        if (!bof_is_blob(bof))
00163               return 0;
00164        return bof->size - 12;
00165 }
00166 
00167 void *bof_blob_value(bof_t *bof)
00168 {
00169        if (!bof_is_blob(bof))
00170               return NULL;
00171        return bof->value;
00172 }
00173 
00174 /*
00175  * string
00176  */
00177 bof_t *bof_string(const char *value)
00178 {
00179        bof_t *string = bof_object();
00180 
00181        if (string == NULL)
00182               return NULL;
00183        string->type = BOF_TYPE_STRING;
00184        string->size = strlen(value) + 1;
00185        string->value = calloc(1, string->size);
00186        if (string->value == NULL) {
00187               bof_decref(string);
00188               return NULL;
00189        }
00190        strcpy(string->value, value);
00191        string->size += 12;
00192        return string;
00193 }
00194 
00195 /*
00196  *  int32
00197  */
00198 bof_t *bof_int32(int32_t value)
00199 {
00200        bof_t *int32 = bof_object();
00201 
00202        if (int32 == NULL)
00203               return NULL;
00204        int32->type = BOF_TYPE_INT32;
00205        int32->size = 4;
00206        int32->value = calloc(1, int32->size);
00207        if (int32->value == NULL) {
00208               bof_decref(int32);
00209               return NULL;
00210        }
00211        memcpy(int32->value, &value, 4);
00212        int32->size += 12;
00213        return int32;
00214 }
00215 
00216 int32_t bof_int32_value(bof_t *bof)
00217 {
00218        return *((uint32_t*)bof->value);
00219 }
00220 
00221 /*
00222  *  common
00223  */
00224 static void bof_indent(int level)
00225 {
00226        int i;
00227 
00228        for (i = 0; i < level; i++)
00229               fprintf(stderr, " ");
00230 }
00231 
00232 static void bof_print_bof(bof_t *bof, int level, int entry)
00233 {
00234        bof_indent(level);
00235        if (bof == NULL) {
00236               fprintf(stderr, "--NULL-- for entry %d\n", entry);
00237               return;
00238        }
00239        switch (bof->type) {
00240        case BOF_TYPE_STRING:
00241               fprintf(stderr, "%p string [%s %d]\n", bof, (char*)bof->value, bof->size);
00242               break;
00243        case BOF_TYPE_INT32:
00244               fprintf(stderr, "%p int32 [%d %d]\n", bof, *(int*)bof->value, bof->size);
00245               break;
00246        case BOF_TYPE_BLOB:
00247               fprintf(stderr, "%p blob [%d]\n", bof, bof->size);
00248               break;
00249        case BOF_TYPE_NULL:
00250               fprintf(stderr, "%p null [%d]\n", bof, bof->size);
00251               break;
00252        case BOF_TYPE_OBJECT:
00253               fprintf(stderr, "%p object [%d %d]\n", bof, bof->array_size / 2, bof->size);
00254               break;
00255        case BOF_TYPE_ARRAY:
00256               fprintf(stderr, "%p array [%d %d]\n", bof, bof->array_size, bof->size);
00257               break;
00258        default:
00259               fprintf(stderr, "%p unknown [%d]\n", bof, bof->type);
00260               return;
00261        }
00262 }
00263 
00264 static void bof_print_rec(bof_t *bof, int level, int entry)
00265 {
00266        unsigned i;
00267 
00268        bof_print_bof(bof, level, entry);
00269        for (i = 0; i < bof->array_size; i++) {
00270               bof_print_rec(bof->array[i], level + 2, i);
00271        }
00272 }
00273 
00274 void bof_print(bof_t *bof)
00275 {
00276        bof_print_rec(bof, 0, 0);
00277 }
00278 
00279 static int bof_read(bof_t *root, FILE *file, long end, int level)
00280 {
00281        bof_t *bof = NULL;
00282        int r;
00283 
00284        if (ftell(file) >= end) {
00285               return 0;
00286        }
00287        r = bof_entry_grow(root);
00288        if (r)
00289               return r;
00290        bof = bof_object();
00291        if (bof == NULL)
00292               return -ENOMEM;
00293        bof->offset = ftell(file);
00294        r = fread(&bof->type, 4, 1, file);
00295        if (r != 1)
00296               goto out_err;
00297        r = fread(&bof->size, 4, 1, file);
00298        if (r != 1)
00299               goto out_err;
00300        r = fread(&bof->array_size, 4, 1, file);
00301        if (r != 1)
00302               goto out_err;
00303        switch (bof->type) {
00304        case BOF_TYPE_STRING:
00305        case BOF_TYPE_INT32:
00306        case BOF_TYPE_BLOB:
00307               bof->value = calloc(1, bof->size - 12);
00308               if (bof->value == NULL) {
00309                      goto out_err;
00310               }
00311               r = fread(bof->value, bof->size - 12, 1, file);
00312               if (r != 1) {
00313                      fprintf(stderr, "error reading %d\n", bof->size - 12);
00314                      goto out_err;
00315               }
00316               break;
00317        case BOF_TYPE_NULL:
00318               return 0;
00319        case BOF_TYPE_OBJECT:
00320        case BOF_TYPE_ARRAY:
00321               r = bof_read(bof, file, bof->offset + bof->size, level + 2);
00322               if (r)
00323                      goto out_err;
00324               break;
00325        default:
00326               fprintf(stderr, "invalid type %d\n", bof->type);
00327               goto out_err;
00328        }
00329        root->array[root->centry++] = bof;
00330        return bof_read(root, file, end, level);
00331 out_err:
00332        bof_decref(bof);
00333        return -EINVAL;
00334 }
00335 
00336 bof_t *bof_load_file(const char *filename)
00337 {
00338        bof_t *root = bof_object();
00339        int r;
00340 
00341        if (root == NULL) {
00342               fprintf(stderr, "%s failed to create root object\n", __func__);
00343               return NULL;
00344        }
00345        root->file = fopen(filename, "r");
00346        if (root->file == NULL)
00347               goto out_err;
00348        r = fseek(root->file, 0L, SEEK_SET);
00349        if (r) {
00350               fprintf(stderr, "%s failed to seek into file %s\n", __func__, filename);
00351               goto out_err;
00352        }
00353        root->offset = ftell(root->file);
00354        r = fread(&root->type, 4, 1, root->file);
00355        if (r != 1)
00356               goto out_err;
00357        r = fread(&root->size, 4, 1, root->file);
00358        if (r != 1)
00359               goto out_err;
00360        r = fread(&root->array_size, 4, 1, root->file);
00361        if (r != 1)
00362               goto out_err;
00363        r = bof_read(root, root->file, root->offset + root->size, 2);
00364        if (r)
00365               goto out_err;
00366        return root;
00367 out_err:
00368        bof_decref(root);
00369        return NULL;
00370 }
00371 
00372 void bof_incref(bof_t *bof)
00373 {
00374        bof->refcount++;
00375 }
00376 
00377 void bof_decref(bof_t *bof)
00378 {
00379        unsigned i;
00380 
00381        if (bof == NULL)
00382               return;
00383        if (--bof->refcount > 0)
00384               return;
00385        for (i = 0; i < bof->array_size; i++) {
00386               bof_decref(bof->array[i]);
00387               bof->array[i] = NULL;
00388        }
00389        bof->array_size = 0;
00390        if (bof->file) {
00391               fclose(bof->file);
00392               bof->file = NULL;
00393        }
00394        free(bof->array);
00395        free(bof->value);
00396        free(bof);
00397 }
00398 
00399 static int bof_file_write(bof_t *bof, FILE *file)
00400 {
00401        unsigned i;
00402        int r;
00403 
00404        r = fwrite(&bof->type, 4, 1, file);
00405        if (r != 1)
00406               return -EINVAL;
00407        r = fwrite(&bof->size, 4, 1, file);
00408        if (r != 1)
00409               return -EINVAL;
00410        r = fwrite(&bof->array_size, 4, 1, file);
00411        if (r != 1)
00412               return -EINVAL;
00413        switch (bof->type) {
00414        case BOF_TYPE_NULL:
00415               if (bof->size)
00416                      return -EINVAL;
00417               break;
00418        case BOF_TYPE_STRING:
00419        case BOF_TYPE_INT32:
00420        case BOF_TYPE_BLOB:
00421               r = fwrite(bof->value, bof->size - 12, 1, file);
00422               if (r != 1)
00423                      return -EINVAL;
00424               break;
00425        case BOF_TYPE_OBJECT:
00426        case BOF_TYPE_ARRAY:
00427               for (i = 0; i < bof->array_size; i++) {
00428                      r = bof_file_write(bof->array[i], file);
00429                      if (r)
00430                             return r;
00431               }
00432               break;
00433        default:
00434               return -EINVAL;
00435        }
00436        return 0;
00437 }
00438 
00439 int bof_dump_file(bof_t *bof, const char *filename)
00440 {
00441        unsigned i;
00442        int r = 0;
00443 
00444        if (bof->file) {
00445               fclose(bof->file);
00446               bof->file = NULL;
00447        }
00448        bof->file = fopen(filename, "w");
00449        if (bof->file == NULL) {
00450               fprintf(stderr, "%s failed to open file %s\n", __func__, filename);
00451               r = -EINVAL;
00452               goto out_err;
00453        }
00454        r = fseek(bof->file, 0L, SEEK_SET);
00455        if (r) {
00456               fprintf(stderr, "%s failed to seek into file %s\n", __func__, filename);
00457               goto out_err;
00458        }
00459        r = fwrite(&bof->type, 4, 1, bof->file);
00460        if (r != 1)
00461               goto out_err;
00462        r = fwrite(&bof->size, 4, 1, bof->file);
00463        if (r != 1)
00464               goto out_err;
00465        r = fwrite(&bof->array_size, 4, 1, bof->file);
00466        if (r != 1)
00467               goto out_err;
00468        for (i = 0; i < bof->array_size; i++) {
00469               r = bof_file_write(bof->array[i], bof->file);
00470               if (r)
00471                      return r;
00472        }
00473 out_err:
00474        fclose(bof->file);
00475        bof->file = NULL;
00476        return r;
00477 }