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 // count the characters 6016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int count = 0; 6116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood char ch; 62014897f5aece2c6212418934bd4618326979f17aYin Liu char* dest = (char*)mBuffer; 63014897f5aece2c6212418934bd4618326979f17aYin Liu 64014897f5aece2c6212418934bd4618326979f17aYin Liu while ((ch = *src++) != 0 && count < MTP_STRING_MAX_CHARACTER_NUMBER) { 6516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if ((ch & 0x80) == 0) { 6616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // single byte character 67014897f5aece2c6212418934bd4618326979f17aYin Liu *dest++ = ch; 6816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } else if ((ch & 0xE0) == 0xC0) { 6916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // two byte character 70014897f5aece2c6212418934bd4618326979f17aYin Liu char ch1 = *src++; 71014897f5aece2c6212418934bd4618326979f17aYin Liu if (! ch1) { 7216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // last character was truncated, so ignore last byte 7316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 7416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 75014897f5aece2c6212418934bd4618326979f17aYin Liu 76014897f5aece2c6212418934bd4618326979f17aYin Liu *dest++ = ch; 77014897f5aece2c6212418934bd4618326979f17aYin Liu *dest++ = ch1; 7816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } else if ((ch & 0xF0) == 0xE0) { 7916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // 3 byte char 80014897f5aece2c6212418934bd4618326979f17aYin Liu char ch1 = *src++; 81014897f5aece2c6212418934bd4618326979f17aYin Liu if (! ch1) { 8216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // last character was truncated, so ignore last byte 8316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 8416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 85014897f5aece2c6212418934bd4618326979f17aYin Liu char ch2 = *src++; 86014897f5aece2c6212418934bd4618326979f17aYin Liu if (! ch2) { 87014897f5aece2c6212418934bd4618326979f17aYin Liu // last character was truncated, so ignore last byte 8816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 8916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 90014897f5aece2c6212418934bd4618326979f17aYin Liu 91014897f5aece2c6212418934bd4618326979f17aYin Liu *dest++ = ch; 92014897f5aece2c6212418934bd4618326979f17aYin Liu *dest++ = ch1; 93014897f5aece2c6212418934bd4618326979f17aYin Liu *dest++ = ch2; 9416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 9516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood count++; 9616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 9716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 98014897f5aece2c6212418934bd4618326979f17aYin Liu *dest++ = 0; 99014897f5aece2c6212418934bd4618326979f17aYin Liu mByteCount = dest - (char*)mBuffer; 10016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mCharCount = count; 10116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 10216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 103dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwoodvoid MtpStringBuffer::set(const uint16_t* src) { 104dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood int count = 0; 105dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood uint16_t ch; 106dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood uint8_t* dest = mBuffer; 107dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood 108014897f5aece2c6212418934bd4618326979f17aYin Liu while ((ch = *src++) != 0 && count < MTP_STRING_MAX_CHARACTER_NUMBER) { 109dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood if (ch >= 0x0800) { 110dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood *dest++ = (uint8_t)(0xE0 | (ch >> 12)); 111dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood *dest++ = (uint8_t)(0x80 | ((ch >> 6) & 0x3F)); 112dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood *dest++ = (uint8_t)(0x80 | (ch & 0x3F)); 113dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood } else if (ch >= 0x80) { 114dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood *dest++ = (uint8_t)(0xC0 | (ch >> 6)); 115dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood *dest++ = (uint8_t)(0x80 | (ch & 0x3F)); 116dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood } else { 117dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood *dest++ = ch; 118dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood } 119dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood count++; 120dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood } 121dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood *dest++ = 0; 122dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood mCharCount = count; 123dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood mByteCount = dest - mBuffer; 124dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood} 125dde372033b4da75ebde7ea2afdec1c1b86ab5a42Mike Lockwood 126ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwoodbool MtpStringBuffer::readFromPacket(MtpDataPacket* packet) { 127ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood uint8_t count; 128ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (!packet->getUInt8(count)) 129ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return false; 130ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood 13116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood uint8_t* dest = mBuffer; 13216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood for (int i = 0; i < count; i++) { 133ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood uint16_t ch; 134ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood 135ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (!packet->getUInt16(ch)) 136ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return false; 13716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (ch >= 0x0800) { 13816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood *dest++ = (uint8_t)(0xE0 | (ch >> 12)); 13916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood *dest++ = (uint8_t)(0x80 | ((ch >> 6) & 0x3F)); 14016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood *dest++ = (uint8_t)(0x80 | (ch & 0x3F)); 14116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } else if (ch >= 0x80) { 14216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood *dest++ = (uint8_t)(0xC0 | (ch >> 6)); 14316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood *dest++ = (uint8_t)(0x80 | (ch & 0x3F)); 14416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } else { 14516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood *dest++ = ch; 14616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 14716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 14816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood *dest++ = 0; 14916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mCharCount = count; 15016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mByteCount = dest - mBuffer; 151ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return true; 15216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 15316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 15416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodvoid MtpStringBuffer::writeToPacket(MtpDataPacket* packet) const { 15516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int count = mCharCount; 15616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood const uint8_t* src = mBuffer; 157de1e37aad04640ef76f3c017b65adca087c7be0fMike Lockwood packet->putUInt8(count > 0 ? count + 1 : 0); 15816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 15916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // expand utf8 to 16 bit chars 16016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood for (int i = 0; i < count; i++) { 16116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood uint16_t ch; 16216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood uint16_t ch1 = *src++; 16316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if ((ch1 & 0x80) == 0) { 16416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // single byte character 16516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood ch = ch1; 16616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } else if ((ch1 & 0xE0) == 0xC0) { 16716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // two byte character 16816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood uint16_t ch2 = *src++; 16916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood ch = ((ch1 & 0x1F) << 6) | (ch2 & 0x3F); 17016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } else { 17116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // three byte character 17216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood uint16_t ch2 = *src++; 17316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood uint16_t ch3 = *src++; 17416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood ch = ((ch1 & 0x0F) << 12) | ((ch2 & 0x3F) << 6) | (ch3 & 0x3F); 17516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 17616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood packet->putUInt16(ch); 17716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 178de1e37aad04640ef76f3c017b65adca087c7be0fMike Lockwood // only terminate with zero if string is not empty 179de1e37aad04640ef76f3c017b65adca087c7be0fMike Lockwood if (count > 0) 180de1e37aad04640ef76f3c017b65adca087c7be0fMike Lockwood packet->putUInt16(0); 18116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 1827850ef999740f214a1990a9c090d3f3865d435aaMike Lockwood 1837850ef999740f214a1990a9c090d3f3865d435aaMike Lockwood} // namespace android 184