Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(75)

Side by Side Diff: utilities.cc

Issue 6612044: Added an SmsMessage class, and code for parsing a PDU to an SMS message. (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/cromo.git@master
Patch Set: Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « utilities.h ('k') | utilities_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // Plugin tests link against this file, but not against the rest of 5 // Plugin tests link against this file, but not against the rest of
6 // cromo. Therefore this file should not have dependencies on the 6 // cromo. Therefore this file should not have dependencies on the
7 // rest of cromo. 7 // rest of cromo.
8 #include "utilities.h" 8 #include "utilities.h"
9 9
10 #include <glog/logging.h> 10 #include <glog/logging.h>
11 #include <stdio.h> 11 #include <stdio.h>
12 #include <stdlib.h> 12 #include <stdlib.h>
13 13
14 #include <iomanip>
15 #include <sstream>
16
14 namespace utilities { 17 namespace utilities {
15 18
16 const char *ExtractString(const DBusPropertyMap properties, 19 const char* ExtractString(const DBusPropertyMap properties,
17 const char *key, 20 const char* key,
18 const char *not_found_response, 21 const char* not_found_response,
19 DBus::Error &error) { 22 DBus::Error& error) {
20 DBusPropertyMap::const_iterator p; 23 DBusPropertyMap::const_iterator p;
21 const char *to_return = not_found_response; 24 const char* to_return = not_found_response;
22 try { 25 try {
23 p = properties.find(key); 26 p = properties.find(key);
24 if (p != properties.end()) { 27 if (p != properties.end()) {
25 to_return = p->second.reader().get_string(); 28 to_return = p->second.reader().get_string();
26 } 29 }
27 } catch (const DBus::Error &e) { 30 } catch (const DBus::Error& e) {
28 LOG(ERROR)<<"Bad type for: " << key; 31 LOG(ERROR)<<"Bad type for: " << key;
29 // Setting an already-set error causes an assert fail inside dbus-c++. 32 // Setting an already-set error causes an assert fail inside dbus-c++.
30 if (!error.is_set()) { 33 if (!error.is_set()) {
31 // NB: the copy constructor for DBus::Error causes a template to 34 // NB: the copy constructor for DBus::Error causes a template to
32 // be instantiated that kills our -Werror build 35 // be instantiated that kills our -Werror build
33 error.set(e.name(), e.message()); 36 error.set(e.name(), e.message());
34 } 37 }
35 } 38 }
36 return to_return; 39 return to_return;
37 } 40 }
38 41
39 uint32_t ExtractUint32(const DBusPropertyMap properties, 42 uint32_t ExtractUint32(const DBusPropertyMap properties,
40 const char *key, 43 const char* key,
41 uint32_t not_found_response, 44 uint32_t not_found_response,
42 DBus::Error &error) { 45 DBus::Error& error) {
43 DBusPropertyMap::const_iterator p; 46 DBusPropertyMap::const_iterator p;
44 unsigned int to_return = not_found_response; 47 unsigned int to_return = not_found_response;
45 try { 48 try {
46 p = properties.find(key); 49 p = properties.find(key);
47 if (p != properties.end()) { 50 if (p != properties.end()) {
48 to_return = p->second.reader().get_uint32(); 51 to_return = p->second.reader().get_uint32();
49 } 52 }
50 } catch (const DBus::Error &e) { 53 } catch (const DBus::Error& e) {
51 LOG(ERROR)<<"Bad type for: " << key; 54 LOG(ERROR)<<"Bad type for: " << key;
52 // Setting an already-set error causes an assert fail inside dbus-c++. 55 // Setting an already-set error causes an assert fail inside dbus-c++.
53 if (!error.is_set()) { 56 if (!error.is_set()) {
54 // NB: the copy constructor for DBus::Error causes a template to 57 // NB: the copy constructor for DBus::Error causes a template to
55 // be instantiated that kills our -Werror build 58 // be instantiated that kills our -Werror build
56 error.set(e.name(), e.message()); 59 error.set(e.name(), e.message());
57 } 60 }
58 } 61 }
59 return to_return; 62 return to_return;
60 } 63 }
61 64
62 bool HexEsnToDecimal(const std::string &esn_hex, std::string *out) { 65 bool HexEsnToDecimal(const std::string& esn_hex, std::string* out) {
63 size_t length = esn_hex.length(); 66 size_t length = esn_hex.length();
64 if (length > 8) { 67 if (length > 8) {
65 LOG(ERROR) << "Long ESN: " << esn_hex; 68 LOG(ERROR) << "Long ESN: " << esn_hex;
66 return false; 69 return false;
67 } 70 }
68 errno = 0; 71 errno = 0;
69 const char *start = esn_hex.c_str(); 72 const char* start = esn_hex.c_str();
70 char *end; 73 char* end;
71 uint32_t esn = strtoul(start, &end, 16); 74 uint32_t esn = strtoul(start, &end, 16);
72 if (errno != 0 || *end != '\0') { 75 if (errno != 0 || *end != '\0') {
73 LOG(ERROR) << "Bad ESN: " << esn_hex; 76 LOG(ERROR) << "Bad ESN: " << esn_hex;
74 return false; 77 return false;
75 } 78 }
76 uint32_t mfr = (esn >> 24) & 0xff; 79 uint32_t mfr = (esn >> 24) & 0xff;
77 uint32_t serial = esn & 0x00ffffff; 80 uint32_t serial = esn & 0x00ffffff;
78 81
79 // Decimal ESN is 11 chars 82 // Decimal ESN is 11 chars
80 char decimal[12]; 83 char decimal[12];
81 memset(decimal, '\0', sizeof(decimal)); 84 memset(decimal, '\0', sizeof(decimal));
82 int rc = snprintf(decimal, sizeof(decimal), "%03d%08d", mfr, serial); 85 int rc = snprintf(decimal, sizeof(decimal), "%03d%08d", mfr, serial);
83 if (rc != 11) { 86 if (rc != 11) {
84 LOG(ERROR) << "Format failure"; 87 LOG(ERROR) << "Format failure";
85 return false; 88 return false;
86 } 89 }
87 if (out) { 90 if (out) {
88 *out = decimal; 91 *out = decimal;
89 } 92 }
90 return true; 93 return true;
91 } 94 }
95
96 #define C(c) {c}
97 #define C2(c) {0xc2, c}
98 #define C3(c) {0xc3, c}
99 #define CE(c) {0xce, c}
100
101 static uint8_t Gsm7ToUtf8Map[][3] = {
102 C('@'), C2(0xa3), C('$'), C2(0xa5), C3(0xa8), C3(0xa9), C3(0xb9), C3(0xac),
103 C3(0xb2), C3(0x87), C('\n'), C3(0x98), C3(0xb8), C('\r'), C3(0x85), C3(0xa5),
104 CE(0x94), C('_'), CE(0xa6), CE(0x93), CE(0x9b), CE(0xa9), CE(0xa0), CE(0xa8),
105 CE(0xa3), CE(0x98), CE(0x9e), C(' '), C3(0x86), C3(0xa6), C3(0x9f), C3(0x89),
106 C(' '), C('!'), C('"'), C('#'), C2(0xa4), C('%'), C('&'), C('\''),
107 C('('), C(')'), C('*'), C('+'), C(','), C('-'), C('.'), C('/'),
108 C('0'), C('1'), C('2'), C('3'), C('4'), C('5'), C('6'), C('7'),
109 C('8'), C('9'), C(':'), C(';'), C('<'), C('='), C('>'), C('?'),
110 C2(0xa1), C('A'), C('B'), C('C'), C('D'), C('E'), C('F'), C('G'),
111 C('H'), C('I'), C('J'), C('K'), C('L'), C('M'), C('N'), C('O'),
112 C('P'), C('Q'), C('R'), C('S'), C('T'), C('U'), C('V'), C('W'),
113 C('X'), C('Y'), C('Z'), C3(0x84), C3(0x96), C3(0x91), C3(0x9c), C2(0xa7),
114 C2(0xbf), C('a'), C('b'), C('c'), C('d'), C('e'), C('f'), C('g'),
115 C('h'), C('i'), C('j'), C('k'), C('l'), C('m'), C('n'), C('o'),
116 C('p'), C('q'), C('r'), C('s'), C('t'), C('u'), C('v'), C('w'),
117 C('x'), C('y'), C('z'), C3(0xa4), C3(0xb6), C3(0xb1), C3(0xbc), C3(0xa0)
118 };
119
120 // 2nd dimension == 5 ensures that all the sub-arrays end with a 0 byte
121 static uint8_t ExtGsm7ToUtf8Map[][5] = {
122 {0x0a, 0xc},
123 {0x14, '^'},
124 {0x28, '{'},
125 {0x29, '}'},
126 {0x2f, '\\'},
127 {0x3c, '['},
128 {0x3d, '~'},
129 {0x3e, ']'},
130 {0x40, '|'},
131 {0x65, 0xe2, 0x82, 0xac}
132 };
133
134 static std::map<std::pair<uint8_t, uint8_t>,char> Utf8ToGsm7Map;
135
136 /*
137 * Convert a packed GSM7 encoded string to UTF-8 by first unpacking
138 * the string into septets, then mapping each character to its UTF-8
139 * equivalent.
140 */
141 std::string Gsm7ToUtf8String(const uint8_t* gsm7) {
142 size_t datalen = *gsm7++;
143 uint8_t* septets = new uint8_t[datalen];
144 uint8_t saved_bits = 0;
145 size_t written = 0;
146 uint8_t* cp = septets;
147 int i = 0;
148
149 // unpack
150 while (written < datalen) {
151 for (int j = 0; written < datalen && j < 7; j++) {
152 uint8_t octet = gsm7[i];
153 uint8_t mask = 0xff >> (j + 1);
154 uint8_t c = ((octet & mask) << j) | saved_bits;
155 *cp++ = c;
156 ++written;
157 saved_bits = (octet & ~mask) >> (7 - j);
158 ++i;
159 }
160 if (written < datalen) {
161 *cp++ = saved_bits;
162 ++written;
163 }
164 saved_bits = 0;
165 }
166 int nseptets = cp - septets;
167 cp = septets;
168
169 // now map the septets into their corresponding UTF-8 characters
170 std::string str;
171 for (i = 0; i < nseptets; ++i, ++cp) {
172 uint8_t* mp = NULL;
173 if (*cp == 0x1b) {
174 ++cp;
175 for (int k = 0; k < 10; k++) {
176 mp = &ExtGsm7ToUtf8Map[k][0];
177 if (*mp == *cp) {
178 ++mp;
179 ++i;
180 break;
181 }
182 }
183 } else {
184 mp = &Gsm7ToUtf8Map[*cp][0];
185 }
186 if (mp != NULL)
187 while (*mp != '\0')
188 str += *mp++;
189 }
190
191 delete septets;
192 return str;
193 }
194
195 static void InitializeUtf8ToGsm7Map() {
196 for (int i = 0; i < 128; i++) {
197 Utf8ToGsm7Map[std::pair<uint8_t,uint8_t>(Gsm7ToUtf8Map[i][0],
198 Gsm7ToUtf8Map[i][1])] = i;
199
200 }
201 }
202
203 std::vector<uint8_t> Utf8StringToGsm7(const std::string& input) {
204 if (Utf8ToGsm7Map.size() == 0)
205 InitializeUtf8ToGsm7Map();
206
207 std::vector<uint8_t> septets;
208 size_t length = input.length();
209 size_t num_septets = 0;
210
211 // First map each UTF-8 character to its GSM7 equivalent.
212 for (size_t i = 0; i < length; i++) {
213 std::pair<uint8_t, uint8_t> chpair;
214 char ch = input.at(i);
215 uint8_t thirdch = 0xff;
216 // Check whether this is a one byte UTF-8 sequence, or the
217 // start of a two or three byte sequence.
218 if ((ch & 0x80) == 0) {
219 chpair.first = ch;
220 chpair.second = 0;
221 } else if ((ch & 0xe0) == 0xc0) {
222 chpair.first = ch;
223 chpair.second = input.at(++i);
224 } else if ((ch & 0xf0) == 0xe0) {
225 chpair.first = ch;
226 chpair.second = input.at(++i);
227 thirdch = input.at(++i);
228 }
229 std::map<std::pair<uint8_t,uint8_t>, char>::iterator it;
230 it = Utf8ToGsm7Map.find(chpair);
231 if (it != Utf8ToGsm7Map.end()) {
232 septets.push_back(it->second);
233 } else {
234 // not found in the map. search the list of extended characters,
235 // but first handle one special case for the 3-byte Euro sign
236 if (chpair.first == 0xe2 && chpair.second == 0x82 && thirdch == 0xac) {
237 septets.push_back(0x1b);
238 septets.push_back(0x65);
239 } else if (chpair.second == 0) {
240 for (int j = 0; j < 9; ++j) {
241 if (ExtGsm7ToUtf8Map[j][1] == chpair.first) {
242 septets.push_back(0x1b);
243 septets.push_back(ExtGsm7ToUtf8Map[j][0]);
244 }
245 }
246 }
247 }
248 // If character wasn't mapped successfully, insert a space
249 if (septets.size() == num_septets)
250 septets.push_back(' ');
251 num_septets = septets.size();
252 }
253
254 // Now pack the septets into octets. The
255 // first byte gives the number of septets.
256 std::vector<uint8_t> octets;
257
258 octets.push_back(num_septets);
259 int shift = 0;
260 for (size_t k = 0; k < num_septets; ++k) {
261 uint8_t septet = septets.at(k);
262 uint8_t octet;
263 if (shift != 7) {
264 octet = (septet >> shift);
265 if (k < num_septets - 1)
266 octet |= septets.at(k+1) << (7-shift);
267 octets.push_back(octet);
268 }
269 if (++shift == 8)
270 shift = 0;
271 }
272
273 return octets;
274 }
275
276 void DumpHex(const uint8_t* buf, size_t size) {
277 size_t nlines = (size+15) / 16;
278 size_t limit;
279
280 for (size_t i = 0; i < nlines; i++) {
281 std::ostringstream ostr;
282 ostr << std::hex;
283 ostr.fill('0');
284 ostr.width(8);
285 if (i*16 + 16 >= size)
286 limit = size - i*16;
287 else
288 limit = 16;
289 ostr << i*16 << " ";
290 ostr.fill('0');
291 ostr.width(2);
292 for (size_t j = 0; j < limit; j++) {
293 uint8_t byte = buf[i*16+j];
294 ostr << std::setw(0) << " " << std::setw(2) << std::setfill('0')
295 << static_cast<unsigned int>(byte);
296 }
297 LOG(INFO) << ostr.str();
298 }
299 }
300
92 } // namespace utilities 301 } // namespace utilities
OLDNEW
« no previous file with comments | « utilities.h ('k') | utilities_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698