MtpStringBuffer.cpp revision b14e588bec4d5e39e61b020b5b575f2ce555d316
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 24namespace android { 25 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; 115 packet->putUInt8(count); 116 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 } 136} 137 138} // namespace android 139