blob: 26d28f55233720242a46a26b96c715dc725d2ee1 [file] [log] [blame]
[email protected]421de2ab2011-04-13 18:43:051// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]b9f93832009-11-13 19:27:482// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/utf_offset_string_conversions.h"
6
[email protected]421de2ab2011-04-13 18:43:057#include <algorithm>
8
[email protected]e57a7162011-06-15 04:14:239#include "base/memory/scoped_ptr.h"
[email protected]b9f93832009-11-13 19:27:4810#include "base/string_piece.h"
11#include "base/utf_string_conversion_utils.h"
12
13using base::PrepareForUTF16Or32Output;
14using base::ReadUnicodeCharacter;
15using base::WriteUnicodeCharacter;
16
[email protected]b9f93832009-11-13 19:27:4817// Converts the given source Unicode character type to the given destination
18// Unicode character type as a STL string. The given input buffer and size
19// determine the source, and the given output STL string will be replaced by
20// the result.
[email protected]04866c42011-05-03 20:03:5021bool ConvertUnicode(const char* src,
[email protected]b9f93832009-11-13 19:27:4822 size_t src_len,
[email protected]04866c42011-05-03 20:03:5023 string16* output,
[email protected]421de2ab2011-04-13 18:43:0524 std::vector<size_t>* offsets_for_adjustment) {
25 if (offsets_for_adjustment) {
26 std::for_each(offsets_for_adjustment->begin(),
27 offsets_for_adjustment->end(),
[email protected]04866c42011-05-03 20:03:5028 LimitOffset<string16>(src_len));
[email protected]421de2ab2011-04-13 18:43:0529 }
[email protected]b9f93832009-11-13 19:27:4830
31 // ICU requires 32-bit numbers.
32 bool success = true;
[email protected]04866c42011-05-03 20:03:5033 OffsetAdjuster offset_adjuster(offsets_for_adjustment);
[email protected]b9f93832009-11-13 19:27:4834 int32 src_len32 = static_cast<int32>(src_len);
35 for (int32 i = 0; i < src_len32; i++) {
36 uint32 code_point;
37 size_t original_i = i;
38 size_t chars_written = 0;
39 if (ReadUnicodeCharacter(src, src_len32, &i, &code_point)) {
40 chars_written = WriteUnicodeCharacter(code_point, output);
41 } else {
[email protected]d7a3e8e2010-01-01 22:16:3842 chars_written = WriteUnicodeCharacter(0xFFFD, output);
[email protected]b9f93832009-11-13 19:27:4843 success = false;
44 }
[email protected]421de2ab2011-04-13 18:43:0545 if (offsets_for_adjustment) {
[email protected]b9f93832009-11-13 19:27:4846 // NOTE: ReadUnicodeCharacter() adjusts |i| to point _at_ the last
47 // character read, not after it (so that incrementing it in the loop
48 // increment will place it at the right location), so we need to account
49 // for that in determining the amount that was read.
[email protected]04866c42011-05-03 20:03:5050 offset_adjuster.Add(OffsetAdjuster::Adjustment(original_i,
51 i - original_i + 1, chars_written));
[email protected]b9f93832009-11-13 19:27:4852 }
53 }
[email protected]b9f93832009-11-13 19:27:4854 return success;
55}
56
[email protected]04866c42011-05-03 20:03:5057bool UTF8ToUTF16AndAdjustOffset(const char* src,
58 size_t src_len,
59 string16* output,
60 size_t* offset_for_adjustment) {
[email protected]421de2ab2011-04-13 18:43:0561 std::vector<size_t> offsets;
62 if (offset_for_adjustment)
63 offsets.push_back(*offset_for_adjustment);
[email protected]b9f93832009-11-13 19:27:4864 PrepareForUTF16Or32Output(src, src_len, output);
[email protected]421de2ab2011-04-13 18:43:0565 bool ret = ConvertUnicode(src, src_len, output, &offsets);
66 if (offset_for_adjustment)
67 *offset_for_adjustment = offsets[0];
68 return ret;
69}
70
[email protected]04866c42011-05-03 20:03:5071bool UTF8ToUTF16AndAdjustOffsets(const char* src,
72 size_t src_len,
73 string16* output,
74 std::vector<size_t>* offsets_for_adjustment) {
[email protected]421de2ab2011-04-13 18:43:0575 PrepareForUTF16Or32Output(src, src_len, output);
76 return ConvertUnicode(src, src_len, output, offsets_for_adjustment);
[email protected]b9f93832009-11-13 19:27:4877}
78
[email protected]04866c42011-05-03 20:03:5079string16 UTF8ToUTF16AndAdjustOffset(const base::StringPiece& utf8,
[email protected]b9f93832009-11-13 19:27:4880 size_t* offset_for_adjustment) {
[email protected]421de2ab2011-04-13 18:43:0581 std::vector<size_t> offsets;
82 if (offset_for_adjustment)
83 offsets.push_back(*offset_for_adjustment);
[email protected]04866c42011-05-03 20:03:5084 string16 result;
85 UTF8ToUTF16AndAdjustOffsets(utf8.data(), utf8.length(), &result,
[email protected]421de2ab2011-04-13 18:43:0586 &offsets);
87 if (offset_for_adjustment)
88 *offset_for_adjustment = offsets[0];
89 return result;
90}
91
[email protected]04866c42011-05-03 20:03:5092string16 UTF8ToUTF16AndAdjustOffsets(
93 const base::StringPiece& utf8,
[email protected]421de2ab2011-04-13 18:43:0594 std::vector<size_t>* offsets_for_adjustment) {
[email protected]04866c42011-05-03 20:03:5095 string16 result;
96 UTF8ToUTF16AndAdjustOffsets(utf8.data(), utf8.length(), &result,
[email protected]421de2ab2011-04-13 18:43:0597 offsets_for_adjustment);
98 return result;
[email protected]b9f93832009-11-13 19:27:4899}
100
[email protected]04866c42011-05-03 20:03:50101OffsetAdjuster::Adjustment::Adjustment(size_t original_offset,
102 size_t original_length,
103 size_t output_length)
104 : original_offset(original_offset),
105 original_length(original_length),
106 output_length(output_length) {
107}
[email protected]421de2ab2011-04-13 18:43:05108
[email protected]04866c42011-05-03 20:03:50109OffsetAdjuster::OffsetAdjuster(std::vector<size_t>* offsets_for_adjustment)
110 : offsets_for_adjustment_(offsets_for_adjustment) {
111}
[email protected]421de2ab2011-04-13 18:43:05112
[email protected]04866c42011-05-03 20:03:50113OffsetAdjuster::~OffsetAdjuster() {
114 if (!offsets_for_adjustment_ || adjustments_.empty())
115 return;
116 for (std::vector<size_t>::iterator i(offsets_for_adjustment_->begin());
117 i != offsets_for_adjustment_->end(); ++i)
118 AdjustOffset(i);
119}
[email protected]421de2ab2011-04-13 18:43:05120
[email protected]04866c42011-05-03 20:03:50121void OffsetAdjuster::Add(const Adjustment& adjustment) {
122 adjustments_.push_back(adjustment);
123}
124
125void OffsetAdjuster::AdjustOffset(std::vector<size_t>::iterator offset) {
126 if (*offset == string16::npos)
[email protected]421de2ab2011-04-13 18:43:05127 return;
128 size_t adjustment = 0;
[email protected]04866c42011-05-03 20:03:50129 for (std::vector<Adjustment>::const_iterator i = adjustments_.begin();
[email protected]421de2ab2011-04-13 18:43:05130 i != adjustments_.end(); ++i) {
[email protected]04866c42011-05-03 20:03:50131 if (*offset == i->original_offset && i->output_length == 0) {
132 *offset = string16::npos;
[email protected]421de2ab2011-04-13 18:43:05133 return;
134 }
[email protected]04866c42011-05-03 20:03:50135 if (*offset <= i->original_offset)
[email protected]421de2ab2011-04-13 18:43:05136 break;
[email protected]04866c42011-05-03 20:03:50137 if (*offset < (i->original_offset + i->original_length)) {
138 *offset = string16::npos;
[email protected]421de2ab2011-04-13 18:43:05139 return;
140 }
[email protected]04866c42011-05-03 20:03:50141 adjustment += (i->original_length - i->output_length);
[email protected]421de2ab2011-04-13 18:43:05142 }
[email protected]04866c42011-05-03 20:03:50143 *offset -= adjustment;
[email protected]421de2ab2011-04-13 18:43:05144}