OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2004, 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. | 2 * Copyright (C) 2004, 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. |
3 * Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com> | 3 * Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com> |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
7 * are met: | 7 * are met: |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
(...skipping 19 matching lines...) Expand all Loading... |
30 #include "wtf/Assertions.h" | 30 #include "wtf/Assertions.h" |
31 #include "wtf/StringExtras.h" | 31 #include "wtf/StringExtras.h" |
32 #include "wtf/Threading.h" | 32 #include "wtf/Threading.h" |
33 #include "wtf/WTFThreadData.h" | 33 #include "wtf/WTFThreadData.h" |
34 #include "wtf/text/CString.h" | 34 #include "wtf/text/CString.h" |
35 #include "wtf/text/CharacterNames.h" | 35 #include "wtf/text/CharacterNames.h" |
36 #include "wtf/text/StringBuilder.h" | 36 #include "wtf/text/StringBuilder.h" |
37 #include <unicode/ucnv.h> | 37 #include <unicode/ucnv.h> |
38 #include <unicode/ucnv_cb.h> | 38 #include <unicode/ucnv_cb.h> |
39 | 39 |
40 using std::min; | |
41 | |
42 namespace WTF { | 40 namespace WTF { |
43 | 41 |
44 const size_t ConversionBufferSize = 16384; | 42 const size_t ConversionBufferSize = 16384; |
45 | 43 |
46 ICUConverterWrapper::~ICUConverterWrapper() | 44 ICUConverterWrapper::~ICUConverterWrapper() |
47 { | 45 { |
48 if (converter) | 46 if (converter) |
49 ucnv_close(converter); | 47 ucnv_close(converter); |
50 } | 48 } |
51 | 49 |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
310 | 308 |
311 class ErrorCallbackSetter { | 309 class ErrorCallbackSetter { |
312 public: | 310 public: |
313 ErrorCallbackSetter(UConverter* converter, bool stopOnError) | 311 ErrorCallbackSetter(UConverter* converter, bool stopOnError) |
314 : m_converter(converter) | 312 : m_converter(converter) |
315 , m_shouldStopOnEncodingErrors(stopOnError) | 313 , m_shouldStopOnEncodingErrors(stopOnError) |
316 { | 314 { |
317 if (m_shouldStopOnEncodingErrors) { | 315 if (m_shouldStopOnEncodingErrors) { |
318 UErrorCode err = U_ZERO_ERROR; | 316 UErrorCode err = U_ZERO_ERROR; |
319 ucnv_setToUCallBack(m_converter, UCNV_TO_U_CALLBACK_SUBSTITUTE, | 317 ucnv_setToUCallBack(m_converter, UCNV_TO_U_CALLBACK_SUBSTITUTE, |
320 UCNV_SUB_STOP_ON_ILLEGAL, &m_savedAction, | 318 UCNV_SUB_STOP_ON_ILLEGAL, &m_savedAction, |
321 &m_savedContext, &err); | 319 &m_savedContext, &err); |
322 ASSERT(err == U_ZERO_ERROR); | 320 ASSERT(err == U_ZERO_ERROR); |
323 } | 321 } |
324 } | 322 } |
325 ~ErrorCallbackSetter() | 323 ~ErrorCallbackSetter() |
326 { | 324 { |
327 if (m_shouldStopOnEncodingErrors) { | 325 if (m_shouldStopOnEncodingErrors) { |
328 UErrorCode err = U_ZERO_ERROR; | 326 UErrorCode err = U_ZERO_ERROR; |
329 const void* oldContext; | 327 const void* oldContext; |
330 UConverterToUCallback oldAction; | 328 UConverterToUCallback oldAction; |
331 ucnv_setToUCallBack(m_converter, m_savedAction, | 329 ucnv_setToUCallBack(m_converter, m_savedAction, m_savedContext, &old
Action, &oldContext, &err); |
332 m_savedContext, &oldAction, | |
333 &oldContext, &err); | |
334 ASSERT(oldAction == UCNV_TO_U_CALLBACK_SUBSTITUTE); | 330 ASSERT(oldAction == UCNV_TO_U_CALLBACK_SUBSTITUTE); |
335 ASSERT(!strcmp(static_cast<const char*>(oldContext), UCNV_SUB_STOP_O
N_ILLEGAL)); | 331 ASSERT(!strcmp(static_cast<const char*>(oldContext), UCNV_SUB_STOP_O
N_ILLEGAL)); |
336 ASSERT(err == U_ZERO_ERROR); | 332 ASSERT(err == U_ZERO_ERROR); |
337 } | 333 } |
338 } | 334 } |
339 | 335 |
340 private: | 336 private: |
341 UConverter* m_converter; | 337 UConverter* m_converter; |
342 bool m_shouldStopOnEncodingErrors; | 338 bool m_shouldStopOnEncodingErrors; |
343 const void* m_savedContext; | 339 const void* m_savedContext; |
(...skipping 13 matching lines...) Expand all Loading... |
357 } | 353 } |
358 | 354 |
359 ErrorCallbackSetter callbackSetter(m_converterICU, stopOnError); | 355 ErrorCallbackSetter callbackSetter(m_converterICU, stopOnError); |
360 | 356 |
361 StringBuilder result; | 357 StringBuilder result; |
362 | 358 |
363 UChar buffer[ConversionBufferSize]; | 359 UChar buffer[ConversionBufferSize]; |
364 UChar* bufferLimit = buffer + ConversionBufferSize; | 360 UChar* bufferLimit = buffer + ConversionBufferSize; |
365 const char* source = reinterpret_cast<const char*>(bytes); | 361 const char* source = reinterpret_cast<const char*>(bytes); |
366 const char* sourceLimit = source + length; | 362 const char* sourceLimit = source + length; |
367 int32_t* offsets = NULL; | 363 int32_t* offsets = nullptr; |
368 UErrorCode err = U_ZERO_ERROR; | 364 UErrorCode err = U_ZERO_ERROR; |
369 | 365 |
370 do { | 366 do { |
371 int ucharsDecoded = decodeToBuffer(buffer, bufferLimit, source, sourceLi
mit, offsets, flush != DoNotFlush, err); | 367 int ucharsDecoded = decodeToBuffer(buffer, bufferLimit, source, sourceLi
mit, offsets, flush != DoNotFlush, err); |
372 result.append(buffer, ucharsDecoded); | 368 result.append(buffer, ucharsDecoded); |
373 } while (err == U_BUFFER_OVERFLOW_ERROR); | 369 } while (err == U_BUFFER_OVERFLOW_ERROR); |
374 | 370 |
375 if (U_FAILURE(err)) { | 371 if (U_FAILURE(err)) { |
376 // flush the converter so it can be reused, and not be bothered by this
error. | 372 // flush the converter so it can be reused, and not be bothered by this
error. |
377 do { | 373 do { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
420 // characters. See the declaration of TextCodec::encode for more. | 416 // characters. See the declaration of TextCodec::encode for more. |
421 static void urlEscapedEntityCallback(const void* context, UConverterFromUnicodeA
rgs* fromUArgs, const UChar* codeUnits, int32_t length, | 417 static void urlEscapedEntityCallback(const void* context, UConverterFromUnicodeA
rgs* fromUArgs, const UChar* codeUnits, int32_t length, |
422 UChar32 codePoint, UConverterCallbackReason reason, UErrorCode* err) | 418 UChar32 codePoint, UConverterCallbackReason reason, UErrorCode* err) |
423 { | 419 { |
424 if (reason == UCNV_UNASSIGNED) { | 420 if (reason == UCNV_UNASSIGNED) { |
425 *err = U_ZERO_ERROR; | 421 *err = U_ZERO_ERROR; |
426 | 422 |
427 UnencodableReplacementArray entity; | 423 UnencodableReplacementArray entity; |
428 int entityLen = TextCodec::getUnencodableReplacement(codePoint, URLEncod
edEntitiesForUnencodables, entity); | 424 int entityLen = TextCodec::getUnencodableReplacement(codePoint, URLEncod
edEntitiesForUnencodables, entity); |
429 ucnv_cbFromUWriteBytes(fromUArgs, entity, entityLen, 0, err); | 425 ucnv_cbFromUWriteBytes(fromUArgs, entity, entityLen, 0, err); |
430 } else | 426 } else { |
431 UCNV_FROM_U_CALLBACK_ESCAPE(context, fromUArgs, codeUnits, length, codeP
oint, reason, err); | 427 UCNV_FROM_U_CALLBACK_ESCAPE(context, fromUArgs, codeUnits, length, codeP
oint, reason, err); |
| 428 } |
432 } | 429 } |
433 | 430 |
434 #if defined(USING_SYSTEM_ICU) | 431 #if defined(USING_SYSTEM_ICU) |
435 // Substitutes special GBK characters, escaping all other unassigned entities. | 432 // Substitutes special GBK characters, escaping all other unassigned entities. |
436 static void gbkCallbackEscape(const void* context, UConverterFromUnicodeArgs* fr
omUArgs, const UChar* codeUnits, int32_t length, | 433 static void gbkCallbackEscape(const void* context, UConverterFromUnicodeArgs* fr
omUArgs, const UChar* codeUnits, int32_t length, |
437 UChar32 codePoint, UConverterCallbackReason reason, UErrorCode* err) | 434 UChar32 codePoint, UConverterCallbackReason reason, UErrorCode* err) |
438 { | 435 { |
439 UChar outChar; | 436 UChar outChar; |
440 if (reason == UCNV_UNASSIGNED && (outChar = fallbackForGBK(codePoint))) { | 437 if (reason == UCNV_UNASSIGNED && (outChar = fallbackForGBK(codePoint))) { |
441 const UChar* source = &outChar; | 438 const UChar* source = &outChar; |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
503 }; | 500 }; |
504 | 501 |
505 CString TextCodecICU::encodeInternal(const TextCodecInput& input, UnencodableHan
dling handling) | 502 CString TextCodecICU::encodeInternal(const TextCodecInput& input, UnencodableHan
dling handling) |
506 { | 503 { |
507 const UChar* source = input.begin(); | 504 const UChar* source = input.begin(); |
508 const UChar* end = input.end(); | 505 const UChar* end = input.end(); |
509 | 506 |
510 UErrorCode err = U_ZERO_ERROR; | 507 UErrorCode err = U_ZERO_ERROR; |
511 | 508 |
512 switch (handling) { | 509 switch (handling) { |
513 case QuestionMarksForUnencodables: | 510 case QuestionMarksForUnencodables: |
514 ucnv_setSubstChars(m_converterICU, "?", 1, &err); | 511 ucnv_setSubstChars(m_converterICU, "?", 1, &err); |
515 #if !defined(USING_SYSTEM_ICU) | 512 #if !defined(USING_SYSTEM_ICU) |
516 ucnv_setFromUCallBack(m_converterICU, UCNV_FROM_U_CALLBACK_SUBSTITUT
E, 0, 0, 0, &err); | 513 ucnv_setFromUCallBack(m_converterICU, UCNV_FROM_U_CALLBACK_SUBSTITUTE, 0
, 0, 0, &err); |
517 #else | 514 #else |
518 ucnv_setFromUCallBack(m_converterICU, m_needsGBKFallbacks ? gbkCallb
ackSubstitute : UCNV_FROM_U_CALLBACK_SUBSTITUTE, 0, 0, 0, &err); | 515 ucnv_setFromUCallBack(m_converterICU, m_needsGBKFallbacks ? gbkCallbackS
ubstitute : UCNV_FROM_U_CALLBACK_SUBSTITUTE, 0, 0, 0, &err); |
519 #endif | 516 #endif |
520 break; | 517 break; |
521 case EntitiesForUnencodables: | 518 case EntitiesForUnencodables: |
522 #if !defined(USING_SYSTEM_ICU) | 519 #if !defined(USING_SYSTEM_ICU) |
523 ucnv_setFromUCallBack(m_converterICU, UCNV_FROM_U_CALLBACK_ESCAPE, U
CNV_ESCAPE_XML_DEC, 0, 0, &err); | 520 ucnv_setFromUCallBack(m_converterICU, UCNV_FROM_U_CALLBACK_ESCAPE, UCNV_
ESCAPE_XML_DEC, 0, 0, &err); |
524 #else | 521 #else |
525 ucnv_setFromUCallBack(m_converterICU, m_needsGBKFallbacks ? gbkCallb
ackEscape : UCNV_FROM_U_CALLBACK_ESCAPE, UCNV_ESCAPE_XML_DEC, 0, 0, &err); | 522 ucnv_setFromUCallBack(m_converterICU, m_needsGBKFallbacks ? gbkCallbackE
scape : UCNV_FROM_U_CALLBACK_ESCAPE, UCNV_ESCAPE_XML_DEC, 0, 0, &err); |
526 #endif | 523 #endif |
527 break; | 524 break; |
528 case URLEncodedEntitiesForUnencodables: | 525 case URLEncodedEntitiesForUnencodables: |
529 #if !defined(USING_SYSTEM_ICU) | 526 #if !defined(USING_SYSTEM_ICU) |
530 ucnv_setFromUCallBack(m_converterICU, urlEscapedEntityCallback, 0, 0
, 0, &err); | 527 ucnv_setFromUCallBack(m_converterICU, urlEscapedEntityCallback, 0, 0, 0,
&err); |
531 #else | 528 #else |
532 ucnv_setFromUCallBack(m_converterICU, m_needsGBKFallbacks ? gbkUrlEs
capedEntityCallack : urlEscapedEntityCallback, 0, 0, 0, &err); | 529 ucnv_setFromUCallBack(m_converterICU, m_needsGBKFallbacks ? gbkUrlEscape
dEntityCallack : urlEscapedEntityCallback, 0, 0, 0, &err); |
533 #endif | 530 #endif |
534 break; | 531 break; |
535 } | 532 } |
536 | 533 |
537 ASSERT(U_SUCCESS(err)); | 534 ASSERT(U_SUCCESS(err)); |
538 if (U_FAILURE(err)) | 535 if (U_FAILURE(err)) |
539 return CString(); | 536 return CString(); |
540 | 537 |
541 Vector<char> result; | 538 Vector<char> result; |
542 size_t size = 0; | 539 size_t size = 0; |
543 do { | 540 do { |
544 char buffer[ConversionBufferSize]; | 541 char buffer[ConversionBufferSize]; |
(...skipping 29 matching lines...) Expand all Loading... |
574 { | 571 { |
575 return encodeCommon(characters, length, handling); | 572 return encodeCommon(characters, length, handling); |
576 } | 573 } |
577 | 574 |
578 CString TextCodecICU::encode(const LChar* characters, size_t length, Unencodable
Handling handling) | 575 CString TextCodecICU::encode(const LChar* characters, size_t length, Unencodable
Handling handling) |
579 { | 576 { |
580 return encodeCommon(characters, length, handling); | 577 return encodeCommon(characters, length, handling); |
581 } | 578 } |
582 | 579 |
583 } // namespace WTF | 580 } // namespace WTF |
OLD | NEW |