1 /* Copyright (c) 2017-2018 Hans-Kristian Arntzen
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining
4 * a copy of this software and associated documentation files (the
5 * "Software"), to deal in the Software without restriction, including
6 * without limitation the rights to use, copy, modify, merge, publish,
7 * distribute, sublicense, and/or sell copies of the Software, and to
8 * permit persons to whom the Software is furnished to do so, subject to
9 * the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be
12 * included in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 */
22
23 #pragma once
24
25 #include <stdio.h>
26 #include <stdint.h>
27 #include <string>
28 #include <sstream>
29 #include <vector>
30 #include <type_traits>
31
32 #if defined(HAVE_LIBRETRO)
33 #include "libretro.h"
34 namespace Granite
35 {
36 extern retro_log_printf_t libretro_log;
37 }
38 #define LOGE(...) do { if (::Granite::libretro_log) ::Granite::libretro_log(RETRO_LOG_ERROR, __VA_ARGS__); } while(0)
39 #define LOGI(...) do { if (::Granite::libretro_log) ::Granite::libretro_log(RETRO_LOG_INFO, __VA_ARGS__); } while(0)
40 #elif defined(_MSC_VER)
41 #define WIN32_LEAN_AND_MEAN
42 #include <windows.h>
43 #define LOGE(...) do { \
44 fprintf(stderr, "[ERROR]: " __VA_ARGS__); \
45 fflush(stderr); \
46 char buffer[4096]; \
47 sprintf(buffer, "[ERROR]: " __VA_ARGS__); \
48 OutputDebugStringA(buffer); \
49 } while(false)
50 #define LOGI(...) do { \
51 fprintf(stderr, "[INFO]: " __VA_ARGS__); \
52 fflush(stderr); \
53 char buffer[4096]; \
54 sprintf(buffer, "[INFO]: " __VA_ARGS__); \
55 OutputDebugStringA(buffer); \
56 } while(false)
57 #elif defined(ANDROID)
58 #include <android/log.h>
59 #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, "Granite", __VA_ARGS__)
60 #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, "Granite", __VA_ARGS__)
61 #else
62 #define LOGE(...) \
63 do \
64 { \
65 fprintf(stderr, "[ERROR]: " __VA_ARGS__); \
66 fflush(stderr); \
67 } while (false)
68
69 #define LOGI(...) \
70 do \
71 { \
72 fprintf(stderr, "[INFO]: " __VA_ARGS__); \
73 fflush(stderr); \
74 } while (false)
75 #endif
76
77 #define STRINGIFY(x) #x
78
79 #ifdef _MSC_VER
80 #include <intrin.h>
81 #endif
82
83 namespace Util
84 {
85 #ifdef __GNUC__
86 #define leading_zeroes(x) ((x) == 0 ? 32 : __builtin_clz(x))
87 #define trailing_zeroes(x) ((x) == 0 ? 32 : __builtin_ctz(x))
88 #define trailing_ones(x) __builtin_ctz(~(x))
89 #elif defined(_MSC_VER)
90 namespace Internal
91 {
92 static inline uint32_t clz(uint32_t x)
93 {
94 unsigned long result;
95 if (_BitScanReverse(&result, x))
96 return 31 - result;
97 else
98 return 32;
99 }
100
101 static inline uint32_t ctz(uint32_t x)
102 {
103 unsigned long result;
104 if (_BitScanForward(&result, x))
105 return result;
106 else
107 return 32;
108 }
109 }
110
111 #define leading_zeroes(x) ::Util::Internal::clz(x)
112 #define trailing_zeroes(x) ::Util::Internal::ctz(x)
113 #define trailing_ones(x) ::Util::Internal::ctz(~(x))
114 #else
115 #error "Implement me."
116 #endif
117
118 template<typename T>
for_each_bit(uint32_t value,const T & func)119 inline void for_each_bit(uint32_t value, const T &func)
120 {
121 while (value)
122 {
123 uint32_t bit = trailing_zeroes(value);
124 func(bit);
125 value &= ~(1u << bit);
126 }
127 }
128
129 template<typename T>
for_each_bit_range(uint32_t value,const T & func)130 inline void for_each_bit_range(uint32_t value, const T &func)
131 {
132 while (value)
133 {
134 uint32_t bit = trailing_zeroes(value);
135 uint32_t range = trailing_ones(value >> bit);
136 func(bit, range);
137 value &= ~((1u << (bit + range)) - 1);
138 }
139 }
140
next_pow2(uint32_t v)141 inline uint32_t next_pow2(uint32_t v)
142 {
143 v--;
144 v |= v >> 16;
145 v |= v >> 8;
146 v |= v >> 4;
147 v |= v >> 2;
148 v |= v >> 1;
149 return v + 1;
150 }
151
152 namespace inner
153 {
154 template<typename T>
join_helper(std::ostringstream & stream,T && t)155 void join_helper(std::ostringstream &stream, T &&t)
156 {
157 stream << std::forward<T>(t);
158 }
159
160 template<typename T, typename... Ts>
join_helper(std::ostringstream & stream,T && t,Ts &&...ts)161 void join_helper(std::ostringstream &stream, T &&t, Ts &&... ts)
162 {
163 stream << std::forward<T>(t);
164 join_helper(stream, std::forward<Ts>(ts)...);
165 }
166 }
167
168 template<typename... Ts>
join(Ts &&...ts)169 std::string join(Ts &&... ts)
170 {
171 std::ostringstream stream;
172 inner::join_helper(stream, std::forward<Ts>(ts)...);
173 return stream.str();
174 }
175
176 std::vector<std::string> split(const std::string &str, const char *delim);
177 std::vector<std::string> split_no_empty(const std::string &str, const char *delim);
178 std::string strip_whitespace(const std::string &str);
179
180 }
181