1 //
2 // Copyright (c) 2017-2020 Advanced Micro Devices, Inc. All rights reserved.
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a copy
5 // of this software and associated documentation files (the "Software"), to deal
6 // in the Software without restriction, including without limitation the rights
7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 // copies of the Software, and to permit persons to whom the Software is
9 // furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 // THE SOFTWARE.
21 //
22
23 #pragma once
24
25 #include "VmaUsage.h"
26
27 #include <iostream>
28 #include <fstream>
29 #include <vector>
30 #include <memory>
31 #include <algorithm>
32 #include <numeric>
33 #include <array>
34 #include <type_traits>
35 #include <utility>
36 #include <chrono>
37 #include <string>
38 #include <limits>
39
40 #include <cassert>
41 #include <cstdlib>
42 #include <cstdio>
43 #include <cstdarg>
44
45 typedef std::chrono::high_resolution_clock::time_point time_point;
46 typedef std::chrono::high_resolution_clock::duration duration;
47
ToFloatSeconds(duration d)48 inline float ToFloatSeconds(duration d)
49 {
50 return std::chrono::duration_cast<std::chrono::duration<float>>(d).count();
51 }
52
53 void SecondsToFriendlyStr(float seconds, std::string& out);
54
55 template <typename T>
ceil_div(T x,T y)56 T ceil_div(T x, T y)
57 {
58 return (x+y-1) / y;
59 }
60 template <typename T>
round_div(T x,T y)61 inline T round_div(T x, T y)
62 {
63 return (x+y/(T)2) / y;
64 }
65
66 template <typename T>
align_up(T val,T align)67 inline T align_up(T val, T align)
68 {
69 return (val + align - 1) / align * align;
70 }
71
72 struct StrRange
73 {
74 const char* beg;
75 const char* end;
76
StrRangeStrRange77 StrRange() { }
StrRangeStrRange78 StrRange(const char* beg, const char* end) : beg(beg), end(end) { }
StrRangeStrRange79 explicit StrRange(const char* sz) : beg(sz), end(sz + strlen(sz)) { }
StrRangeStrRange80 explicit StrRange(const std::string& s) : beg(s.data()), end(s.data() + s.length()) { }
81
lengthStrRange82 size_t length() const { return end - beg; }
to_strStrRange83 void to_str(std::string& out) const { out.assign(beg, end); }
84 };
85
StrRangeEq(const StrRange & lhs,const char * rhsSz)86 inline bool StrRangeEq(const StrRange& lhs, const char* rhsSz)
87 {
88 const size_t rhsLen = strlen(rhsSz);
89 return rhsLen == lhs.length() &&
90 memcmp(lhs.beg, rhsSz, rhsLen) == 0;
91 }
92
StrRangeToUint(const StrRange & s,uint32_t & out)93 inline bool StrRangeToUint(const StrRange& s, uint32_t& out)
94 {
95 char* end = (char*)s.end;
96 out = (uint32_t)strtoul(s.beg, &end, 10);
97 return end == s.end;
98 }
StrRangeToUint(const StrRange & s,uint64_t & out)99 inline bool StrRangeToUint(const StrRange& s, uint64_t& out)
100 {
101 char* end = (char*)s.end;
102 out = (uint64_t)strtoull(s.beg, &end, 10);
103 return end == s.end;
104 }
StrRangeToPtr(const StrRange & s,uint64_t & out)105 inline bool StrRangeToPtr(const StrRange& s, uint64_t& out)
106 {
107 char* end = (char*)s.end;
108 out = (uint64_t)strtoull(s.beg, &end, 16);
109 return end == s.end;
110 }
StrRangeToFloat(const StrRange & s,float & out)111 inline bool StrRangeToFloat(const StrRange& s, float& out)
112 {
113 char* end = (char*)s.end;
114 out = strtof(s.beg, &end);
115 return end == s.end;
116 }
StrRangeToBool(const StrRange & s,bool & out)117 inline bool StrRangeToBool(const StrRange& s, bool& out)
118 {
119 if(s.end - s.beg == 1)
120 {
121 if(*s.beg == '1')
122 {
123 out = true;
124 }
125 else if(*s.beg == '0')
126 {
127 out = false;
128 }
129 else
130 {
131 return false;
132 }
133 }
134 else
135 {
136 return false;
137 }
138
139 return true;
140 }
141 bool StrRangeToPtrList(const StrRange& s, std::vector<uint64_t>& out);
142
143 class LineSplit
144 {
145 public:
LineSplit(const char * data,size_t numBytes)146 LineSplit(const char* data, size_t numBytes) :
147 m_Data(data),
148 m_NumBytes(numBytes),
149 m_NextLineBeg(0),
150 m_NextLineIndex(0)
151 {
152 }
153
154 bool GetNextLine(StrRange& out);
GetNextLineIndex()155 size_t GetNextLineIndex() const { return m_NextLineIndex; }
156
157 private:
158 const char* const m_Data;
159 const size_t m_NumBytes;
160 size_t m_NextLineBeg;
161 size_t m_NextLineIndex;
162 };
163
164 class CsvSplit
165 {
166 public:
167 static const size_t RANGE_COUNT_MAX = 32;
168
169 void Set(const StrRange& line, size_t maxCount = RANGE_COUNT_MAX);
170
GetLine()171 const StrRange& GetLine() const { return m_Line; }
172
GetCount()173 size_t GetCount() const { return m_Count; }
GetRange(size_t index)174 StrRange GetRange(size_t index) const
175 {
176 if(index < m_Count)
177 {
178 return StrRange {
179 m_Line.beg + m_Ranges[index * 2],
180 m_Line.beg + m_Ranges[index * 2 + 1] };
181 }
182 else
183 {
184 return StrRange{0, 0};
185 }
186 }
187
188 private:
189 StrRange m_Line = { nullptr, nullptr };
190 size_t m_Count = 0;
191 size_t m_Ranges[RANGE_COUNT_MAX * 2]; // Pairs of begin-end.
192 };
193
194 class CmdLineParser
195 {
196 public:
197 enum RESULT
198 {
199 RESULT_OPT,
200 RESULT_PARAMETER,
201 RESULT_END,
202 RESULT_ERROR,
203 };
204
205 CmdLineParser(int argc, char **argv);
206 CmdLineParser(const char *CmdLine);
207
208 void RegisterOpt(uint32_t Id, char Opt, bool Parameter);
209 void RegisterOpt(uint32_t Id, const std::string &Opt, bool Parameter);
210
211 RESULT ReadNext();
212 uint32_t GetOptId();
213 const std::string & GetParameter();
214
215 private:
216 struct SHORT_OPT
217 {
218 uint32_t Id;
219 char Opt;
220 bool Parameter;
221
SHORT_OPTSHORT_OPT222 SHORT_OPT(uint32_t Id, char Opt, bool Parameter) : Id(Id), Opt(Opt), Parameter(Parameter) { }
223 };
224
225 struct LONG_OPT
226 {
227 uint32_t Id;
228 std::string Opt;
229 bool Parameter;
230
LONG_OPTLONG_OPT231 LONG_OPT(uint32_t Id, std::string Opt, bool Parameter) : Id(Id), Opt(Opt), Parameter(Parameter) { }
232 };
233
234 char **m_argv;
235 const char *m_CmdLine;
236 int m_argc;
237 size_t m_CmdLineLength;
238 size_t m_ArgIndex;
239
240 bool ReadNextArg(std::string *OutArg);
241
242 std::vector<SHORT_OPT> m_ShortOpts;
243 std::vector<LONG_OPT> m_LongOpts;
244
245 SHORT_OPT * FindShortOpt(char Opt);
246 LONG_OPT * FindLongOpt(const std::string &Opt);
247
248 bool m_InsideMultioption;
249 std::string m_LastArg;
250 size_t m_LastArgIndex;
251 uint32_t m_LastOptId;
252 std::string m_LastParameter;
253 };
254
255 /*
256 Parses and stores a sequence of ranges.
257
258 Upper range is inclusive.
259
260 Examples:
261
262 "1" -> [ {1, 1} ]
263 "1,10" -> [ {1, 1}, {10, 10} ]
264 "2-6" -> [ {2, 6} ]
265 "-8" -> [ {MIN, 8} ]
266 "12-" -> [ {12, MAX} ]
267 "1-10,12,15-" -> [ {1, 10}, {12, 12}, {15, MAX} ]
268
269 TODO: Optimize it: Do sorting and merging while parsing. Do binary search while
270 reading.
271 */
272 template<typename T>
273 class RangeSequence
274 {
275 public:
276 typedef std::pair<T, T> RangeType;
277
Clear()278 void Clear() { m_Ranges.clear(); }
279 bool Parse(const StrRange& str);
280
IsEmpty()281 bool IsEmpty() const { return m_Ranges.empty(); }
GetCount()282 size_t GetCount() const { return m_Ranges.size(); }
GetRanges()283 const RangeType* GetRanges() const { return m_Ranges.data(); }
284
285 bool Includes(T number) const;
286
287 private:
288 std::vector<RangeType> m_Ranges;
289 };
290
291 template<typename T>
Parse(const StrRange & str)292 bool RangeSequence<T>::Parse(const StrRange& str)
293 {
294 m_Ranges.clear();
295
296 StrRange currRange = { str.beg, str.beg };
297 while(currRange.beg < str.end)
298 {
299 currRange.end = currRange.beg + 1;
300 // Find next ',' or the end.
301 while(currRange.end < str.end && *currRange.end != ',')
302 {
303 ++currRange.end;
304 }
305
306 // Find '-' within this range.
307 const char* hyphenPos = currRange.beg;
308 while(hyphenPos < currRange.end && *hyphenPos != '-')
309 {
310 ++hyphenPos;
311 }
312
313 // No hyphen - single number like '10'.
314 if(hyphenPos == currRange.end)
315 {
316 RangeType range;
317 if(!StrRangeToUint(currRange, range.first))
318 {
319 return false;
320 }
321 range.second = range.first;
322 m_Ranges.push_back(range);
323 }
324 // Hyphen at the end, like '10-'.
325 else if(hyphenPos + 1 == currRange.end)
326 {
327 const StrRange numberRange = { currRange.beg, hyphenPos };
328 RangeType range;
329 if(!StrRangeToUint(numberRange, range.first))
330 {
331 return false;
332 }
333 range.second = std::numeric_limits<T>::max();
334 m_Ranges.push_back(range);
335 }
336 // Hyphen at the beginning, like "-10".
337 else if(hyphenPos == currRange.beg)
338 {
339 const StrRange numberRange = { currRange.beg + 1, currRange.end };
340 RangeType range;
341 range.first = std::numeric_limits<T>::min();
342 if(!StrRangeToUint(numberRange, range.second))
343 {
344 return false;
345 }
346 m_Ranges.push_back(range);
347 }
348 // Hyphen in the middle, like "1-10".
349 else
350 {
351 const StrRange numberRange1 = { currRange.beg, hyphenPos };
352 const StrRange numberRange2 = { hyphenPos + 1, currRange.end };
353 RangeType range;
354 if(!StrRangeToUint(numberRange1, range.first) ||
355 !StrRangeToUint(numberRange2, range.second) ||
356 range.second < range.first)
357 {
358 return false;
359 }
360 m_Ranges.push_back(range);
361 }
362
363 // Skip ','
364 currRange.beg = currRange.end + 1;
365 }
366
367 return true;
368 }
369
370 template<typename T>
Includes(T number)371 bool RangeSequence<T>::Includes(T number) const
372 {
373 for(const auto& it : m_Ranges)
374 {
375 if(number >= it.first && number <= it.second)
376 {
377 return true;
378 }
379 }
380 return false;
381 }
382
383 /*
384 class RandomNumberGenerator
385 {
386 public:
387 RandomNumberGenerator() : m_Value{GetTickCount()} {}
388 RandomNumberGenerator(uint32_t seed) : m_Value{seed} { }
389 void Seed(uint32_t seed) { m_Value = seed; }
390 uint32_t Generate() { return GenerateFast() ^ (GenerateFast() >> 7); }
391
392 private:
393 uint32_t m_Value;
394 uint32_t GenerateFast() { return m_Value = (m_Value * 196314165 + 907633515); }
395 };
396
397 enum class CONSOLE_COLOR
398 {
399 INFO,
400 NORMAL,
401 WARNING,
402 ERROR_,
403 COUNT
404 };
405
406 void SetConsoleColor(CONSOLE_COLOR color);
407
408 void PrintMessage(CONSOLE_COLOR color, const char* msg);
409 void PrintMessage(CONSOLE_COLOR color, const wchar_t* msg);
410
411 inline void Print(const char* msg) { PrintMessage(CONSOLE_COLOR::NORMAL, msg); }
412 inline void Print(const wchar_t* msg) { PrintMessage(CONSOLE_COLOR::NORMAL, msg); }
413 inline void PrintWarning(const char* msg) { PrintMessage(CONSOLE_COLOR::WARNING, msg); }
414 inline void PrintWarning(const wchar_t* msg) { PrintMessage(CONSOLE_COLOR::WARNING, msg); }
415 inline void PrintError(const char* msg) { PrintMessage(CONSOLE_COLOR::ERROR_, msg); }
416 inline void PrintError(const wchar_t* msg) { PrintMessage(CONSOLE_COLOR::ERROR_, msg); }
417
418 void PrintMessageV(CONSOLE_COLOR color, const char* format, va_list argList);
419 void PrintMessageV(CONSOLE_COLOR color, const wchar_t* format, va_list argList);
420 void PrintMessageF(CONSOLE_COLOR color, const char* format, ...);
421 void PrintMessageF(CONSOLE_COLOR color, const wchar_t* format, ...);
422 void PrintWarningF(const char* format, ...);
423 void PrintWarningF(const wchar_t* format, ...);
424 void PrintErrorF(const char* format, ...);
425 void PrintErrorF(const wchar_t* format, ...);
426 */
427