1 /*!
2  *  Copyright (c) 2014 by Contributors
3  * \file utils.h
4  * \brief simple utils to support the code
5  * \author Tianqi Chen
6  */
7 #ifndef RABIT_INTERNAL_UTILS_H_
8 #define RABIT_INTERNAL_UTILS_H_
9 
10 #include <rabit/base.h>
11 #include <cstring>
12 #include <cstdio>
13 #include <string>
14 #include <cstdlib>
15 #include <stdexcept>
16 #include <vector>
17 #include "dmlc/io.h"
18 #include "xgboost/logging.h"
19 #include <cstdarg>
20 
21 #if !defined(__GNUC__) || defined(__FreeBSD__) || defined(__DragonFly__)
22 #define fopen64 std::fopen
23 #endif  // !defined(__GNUC__) || defined(__FreeBSD__)
24 
25 #ifdef _MSC_VER
26 // NOTE: sprintf_s is not equivalent to snprintf,
27 // they are equivalent when success, which is sufficient for our case
28 #define snprintf sprintf_s
29 #define vsnprintf vsprintf_s
30 
31 #else
32 
33 #ifdef _FILE_OFFSET_BITS
34 #if _FILE_OFFSET_BITS == 32
35 #pragma message("Warning: FILE OFFSET BITS defined to be 32 bit")
36 #endif  // _FILE_OFFSET_BITS == 32
37 #endif  // _FILE_OFFSET_BITS
38 
39 #ifdef __APPLE__
40 #define off64_t off_t
41 #define fopen64 std::fopen
42 #endif  // __APPLE__
43 
44 extern "C" {
45 #include <sys/types.h>
46 }
47 #endif  // _MSC_VER
48 
49 #include <cinttypes>
50 
51 namespace rabit {
52 /*! \brief namespace for helper utils of the project */
53 namespace utils {
54 
55 /*! \brief error message buffer length */
56 const int kPrintBuffer = 1 << 12;
57 
58 /* \brief Case-insensitive string comparison */
CompareStringsCaseInsensitive(const char * s1,const char * s2)59 inline int CompareStringsCaseInsensitive(const char* s1, const char* s2) {
60 #ifdef _MSC_VER
61   return _stricmp(s1, s2);
62 #else  // _MSC_VER
63   return strcasecmp(s1, s2);
64 #endif  // _MSC_VER
65 }
66 
67 /* \brief parse config string too bool*/
StringToBool(const char * s)68 inline bool StringToBool(const char* s) {
69   return CompareStringsCaseInsensitive(s, "true") == 0 || atoi(s) != 0;
70 }
71 
72 /*! \brief printf, prints messages to the console */
Printf(const char * fmt,...)73 inline void Printf(const char *fmt, ...) {
74   std::string msg(kPrintBuffer, '\0');
75   va_list args;
76   va_start(args, fmt);
77   vsnprintf(&msg[0], kPrintBuffer, fmt, args);
78   va_end(args);
79   LOG(CONSOLE) << msg;
80 }
81 
82 /*! \brief assert a condition is true, use this to handle debug information */
Assert(bool exp,const char * fmt,...)83 inline void Assert(bool exp, const char *fmt, ...) {
84   if (!exp) {
85     std::string msg(kPrintBuffer, '\0');
86     va_list args;
87     va_start(args, fmt);
88     vsnprintf(&msg[0], kPrintBuffer, fmt, args);
89     va_end(args);
90     LOG(FATAL) << msg;
91   }
92 }
93 
94 /*!\brief same as assert, but this is intended to be used as a message for users */
Check(bool exp,const char * fmt,...)95 inline void Check(bool exp, const char *fmt, ...) {
96   if (!exp) {
97     std::string msg(kPrintBuffer, '\0');
98     va_list args;
99     va_start(args, fmt);
100     vsnprintf(&msg[0], kPrintBuffer, fmt, args);
101     va_end(args);
102     LOG(FATAL) << msg;
103   }
104 }
105 
106 /*! \brief report error message, same as check */
Error(const char * fmt,...)107 inline void Error(const char *fmt, ...) {
108   {
109     std::string msg(kPrintBuffer, '\0');
110     va_list args;
111     va_start(args, fmt);
112     vsnprintf(&msg[0], kPrintBuffer, fmt, args);
113     va_end(args);
114     LOG(FATAL) << msg;
115   }
116 }
117 }  // namespace utils
118 
119 // Can not use std::min on Windows with msvc due to:
120 // error C2589: '(': illegal token on right side of '::'
121 template <typename T>
Min(T const & l,T const & r)122 auto Min(T const& l, T const& r) {
123   return l < r ? l : r;
124 }
125 // same with Min
126 template <typename T>
Max(T const & l,T const & r)127 auto Max(T const& l, T const& r) {
128   return l > r ? l : r;
129 }
130 
131 // easy utils that can be directly accessed in xgboost
132 /*! \brief get the beginning address of a vector */
133 template<typename T>
BeginPtr(std::vector<T> & vec)134 inline T *BeginPtr(std::vector<T> &vec) {  // NOLINT(*)
135   if (vec.size() == 0) {
136     return nullptr;
137   } else {
138     return &vec[0];
139   }
140 }
BeginPtr(std::string & str)141 inline char* BeginPtr(std::string &str) {  // NOLINT(*)
142   if (str.length() == 0) return nullptr;
143   return &str[0];
144 }
BeginPtr(const std::string & str)145 inline const char* BeginPtr(const std::string &str) {
146   if (str.length() == 0) return nullptr;
147   return &str[0];
148 }
149 }  // namespace rabit
150 #endif  // RABIT_INTERNAL_UTILS_H_
151