6767#define CLEAR_HEX (C ) (C &= ~(HEX(1 )&HEX (2 )&HEX(3 )&HEX(4 )&HEX(5 )&HEX(6 )&HEX(7 )&HEX(8 )))
6868
6969using namespace IfcParse;
70+ using namespace IfcWrite ;
7071
7172void IfcCharacterDecoder::addChar (std::stringstream& s,const UChar32& ch) {
7273#ifdef HAVE_ICU
@@ -296,3 +297,61 @@ std::string IfcCharacterDecoder::compatibility_charset = "";
296297#else
297298char IfcCharacterDecoder::substitution_character = ' _' ;
298299#endif
300+
301+
302+ IfcCharacterEncoder::IfcCharacterEncoder (const std::string& input) {
303+ if ( !converter) converter = ucnv_open (" utf-8" , &status);
304+ str = input;
305+ }
306+
307+ IfcCharacterEncoder::~IfcCharacterEncoder () {
308+ if ( !converter) ucnv_close (converter);
309+ converter = 0 ;
310+ }
311+
312+ IfcCharacterEncoder::operator std::string () {
313+ #ifdef HAVE_ICU
314+ // Either 2 or 4 to uses \X2 or \X4 respectively.
315+ // Currently hardcoded to 4, but \X2 might be
316+ // sufficient for nearly all purposes.
317+ const int num_bytes = 4 ;
318+ const std::string num_bytes_str = std::string (1 ,num_bytes + 0x30 );
319+
320+ std::ostringstream oss;
321+ UChar32 ch;
322+
323+ const char * source = str.c_str ();
324+ const char * limit = &*str.end ();
325+
326+ bool in_extended = false ;
327+
328+ while (source < limit) {
329+ ch = ucnv_getNextUChar (converter, &source, limit, &status);
330+ const bool within_spf_range = ch >= 0x20 && ch <= 0x7e ;
331+ if ( in_extended && within_spf_range ) {
332+ oss << " \\ X0\\ " ;
333+ } else if ( !in_extended && !within_spf_range ) {
334+ oss << " \\ X" << num_bytes_str << " \\ " ;
335+ }
336+ if ( within_spf_range ) {
337+ oss.put (ch);
338+ if ( ch == ' \\ ' ) oss.put (ch);
339+ } else {
340+ oss << std::hex << std::setw (num_bytes*2 ) << std::uppercase << std::setfill (' 0' ) << (int ) ch;
341+ }
342+ in_extended = !within_spf_range;
343+ }
344+
345+ if ( in_extended ) oss << " \\ X0\\ " ;
346+
347+ return oss.str ();
348+ #else
349+ return str;
350+ #endif
351+ }
352+
353+
354+ #ifdef HAVE_ICU
355+ UErrorCode IfcCharacterEncoder::status = U_ZERO_ERROR;
356+ UConverter* IfcCharacterEncoder::converter = 0 ;
357+ #endif
0 commit comments