~hikiko/nux/arb-srgba-shader

« back to all changes in this revision

Viewing changes to NuxCore/NFile.cpp

  • Committer: Neil Jagdish Patel
  • Date: 2010-09-01 19:25:37 UTC
  • Revision ID: neil.patel@canonical.com-20100901192537-mfz7rm6q262pewg6
Import and build NuxCore

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "NKernel.h" 
 
2
#include "NFile.h"
 
3
 
 
4
NAMESPACE_BEGIN
 
5
//
 
6
// Load a binary file to a dynamic array.
 
7
//
 
8
bool LoadFileToArray(std::vector<BYTE>& Result, const TCHAR* Filename, NFileManager& FileManager )
 
9
{
 
10
    NSerializer* Reader = FileManager.CreateFileReader( Filename );
 
11
    if( !Reader )
 
12
        return FALSE;
 
13
    Result.clear();
 
14
    if(Reader->GetFileSize() < 0)
 
15
    {
 
16
        Reader->Close();
 
17
        delete Reader;
 
18
        return FALSE;
 
19
    }
 
20
    Result.resize(Reader->GetFileSize());
 
21
    Reader->Serialize(&Result[0], Result.size());
 
22
    bool Success = Reader->Close();
 
23
    delete Reader;
 
24
    return Success;
 
25
}
 
26
 
 
27
/*!
 
28
    Load a text file the a ANSICHAR array. The Array is null terminated. Useful for loading shader files.
 
29
*/
 
30
bool LoadTextFileToAnsiArray( std::vector<ANSICHAR>& Result, const TCHAR* Filename, NFileManager& FileManager )
 
31
{
 
32
    Result.clear();
 
33
    NSerializer* Reader = FileManager.CreateFileReader( Filename );
 
34
    if( !Reader )
 
35
        return FALSE;
 
36
 
 
37
    int Size = Reader->GetFileSize();
 
38
    if(Size<0)
 
39
    {
 
40
        Reader->Close();
 
41
        delete Reader;
 
42
        return FALSE;
 
43
    }
 
44
 
 
45
    std::vector<BYTE> ByteArray;
 
46
    ByteArray.clear();
 
47
    ByteArray.resize(Size);
 
48
    Reader->Serialize(&ByteArray[0], Result.size() );
 
49
    bool Success = Reader->Close();
 
50
    delete Reader;
 
51
 
 
52
    if( Size>=2 && !(Size&1) && Memcmp(&Result[0], &INL_UTF16_LE[1], INL_UTF16_LE[0])==0) // (BYTE)ByteArray[0]==0xff && (BYTE)ByteArray[1]==0xfe )
 
53
    {
 
54
        // UTF16 - Little Endian
 
55
        int numElement = Size/sizeof(UNICHAR) + 1; // +1 for null char
 
56
        Result.resize(numElement);
 
57
        for( int i=0; i<numElement-1; i++ )
 
58
            Result[i] = ConvertUnicodeCharToTCHAR( (WORD)(ANSIUCHAR)ByteArray[i*2+2] + (WORD)(ANSIUCHAR)ByteArray[i*2+3]*256 );
 
59
        Result[numElement] = 0;
 
60
    }
 
61
    else if( Size>=2 && !(Size&1) && Memcmp(&Result[0], &INL_UTF16_LE[1], INL_UTF16_LE[0])==0)
 
62
    {
 
63
        // UTF16 - Big Endian.
 
64
        int numElement = Size/sizeof(TCHAR) + 1; // +1 for null char
 
65
        Result.resize(numElement);
 
66
        for( int i=0; i<numElement-1; i++ )
 
67
            Result[i] = ConvertUnicodeCharToTCHAR( (WORD)(ANSIUCHAR)ByteArray[i*2+3] + (WORD)(ANSIUCHAR)ByteArray[i*2+2]*256 );
 
68
        Result[numElement] = 0;
 
69
    }
 
70
    else
 
71
    {
 
72
        // ANSI.
 
73
        Result.clear();
 
74
        Result.resize(Size + 1); // +1 for null char
 
75
        for(int i = 0; i < Size; i++)
 
76
            Result[i] = ByteArray[i];
 
77
        Result[Size] = 0;
 
78
    }
 
79
 
 
80
    return Success;
 
81
}
 
