blob: e2302df757a01e787130edc484440785d6760ec9 [file] [log] [blame]
bigbiff bigbiffaf32bb92018-12-18 18:39:53 -05001/*
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#define LOG_TAG "MtpStringBuffer"
18
19#include <codecvt>
20#include <locale>
21#include <string>
22#include <vector>
23
24#include "MtpDataPacket.h"
25#include "MtpStringBuffer.h"
26
27namespace {
28
29std::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);
33}
34
35static std::u16string utf8ToUtf16(std::string input_str) {
36 return gConvert.from_bytes(input_str);
37}
38
39} // namespace
40
41MtpStringBuffer::MtpStringBuffer(const char* src)
42{
43 set(src);
44}
45
46MtpStringBuffer::MtpStringBuffer(const uint16_t* src)
47{
48 set(src);
49}
50
51MtpStringBuffer::MtpStringBuffer(const MtpStringBuffer& src)
52{
53 mString = src.mString;
54}
55
56void MtpStringBuffer::set(const char* src) {
57 mString = std::string(src);
58}
59
60void MtpStringBuffer::set(const uint16_t* src) {
61 mString = utf16ToUtf8(std::u16string((const char16_t*)src));
62}
63
64bool MtpStringBuffer::readFromPacket(MtpDataPacket* packet) {
65 uint8_t count;
66 if (!packet->getUInt8(count))
67 return false;
68 if (count == 0)
69 return true;
70
71 std::vector<char16_t> buffer(count);
72 for (int i = 0; i < count; i++) {
73 uint16_t ch;
74 if (!packet->getUInt16(ch))
75 return false;
76 buffer[i] = ch;
77 }
78 if (buffer[count-1] != '\0') {
79 MTPE("Mtp string not null terminated\n");
80 return false;
81 }
82 mString = utf16ToUtf8(std::u16string(buffer.data()));
83 return true;
84}
85
86void MtpStringBuffer::writeToPacket(MtpDataPacket* packet) const {
87 std::u16string src16 = utf8ToUtf16(mString);
88 int count = src16.length();
89
90 if (count == 0) {
91 packet->putUInt8(0);
92 return;
93 }
94 packet->putUInt8(std::min(count + 1, MTP_STRING_MAX_CHARACTER_NUMBER));
95
96 int i = 0;
97 for (char16_t &c : src16) {
98 if (i == MTP_STRING_MAX_CHARACTER_NUMBER - 1) {
99 // Leave a slot for null termination.
100 MTPD("Mtp truncating long string\n");
101 break;
102 }
103 packet->putUInt16(c);
104 i++;
105 }
106 // only terminate with zero if string is not empty
107 packet->putUInt16(0);
108}