7 #ifndef TREELITE_COMMON_H_ 8 #define TREELITE_COMMON_H_ 11 #include <dmlc/logging.h> 12 #include <dmlc/json.h> 13 #include <dmlc/data.h> 32 #define CLONEABLE_BOILERPLATE(className) \ 33 explicit className(const className& other) = default; \ 34 explicit className(className&& other) = default; \ 35 Cloneable* clone() const override { \ 36 return new className(*this); \ 38 Cloneable* move_clone() override { \ 39 return new className(std::move(*this)); \ 49 static_assert(std::is_base_of<Cloneable, T>::value,
50 "DeepCopyUniquePtr requires a Cloneable type");
54 : ptr(dynamic_cast<T*>(other.clone())) {}
57 : ptr(dynamic_cast<T*>(other.move_clone())) {}
59 : ptr(dynamic_cast<T*>(other.ptr->clone())) {}
61 : ptr(std::move(other.ptr)) {}
63 inline T& operator*() {
66 const inline T& operator*()
const {
70 return ptr.operator->();
72 const T* operator->()
const {
73 return ptr.operator->();
77 std::unique_ptr<T> ptr;
89 template<
typename T,
typename ...Args>
92 return std::unique_ptr<T>(
new T(std::forward<Args>(args)...));
108 template <
typename T>
110 return std::move(*ptr.get());
123 inline void WrapText(std::ostringstream* p_stm,
size_t* p_length,
124 const std::string& str,
size_t textwidth) {
125 std::ostringstream& stm = *p_stm;
126 size_t& length = *p_length;
127 if (length + str.length() + 2 <= textwidth) {
129 length += str.length() + 2;
131 stm <<
"\n " << str <<
", ";
132 length = str.length() + 4;
145 template<
class Iter,
class T>
148 Iter i = std::lower_bound(begin, end, val);
149 if (i != end && !(val < *i)) {
161 template <
typename T>
163 std::ostringstream oss;
176 const std::vector<std::string>& lines) {
177 std::unique_ptr<dmlc::Stream> fo(dmlc::Stream::Create(filename.c_str(),
"w"));
178 dmlc::ostream os(fo.get());
179 std::copy(lines.begin(), lines.end(),
180 std::ostream_iterator<std::string>(os,
"\n"));
182 os.set_stream(
nullptr);
193 const std::vector<std::string>& lines,
194 std::function<std::string(std::string)> func) {
195 auto& dest = *p_dest;
196 std::transform(lines.begin(), lines.end(), std::back_inserter(dest), func);
205 template <
typename T>
207 static_assert(std::is_same<T, float>::value
208 || std::is_same<T, double>::value
209 || std::is_same<T, int>::value
210 || std::is_same<T, int8_t>::value
211 || std::is_same<T, uint32_t>::value,
212 "unsupported data type for TextToNumber; use float, double, " 213 "int, int8_t, or uint32_t.");
220 float val = std::strtof(str.c_str(), &endptr);
221 if (errno == ERANGE) {
222 LOG(FATAL) <<
"Range error while converting string to double";
224 else if (errno != 0) {
225 LOG(FATAL) <<
"Unknown error";
227 else if (*endptr !=
'\0') {
228 LOG(FATAL) <<
"String does not represent a valid floating-point number";
237 double val = std::strtod(str.c_str(), &endptr);
238 if (errno == ERANGE) {
239 LOG(FATAL) <<
"Range error while converting string to double";
241 else if (errno != 0) {
242 LOG(FATAL) <<
"Unknown error";
244 else if (*endptr !=
'\0') {
245 LOG(FATAL) <<
"String does not represent a valid floating-point number";
254 long int val = std::strtol(str.c_str(), &endptr, 10);
255 if (errno == ERANGE || val < INT_MIN || val > INT_MAX) {
256 LOG(FATAL) <<
"Range error while converting string to int";
258 else if (errno != 0) {
259 LOG(FATAL) <<
"Unknown error";
261 else if (*endptr !=
'\0') {
262 LOG(FATAL) <<
"String does not represent a valid integer";
264 return static_cast<int>(val);
271 long int val = std::strtol(str.c_str(), &endptr, 10);
272 if (errno == ERANGE || val < INT8_MIN || val > INT8_MAX) {
273 LOG(FATAL) <<
"Range error while converting string to int8_t";
275 else if (errno != 0) {
276 LOG(FATAL) <<
"Unknown error";
278 else if (*endptr !=
'\0') {
279 LOG(FATAL) <<
"String does not represent a valid integer";
281 return static_cast<int8_t
>(val);
286 static_assert(
sizeof(uint32_t) <=
sizeof(
unsigned long int),
287 "unsigned long int too small to hold uint32_t");
290 unsigned long int val = std::strtoul(str.c_str(), &endptr, 10);
291 if (errno == ERANGE || val > UINT32_MAX) {
292 LOG(FATAL) <<
"Range error while converting string to uint32_t";
294 else if (errno != 0) {
295 LOG(FATAL) <<
"Unknown error";
297 else if (*endptr !=
'\0') {
298 LOG(FATAL) <<
"String does not represent a valid integer";
300 return static_cast<uint32_t
>(val);
309 template <
typename T>
310 inline std::vector<T>
TextToArray(
const std::string& text,
int num_entry) {
311 std::vector<T> array;
312 std::istringstream ss(text);
314 for (
int i = 0; i < num_entry; ++i) {
315 std::getline(ss, token,
' ');
316 array.push_back(TextToNumber<T>(token));
327 inline std::vector<std::string>
Split(
const std::string& text,
char delim) {
328 std::vector<std::string> array;
329 std::istringstream ss(text);
331 while (std::getline(ss, token, delim)) {
332 array.push_back(token);
339 #endif // TREELITE_COMMON_H_
std::vector< T > TextToArray(const std::string &text, int num_entry)
convert text to number array
void WriteToFile(const std::string &filename, const std::vector< std::string > &lines)
write a sequence of strings to a text file, with newline character ( ) inserted between strings...
void TransformPushBack(std::vector< std::string > *p_dest, const std::vector< std::string > &lines, std::function< std::string(std::string)> func)
apply a given transformation to a sequence of strings and append them to another sequence.
std::string ToString(T value)
obtain a string representation of primitive type using ostringstream
abstract interface for classes that can be cloned
a wrapper around std::unique_ptr that supports deep copying and moving.
std::vector< std::string > Split(const std::string &text, char delim)
split text using a delimiter
Iter binary_search(Iter begin, Iter end, const T &val)
perform binary search on the range [begin, end).
defines configuration macros of treelite
void WrapText(std::ostringstream *p_stm, size_t *p_length, const std::string &str, size_t textwidth)
insert a string into a string stream, adding a newline character ( ) so that the string stream has no...
T && MoveUniquePtr(const std::unique_ptr< T > &ptr)
utility function to move an object pointed by a std::unique_ptr. After the move operation, the unique_ptr will hold an invalid object. Usage example:
std::unique_ptr< T > make_unique(Args &&...args)
construct a new object of type T and wraps it with a std::unique_ptr. This is support legacy compiles...
T TextToNumber(const std::string &str)
convert text to number