blob: d8d425b1100810103f0f042012c029f4d2277146 [file] [log] [blame]
Mike Lockwood16864ba2010-05-11 17:16:59 -04001/*
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
Mike Lockwoodb14e5882010-06-29 18:11:52 -040017#define LOG_TAG "MtpStringBuffer"
18
Jerry Zhangbc1d4b42018-03-27 15:25:03 -070019#include <codecvt>
20#include <locale>
21#include <string>
22#include <vector>
Mike Lockwood16864ba2010-05-11 17:16:59 -040023
24#include "MtpDataPacket.h"
25#include "MtpStringBuffer.h"
26
Jerry Zhangbc1d4b42018-03-27 15:25:03 -070027namespace {
Mike Lockwood16864ba2010-05-11 17:16:59 -040028
Grant Hernandez995c91c2019-07-17 12:53:48 -070029const char * utf16_cerror = "__CONVERSION_ERROR__";
30const char16_t * utf8_cerror = u"__CONVERSION_ERROR__";
31
32std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> gConvert(utf16_cerror, utf8_cerror);
Jerry Zhangbc1d4b42018-03-27 15:25:03 -070033
34static std::string utf16ToUtf8(std::u16string input_str) {
Grant Hernandez995c91c2019-07-17 12:53:48 -070035 std::string conversion = gConvert.to_bytes(input_str);
36
37 if (conversion == utf16_cerror) {
38 ALOGE("Unable to convert UTF-16 string to UTF-8");
39 return "";
40 } else {
41 return conversion;
42 }
Mike Lockwood16864ba2010-05-11 17:16:59 -040043}
44
Jerry Zhangbc1d4b42018-03-27 15:25:03 -070045static std::u16string utf8ToUtf16(std::string input_str) {
Grant Hernandez995c91c2019-07-17 12:53:48 -070046 std::u16string conversion = gConvert.from_bytes(input_str);
47
48 if (conversion == utf8_cerror) {
49 ALOGE("Unable to convert UTF-8 string to UTF-16");
50 return u"";
51 } else {
52 return conversion;
53 }
Jerry Zhangbc1d4b42018-03-27 15:25:03 -070054}
55
56} // namespace
57
58namespace android {
59
Mike Lockwood16864ba2010-05-11 17:16:59 -040060MtpStringBuffer::MtpStringBuffer(const char* src)
Mike Lockwood16864ba2010-05-11 17:16:59 -040061{
62 set(src);
63}
64
Mike Lockwooddde37202010-09-25 21:21:05 -040065MtpStringBuffer::MtpStringBuffer(const uint16_t* src)
Mike Lockwooddde37202010-09-25 21:21:05 -040066{
67 set(src);
68}
69
Mike Lockwood16864ba2010-05-11 17:16:59 -040070MtpStringBuffer::MtpStringBuffer(const MtpStringBuffer& src)
Mike Lockwood16864ba2010-05-11 17:16:59 -040071{
Jerry Zhangbc1d4b42018-03-27 15:25:03 -070072 mString = src.mString;
Mike Lockwood16864ba2010-05-11 17:16:59 -040073}
74
75void MtpStringBuffer::set(const char* src) {
Jerry Zhangbc1d4b42018-03-27 15:25:03 -070076 mString = std::string(src);
Mike Lockwood16864ba2010-05-11 17:16:59 -040077}
78
Mike Lockwooddde37202010-09-25 21:21:05 -040079void MtpStringBuffer::set(const uint16_t* src) {
Jerry Zhangbc1d4b42018-03-27 15:25:03 -070080 mString = utf16ToUtf8(std::u16string((const char16_t*)src));
Mike Lockwooddde37202010-09-25 21:21:05 -040081}
82
Mike Lockwoodab063842014-11-12 14:20:06 -080083bool MtpStringBuffer::readFromPacket(MtpDataPacket* packet) {
84 uint8_t count;
85 if (!packet->getUInt8(count))
86 return false;
Jerry Zhangbc1d4b42018-03-27 15:25:03 -070087 if (count == 0)
88 return true;
Mike Lockwoodab063842014-11-12 14:20:06 -080089
Jerry Zhangbc1d4b42018-03-27 15:25:03 -070090 std::vector<char16_t> buffer(count);
Mike Lockwood16864ba2010-05-11 17:16:59 -040091 for (int i = 0; i < count; i++) {
Mike Lockwoodab063842014-11-12 14:20:06 -080092 uint16_t ch;
Mike Lockwoodab063842014-11-12 14:20:06 -080093 if (!packet->getUInt16(ch))
94 return false;
Jerry Zhangbc1d4b42018-03-27 15:25:03 -070095 buffer[i] = ch;
Mike Lockwood16864ba2010-05-11 17:16:59 -040096 }
Jerry Zhangbc1d4b42018-03-27 15:25:03 -070097 if (buffer[count-1] != '\0') {
98 ALOGE("Mtp string not null terminated\n");
99 return false;
100 }
101 mString = utf16ToUtf8(std::u16string(buffer.data()));
Mike Lockwoodab063842014-11-12 14:20:06 -0800102 return true;
Mike Lockwood16864ba2010-05-11 17:16:59 -0400103}
104
105void MtpStringBuffer::writeToPacket(MtpDataPacket* packet) const {
Jerry Zhangbc1d4b42018-03-27 15:25:03 -0700106 std::u16string src16 = utf8ToUtf16(mString);
107 int count = src16.length();
Mike Lockwood16864ba2010-05-11 17:16:59 -0400108
Jerry Zhangbc1d4b42018-03-27 15:25:03 -0700109 if (count == 0) {
110 packet->putUInt8(0);
111 return;
112 }
113 packet->putUInt8(std::min(count + 1, MTP_STRING_MAX_CHARACTER_NUMBER));
114
115 int i = 0;
116 for (char16_t &c : src16) {
117 if (i == MTP_STRING_MAX_CHARACTER_NUMBER - 1) {
118 // Leave a slot for null termination.
119 ALOGI("Mtp truncating long string\n");
120 break;
Mike Lockwood16864ba2010-05-11 17:16:59 -0400121 }
Jerry Zhangbc1d4b42018-03-27 15:25:03 -0700122 packet->putUInt16(c);
123 i++;
Mike Lockwood16864ba2010-05-11 17:16:59 -0400124 }
Mike Lockwoodde1e37a2010-08-18 12:31:09 -0400125 // only terminate with zero if string is not empty
Jerry Zhangbc1d4b42018-03-27 15:25:03 -0700126 packet->putUInt16(0);
Mike Lockwood16864ba2010-05-11 17:16:59 -0400127}
Mike Lockwood7850ef92010-05-14 10:10:36 -0400128
129} // namespace android