82
 
 
83
/*!
 
84
    Load a text file in an ANSICHAR array. The Array is null terminated.
 
85
*/
 
86
bool LoadTextFileToUnicodeArray( std::vector<UNICHAR>& Result, const TCHAR* Filename, NFileManager& FileManager )
 
87
{
 
88
    Result.clear();
 
89
    NSerializer* Reader = FileManager.CreateFileReader( Filename );
 
90
    if( !Reader )
 
91
        return FALSE;
 
92
 
 
93
    int Size = Reader->GetFileSize();
 
94
    if(Size<0)
 
95
    {
 
96
        Reader->Close();
 
97
        delete Reader;
 
98
        return FALSE;
 
99
    }
 
100
 
 
101
    std::vector<BYTE> ByteArray;
 
102
    ByteArray.clear();
 
103
    ByteArray.resize(Size);
 
104
    Reader->Serialize( &ByteArray[0], Result.size() );
 
105
    bool Success = Reader->Close();
 
106
    delete Reader;
 
107
 
 
108
    if( Size>=2 && !(Size&1) && Memcmp(&Result[0], &INL_UTF16_LE[1], INL_UTF16_LE[0])==0) // (BYTE)ByteArray[0]==0xff && (BYTE)ByteArray[1]==0xfe )
 
109
    {
 
110
        // UTF16 - Little Endian
 
111
        int numElement = Size + 1; // +1 for null char
 
112
        Result.resize(numElement);
 
113
        for( int i=0; i<numElement-1; i++ )
 
114
            Result[i] = ( (WORD)(ANSIUCHAR)ByteArray[i*2+2] + (WORD)(ANSIUCHAR)ByteArray[i*2+3]*256 );
 
115
        Result[numElement] = 0;
 
116
    }
 
117
    else if( Size>=2 && !(Size&1) && Memcmp(&Result[0], &INL_UTF16_LE[1], INL_UTF16_LE[0])==0)
 
118
    {
 
119
        // UTF16 - Big Endian.
 
120
        int numElement = Size + 1; // +1 for null char
 
121
        Result.resize(numElement);
 
122
        for( int i=0; i<numElement-1; i++ )
 
123
            Result[i] = ConvertUnicodeCharToTCHAR( (WORD)(ANSIUCHAR)ByteArray[i*2+3] + (WORD)(ANSIUCHAR)ByteArray[i*2+2]*256 );
 
124
        Result[numElement] = 0;
 
125
    }
 
126
    else
 
127
    {
 
128
        // There is no way to detect that a file really contains ascii. Or is there?
 
129
        // Make sure this file is really ascii.
 
130
        /*
 
131
        However as an additional check to
 
132
        the heuristic of looking for unprintable characters, another trick is to
 
133
        check if the newline string is consistent. It should always be either "\n"
 
134
        (for UNIX-like systems), "\r" (for Mac-like systems) or "\r\n" (for
 
135
        Windows-like systems). If the file starts switching around between these, it
 
136
        probably isn't a valid ASCII file on any of the above three platforms.
 
137
        */
 
138
 
 
139
        BOOL isASCII = TRUE;
 
140
        for( int i=0; i<Size; i++ )
 
141
        {
 
142
            if(Result[i] == 0 && (i!=Size-1))
 
143
            {
 
144
                isASCII = FALSE;
 
145
            }
 
146
 
 
147
            if((Result[i] < 0x20 || Result[i]>=0xFF) && ((Result[i]!=0x0A/*New Line, Line feed*/) && (Result[i]!=0x0D/*Carriage return*/)))
 
148
            {
 
149
                isASCII = FALSE;
 
150
            }
 
151
 
 
152
            // http://www.websiterepairguy.com/articles/os/crlf.html
 
153
            /*
 
154
                The carriage return is often referred to by the capital letters CR.
 
155
                On a Macintosh, every line has a CR at the end.
 
156
 
 
157
                Under Linux (a variant of Unix), the end of a line is indicated by
 
158
                a line feed. Every line ends with a line feed or LF.
 
159
 
 
160
                Calling the end of a line an LF versus a CR is not just semantics.
 
161
                These are 2 very real characters with 2 very real and very separate
 
162
                numeric representations on a computer. A CR is a 13 in the ASCII table
 
163
                of characters and an LF is a 10 in the ASCII table of characters.
 
164
 
 
165
                Contributing to the confusion is that fact that Microsoft Windows does
 
166
                things yet another way. Under Microsoft Windows, lines end with a combination
 
167
                of 2 characters -- a CR followed by a LF. Symbolically, this is represented
 
168
                as CRLF or carriage return, line feed. 
 
169
            */
 
170
            // Todo. Check if the file mixes a combination of \n (Linux) \r (Mac) and \r\n (Windows).
 
171
            // If it does, the file is not ASCII.
 
172
 
 
173
            if(isASCII==FALSE)
 
174
                return FALSE;
 
175
        }
 
176
        Result.clear();
 
177
        Result.resize(Size+1);
 
178
        for( int i=0; i<Size; i++ )
 
179
            Result[i] = ConvertAnsiCharToUnicodeChar(ByteArray[i]);
 
180
        Result[Size] = 0;
 
181
    }
 
182
 
 
183
    
 
184
    return Success;
 
185
}
 
