一个资源打包工具完整代码

来源:互联网 发布:农村淘宝的规划 编辑:程序博客网 时间:2024/06/05 14:19
#include <stdio.h>#include <string.h>static char g_mem[5 * 1024 * 1024];#define MORE17#define min(a, b) ((a) < (b) ? (a) : (b))typedef struct _ResMap{    char *pName;    int iPos;    int iLen;    int iOrgLen;    char *pData;    int iDstBegin;} ResMap;typedef struct _Item{    ResMap *rm;    int next;} Item;int ReadFile(char *pName){    FILE *pFile = fopen(pName, "rb");    int n = 0;    char *p = g_mem;    while (1)    {        n = fread(p, 1, 10240, pFile);        if (n == 0)            break;        p += n;    }    fclose(pFile);    return p - g_mem;}int Hash(char *str, int n){    unsigned int val = 0;    n += MORE;    for (; *str; ++str)    {        val = val * 31 + *str;    }    return val % n;}static char g_hex[] = "0123456789abcdef";void ChangeHex(char *pFileName, ResMap *pMapBuf, int iIsLast, int *piFrom){    int iLen = ReadFile(pFileName);    int nlen = strlen(pFileName) + 1;    int iRstLen = (iLen + nlen) * 5;    char *pMem = malloc(iRstLen);    char *pCur = pMem;    unsigned char *pSrc = (unsigned char *)g_mem;        int i = 0;    for (i = 0; i < nlen; i++, pCur += 5)     {   pCur[0] = '0';        pCur[1] = 'x';        pCur[2] = g_hex[(pFileName[i] >> 4) & 0xf];        pCur[3] = g_hex[pFileName[i] & 0xf];        pCur[4] = ',';    }        for (i = 0; i < iLen; i++, pCur += 5)    {        pCur[0] = '0';        pCur[1] = 'x';        pCur[2] = g_hex[(pSrc[i] >> 4) & 0xf];        pCur[3] = g_hex[pSrc[i] & 0xf];        pCur[4] = ',';    }    iLen += nlen;    iRstLen -= (iIsLast ? 1 : 0);    pMapBuf->pName = pFileName;    pMapBuf->iLen = iRstLen;    pMapBuf->pData = pMem;    pMapBuf->iOrgLen = iLen;    pMapBuf->iDstBegin = *piFrom;    *piFrom += iLen;}void WriteHead(FILE *pC){    char *p = "#include <string.h>\n\n"  "typedef struct _ResMap {\n"              "int iPos;\n"              "int iDatLen;\n"              "short sNameLen;\n"              "short sNext;\n"              "} ResMap;\n\n";    fwrite(p, strlen(p), 1, pC);}void WriteFunc(FILE *pC, int n){    char *p = "static int Hash(const char *str)\n"              "{\n"              "unsigned int val = 0;\n"              "for (; *str; ++str)\n"              "val = val * 31 + *str;\n"              "return val % ";    fwrite(p, strlen(p), 1, pC);    char buf[10];    sprintf(buf, "%d;\n", n + MORE);    fwrite(buf, strlen(buf), 1, pC);    p = "}\n\n"        "void * LoadRes(const char* pName, int *piLen)\n"        "{\n"        "int i = 0;\n"        "if (!pName || !piLen)\n"        "    return 0;\n\n"        "i = Hash(pName);\n"        "*piLen = 0;\n\n"        " while (i != -1) {\n"        "if (! g_map[i].iDatLen)\n"        "return 0;\n"        "char *pExName = g_dat + g_map[i].iPos;\n"        "    if (strcmp(pName, pExName) == 0) {\n"        "      *piLen = g_map[i].iDatLen;\n"        "         return (g_dat + g_map[i].iPos + g_map[i].sNameLen);\n"        "}\n"        "i = g_map[i].sNext;\n"        "}\n"        "return 0;\n"        "}\n\n\n";    fwrite(p, strlen(p), 1, pC);}void WriteCnt(FILE *pC, ResMap *pMap, int iResNum){    int i = 0;    char *p = "static char g_dat[] = {";    fwrite(p, strlen(p), 1, pC);    for (; i < iResNum; i++)    {        int len = pMap->iLen;        char *dat = pMap->pData;        while (len > 0) {        fwrite("\n\t", 2, 1, pC);        fwrite(dat, min(len, 80), 1, pC); len -= 80;dat += 80;        }        ++pMap;    }    fwrite("\n};\n\n", 4, 1, pC);}void WriteTail(FILE *pC, Item *pIt, int iResNum){    char tmp[100];    char name[100];    int iMn = iResNum + MORE;    sprintf(tmp, "static ResMap g_map[] = {");    fwrite(tmp, strlen(tmp), 1, pC);    int i = 0, line = 0;fwrite("\n\t", 2, 1, pC);    for (; i < iMn; i++)    {        char *p = (i == iMn - 1) ? "" : ",";        if (pIt->rm)        {        int iLen = strlen(pIt->rm->pName) + 1;            sprintf(tmp, "{0x%x,0x%x,0x%x,%d}%s", pIt->rm->iDstBegin, pIt->rm->iOrgLen - iLen, iLen, pIt->next, p);        }        else        {            sprintf(tmp, "{0}%s", p);        }        line += strlen(tmp);        if (line > 80) {        fwrite("\n\t", 2, 1, pC);        line = strlen(tmp);        }        fwrite(tmp, strlen(tmp), 1, pC);        ++pIt;    }    fwrite("\n};\n\n\n", 6, 1, pC);}static char ** GetFileName(int *pNum){    char **pList = malloc(1000 * sizeof(char *));;    char buf[100];    *pNum = 0;    char *p = g_mem;    int len = ReadFile("r.txt");    p[len] = '\0';    while (sscanf(p, "%s\n", buf) > 0)    {        pList[*pNum] = malloc(strlen(buf) + 1);        strcpy(pList[*pNum], buf);        if (*buf == '\0')            break;        (*pNum)++;        p += strlen(buf) + 1;    }    return pList;}int FindPos(Item *pIt, int start, char *name){    if (strcmp(pIt[start].rm->pName, name) == 0)        return -1;    int i = start, old ;    while (1)    {        int mi = pIt[i].next;        if (mi == -1)        {            old = i;            break;        }        i = mi;    }    i = 0;    while (1)    {        if (! pIt[i].rm)            break;        i++;    }    pIt[old].next = i;    return i;}int main(){    int n = 0;    int mn = 0;    char **pNames = GetFileName(&n);    ResMap *pMap = malloc(sizeof(ResMap) * n);    mn = n + MORE;    Item *pIt = malloc(sizeof(Item) * mn);    memset(pIt, 0, sizeof(Item) * mn);    int i = 0, from = 0;    for (; i < mn; i++)        pIt[i].next = -1;    for (i = 0; i < n; i++)    {        ChangeHex(pNames[i], pMap + i, i == n - 1, &from);        int v = Hash(pNames[i], n);        if (! pIt[v].rm)        {            pIt[v].rm = pMap + i;        }    }    for (i = 0; i < n; i++)    {        int v = Hash(pNames[i], n);        int pos = FindPos(pIt, v, pNames[i]);        if (pos != -1)        {            pIt[pos].rm = pMap + i;        }    }        FILE *pC = fopen("R.c", "wb");    WriteHead(pC);    WriteCnt(pC, pMap, n);    WriteTail(pC, pIt, n);    WriteFunc(pC, n);    fclose(pC);       return 0;}


