Logo Search packages:      
Sourcecode: icu version File versions

uresdata.c

/*
*******************************************************************************
*                                                                             *
* Copyright (C) 1999-2001, International Business Machines Corporation        *
*               and others. All Rights Reserved.                              *
*                                                                             *
*******************************************************************************
*   file name:  uresdata.c
*   encoding:   US-ASCII
*   tab size:   8 (not used)
*   indentation:4
*
*   created on: 1999dec08
*   created by: Markus W. Scherer
* Modification History:
*
*   Date        Name        Description
*   06/20/2000  helena      OS/400 port changes; mostly typecast.
*/

#include "unicode/utypes.h"
#include "cstring.h"
#include "unicode/udata.h"
#include "uresdata.h"
#include "uresimp.h"

/*
 * Resource access helpers
 */

/* get a const char* pointer to the key with the keyOffset byte offset from pRoot */
#define RES_GET_KEY(pRoot, keyOffset) ((const char *)(pRoot)+(keyOffset))
#define URESDATA_ITEM_NOT_FOUND 0xFFFF

/*
 * All the type-access functions assume that
 * the resource is of the expected type.
 */


/*
 * Array functions
 */
static Resource
_res_getArrayItem(Resource *pRoot, Resource res, int32_t indexR) {
    int32_t *p=(int32_t *)RES_GET_POINTER(pRoot, res);
    if(indexR<*p) {
        return ((Resource *)(p))[1+indexR];
    } else {
        return RES_BOGUS;   /* indexR>itemCount */
    }
}

/*
 * Table functions
 *
 * Important: the key offsets are 16-bit byte offsets from pRoot,
 * and the itemCount is one more 16-bit, too.
 * Thus, there are (count+1) uint16_t values.
 * In order to 4-align the Resource item values, there is a padding
 * word if count is even, i.e., there is exactly (~count&1)
 * 16-bit padding words.
 */
static const char *
_res_getTableKey(const Resource *pRoot, const Resource res, uint16_t indexS) {
    uint16_t *p=(uint16_t *)RES_GET_POINTER(pRoot, res);
    if(indexS<*p) {
        return RES_GET_KEY(pRoot, p[indexS+1]);
    } else {
        return NULL;    /* indexS>itemCount */
    }
}

static Resource
_res_getTableItem(const Resource *pRoot, const Resource res, uint16_t indexR) {
    uint16_t *p=(uint16_t *)RES_GET_POINTER(pRoot, res);
    uint16_t count=*p;
    if(indexR<count) {
        return ((Resource *)(p+1+count+(~count&1)))[indexR];
    } else {
        return RES_BOGUS;   /* indexR>itemCount */
    }
}

static Resource
_res_findTableItem(const Resource *pRoot, const Resource res, const char *key) {
    uint16_t *p=(uint16_t *)RES_GET_POINTER(pRoot, res);
    uint16_t i, start, limit;

    limit=*p++; /* number of entries */

    if(limit == 0) { /* this table is empty */
      return RES_BOGUS;
    }

    /* do a binary search for the key */
    start=0;
    while(start<limit-1) {
        i=(uint16_t)((start+limit)/2);
        if(uprv_strcmp(key, RES_GET_KEY(pRoot, p[i]))<0) {
            limit=i;
        } else {
            start=i;
        }
    }

    /* did we really find it? */
    if(uprv_strcmp(key, RES_GET_KEY(pRoot, p[start]))==0) {
        limit=*(p-1);   /* itemCount */
        return ((Resource *)(p+limit+(~limit&1)))[start];
    } else {
        return RES_BOGUS;   /* not found */
    }
}

static uint16_t
_res_findTableIndex(const Resource *pRoot, const Resource res, const char *key) {
    uint16_t *p=(uint16_t *)RES_GET_POINTER(pRoot, res);
    uint16_t i, start, limit;

    limit=*p++; /* number of entries */

    if(limit == 0) { /* this table is empty */
      return URESDATA_ITEM_NOT_FOUND;
    }

    /* do a binary search for the key */
    start=0;
    while(start<limit-1) {
        i=(uint16_t)((start+limit)/2);
        if(uprv_strcmp(key, RES_GET_KEY(pRoot, p[i]))<0) {
            limit=i;
        } else {
            start=i;
        }
    }
    
    /* did we really find it? */
    if(uprv_strcmp(key, RES_GET_KEY(pRoot, p[start]))==0) {
        limit=*(p-1);   /* itemCount */
        return start;
    } else {
        return URESDATA_ITEM_NOT_FOUND;   /* not found */
    }
}

/* helper for res_load() ---------------------------------------------------- */

static UBool
isAcceptable(void *context,
             const char *type, const char *name,
             const UDataInfo *pInfo) {
    return (UBool)(
        pInfo->size>=20 &&
        pInfo->isBigEndian==U_IS_BIG_ENDIAN &&
        pInfo->charsetFamily==U_CHARSET_FAMILY &&
        pInfo->sizeofUChar==U_SIZEOF_UCHAR &&
        pInfo->dataFormat[0]==0x52 &&   /* dataFormat="ResB" */
        pInfo->dataFormat[1]==0x65 &&
        pInfo->dataFormat[2]==0x73 &&
        pInfo->dataFormat[3]==0x42 &&
        pInfo->formatVersion[0]==1);
}

