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