本程序从r.txt中读取需要打包的资源文件名, 最终生成了一个R.c文件

将R.c与其它c文件一起编译即可。

r.txt文件格式如下所示:

abc.png

def.jpg

.....

每个文件名占一行。


生成的R.c文件内容大概是这样子的:

#include <string.h>typedef struct _ResMap {int iPos;int iDatLen;short sNameLen;short sNext;} ResMap;static char g_dat[] = {0x6d,0x61,0x69,0x6e,0x2e,0x63,0x00,0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,0x20,0x3c,0x73,0x74,0x64,0x69,0x6f,0x2e,0x68,0x3e,0x0d,0x0a,0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,0x20,0x3c,0x73,0x74,0x72,0x69,0x6e,.....};static ResMap g_map[] = {{0x8b90,0x32ef,0x7,-1},{0},{0x1ab4,0x70d3,0x9,0},{0},{0},{0},{0},{0},{0},{0},{0},{0x0,0x1aad,0x7,-1},{0},{0},{0},{0xbe86,0x19,0x2,-1},.....};static int Hash(const char *str){unsigned int val = 0;for (; *str; ++str)val = val * 31 + *str;return val % 21;}void * LoadRes(const char* pName, int *piLen){int i = 0;if (!pName || !piLen)    return 0;i = Hash(pName);*piLen = 0; while (i != -1) {if (! g_map[i].iDatLen)return 0;char *pExName = g_dat + g_map[i].iPos;    if (strcmp(pName, pExName) == 0) {      *piLen = g_map[i].iDatLen;         return (g_dat + g_map[i].iPos + g_map[i].sNameLen);}i = g_map[i].sNext;}return 0;}

通过LoadRes即可得到资源的内容, 时间复杂度接近于O(1)





原创粉丝点击