Loading tools/UTF8.cpp +84 −44 Original line number Original line Diff line number Diff line Loading @@ -2,50 +2,40 @@ #include <stdio.h> #include <stdio.h> #include <string> #include <string> #include <wx/string.h> #include <wx/string.h> #include <stdint.h> #include <assert.h> /** /** * Class UTF8 * Class UTF8 * is an 8 bit std::string assuredly encoded in UTF8 that supplies special * is an 8 bit std::string that is assuredly encoded in UTF8, and supplies special * conversion support to and from wxString, and has iteration over * conversion support to and from wxString, and has iteration over unicode characters. * UTF8 code points. * * @author Dick Hollenbeck */ */ class UTF8 : public std::string class UTF8 : public std::string { { public: public: UTF8( const wxString& o ) : UTF8( const wxString& o ); std::string( (const char*) o.utf8_str() ) { // @todo: should not be inline. } /// This is the only constructor for which you could end up with /// non-UTF8 encoding, but that would be your fault. UTF8( const char* txt ) : UTF8( const char* txt ) : std::string( txt ) std::string( txt ) { { // ok inline } } explicit UTF8( const std::string& o ) : explicit UTF8( const std::string& o ) : std::string( o ) std::string( o ) { { // ok inline } } UTF8() : UTF8() : std::string() std::string() { { // ok inline } } UTF8& operator = ( const wxString& o ) UTF8& operator=( const wxString& o ); { // @todo: should not be inline. std::string::operator=( (const char*) o.utf8_str() ); return *this; } UTF8& operator=( const std::string& o ) UTF8& operator=( const std::string& o ) { { Loading @@ -53,17 +43,28 @@ public: return *this; return *this; } } operator wxString () const operator wxString () const; /// This one is not in std::string, and one wonders why... might be a solid /// enough reason to remove it still. operator char* () const { { // @todo: should not be inline. return (char*) c_str(); return wxString( c_str(), wxConvUTF8 ); } } static int uni_forward( unsigned char* it, uint32_t* result ) /** * Function uni_forward * advances over a UTF8 encoded multibyte character, capturing the unicode * character as it goes, and returning the number of bytes consumed. * * @param aSequence is the UTF8 byte sequence. * @param aResult is where to put the unicode character. */ static int uni_forward( unsigned char* aSequence, unsigned* aResult ) { { // @todo: have this read UTF8 characters into result, not bytes. // @todo: have this read UTF8 characters into result, not bytes. // What's here now is scaffolding, reading single byte characters only. // What's here now is scaffolding, reading single byte characters only. *result = *it; *aResult = *aSequence; return 1; return 1; } } Loading @@ -71,37 +72,40 @@ public: * class uni_iter * class uni_iter * is a non-mutable iterator that walks through code points in the UTF8 encoded * is a non-mutable iterator that walks through code points in the UTF8 encoded * string. The normal ++(), ++(int), ->(), and *() operators are all supported and * string. The normal ++(), ++(int), ->(), and *() operators are all supported and * they return a uint32_t holding the unicode character appropriate for respective * they return a unsigned holding the unicode character appropriate for respective * operation. * operation. */ */ class uni_iter class uni_iter { { friend class UTF8; unsigned char* it; unsigned char* it; public: uni_iter( const char* start ) : uni_iter( const char* start ) : it( (unsigned char*) start ) it( (unsigned char*) start ) { { assert( sizeof(unsigned) >= 4 ); } } public: /// pre-increment and return unicode at new position /// pre-increment and return unicode at new position uint32_t operator++() unsigned operator++() { { uint32_t result; unsigned result; // advance, and toss the result // advance, and toss the result it += uni_forward( it, &result ); it += uni_forward( it, &result ); // get the next result, but do not advance: // get the next result, but do not advance: uni_forward( it, &result ); uni_forward( it, &result ); return result; return result; } } /// post-increment and return unicode at initial position /// post-increment and return unicode at initial position uint32_t operator++( int ) unsigned operator++( int ) { { uint32_t result; unsigned result; // grab the result and advance. // grab the result and advance. it += uni_forward( it, &result ); it += uni_forward( it, &result ); Loading @@ -109,9 +113,9 @@ public: } } /// return unicode at current position /// return unicode at current position uint32_t operator->() const unsigned operator->() const { { uint32_t result; unsigned result; // grab the result, do not advance // grab the result, do not advance uni_forward( it, &result ); uni_forward( it, &result ); Loading @@ -119,9 +123,9 @@ public: } } /// return unicode at current position /// return unicode at current position uint32_t operator*() const unsigned operator*() const { { uint32_t result; unsigned result; // grab the result, do not advance // grab the result, do not advance uni_forward( it, &result ); uni_forward( it, &result ); Loading @@ -136,11 +140,19 @@ public: bool operator>=( const uni_iter& other ) const { return it >= other.it; } bool operator>=( const uni_iter& other ) const { return it >= other.it; } }; }; /** * Function ubegin * returns a @a uni_iter initialized to the start of this UTF8 byte sequence. */ uni_iter ubegin() const uni_iter ubegin() const { { return uni_iter( data() ); return uni_iter( data() ); } } /** * Function uend * returns a @a uni_iter initialized to the end of this UTF8 byte sequence. */ uni_iter uend() const uni_iter uend() const { { return uni_iter( data() + size() ); return uni_iter( data() + size() ); Loading @@ -148,8 +160,10 @@ public: }; }; wxString aFunctionTaking_wxString( const wxString& wx ) wxString wxFunctionTaking_wxString( const wxString& wx ) { { printf( "%s:'%s'\n", __func__, (char*) UTF8( wx ) ); printf( "%s:'%s'\n", __func__, (const char*) UTF8( wx ) ); printf( "%s:'%s'\n", __func__, UTF8( wx ).c_str() ); printf( "%s:'%s'\n", __func__, UTF8( wx ).c_str() ); return wx; return wx; Loading @@ -158,9 +172,11 @@ wxString aFunctionTaking_wxString( const wxString& wx ) int main() int main() { { UTF8 u1 = "output"; std::string str = "input"; std::string str = "input"; wxString wx = wxT( "input" ); UTF8 u1 = "initial"; wxString wx = wxT( "input2" ); printf( "u1:'%s'\n", u1.c_str() ); u1 = str; u1 = str; Loading @@ -170,25 +186,49 @@ int main() u2 += 'X'; u2 += 'X'; printf( "utf2:'%s'\n", u2.c_str() ); printf( "u2:'%s'\n", u2.c_str() ); // key accomplishments here: // key accomplishments here: // 1) passing a UTF8 to a function which normally takes a wxString. // 1) passing a UTF8 to a function which normally takes a wxString. // 2) return a wxString back into a UTF8. // 2) return a wxString back into a UTF8. UTF8 result = aFunctionTaking_wxString( u2 ); UTF8 result = wxFunctionTaking_wxString( u2 ); printf( "result:'%s'\n", result.c_str() ); printf( "result:'%s'\n", result.c_str() ); // test the unicode iterator: // test the unicode iterator: for( UTF8::uni_iter it = u2.ubegin(); it != u2.uend(); ) for( UTF8::uni_iter it = u2.ubegin(); it != u2.uend(); ) { { // test post-increment: printf( " _%c_", it++ ); printf( " _%c_", it++ ); // after UTF7::uni_forward() is implemented, it++ %c is no longer useable. // after UTF8::uni_forward() is implemented, %c is no longer useable. // printf( " _%02x_", it++ ); // printf( " _%02x_", it++ ); } } printf( "\n" ); printf( "\n" ); return 0; return 0; } } // These to go into a library *.cpp, they are not inlined so that code space // is saved creating the intermediate objects and referencing wxConvUTF8. UTF8::UTF8( const wxString& o ) : std::string( (const char*) o.utf8_str() ) { } UTF8::operator wxString () const { return wxString( c_str(), wxConvUTF8 ); } UTF8& UTF8::operator=( const wxString& o ) { std::string::operator=( (const char*) o.utf8_str() ); return *this; } Loading
tools/UTF8.cpp +84 −44 Original line number Original line Diff line number Diff line Loading @@ -2,50 +2,40 @@ #include <stdio.h> #include <stdio.h> #include <string> #include <string> #include <wx/string.h> #include <wx/string.h> #include <stdint.h> #include <assert.h> /** /** * Class UTF8 * Class UTF8 * is an 8 bit std::string assuredly encoded in UTF8 that supplies special * is an 8 bit std::string that is assuredly encoded in UTF8, and supplies special * conversion support to and from wxString, and has iteration over * conversion support to and from wxString, and has iteration over unicode characters. * UTF8 code points. * * @author Dick Hollenbeck */ */ class UTF8 : public std::string class UTF8 : public std::string { { public: public: UTF8( const wxString& o ) : UTF8( const wxString& o ); std::string( (const char*) o.utf8_str() ) { // @todo: should not be inline. } /// This is the only constructor for which you could end up with /// non-UTF8 encoding, but that would be your fault. UTF8( const char* txt ) : UTF8( const char* txt ) : std::string( txt ) std::string( txt ) { { // ok inline } } explicit UTF8( const std::string& o ) : explicit UTF8( const std::string& o ) : std::string( o ) std::string( o ) { { // ok inline } } UTF8() : UTF8() : std::string() std::string() { { // ok inline } } UTF8& operator = ( const wxString& o ) UTF8& operator=( const wxString& o ); { // @todo: should not be inline. std::string::operator=( (const char*) o.utf8_str() ); return *this; } UTF8& operator=( const std::string& o ) UTF8& operator=( const std::string& o ) { { Loading @@ -53,17 +43,28 @@ public: return *this; return *this; } } operator wxString () const operator wxString () const; /// This one is not in std::string, and one wonders why... might be a solid /// enough reason to remove it still. operator char* () const { { // @todo: should not be inline. return (char*) c_str(); return wxString( c_str(), wxConvUTF8 ); } } static int uni_forward( unsigned char* it, uint32_t* result ) /** * Function uni_forward * advances over a UTF8 encoded multibyte character, capturing the unicode * character as it goes, and returning the number of bytes consumed. * * @param aSequence is the UTF8 byte sequence. * @param aResult is where to put the unicode character. */ static int uni_forward( unsigned char* aSequence, unsigned* aResult ) { { // @todo: have this read UTF8 characters into result, not bytes. // @todo: have this read UTF8 characters into result, not bytes. // What's here now is scaffolding, reading single byte characters only. // What's here now is scaffolding, reading single byte characters only. *result = *it; *aResult = *aSequence; return 1; return 1; } } Loading @@ -71,37 +72,40 @@ public: * class uni_iter * class uni_iter * is a non-mutable iterator that walks through code points in the UTF8 encoded * is a non-mutable iterator that walks through code points in the UTF8 encoded * string. The normal ++(), ++(int), ->(), and *() operators are all supported and * string. The normal ++(), ++(int), ->(), and *() operators are all supported and * they return a uint32_t holding the unicode character appropriate for respective * they return a unsigned holding the unicode character appropriate for respective * operation. * operation. */ */ class uni_iter class uni_iter { { friend class UTF8; unsigned char* it; unsigned char* it; public: uni_iter( const char* start ) : uni_iter( const char* start ) : it( (unsigned char*) start ) it( (unsigned char*) start ) { { assert( sizeof(unsigned) >= 4 ); } } public: /// pre-increment and return unicode at new position /// pre-increment and return unicode at new position uint32_t operator++() unsigned operator++() { { uint32_t result; unsigned result; // advance, and toss the result // advance, and toss the result it += uni_forward( it, &result ); it += uni_forward( it, &result ); // get the next result, but do not advance: // get the next result, but do not advance: uni_forward( it, &result ); uni_forward( it, &result ); return result; return result; } } /// post-increment and return unicode at initial position /// post-increment and return unicode at initial position uint32_t operator++( int ) unsigned operator++( int ) { { uint32_t result; unsigned result; // grab the result and advance. // grab the result and advance. it += uni_forward( it, &result ); it += uni_forward( it, &result ); Loading @@ -109,9 +113,9 @@ public: } } /// return unicode at current position /// return unicode at current position uint32_t operator->() const unsigned operator->() const { { uint32_t result; unsigned result; // grab the result, do not advance // grab the result, do not advance uni_forward( it, &result ); uni_forward( it, &result ); Loading @@ -119,9 +123,9 @@ public: } } /// return unicode at current position /// return unicode at current position uint32_t operator*() const unsigned operator*() const { { uint32_t result; unsigned result; // grab the result, do not advance // grab the result, do not advance uni_forward( it, &result ); uni_forward( it, &result ); Loading @@ -136,11 +140,19 @@ public: bool operator>=( const uni_iter& other ) const { return it >= other.it; } bool operator>=( const uni_iter& other ) const { return it >= other.it; } }; }; /** * Function ubegin * returns a @a uni_iter initialized to the start of this UTF8 byte sequence. */ uni_iter ubegin() const uni_iter ubegin() const { { return uni_iter( data() ); return uni_iter( data() ); } } /** * Function uend * returns a @a uni_iter initialized to the end of this UTF8 byte sequence. */ uni_iter uend() const uni_iter uend() const { { return uni_iter( data() + size() ); return uni_iter( data() + size() ); Loading @@ -148,8 +160,10 @@ public: }; }; wxString aFunctionTaking_wxString( const wxString& wx ) wxString wxFunctionTaking_wxString( const wxString& wx ) { { printf( "%s:'%s'\n", __func__, (char*) UTF8( wx ) ); printf( "%s:'%s'\n", __func__, (const char*) UTF8( wx ) ); printf( "%s:'%s'\n", __func__, UTF8( wx ).c_str() ); printf( "%s:'%s'\n", __func__, UTF8( wx ).c_str() ); return wx; return wx; Loading @@ -158,9 +172,11 @@ wxString aFunctionTaking_wxString( const wxString& wx ) int main() int main() { { UTF8 u1 = "output"; std::string str = "input"; std::string str = "input"; wxString wx = wxT( "input" ); UTF8 u1 = "initial"; wxString wx = wxT( "input2" ); printf( "u1:'%s'\n", u1.c_str() ); u1 = str; u1 = str; Loading @@ -170,25 +186,49 @@ int main() u2 += 'X'; u2 += 'X'; printf( "utf2:'%s'\n", u2.c_str() ); printf( "u2:'%s'\n", u2.c_str() ); // key accomplishments here: // key accomplishments here: // 1) passing a UTF8 to a function which normally takes a wxString. // 1) passing a UTF8 to a function which normally takes a wxString. // 2) return a wxString back into a UTF8. // 2) return a wxString back into a UTF8. UTF8 result = aFunctionTaking_wxString( u2 ); UTF8 result = wxFunctionTaking_wxString( u2 ); printf( "result:'%s'\n", result.c_str() ); printf( "result:'%s'\n", result.c_str() ); // test the unicode iterator: // test the unicode iterator: for( UTF8::uni_iter it = u2.ubegin(); it != u2.uend(); ) for( UTF8::uni_iter it = u2.ubegin(); it != u2.uend(); ) { { // test post-increment: printf( " _%c_", it++ ); printf( " _%c_", it++ ); // after UTF7::uni_forward() is implemented, it++ %c is no longer useable. // after UTF8::uni_forward() is implemented, %c is no longer useable. // printf( " _%02x_", it++ ); // printf( " _%02x_", it++ ); } } printf( "\n" ); printf( "\n" ); return 0; return 0; } } // These to go into a library *.cpp, they are not inlined so that code space // is saved creating the intermediate objects and referencing wxConvUTF8. UTF8::UTF8( const wxString& o ) : std::string( (const char*) o.utf8_str() ) { } UTF8::operator wxString () const { return wxString( c_str(), wxConvUTF8 ); } UTF8& UTF8::operator=( const wxString& o ) { std::string::operator=( (const char*) o.utf8_str() ); return *this; }