1 #include "xmpmeta/base64.h"
2 
3 #include "android-base/logging.h"
4 #include "strings/escaping.h"
5 
6 namespace dynamic_depth {
7 namespace xmpmeta {
8 namespace {
9 
EncodeBase64RawData(const uint8 * data,size_t data_size,string * output)10 bool EncodeBase64RawData(const uint8* data, size_t data_size, string* output) {
11   // Disable linting because string_view doesn't appear to support uint8_t.
12   dynamic_depth::Base64Escape(data, data_size, output, false);  // NOLINT
13   return output->length() > 0;
14 }
15 
16 template <typename T>
InternalEncodeArrayBase64(const std::vector<T> & data,string * output)17 bool InternalEncodeArrayBase64(const std::vector<T>& data, string* output) {
18   size_t buffer_size = data.size() * sizeof(T);
19   return EncodeBase64RawData(reinterpret_cast<const uint8_t*>(data.data()),
20                              buffer_size, output);
21 }
22 
23 template <typename T>
InternalDecodeArrayBase64(const string & data,std::vector<T> * output)24 bool InternalDecodeArrayBase64(const string& data, std::vector<T>* output) {
25   string bytes;
26   if (!DecodeBase64(data, &bytes)) {
27     return false;
28   }
29 
30   const int count = bytes.size() / sizeof(T);
31   output->clear();
32   output->resize(count);
33   memcpy(output->data(), bytes.data(), output->size() * sizeof(T));
34   return !output->empty();
35 }
36 
37 }  // namespace
38 
39 // Decodes the base64-encoded input range.
DecodeBase64(const string & data,string * output)40 bool DecodeBase64(const string& data, string* output) {
41   // Support decoding of both web-safe and regular base64.
42   // "Web-safe" base-64 replaces + with - and / with _, and omits
43   // trailing = padding characters.
44   if (dynamic_depth::Base64Unescape(data, output)) {
45     return true;
46   }
47   return dynamic_depth::WebSafeBase64Unescape(data, output);
48 }
49 
50 // Base64-encodes the given data.
EncodeBase64(const string & data,string * output)51 bool EncodeBase64(const string& data, string* output) {
52   return EncodeBase64RawData(reinterpret_cast<const uint8*>(data.c_str()),
53                              data.length(), output);
54 }
55 
56 // Base64-encodes the given int array.
EncodeIntArrayBase64(const std::vector<int32_t> & data,string * output)57 bool EncodeIntArrayBase64(const std::vector<int32_t>& data, string* output) {
58   return InternalEncodeArrayBase64<int32_t>(data, output);
59 }
60 
61 // Base64-decodes the given base64-encoded string.
DecodeIntArrayBase64(const string & data,std::vector<int32_t> * output)62 bool DecodeIntArrayBase64(const string& data, std::vector<int32_t>* output) {
63   return InternalDecodeArrayBase64<int32_t>(data, output);
64 }
65 
66 // Base64-encodes the given float array.
EncodeFloatArrayBase64(const std::vector<float> & data,string * output)67 bool EncodeFloatArrayBase64(const std::vector<float>& data, string* output) {
68   return InternalEncodeArrayBase64<float>(data, output);
69 }
70 
71 // Base64-decodes the given base64-encoded string.
DecodeFloatArrayBase64(const string & data,std::vector<float> * output)72 bool DecodeFloatArrayBase64(const string& data, std::vector<float>* output) {
73   return InternalDecodeArrayBase64<float>(data, output);
74 }
75 
76 // Base64-encodes the given double array.
EncodeDoubleArrayBase64(const std::vector<double> & data,string * output)77 bool EncodeDoubleArrayBase64(const std::vector<double>& data, string* output) {
78   return InternalEncodeArrayBase64<double>(data, output);
79 }
80 
81 // Base64-decodes the given base64-encoded string.
DecodeDoubleArrayBase64(const string & data,std::vector<double> * output)82 bool DecodeDoubleArrayBase64(const string& data, std::vector<double>* output) {
83   return InternalDecodeArrayBase64<double>(data, output);
84 }
85 }  // namespace xmpmeta
86 }  // namespace dynamic_depth
87