| 87 | |
| 88 | namespace { |
| 89 | std::string read_string(IfcParse::FileReader& stream_, IfcParse::IfcCharacterDecoder::ConversionMode mode, char substitution_character) { |
| 90 | std::u32string builder_; |
| 91 | |
| 92 | unsigned int parse_state = 0; |
| 93 | builder_.clear(); |
| 94 | builder_.push_back('\''); |
| 95 | char current_char; |
| 96 | int codepage = 1; |
| 97 | unsigned int hex = 0; |
| 98 | unsigned int hex_count = 0; |
| 99 | |
| 100 | while ((current_char = stream_.peek()) != 0) { |
| 101 | if (EXPECTS_CHARACTER(parse_state)) { |
| 102 | builder_.push_back(IfcUtil::convert_codepage(codepage, current_char + 0x80)); |
| 103 | parse_state = 0; |
| 104 | } else if (current_char == '\'' && (parse_state == 0U)) { |
| 105 | parse_state = APOSTROPHE; |
| 106 | } else if (current_char == '\\' && (parse_state == 0U)) { |
| 107 | parse_state = FIRST_SOLIDUS; |
| 108 | } else if (current_char == '\\' && EXPECTS_SOLIDUS(parse_state)) { |
| 109 | if (((parse_state & ALPHABET_DEFINITION) != 0U) || |
| 110 | ((parse_state & IGNORED_DIRECTIVE) != 0U) || |
| 111 | ((parse_state & ENDEXTENDED_0) != 0U)) { |
| 112 | parse_state = hex = hex_count = 0; |
| 113 | } else if ((parse_state & ENCOUNTERED_HEX) != 0U) { |
| 114 | parse_state += THIRD_SOLIDUS; |
| 115 | parse_state -= ENCOUNTERED_HEX; |
| 116 | } else { |
| 117 | parse_state += SECOND_SOLIDUS; |
| 118 | } |
| 119 | } else if (current_char == 'X' && EXPECTS_ENDEXTENDED_X(parse_state)) { |
| 120 | parse_state += ENDEXTENDED_X; |
| 121 | } else if (current_char == '0' && EXPECTS_ENDEXTENDED_0(parse_state)) { |
| 122 | parse_state += ENDEXTENDED_0; |
| 123 | } else if (current_char == 'X' && EXPECTS_ARBITRARY(parse_state)) { |
| 124 | parse_state += ARBITRARY; |
| 125 | } else if (current_char == '2' && EXPECTS_ARBITRARY2(parse_state)) { |
| 126 | parse_state += EXTENDED2; |
| 127 | } else if (current_char == '4' && EXPECTS_ARBITRARY2(parse_state)) { |
| 128 | parse_state += EXTENDED2 + EXTENDED4; |
| 129 | } else if (current_char == 'P' && EXPECTS_ALPHABET(parse_state)) { |
| 130 | parse_state += ALPHABET; |
| 131 | } else if ((current_char == 'N' || current_char == 'F') && EXPECTS_N_OR_F(parse_state)) { |
| 132 | parse_state += IGNORED_DIRECTIVE; |
| 133 | } else if (IS_VALID_ALPHABET_DEFINITION(current_char) && EXPECTS_ALPHABET_DEFINITION(parse_state)) { |
| 134 | codepage = current_char - 0x40; |
| 135 | parse_state += ALPHABET_DEFINITION; |
| 136 | } else if (current_char == 'S' && EXPECTS_PAGE(parse_state)) { |
| 137 | parse_state += PAGE; |
| 138 | } else if (IS_HEXADECIMAL(current_char) && EXPECTS_HEX(parse_state)) { |
| 139 | if (IS_LOWERCASE_HEX(current_char)) { |
| 140 | Logger::Warning("Lowercase hexadecimal character '" + std::string(1, current_char) + |
| 141 | "' found at offset " + std::to_string(stream_.tell()) + |
| 142 | ". It is recommended to use uppercase for hexadecimal."); |
| 143 | } |
| 144 | hex <<= 4; |
| 145 | parse_state += HEX((++hex_count)); |
| 146 | hex += HEX_TO_INT(current_char); |