1. 程式人生 > >C語言實現ini解析函式 getPrivateProfileString

C語言實現ini解析函式 getPrivateProfileString

//
//  myGetProfileLine.c
//  Version 0.9.3
//
//  Created by LancerLian on 15-1-21.
//

#include 
#include 
#include 
#include 
#include 

#define ERROR -1
#define MAXSIZE 1024

long myGetPrivateProfileString (char *lpAppName,char *lpKeyName,char *lpDefault,char *lpReturnedString,int nSize,char* lpFileName);

int main()
{
    char *strFileName = "initest.txt";
    
    int ret = 0;
    char *szKeyValue = (char *) malloc (MAXSIZE * sizeof(char));  //szKeyValue用於存入get到的值
    ret = myGetPrivateProfileString( "player", "name", "Default:Williams", szKeyValue, 25, strFileName);
    printf("ret = %d, szKeyValue = %s \n", ret, szKeyValue);
    return 0;
    
}

long myGetPrivateProfileString (char *lpAppName, char *lpKeyName, char *lpDefault, char *lpReturnedString, int nSize, char *lpFileName)
{
    //初始化返回字串
    memset (lpReturnedString, 0, nSize * sizeof(char));
    int ret = 0;
    bool bIsfind = false;
    
    FILE *fp = NULL;
    fp = fopen (lpFileName, "r");
    if (!fp)
    {
        printf("Fail to fopen!\n");
        return ERROR;      //初始化檔案失敗,返回'0x2'
    }
    
    int nAppNameLen = 0;
    int nKeyNameLen = 0;
    
    bool bIsFindAppName = false;
    bool bIsFindKeyName = false;
    char *szReadBuffer = NULL;
    char *szLineStart = NULL;
    char *szLineEnd = NULL;
    char *szEnd = NULL;
    char *szNextLine = NULL;
    char *szValueStart = NULL;
    char szTempAppName[MAXSIZE] = "";
    char szTempKeyName[MAXSIZE] = "";
    
    char *szTempValue = NULL;
    char *szCopySectionName = (char *) malloc (nSize * sizeof(char));
    char *szCopyKeyName = (char *) malloc (nSize * sizeof(char));
    char szSectionList[MAXSIZE] = "";
    char szKeyList[MAXSIZE] = "";
    
    if (!szCopyKeyName || !szCopySectionName)
    {
        
        printf("malloc error!\n");
        ret = ERROR;
        goto _OUT;     //_OUT: 統一釋放記憶體並返回值
    }
    
    int len = 0;
    int defLen = 0;
    bool bSectionCopyOver = false;
    bool bEntryCopyOver = false;
    
    memset(szCopySectionName, 0, nSize);
    memset(szCopyKeyName, 0, nSize);
    
    char *p = szCopySectionName;
    char *q = szCopyKeyName;
    
    int pLen = nSize - 1;   //能用於存AppName的空間長度
    int qLen = nSize - 1;   //能用於存KeyName的空間長度
    
    //算出檔案長度,並將指標返回檔案開頭
    fseek(fp,0,SEEK_END);
    long nFileSize = ftell(fp);
    fseek(fp,0,SEEK_SET);
    
    //檔案長度為空,則返回預設值
    if (nFileSize == 0)
    {
        defLen = (int)strlen(lpDefault);
        if (nSize <= defLen)
        {
            strncpy(lpReturnedString, lpDefault, nSize - 1);
            lpReturnedString[nSize - 1] = '\0';
            ret = nSize - 1;
        }
        else
        {
            strncpy(lpReturnedString, lpDefault, defLen);
            ret = defLen;
        }
        fclose(fp);
        
        return ret;
        
    }
    
    //檔案不為空,則存入szReadBuffer
    else
    {
        szReadBuffer = (char *)malloc((nFileSize + 1) * sizeof(char));
        if (!szReadBuffer)
        {
            printf("malloc failed!\n");
            goto _OUT;      //_OUT: 統一釋放記憶體並返回值
        }
        
        //初始化szReadBuffer,並讀入檔案
        memset(szReadBuffer, 0, nFileSize + 1);
        if (!fread(szReadBuffer,sizeof(char),nFileSize,fp))   ///將檔案讀入szReadBuffer
        {
            goto _OUT;   //_OUT: 統一釋放記憶體並返回值
            
        }
        
    }
    
    len = (int) strlen(szReadBuffer);
    szNextLine = szReadBuffer;
    szEnd = szReadBuffer + len;
    
    //此部分分析存入Buffer中檔案
    while (szNextLine < szEnd)
    {
        szLineStart = szNextLine;
        szNextLine = (char *)memchr (szLineStart, '\n', szEnd - szLineStart); //移至換行符
        //若無換行符,szNextLine移至回車
        if (!szNextLine)
            szNextLine = (char *)memchr (szLineStart, '\r', szEnd - szLineStart); //回車
        //若既無換行符又無回車,則szNextLine指向szEnd
        if (!szNextLine)
            szNextLine = szEnd;
        else
            szNextLine++;
        
        szLineEnd = szNextLine; //行結尾
        
        ///跳過前後空格,使得指標分別指向關鍵字的開頭和結尾
        
        while (szLineStart < szLineEnd && isspace((unsigned char)*szLineStart))
        {
            szLineStart++;
        }
        while ((szLineEnd > szLineStart) && isspace((unsigned char)szLineEnd[-1]))
        {
            szLineEnd--;
        }
        
        
        if (szLineStart >= szLineEnd) continue;  //跳出本次迴圈,進入下一次
        
        //section 開始分析
        if (*szLineStart == '[')
        {
            
            if (bIsFindAppName)
            {
                bEntryCopyOver = true; //AppName 找到
            }
            char *szAppNameEnd;
            if ((szAppNameEnd = (char *) memchr(szLineStart, ']', szLineEnd - szLineStart )))
            {
                szLineStart++;    //跳過[
                len =(int) (szAppNameEnd - szLineStart);  //求出section的長度
                strncpy(szTempAppName,szLineStart,len);  //儲存AppName
                szTempAppName[len] = '\0';
                
                //將所有Section名稱拷貝至 szCopySectionName buffer
                if (!bSectionCopyOver)
                {
                    int tempAppLen = (int)strlen(szTempAppName) + 1;
                    if (tempAppLen >= pLen)
                    {
                        if (pLen > 0)
                        {
                            strncpy(p, szTempAppName,pLen);
                            p += pLen - 1;
                            *p++ = '\0';
                        }
                        *p = '\0';
                        ret = nSize - 2 ;
                        bSectionCopyOver = true;
                    }
                    else
                    {
                        strncpy(p, szTempAppName, tempAppLen - 1);
                        strncpy(p + tempAppLen - 1, "\t", 1);
                    }
                    
                    p += tempAppLen;
                    pLen -= tempAppLen;
                }
                if (lpAppName)
                {
                    //AppName找到
                    nAppNameLen = strlen (lpAppName);
                    if (0 == strncmp(szTempAppName,lpAppName,nAppNameLen) && szTempAppName[nAppNameLen] == '\0')     /////////////
                        
                        bIsFindAppName = true;
                }
                continue;
            }
        }
        
        len =(int) (szLineEnd - szLineStart);
        
        //查詢等號
        if ((szValueStart = (char *)memchr( szLineStart, '=', szLineEnd - szLineStart)) != NULL)
        {
            const char *szKeyNameEnd = szValueStart;  //KeyName結束與鍵值開始
            while (szKeyNameEnd > szLineStart &&isspace((unsigned char)szKeyNameEnd[-1]))
                szKeyNameEnd--;  //去掉Key後面的空格
            len = (int)(szKeyNameEnd - szLineStart);
            szValueStart++;//跳過等號,指向數值
            while (szValueStart < szLineEnd && isspace((unsigned char)*szValueStart))
                szValueStart++;  //跳過空格
            
            //存入鍵值
            if (len > 0  && bIsFindAppName)
            {
                strncpy(szTempKeyName,szLineStart,len);
                szTempKeyName[len] = '\0';
                
                //若AppName找到,將所有KeyName存入szCopyKeyName
                if (!bEntryCopyOver)
                {
                    int tempKeyLen =(int) strlen(szTempKeyName) + 1;
                    if (tempKeyLen >= qLen)
                    {
                        if (qLen > 0)
                        {
                            strncpy(q, szTempKeyName,qLen);
                            q += qLen-1;
                            *q++ = '\0';
                        }
                        *q = '\0';
                        ret = nSize - 2 ;
                        bEntryCopyOver = true;
                    }
                    else
                    {
                        strncpy(q, szTempKeyName, tempKeyLen - 1);
                        strncpy(q + tempKeyLen - 1, "\t", 1);
                    }
                    q += tempKeyLen;
                    qLen -= tempKeyLen;
                }
                
                //拷貝鍵值到szTempValue
                if (lpKeyName)
                {
                    nKeyNameLen = strlen (lpKeyName);
                    if (0 == strncmp(szTempKeyName, lpKeyName, nKeyNameLen) && szTempKeyName[nKeyNameLen] == '\0')    // AppName 和 keyName 找到
                    {
                        bIsFindKeyName = true;
                        len = (int)(szLineEnd - szValueStart );
                        szTempValue =(char*) malloc(len + 1);
                        
                        memcpy(szTempValue, szValueStart, len * sizeof(char));
                        szTempValue[len] = '\0';
                        break;
                        
                    }
                }
            }
        }
    }
    
    // KeyName找到
    if(bIsFindKeyName)
    {
        if (szTempValue)
        {
            len =(int) strlen(szTempValue);
            if (nSize>len)
            {
                strncpy(lpReturnedString,szTempValue,len);
                ret =len;
            }
            else
            {
                strncpy(lpReturnedString,szTempValue,nSize-1);
                lpReturnedString[nSize-1]='\0';
                ret = nSize -1;
            }
        }
        else
            ret=0;
    }
    
    //找到Section, 但是沒有找到key
    else if(bIsFindAppName)
    {
        if (!lpKeyName)
        {
            len =(int) strlen(szCopyKeyName);
            strncpy(lpReturnedString, szCopyKeyName, len);
            ret = len - 1;
        }
        else
        {
            if (lpDefault == NULL)
            {
                printf ("ERROR! lpDefault == NULL.\n");
                return ERROR;
            }
            len = (int)strlen(lpDefault);
            if (nSize>len)
            {
                strncpy(lpReturnedString,lpDefault,len);
                ret = len;
            }
            else
            {
                strncpy(lpReturnedString,lpDefault,nSize - 1);
                lpReturnedString[nSize - 1] = '\0';
                ret = nSize - 1;
            }
        }
    }
    
    //未找到Section
    else
    {
        if (!lpAppName)
        {
            len =(int) strlen(szCopySectionName);
            strncpy(lpReturnedString, szCopySectionName, len);
            ret =len;
        }
        else
        {
            len = (int)strlen(lpDefault);
            if (nSize > len)
            {
                strncpy(lpReturnedString, lpDefault, len);
                ret = len;
            }
            else
            {
                strncpy(lpReturnedString,lpDefault,nSize - 1);
                lpReturnedString[nSize - 1] = '\0';
                ret = nSize - 1;
            }
        }
    }
    
    //_OUT: 統一釋放記憶體並返回值
_OUT:
    if(szCopySectionName) free(szCopySectionName);
    if(szCopyKeyName)     free(szCopyKeyName);
    if(szReadBuffer)      free(szReadBuffer);
    if(szTempValue)       free(szTempValue);
    
    
    fclose(fp);
    return ret;
    
}