2010年1月29日 星期五

CuFileLex - 文字檔剖析

// config.sys
--------------------------------------------
TOTAL_ELEMENT_NUM   8

    ELEMENT_NUM 1
        ELEMENT_TYPE        "element"
        ELEMENT_NAME            "background"
        ELEMENT_POINT       0   0
        ELEMENT_NEEDALPHA   0
        TOTAL_PHOTO_NUM     1
            PHOTO_NAME  "media_bg.bmp" 4
        ELEMENT_END

    ELEMENT_NUM 2
        ELEMENT_TYPE        "button"
        ELEMENT_NAME            "close" 
        ELEMENT_POINT       3   3
        ELEMENT_NEEDALPHA   1
        TOTAL_PHOTO_NUM     4
            PHOTO_NAME  "close.bmp" 0
            PHOTO_NAME  "close_alpha.bmp" 1
            PHOTO_NAME  "close_down.bmp" 2
            PHOTO_NAME  "close_down_alpha.bmp" 3
        ELEMENT_END
        BUTTON_END


    ELEMENT_NUM 3
        ELEMENT_TYPE        "commandbt"
        ELEMENT_NAME            "goto-photo"        
        ELEMENT_POINT       208 85
        ELEMENT_NEEDALPHA   1
        TOTAL_PHOTO_NUM     4
            PHOTO_NAME  "photoviewer_Icon.bmp" 13
            PHOTO_NAME  "photoviewer_Icon_alpha.bmp" 14
            PHOTO_NAME  "photoviewer_animation01.bmp" 15
            PHOTO_NAME  "photoviewer_animation01_alpha.bmp" 16
        ELEMENT_END
        BUTTON_END
        COMMANDBT_ACTIVE_NAME   "photoviewv350.exe"
        COMMANDBT_END

    ELEMENT_NUM 4
        ELEMENT_TYPE        "commandbt"
        ELEMENT_NAME            "goto-music"        
        ELEMENT_POINT       14  85
        ELEMENT_NEEDALPHA   1
        TOTAL_PHOTO_NUM     4
            PHOTO_NAME  "music_Icon.bmp" 9
            PHOTO_NAME  "music_Icon_alpha.bmp" 10
            PHOTO_NAME  "music_animation01.bmp" 11
            PHOTO_NAME  "music_animation01_alpha.bmp" 12
        ELEMENT_END
        BUTTON_END
        COMMANDBT_ACTIVE_NAME   "musicv350.exe"
        COMMANDBT_END


    ELEMENT_NUM 5
        ELEMENT_TYPE        "commandbt"
        ELEMENT_NAME            "goto-video"        
        ELEMENT_POINT       113 85
        ELEMENT_NEEDALPHA   1
        TOTAL_PHOTO_NUM     4
            PHOTO_NAME  "movie_Icon.bmp" 5
            PHOTO_NAME  "movie_Icon_alpha.bmp" 6
            PHOTO_NAME  "movie_animation01.bmp" 7
            PHOTO_NAME  "movie_animation01_alpha.bmp" 8
        ELEMENT_END
        BUTTON_END
        COMMANDBT_ACTIVE_NAME   "video\videov350.exe"
        COMMANDBT_END

    ELEMENT_NUM 6
        ELEMENT_TYPE        "statictext" 
        "PhotoView"
        "text-photoview"
        208 180 98  30
        12
        255 255 255

    ELEMENT_NUM 7
        ELEMENT_TYPE        "statictext" 
        "Music"
        "text-music"
        14  180 98  30
        12
        255 255 255



    ELEMENT_NUM 8
        ELEMENT_TYPE        "statictext" 
        "Video"
        "text-Video"
        113 180 98  30
        12
        255 255 255


//




// CuFileLex.h


class CuFileLex
{
    BOOL    m_bUnicode;
    BOOL    _IsUnicodeFile();
    int     _lexw(void);
    int     _lexa(void);

    CuFile  m_File;
public:
    CuFileLex(void);
    ~CuFileLex(void);


    BOOL Open( LPCSTR lpszFileName, LPCSTR lpszOpenMode);
    virtual BOOL Open( LPCTSTR lpszFileName, LPCTSTR lpszOpenMode);

    int _type; // 最後呼叫 _lex() 的字串類型
    wstring _text; // 將讀到的字串 放到這裡

    enum {UNKNOW = 0, INTEGER = 1, FLOAT, SYMBOL, INDEX, STRING, NODE, BLOCKSTART, BLOCKEND};
    // 讀一段字 並分析字串 傳回字串類型
    int _lex(void);

    void _readInt(int &i);
    void _readInt3(int i[3]);
    void _readInt4(int i[4]);
    void _readFloat(float &f);
    void _readFloat3(float f[3]);
    void _readSymbol(wstring &str);
    void _readIndex();
    void _readString(wstring &str);
    void _readNode();
    void _readBlockStart();
    
    int _skip();

};


// CuFileLex.cpp


CuFileLex::CuFileLex(void) : _type(UNKNOW)
{

}

