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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « utilities.h ('k') | utilities_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: utilities.cc
diff --git a/utilities.cc b/utilities.cc
index 6d400f62f49f221b794e2a568d4be8830f0c6787..41f6c78c22c42cade00a1538b9880da313eb1ee9 100644
--- a/utilities.cc
+++ b/utilities.cc
@@ -11,20 +11,23 @@
#include <stdio.h>
#include <stdlib.h>
+#include <iomanip>
+#include <sstream>
+
namespace utilities {
-const char *ExtractString(const DBusPropertyMap properties,
- const char *key,
- const char *not_found_response,
- DBus::Error &error) {
+const char* ExtractString(const DBusPropertyMap properties,
+ const char* key,
+ const char* not_found_response,
+ DBus::Error& error) {
DBusPropertyMap::const_iterator p;
- const char *to_return = not_found_response;
+ const char* to_return = not_found_response;
try {
p = properties.find(key);
if (p != properties.end()) {
to_return = p->second.reader().get_string();
}
- } catch (const DBus::Error &e) {
+ } catch (const DBus::Error& e) {
LOG(ERROR)<<"Bad type for: " << key;
// Setting an already-set error causes an assert fail inside dbus-c++.
if (!error.is_set()) {
@@ -37,9 +40,9 @@ const char *ExtractString(const DBusPropertyMap properties,
}
uint32_t ExtractUint32(const DBusPropertyMap properties,
- const char *key,
+ const char* key,
uint32_t not_found_response,
- DBus::Error &error) {
+ DBus::Error& error) {
DBusPropertyMap::const_iterator p;
unsigned int to_return = not_found_response;
try {
@@ -47,7 +50,7 @@ uint32_t ExtractUint32(const DBusPropertyMap properties,
if (p != properties.end()) {
to_return = p->second.reader().get_uint32();
}
- } catch (const DBus::Error &e) {
+ } catch (const DBus::Error& e) {
LOG(ERROR)<<"Bad type for: " << key;
// Setting an already-set error causes an assert fail inside dbus-c++.
if (!error.is_set()) {
@@ -59,15 +62,15 @@ uint32_t ExtractUint32(const DBusPropertyMap properties,
return to_return;
}
-bool HexEsnToDecimal(const std::string &esn_hex, std::string *out) {
+bool HexEsnToDecimal(const std::string& esn_hex, std::string* out) {
size_t length = esn_hex.length();
if (length > 8) {
LOG(ERROR) << "Long ESN: " << esn_hex;
return false;
}
errno = 0;
- const char *start = esn_hex.c_str();
- char *end;
+ const char* start = esn_hex.c_str();
+ char* end;
uint32_t esn = strtoul(start, &end, 16);
if (errno != 0 || *end != '\0') {
LOG(ERROR) << "Bad ESN: " << esn_hex;
@@ -89,4 +92,210 @@ bool HexEsnToDecimal(const std::string &esn_hex, std::string *out) {
}
return true;
}
+
+#define C(c) {c}
+#define C2(c) {0xc2, c}
+#define C3(c) {0xc3, c}
+#define CE(c) {0xce, c}
+
+static uint8_t Gsm7ToUtf8Map[][3] = {
+ C('@'), C2(0xa3), C('$'), C2(0xa5), C3(0xa8), C3(0xa9), C3(0xb9), C3(0xac),
+ C3(0xb2), C3(0x87), C('\n'), C3(0x98), C3(0xb8), C('\r'), C3(0x85), C3(0xa5),
+ CE(0x94), C('_'), CE(0xa6), CE(0x93), CE(0x9b), CE(0xa9), CE(0xa0), CE(0xa8),
+ CE(0xa3), CE(0x98), CE(0x9e), C(' '), C3(0x86), C3(0xa6), C3(0x9f), C3(0x89),
+ C(' '), C('!'), C('"'), C('#'), C2(0xa4), C('%'), C('&'), C('\''),
+ C('('), C(')'), C('*'), C('+'), C(','), C('-'), C('.'), C('/'),
+ C('0'), C('1'), C('2'), C('3'), C('4'), C('5'), C('6'), C('7'),
+ C('8'), C('9'), C(':'), C(';'), C('<'), C('='), C('>'), C('?'),
+ C2(0xa1), C('A'), C('B'), C('C'), C('D'), C('E'), C('F'), C('G'),
+ C('H'), C('I'), C('J'), C('K'), C('L'), C('M'), C('N'), C('O'),
+ C('P'), C('Q'), C('R'), C('S'), C('T'), C('U'), C('V'), C('W'),
+ C('X'), C('Y'), C('Z'), C3(0x84), C3(0x96), C3(0x91), C3(0x9c), C2(0xa7),
+ C2(0xbf), C('a'), C('b'), C('c'), C('d'), C('e'), C('f'), C('g'),
+ C('h'), C('i'), C('j'), C('k'), C('l'), C('m'), C('n'), C('o'),
+ C('p'), C('q'), C('r'), C('s'), C('t'), C('u'), C('v'), C('w'),
+ C('x'), C('y'), C('z'), C3(0xa4), C3(0xb6), C3(0xb1), C3(0xbc), C3(0xa0)
+};
+
+// 2nd dimension == 5 ensures that all the sub-arrays end with a 0 byte
+static uint8_t ExtGsm7ToUtf8Map[][5] = {
+ {0x0a, 0xc},
+ {0x14, '^'},
+ {0x28, '{'},
+ {0x29, '}'},
+ {0x2f, '\\'},
+ {0x3c, '['},
+ {0x3d, '~'},
+ {0x3e, ']'},
+ {0x40, '|'},
+ {0x65, 0xe2, 0x82, 0xac}
+};
+
+static std::map<std::pair<uint8_t, uint8_t>,char> Utf8ToGsm7Map;
+
+/*
+ * Convert a packed GSM7 encoded string to UTF-8 by first unpacking
+ * the string into septets, then mapping each character to its UTF-8
+ * equivalent.
+ */
+std::string Gsm7ToUtf8String(const uint8_t* gsm7) {
+ size_t datalen = *gsm7++;
+ uint8_t* septets = new uint8_t[datalen];
+ uint8_t saved_bits = 0;
+ size_t written = 0;
+ uint8_t* cp = septets;
+ int i = 0;
+
+ // unpack
+ while (written < datalen) {
+ for (int j = 0; written < datalen && j < 7; j++) {
+ uint8_t octet = gsm7[i];
+ uint8_t mask = 0xff >> (j + 1);
+ uint8_t c = ((octet & mask) << j) | saved_bits;
+ *cp++ = c;
+ ++written;
+ saved_bits = (octet & ~mask) >> (7 - j);
+ ++i;
+ }
+ if (written < datalen) {
+ *cp++ = saved_bits;
+ ++written;
+ }
+ saved_bits = 0;
+ }
+ int nseptets = cp - septets;
+ cp = septets;
+
+ // now map the septets into their corresponding UTF-8 characters
+ std::string str;
+ for (i = 0; i < nseptets; ++i, ++cp) {
+ uint8_t* mp = NULL;
+ if (*cp == 0x1b) {
+ ++cp;
+ for (int k = 0; k < 10; k++) {
+ mp = &ExtGsm7ToUtf8Map[k][0];
+ if (*mp == *cp) {
+ ++mp;
+ ++i;
+ break;
+ }
+ }
+ } else {
+ mp = &Gsm7ToUtf8Map[*cp][0];
+ }
+ if (mp != NULL)
+ while (*mp != '\0')
+ str += *mp++;
+ }
+
+ delete septets;
+ return str;
+}
+
+static void InitializeUtf8ToGsm7Map() {
+ for (int i = 0; i < 128; i++) {
+ Utf8ToGsm7Map[std::pair<uint8_t,uint8_t>(Gsm7ToUtf8Map[i][0],
+ Gsm7ToUtf8Map[i][1])] = i;
+
+ }
+}
+
+std::vector<uint8_t> Utf8StringToGsm7(const std::string& input) {
+ if (Utf8ToGsm7Map.size() == 0)
+ InitializeUtf8ToGsm7Map();
+
+ std::vector<uint8_t> septets;
+ size_t length = input.length();
+ size_t num_septets = 0;
+
+ // First map each UTF-8 character to its GSM7 equivalent.
+ for (size_t i = 0; i < length; i++) {
+ std::pair<uint8_t, uint8_t> chpair;
+ char ch = input.at(i);
+ uint8_t thirdch = 0xff;
+ // Check whether this is a one byte UTF-8 sequence, or the
+ // start of a two or three byte sequence.
+ if ((ch & 0x80) == 0) {
+ chpair.first = ch;
+ chpair.second = 0;
+ } else if ((ch & 0xe0) == 0xc0) {
+ chpair.first = ch;
+ chpair.second = input.at(++i);
+ } else if ((ch & 0xf0) == 0xe0) {
+ chpair.first = ch;
+ chpair.second = input.at(++i);
+ thirdch = input.at(++i);
+ }
+ std::map<std::pair<uint8_t,uint8_t>, char>::iterator it;
+ it = Utf8ToGsm7Map.find(chpair);
+ if (it != Utf8ToGsm7Map.end()) {
+ septets.push_back(it->second);
+ } else {
+ // not found in the map. search the list of extended characters,
+ // but first handle one special case for the 3-byte Euro sign
+ if (chpair.first == 0xe2 && chpair.second == 0x82 && thirdch == 0xac) {
+ septets.push_back(0x1b);
+ septets.push_back(0x65);
+ } else if (chpair.second == 0) {
+ for (int j = 0; j < 9; ++j) {
+ if (ExtGsm7ToUtf8Map[j][1] == chpair.first) {
+ septets.push_back(0x1b);
+ septets.push_back(ExtGsm7ToUtf8Map[j][0]);
+ }
+ }
+ }
+ }
+ // If character wasn't mapped successfully, insert a space
+ if (septets.size() == num_septets)
+ septets.push_back(' ');
+ num_septets = septets.size();
+ }
+
+ // Now pack the septets into octets. The
+ // first byte gives the number of septets.
+ std::vector<uint8_t> octets;
+
+ octets.push_back(num_septets);
+ int shift = 0;
+ for (size_t k = 0; k < num_septets; ++k) {
+ uint8_t septet = septets.at(k);
+ uint8_t octet;
+ if (shift != 7) {
+ octet = (septet >> shift);
+ if (k < num_septets - 1)
+ octet |= septets.at(k+1) << (7-shift);
+ octets.push_back(octet);
+ }
+ if (++shift == 8)
+ shift = 0;
+ }
+
+ return octets;
+}
+
+void DumpHex(const uint8_t* buf, size_t size) {
+ size_t nlines = (size+15) / 16;
+ size_t limit;
+
+ for (size_t i = 0; i < nlines; i++) {
+ std::ostringstream ostr;
+ ostr << std::hex;
+ ostr.fill('0');
+ ostr.width(8);
+ if (i*16 + 16 >= size)
+ limit = size - i*16;
+ else
+ limit = 16;
+ ostr << i*16 << " ";
+ ostr.fill('0');
+ ostr.width(2);
+ for (size_t j = 0; j < limit; j++) {
+ uint8_t byte = buf[i*16+j];
+ ostr << std::setw(0) << " " << std::setw(2) << std::setfill('0')
+ << static_cast<unsigned int>(byte);
+ }
+ LOG(INFO) << ostr.str();
+ }
+}
+
} // namespace utilities
« 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