| 248 | } |
| 249 | |
| 250 | SegmentsPtr BuildSegmentsFromLengths(std::string_view text, |
| 251 | const opencc_segment_length_array_t& lengths) { |
| 252 | SegmentsPtr segments(new Segments); |
| 253 | const char* bytes = text.data(); |
| 254 | const size_t inputSize = text.size(); |
| 255 | size_t byteOffset = 0; |
| 256 | |
| 257 | for (size_t i = 0; i < lengths.segment_count; i++) { |
| 258 | const uint32_t codepointLength = lengths.codepoint_lengths[i]; |
| 259 | if (codepointLength == 0) { |
| 260 | throw Exception("Segmentation plugin returned a zero-length segment."); |
| 261 | } |
| 262 | |
| 263 | const size_t segmentStart = byteOffset; |
| 264 | for (uint32_t j = 0; j < codepointLength; j++) { |
| 265 | if (byteOffset >= inputSize) { |
| 266 | throw Exception("Segmentation plugin returned lengths past end of input."); |
| 267 | } |
| 268 | const size_t charLength = UTF8Util::NextCharLengthNoException(bytes + byteOffset); |
| 269 | if (charLength == 0 || byteOffset + charLength > inputSize) { |
| 270 | throw Exception("Input text is not valid UTF-8."); |
| 271 | } |
| 272 | byteOffset += charLength; |
| 273 | } |
| 274 | |
| 275 | segments->AddSegment(text.substr(segmentStart, byteOffset - segmentStart)); |
| 276 | } |
| 277 | |
| 278 | if (byteOffset != inputSize) { |
| 279 | throw Exception("Segmentation plugin lengths do not cover the full input. " |
| 280 | "Consumed bytes: " + std::to_string(byteOffset) + |
| 281 | ", total bytes: " + std::to_string(inputSize) + |
| 282 | ", segments: " + std::to_string(lengths.segment_count) + "."); |
| 283 | } |
| 284 | return segments; |
| 285 | } |
| 286 | |
| 287 | class PluginSegmentationAdapter : public Segmentation { |
| 288 | public: |