Changeset 349
- Timestamp:
- Nov 26, 2009, 12:34:37 AM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
TabularUnified trunk/src/corelib/codecs/qtextcodec.cpp ¶
r340 r349 59 59 #endif 60 60 61 #if defined(Q_OS_OS2) 62 # include <unidef.h> 63 # include <uconv.h> 64 # include "qvector.h" 65 #endif 66 61 67 #include "qutfcodec_p.h" 62 68 #include "qsimplecodec_p.h" … … 392 398 } 393 399 400 #elif defined(Q_OS_OS2) 401 402 class QOs2LocalCodec: public QTextCodec 403 { 404 public: 405 QOs2LocalCodec(); 406 ~QOs2LocalCodec(); 407 408 QString convertToUnicode(const char *, int, ConverterState *) const; 409 QByteArray convertFromUnicode(const QChar *, int, ConverterState *) const; 410 411 QByteArray name() const; 412 int mibEnum() const; 413 414 private: 415 UconvObject uoSubYes; 416 UconvObject uoSubNo; 417 }; 418 419 QOs2LocalCodec::QOs2LocalCodec() : uoSubYes(0), uoSubNo(0) 420 { 421 // create the conversion object for the process code page that performs 422 // substitution of invalid characters with '?' 423 UniCreateUconvObject((UniChar *)L"@sub=yes", &uoSubYes); 424 // same as above but doesn't perform substitution 425 UniCreateUconvObject((UniChar *)L"@sub=no", &uoSubNo); 426 } 427 428 QOs2LocalCodec::~QOs2LocalCodec() 429 { 430 UniFreeUconvObject(uoSubNo); 431 UniFreeUconvObject(uoSubYes); 432 } 433 434 static void qOs2LocalCodecStateFree(QTextCodec::ConverterState *state) 435 { 436 delete reinterpret_cast<char *>(state->d); 437 } 438 439 QString QOs2LocalCodec::convertToUnicode(const char *chars, int length, 440 ConverterState *state) const 441 { 442 QString res; 443 444 if (!chars) 445 return res; 446 if (!length) 447 return QLatin1String(""); 448 449 UconvObject uo = uoSubYes; 450 if (state && (state->flags & ConvertInvalidToNull)) 451 uo = uoSubNo; 452 Q_ASSERT(uo); 453 if (!uo) 454 return res; 455 456 int remainingChars = 0; 457 char *remainingBuffer = 0; 458 459 if (state) { 460 // stateful conversion 461 remainingBuffer = reinterpret_cast<char *>(&state->d); 462 if (remainingBuffer) { 463 // restore state 464 remainingChars = state->remainingChars; 465 } else { 466 // first time, add the destructor for state->d 467 state->flags |= FreeFunction; 468 QTextCodecUnalignedPointer::encode(state->state_data, 469 qOs2LocalCodecStateFree); 470 } 471 } 472 473 const char *mbPtr = chars; 474 size_t mbLeft = length; 475 476 QByteArray mbExtra; 477 if (remainingChars) { 478 // we have to prepend the remaining bytes from the previous conversion 479 mbLeft += remainingChars; 480 mbExtra.resize(mbLeft); 481 mbPtr = mbExtra.data(); 482 483 memcpy(mbExtra.data(), remainingBuffer, remainingChars); 484 memcpy(mbExtra.data() + remainingChars, chars, length); 485 486 remainingBuffer = 0; 487 remainingChars = 0; 488 } 489 490 size_t ucLen = mbLeft; 491 QString ucBuf(ucLen, '\0'); 492 UniChar *ucPtr = reinterpret_cast<UniChar *>(ucBuf.data()); 493 size_t ucLeft = ucLen; 494 495 size_t nonIdent = 0; 496 int rc; 497 498 while (mbLeft) { 499 rc = UniUconvToUcs(uo, (void**)&mbPtr, &mbLeft, &ucPtr, &ucLeft, 500 &nonIdent); 501 if (rc == ULS_BUFFERFULL) { 502 size_t ucDone = ucLen - ucLeft; 503 size_t mbDone = length - mbLeft; 504 // assume that mbLeft/ucLeft is an approximation of mbDone/ucDone 505 ucLen = ucDone + (mbLeft * ucDone) / mbDone; 506 ucBuf.resize(ucLen); 507 ucPtr = reinterpret_cast<UniChar *>(ucBuf.data() + ucDone); 508 } else if (rc == ULS_ILLEGALSEQUENCE && state) { 509 // conversion stopped because the remaining inBytesLeft make up 510 // an incomplete multi-byte sequence; save them for later 511 remainingBuffer = new char[mbLeft]; 512 memcpy(remainingBuffer, mbPtr, mbLeft); 513 remainingChars = mbLeft; 514 break; 515 } else if (rc != ULS_SUCCESS) { 516 // just fail on an unexpected error (will return what we've got) 517 qWarning("QOs2LocalCodec::convertToUnicode: UniUconvToUcs failed " 518 "with %d", rc); 519 break; 520 } 521 } 522 523 ucBuf.resize(ucLen - ucLeft); 524 res = ucBuf; 525 526 if (state) { 527 // update the state 528 state->invalidChars = nonIdent; 529 state->remainingChars = remainingChars; 530 state->d = remainingBuffer; 531 } 532 533 return res; 534 } 535 536 QByteArray QOs2LocalCodec::convertFromUnicode(const QChar *uchars, int length, 537 ConverterState *state) const 538 { 539 QByteArray res; 540 541 if (!uchars) 542 return res; 543 if (!length) 544 return QByteArray(""); 545 546 UconvObject uo = uoSubYes; 547 if (state && (state->flags & ConvertInvalidToNull)) 548 uo = uoSubNo; 549 Q_ASSERT(uo); 550 if (!uo) 551 return res; 552 553 const UniChar *ucPtr = reinterpret_cast<const UniChar *>(uchars); 554 size_t ucLeft = length; 555 556 QVector<QChar> ucExtra; 557 if (state && state->remainingChars) { 558 // we have one surrogate char to be prepended 559 Q_ASSERT(state->remainingChars == 1); 560 ucLeft += 1; 561 ucExtra.resize(ucLeft); 562 ucPtr = reinterpret_cast<const UniChar *>(ucExtra.data()); 563 564 ucExtra[0] = state->state_data[0]; 565 memcpy(ucExtra.data() + 1, uchars, length * sizeof(QChar)); 566 567 state->remainingChars = 0; 568 } 569 570 // be optimistic (imply that one byte is necessary per every Unicode char) 571 size_t mbLen = length; 572 QByteArray mbBuf(mbLen, '\0'); 573 char *mbPtr = mbBuf.data(); 574 size_t mbLeft = mbLen; 575 576 size_t nonIdent = 0; 577 int rc; 578 579 while (ucLeft) { 580 rc = UniUconvFromUcs(uo, const_cast<UniChar **>(&ucPtr), &ucLeft, 581 (void**)&mbPtr, &mbLeft, &nonIdent); 582 if (rc == ULS_BUFFERFULL) { 583 size_t mbDone = mbLen - mbLeft; 584 size_t ucDone = length - ucLeft; 585 size_t newLen = mbLen; 586 if (ucDone) { 587 // assume that ucLeft/mbLeft is an approximation of ucDone/mbDone 588 newLen = mbDone + (ucLeft * mbDone) / ucDone; 589 } 590 if (newLen == mbLen) { 591 // could not process a single Unicode char, double the size 592 mbLen *= 2; 593 } else { 594 mbLen = newLen; 595 } 596 mbBuf.resize(mbLen); 597 mbPtr = mbBuf.data() + mbDone; 598 mbLeft = mbLen - mbDone; 599 } else if (rc == ULS_ILLEGALSEQUENCE && state) { 600 // buffer ends in a surrogate 601 Q_ASSERT(ucLeft == 2); 602 state->state_data[0] = *ucPtr; 603 state->remainingChars = 1; 604 break; 605 } else if (rc != ULS_SUCCESS) { 606 // just fail on an unexpected error (will return what we've got) 607 qWarning("QOs2LocalCodec::convertFromUnicode: UniUconvFromUcs failed " 608 "with %d", rc); 609 break; 610 } 611 } 612 613 mbBuf.resize(mbLen - mbLeft); 614 res = mbBuf; 615 616 if (state) { 617 // update the state 618 state->invalidChars = nonIdent; 619 } 620 621 return res; 622 } 623 624 QByteArray QOs2LocalCodec::name() const 625 { 626 return "System"; 627 } 628 629 int QOs2LocalCodec::mibEnum() const 630 { 631 return 0; 632 } 633 394 634 #else 395 635 … … 509 749 #endif 510 750 511 #if !defined(Q_OS_WIN32) && !defined(Q_OS_WINCE) 751 #if !defined(Q_OS_WIN32) && !defined(Q_OS_WINCE) && !defined(Q_OS_OS2) 512 752 static QTextCodec *checkForCodec(const char *name) { 513 753 QTextCodec *c = QTextCodec::codecForName(name); … … 529 769 { 530 770 #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) 771 localeMapper = QTextCodec::codecForName("System"); 772 #elif defined(Q_OS_OS2) 531 773 localeMapper = QTextCodec::codecForName("System"); 532 774 #else … … 712 954 (void) new QWindowsLocalCodec; 713 955 #endif // Q_OS_WIN32 956 957 #if defined(Q_OS_OS2) 958 (void) new QOs2LocalCodec; 959 #endif // Q_OS_OS2 714 960 715 961 (void)new QUtf16Codec;
Note:
See TracChangeset
for help on using the changeset viewer.