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