blob: cc7e2629db5339a48c8f6e4ed1ea79920a8b09a5 [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -08001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Elliott Hughes814e4032011-08-23 12:07:56 -070016
17#include "utf.h"
18
Elliott Hughes07ed66b2012-12-12 18:34:25 -080019#include "base/logging.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080020#include "mirror/array.h"
Elliott Hughesb465ab02011-08-24 11:21:21 -070021
Elliott Hughes814e4032011-08-23 12:07:56 -070022namespace art {
23
24size_t CountModifiedUtf8Chars(const char* utf8) {
25 size_t len = 0;
26 int ic;
27 while ((ic = *utf8++) != '\0') {
28 len++;
29 if ((ic & 0x80) == 0) {
30 // one-byte encoding
31 continue;
32 }
33 // two- or three-byte encoding
34 utf8++;
35 if ((ic & 0x20) == 0) {
36 // two-byte encoding
37 continue;
38 }
39 // three-byte encoding
40 utf8++;
41 }
42 return len;
43}
44
45void ConvertModifiedUtf8ToUtf16(uint16_t* utf16_data_out, const char* utf8_data_in) {
46 while (*utf8_data_in != '\0') {
47 *utf16_data_out++ = GetUtf16FromUtf8(&utf8_data_in);
48 }
49}
50
Elliott Hughesb465ab02011-08-24 11:21:21 -070051void ConvertUtf16ToModifiedUtf8(char* utf8_out, const uint16_t* utf16_in, size_t char_count) {
52 while (char_count--) {
53 uint16_t ch = *utf16_in++;
54 if (ch > 0 && ch <= 0x7f) {
55 *utf8_out++ = ch;
56 } else {
57 if (ch > 0x07ff) {
58 *utf8_out++ = (ch >> 12) | 0xe0;
59 *utf8_out++ = ((ch >> 6) & 0x3f) | 0x80;
60 *utf8_out++ = (ch & 0x3f) | 0x80;
61 } else /*(ch > 0x7f || ch == 0)*/ {
62 *utf8_out++ = (ch >> 6) | 0xc0;
63 *utf8_out++ = (ch & 0x3f) | 0x80;
64 }
65 }
66 }
67}
68
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080069int32_t ComputeUtf16Hash(const mirror::CharArray* chars, int32_t offset,
Ian Rogers0cfe1fb2011-08-26 03:29:44 -070070 size_t char_count) {
71 int32_t hash = 0;
72 for (size_t i = 0; i < char_count; i++) {
73 hash = hash * 31 + chars->Get(offset + i);
74 }
75 return hash;
76}
77
Elliott Hughes814e4032011-08-23 12:07:56 -070078int32_t ComputeUtf16Hash(const uint16_t* chars, size_t char_count) {
79 int32_t hash = 0;
80 while (char_count--) {
81 hash = hash * 31 + *chars++;
82 }
83 return hash;
84}
85
Ian Rogers0cfe1fb2011-08-26 03:29:44 -070086
Elliott Hughes814e4032011-08-23 12:07:56 -070087uint16_t GetUtf16FromUtf8(const char** utf8_data_in) {
88 uint8_t one = *(*utf8_data_in)++;
89 if ((one & 0x80) == 0) {
90 // one-byte encoding
91 return one;
92 }
93 // two- or three-byte encoding
94 uint8_t two = *(*utf8_data_in)++;
95 if ((one & 0x20) == 0) {
96 // two-byte encoding
97 return ((one & 0x1f) << 6) | (two & 0x3f);
98 }
99 // three-byte encoding
100 uint8_t three = *(*utf8_data_in)++;
101 return ((one & 0x0f) << 12) | ((two & 0x3f) << 6) | (three & 0x3f);
102}
103
Ian Rogers0571d352011-11-03 19:51:38 -0700104int CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(const char* utf8_1, const char* utf8_2) {
105 for (;;) {
jeffhao10037c82012-01-23 15:06:23 -0800106 if (*utf8_1 == '\0') {
107 return (*utf8_2 == '\0') ? 0 : -1;
108 } else if (*utf8_2 == '\0') {
Ian Rogers0571d352011-11-03 19:51:38 -0700109 return 1;
jeffhao10037c82012-01-23 15:06:23 -0800110 }
111
112 int c1 = GetUtf16FromUtf8(&utf8_1);
113 int c2 = GetUtf16FromUtf8(&utf8_2);
114
115 if (c1 != c2) {
Ian Rogers0571d352011-11-03 19:51:38 -0700116 return c1 > c2 ? 1 : -1;
117 }
118 }
119}
120
Elliott Hughes814e4032011-08-23 12:07:56 -0700121size_t CountUtf8Bytes(const uint16_t* chars, size_t char_count) {
122 size_t result = 0;
123 while (char_count--) {
124 uint16_t ch = *chars++;
125 if (ch > 0 && ch <= 0x7f) {
126 ++result;
127 } else {
128 if (ch > 0x7ff) {
129 result += 3;
130 } else {
131 result += 2;
132 }
133 }
134 }
135 return result;
136}
137
138} // namespace art