At the end there are some conclusion.
--- Problem:
The following seguence of calls produces an erroneuos xml content if the tag is indented (i.e. is not the root node):
Code: Select all
XMLWriter->writeElement( TAG_NAME );
XMLWriter->writeText( TEXT_CONTENT );
XMLWriter->writeClosingTag( TAG_NAME );
--- Solution:
I added a boolean attribute to the class CXMLWriter, needIndent, that it's setted to true only by writeLineBreak method and it's used in conjuction with Tabs>0 condition to solve the problem.
--- Problem:
the datatype wchar_t is not always 2 bytes long. In linux machines (and in others maybe), the wchar_t is 4 bytes long. This creates troubles when the data is written to the file and in calculation of space occupied.
--- Solution:
It's possibile to force gcc to use 2-byte wchar_t instead of 4-bytes by adding the compiler flags '-fshort-wchar'. I modified the Makefile accordlying.
--- Problem:
A litte preface to this problem: "wchar_t != UTF16 (o UCS-2) encoded character"
But, all irrlicht code assumes that a wchar_t string is encoded in UTF16, but it's not true on all machines!! In particular, modern linux machines encodes wchar_t strings in UCS-4 and declare wchar_t as 4-bytes long datatype. For this reason, the wcslen assume that the wchar_t passed is encoded in UCS-4 (even if -fshort-wchar flags is activated). But the wchar_t strings created by irrlicht are UTF16 encoded, so all lengths returned by wcslen are junks and the CXMLWriter always call the File->Write with the wrong numbers of bytes.
--- Solution:
I created a function, UTF16LEN, to calculate the length of a UTF16 encoded string. I added this function into the CXMLWriter code and I putted a preprocessor condition in order to use my created function instead of wcslen on linux machines. This is only a partial solution to the problem, because actually my UTF16LEN function fails for those characters that UTF16 encodes with 4-bytes. In fact, UCS-2 is different from UTF16 because UCS-2 is 2-bytes fixed encoding and UTF16 allow a range of special chars encoded by 4-bytes codes.
But, due to fact that irrlicht code doesn't care about the 4-byte UTF16 character and it assumes that all UTF16 chars fits in 2-bytes... also my UTF16LEN follow the same (wrong) assumption.
--- Problem:
The literal wide strings declared with the code L"String" doesn't means that "String" is encoded in UTF16. In details, on linux machines the L"String" declaration means that "String" is encoded in UCS-4. Obviosuly, this makes a lot of problems for irrlicht that needs strings encoded in UTF16.
--- Solution:
In order to solve this problem, it's only necessary to add the flag -fwide-exec-charset=UTF16 to gcc compiler. In this ways, all strings declared by L"String" will be encoded in UTF16.
Notes that this doesn't solve the previous problems (i.e. wrong length calculated by wcslen) because the standard library is compiled with 4-bytes wchar_t datatype and with UCS-4 string encoding. This means that all standard function regarding wide character strings assume that the encoding is UCS-4 !!
And also, due to fact that some special UTF-16 chars requires 4-byte in conjuction with -fshort-wchar, the following statement arise a warning:
Code: Select all
wchar_t c = L's';
--- Problem:
Sometimes, (I didn't understand this strange behaviour), when gcc encodes an L"String" declaration it prepends the "String" with the Byte Order Mark (BOM). This makes trouble when you use the string<wchar_t>::append( string<wchar_t> ) because the method will append the BOM inside another string. For instance, if you append "Mondo" to "Ciao " the results will be "Ciao <FEFF> Mondo".
--- Solution:
I added a condition into string<T>::append(string<T>) method for manage this particular condition. The added code if enclosed into a preprocessor condition in order use it only in linux machines.
I admit that the solution proposed by me is not a good solution because: (i) is inside the template definition, so it will executed also for string<char> class, (ii) assumes that wchar_t is 2-bytes long and encodes UTF16 strings and (iii) assumes that if sizeof(T)==2 then T is a wchar_t datatype.
--- Conclusions:
Due to this problems arises from different wide character dimension and encoding on different machines and in order to mantains irrlicht a cross-platform project (i.e. usable on very different architecture's machines), I think that all wide strings and XML module implementation must be redesigned, keeping in mind that the follow assumption used until now by irrlicht are wrongs:
a) wchar_t is 2-byte long
b) L"String" is UTF16 encoded
c) wcslen calculate the lenght of an UTF16 string (same for all standard functions over wchar_t datatype)
d) L's' is a character that always fits in 2-bytes (even if it's encoded in UTF16)
I didn't attach the modified code in this topic, but of course I'm glade to give these modifies to irrlicht's authors. If interested, please tell me in which format I have to send you it (e.g. how to generate diffs file).
Ciao,
Gianluca