/* semi-public functions ---------------------------------------------------- */

U_CFUNC UBool
res_load(ResourceData *pResData,
         const char *path, const char *name, UErrorCode *errorCode) {
    /* load the ResourceBundle file */
    pResData->data=udata_openChoice(path, "res", name, isAcceptable, NULL, errorCode);
    if(U_FAILURE(*errorCode)) {
        return FALSE;
    }

    /* get its memory and root resource */
    pResData->pRoot=(Resource *)udata_getMemory(pResData->data);
    pResData->rootRes=*pResData->pRoot;

    /* currently, we accept only resources that have a Table as their roots */
    if(RES_GET_TYPE(pResData->rootRes)!=RES_TABLE) {
        udata_close(pResData->data);
        pResData->data=NULL; 
        return FALSE;
    }

    return TRUE;
}

U_CFUNC void
res_unload(ResourceData *pResData) {
    if(pResData->data!=NULL) {
        udata_close(pResData->data);
        pResData->data=NULL;
    }
}

U_CFUNC const UChar *
res_getString(const ResourceData *pResData, const Resource res, int32_t *pLength) {
    if(res!=RES_BOGUS && RES_GET_TYPE(res)==RES_STRING) {
        int32_t *p=(int32_t *)RES_GET_POINTER(pResData->pRoot, res);
        if (pLength) {
            *pLength=*p;
        }
        return (UChar *)++p;
    } else {
        if (pLength) {
            *pLength=0;
        }
        return NULL;
    }
}

U_CFUNC const uint8_t *
res_getBinary(const ResourceData *pResData, const Resource res, int32_t *pLength) {
    if(res!=RES_BOGUS) {
        int32_t *p=(int32_t *)RES_GET_POINTER(pResData->pRoot, res);
        *pLength=*p++;
        if (*pLength == 0) {
            p = NULL;
        }
        return (uint8_t *)p;
    } else {
        *pLength=0;
        return NULL;
    }
}


U_CFUNC const int32_t *
res_getIntVector(const ResourceData *pResData, const Resource res, int32_t *pLength) {
    if(res!=RES_BOGUS && RES_GET_TYPE(res)==RES_INT_VECTOR) {
        int32_t *p=(int32_t *)RES_GET_POINTER(pResData->pRoot, res);
        *pLength=*p++;
        if (*pLength == 0) {
            p = NULL;
        }
        return (const int32_t *)p;
    } else {
        *pLength=0;
        return NULL;
    }
}

U_CFUNC int32_t
res_countArrayItems(const ResourceData *pResData, const Resource res) {
    if(res!=RES_BOGUS) {
        if(RES_GET_TYPE(res)==RES_STRING) {
            return 1;
        } else if(RES_GET_TYPE(res)==RES_ARRAY) {
            Resource *p=RES_GET_POINTER(pResData->pRoot, res);
            int32_t count=*(int32_t *)p;   
            return count;
        } else if(RES_GET_TYPE(res)==RES_TABLE) {
            return res_getTableSize(pResData, res);
        }
    } 
    return 0;
}

U_CFUNC Resource
res_getResource(const ResourceData *pResData, const char *key) {
    return _res_findTableItem(pResData->pRoot, pResData->rootRes, key);
}

U_CFUNC Resource 
res_getArrayItem(const ResourceData *pResData, const Resource array, const int32_t indexR) {
    return _res_getArrayItem(pResData->pRoot, array, indexR);
}

U_CFUNC Resource 
res_getTableItemByKey(const ResourceData *pResData, const Resource table, int32_t* indexR, const char* *  key) {
    uint16_t tempIndex;
    if(key != NULL) {
        tempIndex  = _res_findTableIndex(pResData->pRoot, table, *key);
        if(tempIndex != URESDATA_ITEM_NOT_FOUND) {
            *key = _res_getTableKey(pResData->pRoot, table, tempIndex);
            *indexR = tempIndex;
            return _res_getTableItem(pResData->pRoot, table, tempIndex);
        } else {
            return RES_BOGUS;
        }
    } else {
        return RES_BOGUS;
    }
}

U_CFUNC Resource 
res_getTableItemByIndex(const ResourceData *pResData, const Resource table, int32_t indexR, const char * * key) {
    if(indexR>-1) {
        if(key != NULL) {
            *key = _res_getTableKey(pResData->pRoot, table, (uint16_t)indexR);
        }
        return _res_getTableItem(pResData->pRoot, table, (uint16_t)indexR);
    } else {
        return RES_BOGUS;
    }
}

U_CFUNC int32_t 
res_getTableSize(const ResourceData *pResData, Resource table) {
    uint16_t *p=(uint16_t *)RES_GET_POINTER(pResData->pRoot, table);
    return *p;
}


Generated by  Doxygen 1.6.0   Back to index