blob: 8aeb3ca949b30b9fb22be90771c52ffe59f8991e [file] [log] [blame]
bigbiff bigbiffc7eee6f2014-09-02 18:59:01 -04001/*
2 * Copyright (C) 2010 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 *
16 * Copyright (C) 2014 TeamWin - bigbiff and Dees_Troy mtp database conversion to C++
17 */
18
19#include <string.h>
20#include "MtpDataPacket.h"
21#include "MtpStringBuffer.h"
22
23MtpStringBuffer::MtpStringBuffer()
24 : mCharCount(0),
25 mByteCount(1)
26{
27 mBuffer[0] = 0;
28}
29
30MtpStringBuffer::MtpStringBuffer(const char* src)
31 : mCharCount(0),
32 mByteCount(1)
33{
34 set(src);
35}
36
37MtpStringBuffer::MtpStringBuffer(const uint16_t* src)
38 : mCharCount(0),
39 mByteCount(1)
40{
41 set(src);
42}
43
44MtpStringBuffer::MtpStringBuffer(const MtpStringBuffer& src)
45 : mCharCount(src.mCharCount),
46 mByteCount(src.mByteCount)
47{
48 memcpy(mBuffer, src.mBuffer, mByteCount);
49}
50
51
52MtpStringBuffer::~MtpStringBuffer() {
53}
54
55void MtpStringBuffer::set(const char* src) {
56 size_t length = strlen(src);
57 if (length >= sizeof(mBuffer))
58 length = sizeof(mBuffer) - 1;
59 memcpy(mBuffer, src, length);
60
61 // count the characters
62 int count = 0;
63 char ch;
64 while ((ch = *src++) != 0) {
65 if ((ch & 0x80) == 0) {
66 // single byte character
67 } else if ((ch & 0xE0) == 0xC0) {
68 // two byte character
69 if (! *src++) {
70 // last character was truncated, so ignore last byte
71 length--;
72 break;
73 }
74 } else if ((ch & 0xF0) == 0xE0) {
75 // 3 byte char
76 if (! *src++) {
77 // last character was truncated, so ignore last byte
78 length--;
79 break;
80 }
81 if (! *src++) {
82 // last character was truncated, so ignore last two bytes
83 length -= 2;
84 break;
85 }
86 }
87 count++;
88 }
89
90 mByteCount = length + 1;
91 mBuffer[length] = 0;
92 mCharCount = count;
93}
94
95void MtpStringBuffer::set(const uint16_t* src) {
96 int count = 0;
97 uint16_t ch;
98 uint8_t* dest = mBuffer;
99
100 while ((ch = *src++) != 0 && count < 255) {
101 if (ch >= 0x0800) {
102 *dest++ = (uint8_t)(0xE0 | (ch >> 12));
103 *dest++ = (uint8_t)(0x80 | ((ch >> 6) & 0x3F));
104 *dest++ = (uint8_t)(0x80 | (ch & 0x3F));
105 } else if (ch >= 0x80) {
106 *dest++ = (uint8_t)(0xC0 | (ch >> 6));
107 *dest++ = (uint8_t)(0x80 | (ch & 0x3F));
108 } else {
109 *dest++ = ch;
110 }
111 count++;
112 }
113 *dest++ = 0;
114 mCharCount = count;
115 mByteCount = dest - mBuffer;
116}
117
118void MtpStringBuffer::readFromPacket(MtpDataPacket* packet) {
119 int count = packet->getUInt8();
120 uint8_t* dest = mBuffer;
121 for (int i = 0; i < count; i++) {
122 uint16_t ch = packet->getUInt16();
123 if (ch >= 0x0800) {
124 *dest++ = (uint8_t)(0xE0 | (ch >> 12));
125 *dest++ = (uint8_t)(0x80 | ((ch >> 6) & 0x3F));
126 *dest++ = (uint8_t)(0x80 | (ch & 0x3F));
127 } else if (ch >= 0x80) {
128 *dest++ = (uint8_t)(0xC0 | (ch >> 6));
129 *dest++ = (uint8_t)(0x80 | (ch & 0x3F));
130 } else {
131 *dest++ = ch;
132 }
133 }
134 *dest++ = 0;
135 mCharCount = count;
136 mByteCount = dest - mBuffer;
137}
138
139void MtpStringBuffer::writeToPacket(MtpDataPacket* packet) const {
140 int count = mCharCount;
141 const uint8_t* src = mBuffer;
142 packet->putUInt8(count > 0 ? count + 1 : 0);
143
144 // expand utf8 to 16 bit chars
145 for (int i = 0; i < count; i++) {
146 uint16_t ch;
147 uint16_t ch1 = *src++;
148 if ((ch1 & 0x80) == 0) {
149 // single byte character
150 ch = ch1;
151 } else if ((ch1 & 0xE0) == 0xC0) {
152 // two byte character
153 uint16_t ch2 = *src++;
154 ch = ((ch1 & 0x1F) << 6) | (ch2 & 0x3F);
155 } else {
156 // three byte character
157 uint16_t ch2 = *src++;
158 uint16_t ch3 = *src++;
159 ch = ((ch1 & 0x0F) << 12) | ((ch2 & 0x3F) << 6) | (ch3 & 0x3F);
160 }
161 packet->putUInt16(ch);
162 }
163 // only terminate with zero if string is not empty
164 if (count > 0)
165 packet->putUInt16(0);
166}
167