• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
27 namespace {
28 
29 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> gConvert;
30 
utf16ToUtf8(std::u16string input_str)31 static std::string utf16ToUtf8(std::u16string input_str) {
32     return gConvert.to_bytes(input_str);
33 }
34 
utf8ToUtf16(std::string input_str)35 static std::u16string utf8ToUtf16(std::string input_str) {
36     return gConvert.from_bytes(input_str);
37 }
38 
39 } // namespace
40 
41 namespace android {
42 
MtpStringBuffer(const char * src)43 MtpStringBuffer::MtpStringBuffer(const char* src)
44 {
45     set(src);
46 }
47 
MtpStringBuffer(const uint16_t * src)48 MtpStringBuffer::MtpStringBuffer(const uint16_t* src)
49 {
50     set(src);
51 }
52 
MtpStringBuffer(const MtpStringBuffer & src)53 MtpStringBuffer::MtpStringBuffer(const MtpStringBuffer& src)
54 {
55     mString = src.mString;
56 }
57 
set(const char * src)58 void MtpStringBuffer::set(const char* src) {
59     mString = std::string(src);
60 }
61 
set(const uint16_t * src)62 void MtpStringBuffer::set(const uint16_t* src) {
63     mString = utf16ToUtf8(std::u16string((const char16_t*)src));
64 }
65 
readFromPacket(MtpDataPacket * packet)66 bool MtpStringBuffer::readFromPacket(MtpDataPacket* packet) {
67     uint8_t count;
68     if (!packet->getUInt8(count))
69         return false;
70     if (count == 0)
71         return true;
72 
73     std::vector<char16_t> buffer(count);
74     for (int i = 0; i < count; i++) {
75         uint16_t ch;
76         if (!packet->getUInt16(ch))
77             return false;
78         buffer[i] = ch;
79     }
80     if (buffer[count-1] != '\0') {
81         ALOGE("Mtp string not null terminated\n");
82         return false;
83     }
84     mString = utf16ToUtf8(std::u16string(buffer.data()));
85     return true;
86 }
87 
writeToPacket(MtpDataPacket * packet) const88 void MtpStringBuffer::writeToPacket(MtpDataPacket* packet) const {
89     std::u16string src16 = utf8ToUtf16(mString);
90     int count = src16.length();
91 
92     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;
104         }
105         packet->putUInt16(c);
106         i++;
107     }
108     // only terminate with zero if string is not empty
109     packet->putUInt16(0);
110 }
111 
112 }  // namespace android
113