blob: cd379bf3fac4635bff228d8753dcf56f285a361f [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
Jerry Zhangbc1d4b42018-03-27 15:25:03 -070029std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> gConvert;
30
31static std::string utf16ToUtf8(std::u16string input_str) {
32 return gConvert.to_bytes(input_str);
Mike Lockwood16864ba2010-05-11 17:16:59 -040033}
34
Jerry Zhangbc1d4b42018-03-27 15:25:03 -070035static std::u16string utf8ToUtf16(std::string input_str) {
36 return gConvert.from_bytes(input_str);
37}
38
39} // namespace
40
41namespace android {
42
Mike Lockwood16864ba2010-05-11 17:16:59 -040043MtpStringBuffer::MtpStringBuffer(const char* src)
Mike Lockwood16864ba2010-05-11 17:16:59 -040044{
45 set(src);
46}
47
Mike Lockwooddde37202010-09-25 21:21:05 -040048MtpStringBuffer::MtpStringBuffer(const uint16_t* src)
Mike Lockwooddde37202010-09-25 21:21:05 -040049{
50 set(src);
51}
52
Mike Lockwood16864ba2010-05-11 17:16:59 -040053MtpStringBuffer::MtpStringBuffer(const MtpStringBuffer& src)
Mike Lockwood16864ba2010-05-11 17:16:59 -040054{
Jerry Zhangbc1d4b42018-03-27 15:25:03 -070055 mString = src.mString;
Mike Lockwood16864ba2010-05-11 17:16:59 -040056}
57
58void MtpStringBuffer::set(const char* src) {
Jerry Zhangbc1d4b42018-03-27 15:25:03 -070059 mString = std::string(src);
Mike Lockwood16864ba2010-05-11 17:16:59 -040060}
61
Mike Lockwooddde37202010-09-25 21:21:05 -040062void MtpStringBuffer::set(const uint16_t* src) {
Jerry Zhangbc1d4b42018-03-27 15:25:03 -070063 mString = utf16ToUtf8(std::u16string((const char16_t*)src));
Mike Lockwooddde37202010-09-25 21:21:05 -040064}
65
Mike Lockwoodab063842014-11-12 14:20:06 -080066bool MtpStringBuffer::readFromPacket(MtpDataPacket* packet) {
67 uint8_t count;
68 if (!packet->getUInt8(count))
69 return false;
Jerry Zhangbc1d4b42018-03-27 15:25:03 -070070 if (count == 0)
71 return true;
Mike Lockwoodab063842014-11-12 14:20:06 -080072
Jerry Zhangbc1d4b42018-03-27 15:25:03 -070073 std::vector<char16_t> buffer(count);
Mike Lockwood16864ba2010-05-11 17:16:59 -040074 for (int i = 0; i < count; i++) {
Mike Lockwoodab063842014-11-12 14:20:06 -080075 uint16_t ch;
Mike Lockwoodab063842014-11-12 14:20:06 -080076 if (!packet->getUInt16(ch))
77 return false;
Jerry Zhangbc1d4b42018-03-27 15:25:03 -070078 buffer[i] = ch;
Mike Lockwood16864ba2010-05-11 17:16:59 -040079 }
Jerry Zhangbc1d4b42018-03-27 15:25:03 -070080 if (buffer[count-1] != '\0') {
81 ALOGE("Mtp string not null terminated\n");
82 return false;
83 }
84 mString = utf16ToUtf8(std::u16string(buffer.data()));
Mike Lockwoodab063842014-11-12 14:20:06 -080085 return true;
Mike Lockwood16864ba2010-05-11 17:16:59 -040086}
87
88void MtpStringBuffer::writeToPacket(MtpDataPacket* packet) const {
Jerry Zhangbc1d4b42018-03-27 15:25:03 -070089 std::u16string src16 = utf8ToUtf16(mString);
90 int count = src16.length();
Mike Lockwood16864ba2010-05-11 17:16:59 -040091
Jerry Zhangbc1d4b42018-03-27 15:25:03 -070092 if (count == 0) {
93 packet->putUInt8(0);
94 return;
95 }
96 packet->putUInt8(std::min(count + 1, MTP_STRING_MAX_CHARACTER_NUMBER));
97
98 int i = 0;
99 for (char16_t &c : src16) {
100 if (i == MTP_STRING_MAX_CHARACTER_NUMBER - 1) {
101 // Leave a slot for null termination.
102 ALOGI("Mtp truncating long string\n");
103 break;
Mike Lockwood16864ba2010-05-11 17:16:59 -0400104 }
Jerry Zhangbc1d4b42018-03-27 15:25:03 -0700105 packet->putUInt16(c);
106 i++;
Mike Lockwood16864ba2010-05-11 17:16:59 -0400107 }
Mike Lockwoodde1e37a2010-08-18 12:31:09 -0400108 // only terminate with zero if string is not empty
Jerry Zhangbc1d4b42018-03-27 15:25:03 -0700109 packet->putUInt16(0);
Mike Lockwood16864ba2010-05-11 17:16:59 -0400110}
Mike Lockwood7850ef92010-05-14 10:10:36 -0400111
112} // namespace android