blob: 8bf673194b0316640119b7f1c0039e7371cc2318 [file] [log] [blame]
Mike Lockwood56118b52010-05-11 17:16:59 -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
Mike Lockwood3e6616d2010-06-29 18:11:52 -040017#define LOG_TAG "MtpStringBuffer"
18
Mike Lockwood56118b52010-05-11 17:16:59 -040019#include <string.h>
20
21#include "MtpDataPacket.h"
22#include "MtpStringBuffer.h"
23
Mike Lockwood8d3257a2010-05-14 10:10:36 -040024namespace android {
Mike Lockwood56118b52010-05-11 17:16:59 -040025
26MtpStringBuffer::MtpStringBuffer()
27 : mCharCount(0),
28 mByteCount(1)
29{
30 mBuffer[0] = 0;
31}
32
33MtpStringBuffer::MtpStringBuffer(const char* src)
34 : mCharCount(0),
35 mByteCount(1)
36{
37 set(src);
38}
39
40MtpStringBuffer::MtpStringBuffer(const MtpStringBuffer& src)
41 : mCharCount(src.mCharCount),
42 mByteCount(src.mByteCount)
43{
44 memcpy(mBuffer, src.mBuffer, mByteCount);
45}
46
47
48MtpStringBuffer::~MtpStringBuffer() {
49}
50
51void MtpStringBuffer::set(const char* src) {
52 int length = strlen(src);
53 if (length >= sizeof(mBuffer))
54 length = sizeof(mBuffer) - 1;
55 memcpy(mBuffer, src, length);
56
57 // count the characters
58 int count = 0;
59 char ch;
60 while ((ch = *src++) != 0) {
61 if ((ch & 0x80) == 0) {
62 // single byte character
63 } else if ((ch & 0xE0) == 0xC0) {
64 // two byte character
65 if (! *src++) {
66 // last character was truncated, so ignore last byte
67 length--;
68 break;
69 }
70 } else if ((ch & 0xF0) == 0xE0) {
71 // 3 byte char
72 if (! *src++) {
73 // last character was truncated, so ignore last byte
74 length--;
75 break;
76 }
77 if (! *src++) {
78 // last character was truncated, so ignore last two bytes
79 length -= 2;
80 break;
81 }
82 }
83 count++;
84 }
85
86 mByteCount = length + 1;
87 mBuffer[length] = 0;
88 mCharCount = count;
89}
90
91void MtpStringBuffer::readFromPacket(MtpDataPacket* packet) {
92 int count = packet->getUInt8();
93 uint8_t* dest = mBuffer;
94 for (int i = 0; i < count; i++) {
95 uint16_t ch = packet->getUInt16();
96 if (ch >= 0x0800) {
97 *dest++ = (uint8_t)(0xE0 | (ch >> 12));
98 *dest++ = (uint8_t)(0x80 | ((ch >> 6) & 0x3F));
99 *dest++ = (uint8_t)(0x80 | (ch & 0x3F));
100 } else if (ch >= 0x80) {
101 *dest++ = (uint8_t)(0xC0 | (ch >> 6));
102 *dest++ = (uint8_t)(0x80 | (ch & 0x3F));
103 } else {
104 *dest++ = ch;
105 }
106 }
107 *dest++ = 0;
108 mCharCount = count;
109 mByteCount = dest - mBuffer;
110}
111
112void MtpStringBuffer::writeToPacket(MtpDataPacket* packet) const {
113 int count = mCharCount;
114 const uint8_t* src = mBuffer;
Mike Lockwood9e837862010-08-18 12:31:09 -0400115 packet->putUInt8(count > 0 ? count + 1 : 0);
Mike Lockwood56118b52010-05-11 17:16:59 -0400116
117 // expand utf8 to 16 bit chars
118 for (int i = 0; i < count; i++) {
119 uint16_t ch;
120 uint16_t ch1 = *src++;
121 if ((ch1 & 0x80) == 0) {
122 // single byte character
123 ch = ch1;
124 } else if ((ch1 & 0xE0) == 0xC0) {
125 // two byte character
126 uint16_t ch2 = *src++;
127 ch = ((ch1 & 0x1F) << 6) | (ch2 & 0x3F);
128 } else {
129 // three byte character
130 uint16_t ch2 = *src++;
131 uint16_t ch3 = *src++;
132 ch = ((ch1 & 0x0F) << 12) | ((ch2 & 0x3F) << 6) | (ch3 & 0x3F);
133 }
134 packet->putUInt16(ch);
135 }
Mike Lockwood9e837862010-08-18 12:31:09 -0400136 // only terminate with zero if string is not empty
137 if (count > 0)
138 packet->putUInt16(0);
Mike Lockwood56118b52010-05-11 17:16:59 -0400139}
Mike Lockwood8d3257a2010-05-14 10:10:36 -0400140
141} // namespace android