116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood/* 216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * Copyright (C) 2010 The Android Open Source Project 316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * 416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * Licensed under the Apache License, Version 2.0 (the "License"); 516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * you may not use this file except in compliance with the License. 616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * You may obtain a copy of the License at 716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * 816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * http://www.apache.org/licenses/LICENSE-2.0 916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * 1016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * Unless required by applicable law or agreed to in writing, software 1116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * distributed under the License is distributed on an "AS IS" BASIS, 1216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * See the License for the specific language governing permissions and 1416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * limitations under the License. 1516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood */ 1616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 17b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood#define LOG_TAG "MtpStringBuffer" 18b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood 1916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include <string.h> 2016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 2116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include "MtpDataPacket.h" 2216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include "MtpStringBuffer.h" 2316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 247850ef999740f214a1990a9c090d3f3865d435aaMike Lockwoodnamespace android { 2516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 2616864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpStringBuffer::MtpStringBuffer() 2716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood : mCharCount(0), 2816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mByteCount(1) 2916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood{ 3016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mBuffer[0] = 0; 3116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 3216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 3316864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpStringBuffer::MtpStringBuffer(const char* src) 3416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood : mCharCount(0), 3516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mByteCount(1) 3616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood{ 3716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood set(src); 3816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 3916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 40dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike LockwoodMtpStringBuffer::MtpStringBuffer(const uint16_t* src) 41dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood : mCharCount(0), 42dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood mByteCount(1) 43dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood{ 44dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood set(src); 45dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood} 46dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood 4716864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpStringBuffer::MtpStringBuffer(const MtpStringBuffer& src) 4816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood : mCharCount(src.mCharCount), 4916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mByteCount(src.mByteCount) 5016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood{ 5116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood memcpy(mBuffer, src.mBuffer, mByteCount); 5216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 5316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 5416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 5516864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpStringBuffer::~MtpStringBuffer() { 5616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 5716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 5816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodvoid MtpStringBuffer::set(const char* src) { 5916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int length = strlen(src); 6016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (length >= sizeof(mBuffer)) 6116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood length = sizeof(mBuffer) - 1; 6216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood memcpy(mBuffer, src, length); 6316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 6416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // count the characters 6516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int count = 0; 6616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood char ch; 6716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood while ((ch = *src++) != 0) { 6816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if ((ch & 0x80) == 0) { 6916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // single byte character 7016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } else if ((ch & 0xE0) == 0xC0) { 7116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // two byte character 7216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (! *src++) { 7316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // last character was truncated, so ignore last byte 7416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood length--; 7516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 7616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 7716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } else if ((ch & 0xF0) == 0xE0) { 7816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // 3 byte char 7916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (! *src++) { 8016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // last character was truncated, so ignore last byte 8116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood length--; 8216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 8316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 8416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (! *src++) { 8516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // last character was truncated, so ignore last two bytes 8616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood length -= 2; 8716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 8816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 8916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 9016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood count++; 9116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 9216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 9316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mByteCount = length + 1; 9416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mBuffer[length] = 0; 9516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mCharCount = count; 9616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 9716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 98dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwoodvoid MtpStringBuffer::set(const uint16_t* src) { 99dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood int count = 0; 100dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood uint16_t ch; 101dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood uint8_t* dest = mBuffer; 102dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood 103dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood while ((ch = *src++) != 0 && count < 255) { 104dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood if (ch >= 0x0800) { 105dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood *dest++ = (uint8_t)(0xE0 | (ch >> 12)); 106dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood *dest++ = (uint8_t)(0x80 | ((ch >> 6) & 0x3F)); 107dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood *dest++ = (uint8_t)(0x80 | (ch & 0x3F)); 108dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood } else if (ch >= 0x80) { 109dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood *dest++ = (uint8_t)(0xC0 | (ch >> 6)); 110dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood *dest++ = (uint8_t)(0x80 | (ch & 0x3F)); 111dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood } else { 112dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood *dest++ = ch; 113dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood } 114dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood count++; 115dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood } 116dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood *dest++ = 0; 117dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood mCharCount = count; 118dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood mByteCount = dest - mBuffer; 119dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood} 120dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood 12116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodvoid MtpStringBuffer::readFromPacket(MtpDataPacket* packet) { 12216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int count = packet->getUInt8(); 12316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood uint8_t* dest = mBuffer; 12416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood for (int i = 0; i < count; i++) { 12516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood uint16_t ch = packet->getUInt16(); 12616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (ch >= 0x0800) { 12716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood *dest++ = (uint8_t)(0xE0 | (ch >> 12)); 12816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood *dest++ = (uint8_t)(0x80 | ((ch >> 6) & 0x3F)); 12916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood *dest++ = (uint8_t)(0x80 | (ch & 0x3F)); 13016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } else if (ch >= 0x80) { 13116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood *dest++ = (uint8_t)(0xC0 | (ch >> 6)); 13216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood *dest++ = (uint8_t)(0x80 | (ch & 0x3F)); 13316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } else { 13416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood *dest++ = ch; 13516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 13616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 13716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood *dest++ = 0; 13816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mCharCount = count; 13916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mByteCount = dest - mBuffer; 14016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 14116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 14216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodvoid MtpStringBuffer::writeToPacket(MtpDataPacket* packet) const { 14316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int count = mCharCount; 14416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood const uint8_t* src = mBuffer; 145de1e37aad04640ef76f3c017b65adca087c7be0fMike Lockwood packet->putUInt8(count > 0 ? count + 1 : 0); 14616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 14716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // expand utf8 to 16 bit chars 14816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood for (int i = 0; i < count; i++) { 14916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood uint16_t ch; 15016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood uint16_t ch1 = *src++; 15116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if ((ch1 & 0x80) == 0) { 15216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // single byte character 15316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood ch = ch1; 15416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } else if ((ch1 & 0xE0) == 0xC0) { 15516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // two byte character 15616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood uint16_t ch2 = *src++; 15716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood ch = ((ch1 & 0x1F) << 6) | (ch2 & 0x3F); 15816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } else { 15916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // three byte character 16016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood uint16_t ch2 = *src++; 16116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood uint16_t ch3 = *src++; 16216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood ch = ((ch1 & 0x0F) << 12) | ((ch2 & 0x3F) << 6) | (ch3 & 0x3F); 16316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 16416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood packet->putUInt16(ch); 16516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 166de1e37aad04640ef76f3c017b65adca087c7be0fMike Lockwood // only terminate with zero if string is not empty 167de1e37aad04640ef76f3c017b65adca087c7be0fMike Lockwood if (count > 0) 168de1e37aad04640ef76f3c017b65adca087c7be0fMike Lockwood packet->putUInt16(0); 16916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 1707850ef999740f214a1990a9c090d3f3865d435aaMike Lockwood 1717850ef999740f214a1990a9c090d3f3865d435aaMike Lockwood} // namespace android 172