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