CuFileLex::~CuFileLex(void)
{

}

int CuFileLex::_lex(void)
{

//  static 
//  char check[] = "-0123456789._ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\"{}:*";
                 //"12345678901234567890123456789012345678901234567890123456789012345 678901234
                 //"0        1         2         3         4         5         6          7 
                // 1~11  = INTEGER
                // 12 = FLOAT
                // 13~65 = SYMBOL
                // 69 = INDEX
                // 66 = STRING
                // 70 = NODE  
                // 67 = BLOCKSTART
                // 68 = BLOCKEND

    // 字串分析的權位 左邊比較低 右邊比較高 
//  enum {UNKNOW = 0, INTEGER = 1, FLOAT, SYMBOL, INDEX, STRING, NODE, BLOCKSTART, BLOCKEND};

    _text = L"";

    int result;

    int current_type = 0;  
    int type = UNKNOW; // 分析字串的類型

    bool baString = false; // 當正在讀字串時 會一直讀到 下一個 '\"' 


    // 排除前置空白 換行 定位 字元
    do
    {
        result = m_File.get();
    }while( result != EOF && (result == 9 || result == 32 || result == 13 || result == 10 ));
    

    while(result != EOF)
    {

        // ---------------+---------------
        // 字串種類判段

        if( baString )
        {
            if( result == 0x22 )
                baString = !baString;

        }else if( (result >= 0x41 && result <= 0x5a) ||
                (result >= 0x61 && result <= 0x7a) ||
                (result == 0x5f) )
            current_type = SYMBOL;
        else if( (result >= 0x30 && result <= 0x39) || result == 0x2d  )
            current_type = INTEGER;
        else
        {
            switch( result )
            {
            case 0x2e:
                current_type = FLOAT;
                break;
            case 0x3a:
                current_type = INDEX;
                break;
            case 0x22:
                current_type = STRING;
                baString = !baString;
                break;
            case 0x2a:
                current_type = NODE;
                break;
            case 0x7b:
                current_type = BLOCKSTART;
                break;
            case 0x7d:
                current_type = BLOCKEND;
                break;
            default:
                {
                    _type = type;
                    return type;
                }
            }
        }
        if( type < current_type )
            type = current_type;
        // ---------------+---------------

        _text += result;
        result = m_File.get();

    }

    _type = type;

    return type;
}


int CuFileLex::_lexw(void)
{
//  static 
//  TCHAR check[] = L"-0123456789._ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\"{}:*";
                   //"12345678901234567890123456789012345678901234567890123456789012345 678901234
                   //"0        1         2         3         4         5         6          7 
                // 1~11  = INTEGER
                // 12 = FLOAT
                // 13~65 = SYMBOL
                // 69 = INDEX
                // 66 = STRING
                // 70 = NODE  
                // 67 = BLOCKSTART
                // 68 = BLOCKEND

    // 字串分析的權位 左邊比較低 右邊比較高 
//  enum {UNKNOW = 0, INTEGER = 1, FLOAT, SYMBOL, INDEX, STRING, NODE, BLOCKSTART, BLOCKEND};

    _text = L"";

    WORD result;

    int current_type = 0;  
    int type = UNKNOW; // 分析字串的類型

    bool baString = false; // 當正在讀字串時 會一直讀到 下一個 '\"' 

    int nSizeT = 0;

    // 排除前置空白 換行 定位 字元
    do
    {
        nSizeT = m_File.Read(&result, sizeof(result) );
    }while( nSizeT != 0 && (result != EOF && result == 9 || result == 32 || result == 13 || result == 10 ));
    

    while(result != EOF && nSizeT != 0 )
    {

        // ---------------+---------------
        // 字串種類判段

        if( baString )
        {
            if( result == 0x22 )
                baString = !baString;

        }else if( (result >= 0x41 && result <= 0x5a) ||
                (result >= 0x61 && result <= 0x7a) ||
                (result == 0x5f) )
                current_type = SYMBOL;
        else if( (result >= 0x30 && result <= 0x39) || result == 0x2d  )
            current_type = INTEGER;
        else
        {
            switch( result )
            {
            case 0x2e:
                current_type = FLOAT;
                break;
            case 0x3a:
                current_type = INDEX;
                break;
            case 0x22:
                current_type = STRING;
                baString = !baString;
                break;
            case 0x2a:
                current_type = NODE;
                break;
            case 0x7b:
                current_type = BLOCKSTART;
                break;
            case 0x7d:
                current_type = BLOCKEND;
                break;
            default:
                {
                    _type = type;
                    return type;
                }
            }
        }
        if( type < current_type )
            type = current_type;
        // ---------------+---------------

        _text += result;
        nSizeT = m_File.Read(&result, sizeof(result) );
    }

    _type = type;

    return type;
}

// 讀一段字 並分析字串 傳回字串類型
int CuFileLex::_lex(void)
{
    if( m_bUnicode )
        return _lexw();
    else
        return _lexa();

    return m_bUnicode ? _lexw() : _lexa();
}


