[dali_2.3.21] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / devel-api / builder / base64-encoding.cpp
1 /*
2  * Copyright (c) 2023 Samsung Electronics Co., Ltd.
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
18 // EXTERNAL INCLUDES
19 #include <iterator>
20 #include <sstream>
21
22 #include <dali-toolkit/devel-api/builder/base64-encoding.h>
23 #include <dali/public-api/object/property-array.h>
24 #include <dali/public-api/object/property-value.h>
25 #include <dali-toolkit/third-party/base-n/basen.hpp>
26
27 namespace Dali
28 {
29 namespace Toolkit
30 {
31 namespace
32 {
33 const int MAX_PROPERTY_STRING_LENGTH(64); // Cuts larger strings into blocks of this size.
34
35 bool GetStringFromProperty(const Property::Value& value, std::string& output)
36 {
37   bool extracted = false;
38   if(value.Get(output))
39   {
40     extracted = true;
41   }
42   else
43   {
44     const Property::Array* array = value.GetArray();
45     if(array)
46     {
47       const unsigned int arraySize = array->Size();
48       for(unsigned int i = 0; i < arraySize; ++i)
49       {
50         std::string element;
51         if(array->GetElementAt(i).Get(element))
52         {
53           extracted = true;
54           output += element;
55         }
56         else
57         {
58           // If property in array is anything other than a string, then it is invalid so break and clear output.
59           output.clear();
60           extracted = false;
61           break;
62         }
63       }
64     }
65   }
66   return extracted;
67 }
68
69 } //anonymous namespace
70
71 bool DecodeBase64PropertyData(const Property::Value& value, std::vector<uint32_t>& outputData)
72 {
73   bool        decoded = false;
74   std::string encodedString;
75
76   if(GetStringFromProperty(value, encodedString))
77   {
78     std::vector<uint8_t> outputTmpData;
79     // Output required at least ceil(length * 3 / 4)
80     outputData.reserve((encodedString.size() * 3 + 3) / 4);
81     bn::decode_b64(encodedString.begin(), encodedString.end(), std::back_inserter(outputTmpData));
82
83     outputData.clear();
84     uint32_t outputSize = (outputTmpData.size() + sizeof(uint32_t) - 1) / sizeof(uint32_t);
85     outputData.resize(outputSize);
86     // Treat as a block of data
87     memcpy(&outputData[0], &outputTmpData[0], outputTmpData.size());
88
89     decoded = true;
90   }
91   return decoded;
92 }
93
94 bool DecodeBase64PropertyData(const Property::Value& value, std::vector<uint8_t>& outputData)
95 {
96   bool        decoded = false;
97   std::string encodedString;
98
99   if(GetStringFromProperty(value, encodedString))
100   {
101     // Output required at least ceil(length * 3 / 4)
102     outputData.reserve((encodedString.size() * 3 + 3) / 4);
103     bn::decode_b64(encodedString.begin(), encodedString.end(), std::back_inserter(outputData));
104
105     decoded = true;
106   }
107   return decoded;
108 }
109
110 bool DecodeBase64FromString(const std::string_view& encodedString, std::vector<uint8_t>& outputData)
111 {
112   // Output required at least ceil(length * 3 / 4)
113   outputData.reserve((encodedString.size() * 3 + 3) >> 2);
114   bn::decode_b64(encodedString.begin(), encodedString.end(), std::back_inserter(outputData));
115
116   return true; // Always success.
117 }
118
119 void EncodeBase64PropertyData(Property::Value& value, const std::vector<uint32_t>& inputData)
120 {
121   std::ostringstream oss;
122
123   bn::encode_b64(reinterpret_cast<const char*>(&inputData[0]),
124                  reinterpret_cast<const char*>(&inputData[0] + inputData.size()),
125                  std::ostream_iterator<unsigned char>(oss, ""));
126
127   std::string encodedString = oss.str();
128
129   // Add padding
130   int paddingLength = (4 - (encodedString.length() % 4)) % 4;
131   if(paddingLength > 0)
132   {
133     while(paddingLength--)
134     {
135       oss << '=';
136     }
137     encodedString = oss.str();
138   }
139
140   if(encodedString.length() > MAX_PROPERTY_STRING_LENGTH)
141   {
142     // cut string up into blocks of MAX_PROPERTY_STRING_LENGTH and store to an array
143     auto numStrings = (encodedString.length() + MAX_PROPERTY_STRING_LENGTH - 1) / MAX_PROPERTY_STRING_LENGTH;
144
145     Property::Array array;
146     for(auto i = 0u; i < numStrings; ++i)
147     {
148       array.PushBack(encodedString.substr(i * MAX_PROPERTY_STRING_LENGTH, MAX_PROPERTY_STRING_LENGTH));
149     }
150     value = array;
151   }
152   else
153   {
154     value = encodedString;
155   }
156 }
157
158 void EncodeBase64PropertyData(Property::Value& value, const std::vector<uint8_t>& inputData)
159 {
160   std::ostringstream oss;
161
162   bn::encode_b64(reinterpret_cast<const uint8_t*>(&inputData[0]),
163                  reinterpret_cast<const uint8_t*>(&inputData[0] + inputData.size()),
164                  std::ostream_iterator<char>(oss, ""));
165
166   std::string encodedString = oss.str();
167
168   // Add padding
169   int paddingLength = (4 - (encodedString.length() % 4)) % 4;
170   if(paddingLength > 0)
171   {
172     while(paddingLength--)
173     {
174       oss << '=';
175     }
176     encodedString = oss.str();
177   }
178
179   if(encodedString.length() > MAX_PROPERTY_STRING_LENGTH)
180   {
181     // cut string up into blocks of MAX_PROPERTY_STRING_LENGTH and store to an array
182     auto numStrings = (encodedString.length() + MAX_PROPERTY_STRING_LENGTH - 1) / MAX_PROPERTY_STRING_LENGTH;
183
184     Property::Array array;
185     for(auto i = 0u; i < numStrings; ++i)
186     {
187       array.PushBack(encodedString.substr(i * MAX_PROPERTY_STRING_LENGTH, MAX_PROPERTY_STRING_LENGTH));
188     }
189     value = array;
190   }
191   else
192   {
193     value = encodedString;
194   }
195 }
196
197 } // namespace Toolkit
198
199 } // namespace Dali