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