tesseract v5.3.3.20231005
helpers.h
Go to the documentation of this file.
1/******************************************************************************
2 *
3 * File: helpers.h
4 * Description: General utility functions
5 * Author: Daria Antonova
6 *
7 * (c) Copyright 2009, Google Inc.
8 ** Licensed under the Apache License, Version 2.0 (the "License");
9 ** you may not use this file except in compliance with the License.
10 ** You may obtain a copy of the License at
11 ** http://www.apache.org/licenses/LICENSE-2.0
12 ** Unless required by applicable law or agreed to in writing, software
13 ** distributed under the License is distributed on an "AS IS" BASIS,
14 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 ** See the License for the specific language governing permissions and
16 ** limitations under the License.
17 *
18 *****************************************************************************/
19
20#ifndef TESSERACT_CCUTIL_HELPERS_H_
21#define TESSERACT_CCUTIL_HELPERS_H_
22
23#include <cassert>
24#include <climits> // for INT_MIN, INT_MAX
25#include <cmath> // std::isfinite
26#include <cstdio>
27#include <cstring>
28#include <algorithm> // for std::find
29#include <functional>
30#include <random>
31#include <string>
32#include <vector>
33
34#include "serialis.h"
35
36namespace tesseract {
37
38template <class T>
39inline bool contains(const std::vector<T> &data, const T &value) {
40 return std::find(data.begin(), data.end(), value) != data.end();
41}
42
43inline const std::vector<std::string> split(const std::string &s, char c) {
44 std::string buff;
45 std::vector<std::string> v;
46 for (auto n : s) {
47 if (n != c) {
48 buff += n;
49 } else if (n == c && !buff.empty()) {
50 v.push_back(buff);
51 buff.clear();
52 }
53 }
54 if (!buff.empty()) {
55 v.push_back(buff);
56 }
57 return v;
58}
59
60// A simple linear congruential random number generator.
61class TRand {
62public:
63 // Sets the seed to the given value.
64 void set_seed(uint64_t seed) {
65 e.seed(seed);
66 }
67 // Sets the seed using a hash of a string.
68 void set_seed(const std::string &str) {
69 std::hash<std::string> hasher;
70 set_seed(static_cast<uint64_t>(hasher(str)));
71 }
72
73 // Returns an integer in the range 0 to INT32_MAX.
74 int32_t IntRand() {
75 return e();
76 }
77 // Returns a floating point value in the range [-range, range].
78 double SignedRand(double range) {
79 return range * 2.0 * IntRand() / INT32_MAX - range;
80 }
81 // Returns a floating point value in the range [0, range].
82 double UnsignedRand(double range) {
83 return range * IntRand() / INT32_MAX;
84 }
85
86private:
87 std::minstd_rand e;
88};
89
90// Remove newline (if any) at the end of the string.
91inline void chomp_string(char *str) {
92 int last_index = static_cast<int>(strlen(str)) - 1;
93 while (last_index >= 0 && (str[last_index] == '\n' || str[last_index] == '\r')) {
94 str[last_index--] = '\0';
95 }
96}
97
98// return the smallest multiple of block_size greater than or equal to n.
99inline int RoundUp(int n, int block_size) {
100 return block_size * ((n + block_size - 1) / block_size);
101}
102
103// Clip a numeric value to the interval [lower_bound, upper_bound].
104template <typename T>
105inline T ClipToRange(const T &x, const T &lower_bound, const T &upper_bound) {
106 if (x < lower_bound) {
107 return lower_bound;
108 }
109 if (x > upper_bound) {
110 return upper_bound;
111 }
112 return x;
113}
114
115// Extend the range [lower_bound, upper_bound] to include x.
116template <typename T1, typename T2>
117inline void UpdateRange(const T1 &x, T2 *lower_bound, T2 *upper_bound) {
118 if (x < *lower_bound) {
119 *lower_bound = x;
120 }
121 if (x > *upper_bound) {
122 *upper_bound = x;
123 }
124}
125
126// Decrease lower_bound to be <= x_lo AND increase upper_bound to be >= x_hi.
127template <typename T1, typename T2>
128inline void UpdateRange(const T1 &x_lo, const T1 &x_hi, T2 *lower_bound, T2 *upper_bound) {
129 if (x_lo < *lower_bound) {
130 *lower_bound = x_lo;
131 }
132 if (x_hi > *upper_bound) {
133 *upper_bound = x_hi;
134 }
135}
136
137// Intersect the range [*lower2, *upper2] with the range [lower1, upper1],
138// putting the result back in [*lower2, *upper2].
139// If non-intersecting ranges are given, we end up with *lower2 > *upper2.
140template <typename T>
141inline void IntersectRange(const T &lower1, const T &upper1, T *lower2, T *upper2) {
142 if (lower1 > *lower2) {
143 *lower2 = lower1;
144 }
145 if (upper1 < *upper2) {
146 *upper2 = upper1;
147 }
148}
149
150// Proper modulo arithmetic operator. Returns a mod b that works for -ve a.
151// For any integer a and positive b, returns r : 0<=r<b and a=n*b + r for
152// some integer n.
153inline int Modulo(int a, int b) {
154 return (a % b + b) % b;
155}
156
157// Integer division operator with rounding that works for negative input.
158// Returns a divided by b, rounded to the nearest integer, without double
159// counting at 0. With simple rounding 1/3 = 0, 0/3 = 0 -1/3 = 0, -2/3 = 0,
160// -3/3 = 0 and -4/3 = -1.
161// I want 1/3 = 0, 0/3 = 0, -1/3 = 0, -2/3 = -1, -3/3 = -1 and -4/3 = -1.
162inline int DivRounded(int a, int b) {
163 if (b < 0) {
164 return -DivRounded(a, -b);
165 }
166 return a >= 0 ? (a + b / 2) / b : (a - b / 2) / b;
167}
168
169// Return a double cast to int with rounding.
170inline int IntCastRounded(double x) {
171 assert(std::isfinite(x));
172 assert(x < INT_MAX);
173 assert(x > INT_MIN);
174 return x >= 0.0 ? static_cast<int>(x + 0.5) : -static_cast<int>(-x + 0.5);
175}
176
177// Return a float cast to int with rounding.
178inline int IntCastRounded(float x) {
179 assert(std::isfinite(x));
180 return x >= 0.0F ? static_cast<int>(x + 0.5F) : -static_cast<int>(-x + 0.5F);
181}
182
183// Reverse the order of bytes in a n byte quantity for big/little-endian switch.
184inline void ReverseN(void *ptr, int num_bytes) {
185 assert(num_bytes == 1 || num_bytes == 2 || num_bytes == 4 || num_bytes == 8);
186 char *cptr = static_cast<char *>(ptr);
187 int halfsize = num_bytes / 2;
188 for (int i = 0; i < halfsize; ++i) {
189 char tmp = cptr[i];
190 cptr[i] = cptr[num_bytes - 1 - i];
191 cptr[num_bytes - 1 - i] = tmp;
192 }
193}
194
195// Reverse the order of bytes in a 32 bit quantity for big/little-endian switch.
196inline void Reverse32(void *ptr) {
197 ReverseN(ptr, 4);
198}
199
200// Reads a vector of simple types from the given file. Assumes that bitwise
201// read/write will work with ReverseN according to sizeof(T).
202// Returns false in case of error.
203// If swap is true, assumes a big/little-endian swap is needed.
204template <typename T>
205bool DeSerialize(bool swap, FILE *fp, std::vector<T> &data) {
206 uint32_t size;
207 if (fread(&size, sizeof(size), 1, fp) != 1) {
208 return false;
209 }
210 if (swap) {
211 Reverse32(&size);
212 }
213 // Arbitrarily limit the number of elements to protect against bad data.
214 assert(size <= UINT16_MAX);
215 if (size > UINT16_MAX) {
216 return false;
217 }
218 // TODO: optimize.
219 data.resize(size);
220 if (size > 0) {
221 if (fread(&data[0], sizeof(T), size, fp) != size) {
222 return false;
223 }
224 if (swap) {
225 for (uint32_t i = 0; i < size; ++i) {
226 ReverseN(&data[i], sizeof(T));
227 }
228 }
229 }
230 return true;
231}
232
233// Writes a vector of simple types to the given file. Assumes that bitwise
234// read/write of T will work. Returns false in case of error.
235template <typename T>
236bool Serialize(FILE *fp, const std::vector<T> &data) {
237 uint32_t size = data.size();
238 if (fwrite(&size, sizeof(size), 1, fp) != 1) {
239 return false;
240 } else if constexpr (std::is_class<T>::value) {
241 // Serialize a tesseract class.
242 for (auto &item : data) {
243 if (!item.Serialize(fp)) {
244 return false;
245 }
246 }
247 } else if constexpr (std::is_pointer<T>::value) {
248 // Serialize pointers.
249 for (auto &item : data) {
250 uint8_t non_null = (item != nullptr);
251 if (!Serialize(fp, &non_null)) {
252 return false;
253 }
254 if (non_null) {
255 if (!item->Serialize(fp)) {
256 return false;
257 }
258 }
259 }
260 } else if (size > 0) {
261 if (fwrite(&data[0], sizeof(T), size, fp) != size) {
262 return false;
263 }
264 }
265 return true;
266}
267
268} // namespace tesseract
269
270#endif // TESSERACT_CCUTIL_HELPERS_H_
@ T1
Definition: rune.c:27
@ T2
Definition: rune.c:29
int value
void ReverseN(void *ptr, int num_bytes)
Definition: helpers.h:184
int IntCastRounded(double x)
Definition: helpers.h:170
int DivRounded(int a, int b)
Definition: helpers.h:162
bool DeSerialize(bool swap, FILE *fp, std::vector< T > &data)
Definition: helpers.h:205
void chomp_string(char *str)
Definition: helpers.h:91
bool Serialize(FILE *fp, const std::vector< T > &data)
Definition: helpers.h:236
int RoundUp(int n, int block_size)
Definition: helpers.h:99
T ClipToRange(const T &x, const T &lower_bound, const T &upper_bound)
Definition: helpers.h:105
void IntersectRange(const T &lower1, const T &upper1, T *lower2, T *upper2)
Definition: helpers.h:141
void UpdateRange(const T1 &x, T2 *lower_bound, T2 *upper_bound)
Definition: helpers.h:117
void Reverse32(void *ptr)
Definition: helpers.h:196
const std::vector< std::string > split(const std::string &s, char c)
Definition: helpers.h:43
bool contains(const std::vector< T > &data, const T &value)
Definition: helpers.h:39
int Modulo(int a, int b)
Definition: helpers.h:153
void set_seed(const std::string &str)
Definition: helpers.h:68
double SignedRand(double range)
Definition: helpers.h:78
int32_t IntRand()
Definition: helpers.h:74
double UnsignedRand(double range)
Definition: helpers.h:82
void set_seed(uint64_t seed)
Definition: helpers.h:64