186
 
 
187
/*!
 
188
    Load a text file to an NString. The file maybe ANSI or Unicode.
 
189
    The resulting string is TCHAR.
 
190
*/
 
191
bool LoadFileToString( NString& Result, const TCHAR* Filename, NFileManager& FileManager )
 
192
{
 
193
    NSerializer* Reader = FileManager.CreateFileReader(Filename);
 
194
    if( !Reader )
 
195
    {
 
196
        nuxDebugMsg(TEXT("[LoadFileToString] Cannot read from file: %s"), Filename);
 
197
        return false;
 
198
    }
 
199
    t_u32 Size = Reader->GetFileSize();
 
200
    std::vector<ANSICHAR> ByteArray(Size+2);
 
201
    Reader->Serialize(&ByteArray[0], Size);
 
202
    bool Success = Reader->Close();
 
203
    delete Reader;
 
204
    ByteArray[Size+0]=0;
 
205
    ByteArray[Size+1]=0;
 
206
    std::vector<TCHAR> ResultArray;
 
207
 
 
208
    // Detect Unicode Byte Order Mark
 
209
    //      EF BB BF        UTF-8
 
210
    //      FF FE               UTF-16, little endian
 
211
    //      FE FF               UTF-16, big endian
 
212
    //      FF FE 00 00         UTF-32, little endian
 
213
    //      00 00 FE FF         UTF-32, big-endian
 
214
    // Note: Microsoft uses UTF-16, little endian byte order.
 
215
 
 
216
    // Little Endian UTF-16: size should be >=2, even, and the first two bytes should be 0xFF followed by 0xFE
 
217
    if((Size>=2) && !(Size&1) && ((BYTE)ByteArray[0] == 0xff) && ((BYTE)ByteArray[1] == 0xfe))
 
218
    {
 
219
        // UTF16 - Little Endian
 
220
        int numElement = Size/sizeof(TCHAR);
 
221
        ResultArray.clear();
 
222
        ResultArray.resize(numElement);
 
223
        for( int i=0; i<numElement-1; i++ )
 
224
            ResultArray[i] = ConvertUnicodeCharToTCHAR( (WORD)(ANSIUCHAR)ByteArray[i*2+2] + (WORD)(ANSIUCHAR)ByteArray[i*2+3]*256 );
 
225
        ResultArray[numElement] = 0;
 
226
    }
 
227
    else if((Size >= 2) && !(Size & 1) && ((BYTE)ByteArray[0] == 0xfe) && ((BYTE)ByteArray[1] == 0xff))
 
228
    {
 
229
        // UTF16 - Big Endian.
 
230
        int numElement = Size/sizeof(TCHAR);
 
231
        ResultArray.clear();
 
232
        ResultArray.resize(numElement);
 
233
        for(int i = 0; i < numElement - 1; i++)
 
234
            ResultArray[i] = ConvertUnicodeCharToTCHAR( (WORD)(ANSIUCHAR)ByteArray[i*2+3] + (WORD)(ANSIUCHAR)ByteArray[i*2+2]*256 );
 
235
        ResultArray[numElement] = 0;
 
236
    }
 
237
    else
 
238
    {
 
239
        // ANSI.
 
240
        ResultArray.clear();
 
241
        ResultArray.resize(Size + 1);
 
242
        for(t_u32 i = 0; i < Size; i++)
 
243
            ResultArray[i] = ConvertAnsiCharToTCHAR(ByteArray[i]);
 
244
        ResultArray[Size] = 0;
 
245
    }
 
246
    Result = &ResultArray[0];
 
247
    return Success;
 
248
}
 
