| 388 | } |
| 389 | |
| 390 | TextFormat guessFileEncoding( IOStream& ins ) { |
| 391 | auto start = ins.tell(); |
| 392 | ScopedOp op( [] {}, [&start, &ins] { ins.seek( start ); } ); |
| 393 | TextFileStats stats8; |
| 394 | |
| 395 | // Try UTF8 first: |
| 396 | Uint32 numBytesRead = |
| 397 | scanTextFile( stats8, ins, TextEncoding::get<UTF8>(), NumBytesForAutodetect ); |
| 398 | if ( numBytesRead == 0 ) |
| 399 | return { TextFormat::Encoding::UTF8, stats8.getNewLineType(), false }; |
| 400 | |
| 401 | ins.seek( 0 ); |
| 402 | if ( stats8.numInvalidPoints() == 0 && stats8.numControl == 0 ) { |
| 403 | // No UTF-8 encoding errors, and no weird control characters/nulls. Pick UTF-8. |
| 404 | return { TextFormat::Encoding::UTF8, stats8.getNewLineType(), false }; |
| 405 | } |
| 406 | |
| 407 | // If more than 20% of the high bytes in UTF-8 are encoding errors, reinterpret UTF-8 as just |
| 408 | // bytes. |
| 409 | TextFormat::Encoding encoding8 = TextFormat::Encoding::UTF8; |
| 410 | { |
| 411 | Uint32 numHighBytes = numBytesRead - stats8.numPlainAscii - stats8.numControl; |
| 412 | if ( stats8.numInvalidPoints() >= numHighBytes * 0.2f ) { |
| 413 | // Too many UTF-8 errors. Consider it bytes. |
| 414 | encoding8 = TextFormat::Encoding::Latin1; |
| 415 | stats8.numPoints = numBytesRead; |
| 416 | stats8.numValidPoints = numBytesRead; |
| 417 | } |
| 418 | } |
| 419 | |
| 420 | // Examine both UTF16 endianness: |
| 421 | TextFileStats stats16_le; |
| 422 | scanTextFile( stats16_le, ins, TextEncoding::get<UTF16_LE>(), NumBytesForAutodetect ); |
| 423 | ins.seek( 0 ); |
| 424 | |
| 425 | TextFileStats stats16_be; |
| 426 | scanTextFile( stats16_be, ins, TextEncoding::get<UTF16_BE>(), NumBytesForAutodetect ); |
| 427 | ins.seek( 0 ); |
| 428 | |
| 429 | // Choose the better UTF16 candidate: |
| 430 | TextFileStats* stats = &stats16_le; |
| 431 | TextFormat::Encoding encoding = TextFormat::Encoding::UTF16LE; |
| 432 | if ( stats16_be.getScore() > stats16_le.getScore() ) { |
| 433 | stats = &stats16_be; |
| 434 | encoding = TextFormat::Encoding::UTF16BE; |
| 435 | } |
| 436 | |
| 437 | TextFileStats statsShiftJIS; |
| 438 | statsShiftJIS.count16b = true; |
| 439 | scanTextFile( statsShiftJIS, ins, TextEncoding::get<ShiftJIS>(), NumBytesForAutodetect ); |
| 440 | ins.seek( 0 ); |
| 441 | |
| 442 | if ( statsShiftJIS.allValidPoints() && statsShiftJIS.num16bytes && |
| 443 | statsShiftJIS.getScore() > stats->getScore() ) { |
| 444 | stats = &statsShiftJIS; |
| 445 | encoding = TextFormat::Encoding::Shift_JIS; |
| 446 | } |
| 447 |
no test coverage detected