// 讀一段字 並分析字串 傳回字串類型

void CuFileLex::_readInt(int &i)
{

    _lex();
    Assert( _type == INTEGER , L"CuFileLex::_readInt: Expected an integer\n");
    swscanf(_text.c_str(), L"%i", &i);

}

void CuFileLex::_readInt3(int i[3])
{

    _readInt(i[0]);
    _readInt(i[1]);
    _readInt(i[2]);

}

void CuFileLex::_readInt4(int i[4])
{

    _readInt(i[0]);
    _readInt(i[1]);
    _readInt(i[2]);
    _readInt(i[3]);

}

void CuFileLex::_readFloat(float &f)
{

    _lex();
    Assert( _type == FLOAT , L"CuFileLex::_readFloat: Expected an float\n");
    swscanf(_text.c_str(), L"%f", &f);

}

void CuFileLex::_readFloat3(float f[3])
{

    _readFloat(f[0]);
    _readFloat(f[1]);
    _readFloat(f[2]);

}

void CuFileLex::_readSymbol(wstring &str)
{

    _lex();
    Assert( _type == SYMBOL , L"CuFileLex::_readSymbol: Expected a symbol\n");
    str = _text;

}

void CuFileLex::_readIndex()
{

    _lex();
    Assert( _type == INDEX , L"CuFileLex::_readIndex: Expected a index\n");

}

void CuFileLex::_readString(wstring &str)
{

    _lex();
    Assert( _type == STRING , L"CuFileLex::_readString: Expected a string\n");

    // 脫溢字串兩頭的 雙引號
    if( _text.size() != 0 )
        str.assign( _text, 1, _text.size() - 2);

}
void CuFileLex::_readNode()
{

    _lex();
    Assert( _type == NODE , L"CuFileLex::_readNode: Expected a node\n");

}

void CuFileLex::_readBlockStart()
{

    _lex();
    Assert( _type == BLOCKSTART , L"CuFileLex::_readBlockStart: Expected an open brace\n");

}

int CuFileLex::_skip()
{

    int nextToken;
    int depth = 0;
    char neednext = 1;

    do {
        if(neednext) 
            nextToken = _lex();
        else 
            neednext = 1;

        if(nextToken == BLOCKSTART) 
            depth++;
        if(nextToken == BLOCKEND) 
            if(depth > 0) {
            /*printf("skipping %s\n", ASE_text);*/
            depth--;
            nextToken = _lex();
            neednext = 0;
        }
        /*printf("skipping %s (%i) (depth %i)\n", ASE_text, ASE_linenum, depth);*/
    } while(nextToken && (depth || (nextToken != NODE && nextToken != BLOCKEND)));
    /*printf("done (got %s)\n", ASE_text);*/
    return nextToken;

}

BOOL CuFileLex::_IsUnicodeFile()
{

    FILE* pFileStream = m_File.GetFILE();

    WORD result = 0;
    fseek( pFileStream, 0, SEEK_SET);
    int nSizeT = m_File.Read(&result, sizeof(result) );


    if( result != 0xfeff )
    {
        fseek( pFileStream, 0, SEEK_SET);
    }

    return (result == 0xfeff);

}
BOOL CuFileLex::Open( LPCSTR lpszFileName, LPCSTR lpszOpenMode)
{
    string strFileName = lpszFileName;
    string strOpenMode = lpszOpenMode;

    wstring wstrFileName(strFileName.begin(), strFileName.end());
    wstring wstrOpenMode(strOpenMode.begin(), strOpenMode.end());

    return Open(wstrFileName.c_str(),wstrOpenMode.c_str() );

}

BOOL CuFileLex::Open( LPCTSTR lpszFileName, LPCTSTR lpszOpenMode)
{
    

    BOOL bResult = m_File.Open(lpszFileName, lpszOpenMode);

    Assert(bResult != FALSE, L"can't open file" );
    Assert(bResult != FALSE, const_cast<TCHAR *>(lpszFileName) );

    if( bResult == FALSE )
        return FALSE;

    m_bUnicode = this->_IsUnicodeFile();

    if( m_bUnicode )
    {
        if( wcscmp (lpszOpenMode , L"r") == 0 )
        {
            lpszOpenMode = L"rb";
            m_File.Close();
            bResult = m_File.Open(lpszFileName, lpszOpenMode);
            m_bUnicode = this->_IsUnicodeFile();
        }

    }
    else
    {
        m_File.Close();
        bResult = m_File.Open(lpszFileName, lpszOpenMode);
        
    }

    return bResult;
}


從某一隻ASE檔載入器中抓出來的,
CuFileLex 跟CuStringList 相比, 能載入較多格式的文字串, 組合後可以使用更豐富的設定檔
上面有兩大段分別支援一般文字檔跟UNICODE文字檔, 很顯示需要重構! 現在沒打算重構!
重構時間點在何時呢? 在他出錯的時後, 或是下次程式碼"review"的時後!

沒有留言:

張貼留言