249
 
 
250
/*!
 
251
    Save BYTE array to file.
 
252
*/
 
253
bool SaveArrayToFile( const std::vector<BYTE>& Array, const TCHAR* Filename, NFileManager& FileManager )
 
254
{
 
255
    NSerializer* Ar = FileManager.CreateFileWriter( Filename );
 
256
    if( !Ar )
 
257
        return 0;
 
258
    Ar->Serialize( const_cast<BYTE*>(&Array[0]), Array.size() );
 
259
    delete Ar;
 
260
    return 1;
 
261
}
 
262
 
 
263
/*!
 
264
    Save string to File. Attempt to write it as ASCII if possible. If not write as UTF16-BE.
 
265
*/
 
266
bool SaveStringToFile( const NString& String, const TCHAR* Filename, NFileManager& FileManager )
 
267
{
 
268
    if( !String.Length())
 
269
        return 0;
 
270
    NSerializer* Ar = FileManager.CreateFileWriter( Filename );
 
271
    if( !Ar )
 
272
        return 0;
 
273
    bool SaveAsUnicode = false, Success = true;
 
274
#if UNICODE
 
275
    for( int i = 0; i < String.Length(); i++ )
 
276
    {
 
277
        // Test if the UNICODE 0xABCD is the same as the ASCII 0x00CB.
 
278
        if( (*String)[i] != (TCHAR)(ANSIUCHAR)ConvertTCHARToAnsiChar((*String)[i]))
 
279
        { 
 
280
            //The string need to be written in ASCII. We write the string as UTF16-BigEndian
 
281
            Ar->Serialize(INL_CONST_CAST(BYTE*, &UTF16_BE[1]), UTF16_BE[0] /*size*/);
 
282
            SaveAsUnicode = true;
 
283
            break;
 
284
        }
 
285
    }
 
286
#endif
 
287
    if( SaveAsUnicode || (sizeof(TCHAR) == 1) )
 
288
    {
 
289
        t_u32 s = (t_u32)String.Length()*sizeof(TCHAR);
 
290
        Ar->Serialize( INL_CONST_CAST(TCHAR*, String.GetTCharPtr()), (t_u32)s);
 
291
    }
 
292
    else
 
293
    {
 
294
        t_u32 s = (t_u32)String.Length();
 
295
        std::vector<ANSICHAR> AnsiBuffer((t_u32)s);
 
296
        // Cast all character down from UTF16 to ANSI
 
297
        for(t_u32 i = 0; i < (t_u32) String.Length(); i++ )
 
298
            AnsiBuffer[i] = ConvertTCHARToAnsiChar((t_u32)String[i]);
 
299
        // serialize
 
300
        s = (t_u32)String.Length();
 
301
        Ar->Serialize( INL_CONST_CAST(ANSICHAR*, &AnsiBuffer[0]), s);
 
302
    }
 
303
    delete Ar;
 
304
    if( !Success )
 
305
        GFileManager.Delete( Filename );
 
306
    return Success;
 
307
}
 
308
 
 
309
NAMESPACE_END