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