libcrn  3.9.5
A document image processing library
•All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CRNData.cpp
Go to the documentation of this file.
1 /* Copyright 2010-2016 CoReNum, INSA-Lyon, Université Paris-Descartes, ENS-Lyon
2  *
3  * This file is part of libcrn.
4  *
5  * libcrn is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Lesser General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * libcrn is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with libcrn. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * file: CRNData.cpp
19  * \author Yann LEYDIER
20  */
21 
22 #include <CRNData/CRNData.h>
23 #include <CRNi18n.h>
24 #include <array>
25 
26 using namespace crn;
27 
33 UInt crn::Data::ToCRN(int i)
34 {
35  return std::make_unique<Int>(i);
36 }
37 
43 UReal crn::Data::ToCRN(double d)
44 {
45  return std::make_unique<Real>(d);
46 }
47 
53 UString crn::Data::ToCRN(const String &str)
54 {
55  return CloneAs<String>(str);
56 }
57 
63 UStringUTF8 crn::Data::ToCRN(const StringUTF8 &str)
64 {
65  return CloneAs<StringUTF8>(str);
66 }
67 
73 UPath crn::Data::ToCRN(const Path &str)
74 {
75  return CloneAs<Path>(str);
76 }
77 
83 UProp3 crn::Data::ToCRN(const Prop3 &val)
84 {
85  return CloneAs<Prop3>(val);
86 }
87 
88 static const auto asciiOffset = 33;
89 static const auto pow85 = std::vector<unsigned int>{ 85*85*85*85, 85*85*85, 85*85, 85, 1 };
90 static void encodeBlock(size_t count, unsigned int &_tuple, StringUTF8 &s)
91 {
92  auto block = std::array<uint8_t, 5>{};
93  for (auto it = block.rbegin(); it != block.rend(); ++it)
94  {
95  *it = uint8_t((_tuple % 85) + asciiOffset);
96  _tuple /= 85;
97  }
98  for (auto i = size_t(0); i < count; ++i)
99  {
100  s += char(block[i]);
101  }
102 }
103 
109 StringUTF8 crn::Data::ASCII85Encode(const uint8_t * const data, size_t len)
110 {
111  auto count = 0;
112  auto _tuple = 0u;
113  auto s = StringUTF8{};
114 
115  for (auto tmp = size_t(0); tmp < len; ++tmp)
116  {
117  if (count >= 3)
118  {
119  _tuple |= data[tmp];
120  if (_tuple == 0)
121  s += 'z';
122  else
123  encodeBlock(size_t(5), _tuple, s);
124  _tuple = 0;
125  count = 0;
126  }
127  else
128  {
129  _tuple |= (data[tmp] << (24 - (count * 8)));
130  count += 1;
131  }
132  }
133 
134  if (count > 0)
135  encodeBlock(size_t(count + 1), _tuple, s);
136 
137  return s;
138 }
139 
140 
146 std::vector<uint8_t> crn::Data::ASCII85Decode(const StringUTF8 &s)
147 {
148  auto data = std::vector<uint8_t>{};
149  auto count = 0;
150  auto processChar = false;
151  auto block = std::array<uint8_t, 4>{};
152  auto _tuple = 0u;
153 
154  for (auto tmp : crn::Range(s))
155  {
156  const auto c = s[tmp];
157  switch (c)
158  {
159  case 'z':
160  if (count != 0)
161  throw crn::ExceptionInvalidArgument{StringUTF8{"ASCII85Decode()::"} + _("the character 'z' is invalid inside an ASCII85 block.")};
162  std::fill(block.begin(), block.end(), 0);
163  data.insert(data.end(), block.begin(), block.end());
164  processChar = false;
165  break;
166  case '\n': case '\r': case '\t': case '\0': case '\f': case '\b':
167  processChar = false;
168  break;
169  default:
170  if (c < '!' || c > 'u')
171  throw crn::ExceptionInvalidArgument{StringUTF8{"ASCII85Decode()::"} + _("ASCII85 only allows characters '!' to 'u', but found a: ") + StringUTF8{c}};
172  processChar = true;
173  break;
174  }
175 
176  if (processChar)
177  {
178  _tuple += (c - asciiOffset) * pow85[count];
179  count += 1;
180  if (count == 5)
181  {
182  for (auto i : crn::Range(block))
183  block[i] = uint8_t(_tuple >> (24 - (int(i) * 8))); // TODO Check if it is uint8_t((_tuple >> 24) - (int(i) * 8));
184  data.insert(data.end(), block.begin(), block.end());
185  _tuple = 0;
186  count = 0;
187  }
188  }
189  }
190 
191  if (count != 0)
192  {
193  if (count == 1)
194  throw crn::ExceptionInvalidArgument{StringUTF8{"ASCII85Decode()::"} + _("the last block of ASCII85 data cannot be a single byte.")};
195  count -= 1;
196  _tuple += pow85[count];
197  for (auto i = 0; i < count; ++i)
198  block[i] = uint8_t(_tuple >> (24 - (i * 8))); // TODO Check if it is uint8_t((_tuple >> 24) - (int(i) * 8));
199  data.insert(data.end(), block.begin(), block.begin() + count);
200  }
201  return data;
202 }
203 
ScalarRange< T > Range(T b, T e)
Creates a range [[b, e[[.
Definition: CRNType.h:257
#define _(String)
Definition: CRNi18n.h:51
A UTF32 character string class.
Definition: CRNString.h:61
UInt ToCRN(int i)
Converts an int to CRN data.
Definition: CRNData.cpp:33
A convenience class for file paths.
Definition: CRNPath.h:39
std::vector< uint8_t > ASCII85Decode(const crn::StringUTF8 &s)
Decodes an ASCII85 string to a vector of bytes.
Definition: CRNData.h:229
A character string class.
Definition: CRNStringUTF8.h:49
A ternary proposition.
Definition: CRNProp3.h:40
crn::StringUTF8 ASCII85Encode(const uint8_t *const data, size_t len)
Encodes any data into a printable string.
Definition: CRNData.cpp:109
Invalid argument error (e.g.: nullptr pointer)
Definition: CRNException.h:107