source: CLRX/CLRadeonExtender/trunk/CLRX/utils/Utilities.h @ 3370

Last change on this file since 3370 was 3370, checked in by matszpk, 13 months ago

CLRadeonExtender: Add checking C++11 Thread call_once. Add detection OpenCL in MinGW64 environment.

File size: 29.6 KB
Line 
1/*
2 *  CLRadeonExtender - Unofficial OpenCL Radeon Extensions Library
3 *  Copyright (C) 2014-2017 Mateusz Szpakowski
4 *
5 *  This library is free software; you can redistribute it and/or
6 *  modify it under the terms of the GNU Lesser General Public
7 *  License as published by the Free Software Foundation; either
8 *  version 2.1 of the License, or (at your option) any later version.
9 *
10 *  This library is distributed in the hope that it will be useful,
11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 *  Lesser General Public License for more details.
14 *
15 *  You should have received a copy of the GNU Lesser General Public
16 *  License along with this library; if not, write to the Free Software
17 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18 */
19/*! \file Utilities.h
20 * \brief utilities for other libraries and programs
21 */
22
23#ifndef __CLRX_UTILITIES_H__
24#define __CLRX_UTILITIES_H__
25
26#include <CLRX/Config.h>
27#include <exception>
28#include <string>
29#include <vector>
30#include <cstdlib>
31#include <cstring>
32#include <cstdint>
33#include <mutex>
34#include <atomic>
35#include <CLRX/utils/Containers.h>
36#include <CLRX/utils/CString.h>
37
38/// main namespace
39namespace CLRX
40{
41
42/// non copyable and non movable base structure (class)
43struct NonCopyableAndNonMovable
44{
45    /// constructor
46    NonCopyableAndNonMovable() { }
47    /// copy-constructor
48    NonCopyableAndNonMovable(const NonCopyableAndNonMovable&) = delete;
49    /// move-constructor
50    NonCopyableAndNonMovable(NonCopyableAndNonMovable&&) = delete;
51    /// copy-assignment
52    NonCopyableAndNonMovable& operator=(const NonCopyableAndNonMovable&) = delete;
53    /// move-asignment
54    NonCopyableAndNonMovable& operator=(NonCopyableAndNonMovable&&) = delete;
55};
56
57/// exception class
58class Exception: public std::exception
59{
60protected:
61    std::string message;    ///< message
62public:
63    /// empty constructor
64    Exception() = default;
65    /// constructor with messasge
66    explicit Exception(const std::string& message);
67    /// destructor
68    virtual ~Exception() noexcept = default;
69   
70    /// get exception message
71    const char* what() const noexcept;
72};
73
74/// line number type
75typedef uint64_t LineNo;
76
77/// column number type
78typedef size_t ColNo;
79
80/// parse exception class
81class ParseException: public Exception
82{
83public:
84    /// empty constructor
85    ParseException() = default;
86    /// constructor with message
87    explicit ParseException(const std::string& message);
88    /// constructor with message and line number
89    ParseException(LineNo lineNo, const std::string& message);
90    /// constructor with message and line number and column number
91    ParseException(LineNo lineNo, ColNo charNo, const std::string& message);
92    /// destructor
93    virtual ~ParseException() noexcept = default;
94};
95
96/// type for declaring various flags
97typedef uint32_t Flags;
98
99enum: Flags {
100    FLAGS_ALL = 0xffffffffU
101};
102
103enum: Flags {
104    DYNLIB_LOCAL = 0,   ///< treat symbols locally
105    DYNLIB_LAZY = 1,    ///< resolve symbols when is needed
106    DYNLIB_NOW = 2,     ///< resolve symbols now
107    DYNLIB_MODE1_MASK = 7,  ///
108    DYNLIB_GLOBAL = 8   ///< treats symbols globally
109};
110
111/// dynamic library class
112class DynLibrary: public NonCopyableAndNonMovable
113{
114private:
115    void* handle;
116    static std::mutex mutex;
117public:
118    DynLibrary();
119    /** constructor - loads library
120     * \param filename library filename
121     * \param flags flags specifies way to load library and a resolving symbols
122     */
123    DynLibrary(const char* filename, Flags flags = 0);
124    ~DynLibrary();
125   
126    /** loads library
127     * \param filename library filename
128     * \param flags flags specifies way to load library and a resolving symbols
129     */
130    void load(const char* filename, Flags flags = 0);
131    /// unload library
132    void unload();
133   
134    /// get symbol
135    void* getSymbol(const char* symbolName);
136};
137
138/* parse utilities */
139
140/// check whether character is space
141inline bool isSpace(unsigned char c);
142
143inline bool isSpace(unsigned char c)
144{ return (c == 32 || (c < 32 && (0x3e00U & (1U<<c)))); }
145
146/// check whether character is digit
147inline bool isODigit(unsigned char c);
148
149inline bool isODigit(unsigned char c)
150{ return c>='0' && c<= '7'; }
151
152/// check whether character is digit
153inline bool isDigit(unsigned char c);
154
155inline bool isDigit(unsigned char c)
156{ return c>='0' && c<= '9'; }
157
158/// check whether character is hexadecimal digit
159inline bool isXDigit(unsigned char c);
160
161inline bool isXDigit(unsigned char c)
162{ return (c>='0' && c<= '9') || (c>='a' && c<='f') || (c>='A' && c<='F'); }
163
164/// check whether character is digit
165inline bool isAlpha(unsigned char c);
166
167inline bool isAlpha(unsigned char c)
168{ return (c>='a' && c<='z') || (c>='A' && c<='Z'); }
169
170/// check whether character is digit
171inline bool isAlnum(unsigned char c);
172
173inline bool isAlnum(unsigned char c)
174{ return (c>='0' && c<= '9') || (c>='a' && c<='z') || (c>='A' && c<='Z'); }
175
176/// skip spaces from cString
177inline const char* skipSpaces(const char* s);
178
179inline const char* skipSpaces(const char* s)
180{
181    while (isSpace(*s)) s++;
182    return s;
183}
184
185/// skip spaces from cString
186inline const char* skipSpacesAtEnd(const char* s, size_t length);
187
188inline const char* skipSpacesAtEnd(const char* s, size_t length)
189{
190    const char* t = s+length;
191    if (t == s) return s;
192    for (t--; t != s-1 && isSpace(*t); t--);
193    return t+1;
194}
195
196/// parses integer or float point formatted looks like C-style
197/** parses integer or float point from str string. inend can points
198 * to end of string or can be null. Function throws ParseException when number in string
199 * is out of range, when string does not have number or inend points to string.
200 * Function accepts decimal format, octal form (with prefix '0'), hexadecimal form
201 * (prefix '0x' or '0X'), and binary form (prefix '0b' or '0B').
202 * For floating points function accepts decimal format and binary format.
203 * Result is rounded to nearest even
204 * (if two values are equally close will be choosen a even value).
205 * Currently only IEEE-754 format is supported.
206 * \param str input string pointer
207 * \param inend pointer points to end of string or null if not end specified
208 * \param outend returns end of number in string (returned even if exception thrown)
209 * \return parsed integer value
210 */
211template<typename T>
212extern T cstrtovCStyle(const char* str, const char* inend, const char*& outend);
213
214/// parse environment variable
215/** parse environment variable
216 * \param envVar - name of environment variable
217 * \param defaultValue - value that will be returned if environment variable is not present
218 * \return value
219 */
220template<typename T>
221T parseEnvVariable(const char* envVar, const T& defaultValue = T())
222{
223    const char* var = getenv(envVar);
224    if (var == nullptr)
225        return defaultValue;
226    var = skipSpaces(var);
227    if (*var == 0)
228        return defaultValue;
229    const char* outend;
230    try
231    { return cstrtovCStyle<T>(var, nullptr, outend); }
232    catch(const ParseException& ex)
233    { return defaultValue; }
234}
235
236/// parse environment variable of cxuchar type
237extern template
238cxuchar parseEnvVariable<cxuchar>(const char* envVar, const cxuchar& defaultValue);
239
240/// parse environment variable of cxchar type
241extern template
242cxchar parseEnvVariable<cxchar>(const char* envVar, const cxchar& defaultValue);
243
244/// parse environment variable of cxuint type
245extern template
246cxuint parseEnvVariable<cxuint>(const char* envVar, const cxuint& defaultValue);
247
248/// parse environment variable of cxint type
249extern template
250cxint parseEnvVariable<cxint>(const char* envVar, const cxint& defaultValue);
251
252/// parse environment variable of cxushort type
253extern template
254cxushort parseEnvVariable<cxushort>(const char* envVar, const cxushort& defaultValue);
255
256/// parse environment variable of cxshort type
257extern template
258cxshort parseEnvVariable<cxshort>(const char* envVar, const cxshort& defaultValue);
259
260/// parse environment variable of cxulong type
261extern template
262cxulong parseEnvVariable<cxulong>(const char* envVar, const cxulong& defaultValue);
263
264/// parse environment variable of cxlong type
265extern template
266cxlong parseEnvVariable<cxlong>(const char* envVar, const cxlong& defaultValue);
267
268/// parse environment variable of cxullong type
269extern template
270cxullong parseEnvVariable<cxullong>(const char* envVar, const cxullong& defaultValue);
271
272/// parse environment variable of cxllong type
273extern template
274cxllong parseEnvVariable<cxllong>(const char* envVar, const cxllong& defaultValue);
275
276/// parse environment variable of float type
277extern template
278float parseEnvVariable<float>(const char* envVar, const float& defaultValue);
279
280/// parse environment variable of double type
281extern template
282double parseEnvVariable<double>(const char* envVar, const double& defaultValue);
283
284#ifndef __UTILITIES_MODULE__
285
286/// parse environment variable of string type
287extern template
288std::string parseEnvVariable<std::string>(const char* envVar,
289              const std::string& defaultValue);
290
291/// parse environment variable of boolean type
292extern template
293bool parseEnvVariable<bool>(const char* envVar, const bool& defaultValue);
294
295#endif
296
297/// function class that returns true if first C string is less than second
298struct CStringLess
299{
300    /// operator of call
301    inline bool operator()(const char* c1, const char* c2) const
302    { return ::strcmp(c1, c2)<0; }
303};
304
305/// function class that returns true if first C string is less than second (ignore case)
306struct CStringCaseLess
307{
308    /// operator of call
309    inline bool operator()(const char* c1, const char* c2) const
310    { return ::strcasecmp(c1, c2)<0; }
311};
312
313/// function class that returns true if C strings are equal
314struct CStringEqual
315{
316    /// operator of call
317    inline bool operator()(const char* c1, const char* c2) const
318    { return ::strcmp(c1, c2)==0; }
319};
320
321/// generate hash function for C string
322struct CStringHash
323{
324    /// operator of call
325    size_t operator()(const char* c) const
326    {
327        if (c == nullptr)
328            return 0;
329        size_t hash = 0;
330       
331        for (const char* p = c; *p != 0; p++)
332            hash = ((hash<<8)^(cxbyte)*p)*size_t(0xbf146a3dU);
333        return hash;
334    }
335};
336
337/// counts leading zeroes for 32-bit unsigned integer. For zero behavior is undefined
338inline cxuint CLZ32(uint32_t v);
339/// counts leading zeroes for 64-bit unsigned integer. For zero behavior is undefined
340inline cxuint CLZ64(uint64_t v);
341
342inline cxuint CLZ32(uint32_t v)
343{
344#ifdef __GNUC__
345    return __builtin_clz(v);
346#else
347    cxuint count = 0;
348    for (uint32_t t = 1U<<31; t > v; t>>=1, count++);
349    return count;
350#endif
351}
352
353inline cxuint CLZ64(uint64_t v)
354{
355#ifdef __GNUC__
356    return __builtin_clzll(v);
357#else
358    cxuint count = 0;
359    for (uint64_t t = 1ULL<<63; t > v; t>>=1, count++);
360    return count;
361#endif
362}
363
364/// safely compares sum of two unsigned integers with other unsigned integer
365template<typename T, typename T2>
366inline bool usumGt(T a, T b, T2 c)
367{ return ((a+b)>c) || ((a+b)<a); }
368
369/// safely compares sum of two unsigned integers with other unsigned integer
370template<typename T, typename T2>
371inline bool usumGe(T a, T b, T2 c)
372{ return ((a+b)>=c) || ((a+b)<a); }
373
374/// escapes string into C-style string
375extern std::string escapeStringCStyle(size_t strSize, const char* str);
376
377/// escape string into C-style string
378inline std::string escapeStringCStyle(const std::string& str)
379{ return escapeStringCStyle(str.size(), str.c_str()); }
380
381/// escape string into C-style string
382inline std::string escapeStringCStyle(const CString& str)
383{ return escapeStringCStyle(str.size(), str.c_str()); }
384
385
386/// escapes string into C-style string
387/**
388 * \param strSize string size
389 * \param str string
390 * \param outMaxSize output max size (including null-character)
391 * \param outStr output string
392 * \param outSize size of output string
393 * \return number of processed input characters
394 */
395extern size_t escapeStringCStyle(size_t strSize, const char* str,
396                 size_t outMaxSize, char* outStr, size_t& outSize);
397
398/// parses unsigned integer regardless locales
399/** parses unsigned integer in decimal form from str string. inend can points
400 * to end of string or can be null. Function throws ParseException when number in string
401 * is out of range, when string does not have number or inend points to string.
402 * \param str input string pointer
403 * \param inend pointer points to end of string or null if not end specified
404 * \param outend returns end of number in string (returned even if exception thrown)
405 * \return parsed integer value
406 */
407extern cxuint cstrtoui(const char* str, const char* inend, const char*& outend);
408
409/// parse 64-bit signed integer
410extern int64_t cstrtoiXCStyle(const char* str, const char* inend,
411             const char*& outend, cxuint bits);
412
413/// parse 64-bit unsigned integer
414extern uint64_t cstrtouXCStyle(const char* str, const char* inend,
415             const char*& outend, cxuint bits);
416
417/// Unsigned 128-bit integer
418struct UInt128
419{
420    uint64_t lo; ///< low part
421    uint64_t hi; ///< high part
422};
423
424/// parse 64-bit float value
425extern uint64_t cstrtofXCStyle(const char* str, const char* inend,
426             const char*& outend, cxuint expBits, cxuint mantisaBits);
427
428/// parse 128-bit unsigned integer
429extern UInt128 cstrtou128CStyle(const char* str, const char* inend, const char*& outend);
430
431/* cstrtovcstyle impls */
432
433/// parse cxuchar value from string
434template<> inline
435cxuchar cstrtovCStyle<cxuchar>(const char* str, const char* inend, const char*& outend)
436{ return cstrtouXCStyle(str, inend, outend, sizeof(cxuchar)<<3); }
437
438/// parse cxchar value from string
439template<> inline
440cxchar cstrtovCStyle<cxchar>(const char* str, const char* inend, const char*& outend)
441{ return cstrtoiXCStyle(str, inend, outend, sizeof(cxchar)<<3); }
442
443/// parse cxuint value from string
444template<> inline
445cxuint cstrtovCStyle<cxuint>(const char* str, const char* inend, const char*& outend)
446{ return cstrtouXCStyle(str, inend, outend, sizeof(cxuint)<<3); }
447
448/// parse cxint value from string
449template<> inline
450cxint cstrtovCStyle<cxint>(const char* str, const char* inend, const char*& outend)
451{ return cstrtoiXCStyle(str, inend, outend, sizeof(cxint)<<3); }
452
453/// parse cxushort value from string
454template<> inline
455cxushort cstrtovCStyle<cxushort>(const char* str, const char* inend, const char*& outend)
456{ return cstrtouXCStyle(str, inend, outend, sizeof(cxushort)<<3); }
457
458/// parse cxshort value from string
459template<> inline
460cxshort cstrtovCStyle<cxshort>(const char* str, const char* inend, const char*& outend)
461{ return cstrtoiXCStyle(str, inend, outend, sizeof(cxshort)<<3); }
462
463/// parse cxulong value from string
464template<> inline
465cxulong cstrtovCStyle<cxulong>(const char* str, const char* inend, const char*& outend)
466{ return cstrtouXCStyle(str, inend, outend, sizeof(cxulong)<<3); }
467
468/// parse cxlong value from string
469template<> inline
470cxlong cstrtovCStyle<cxlong>(const char* str, const char* inend, const char*& outend)
471{ return cstrtoiXCStyle(str, inend, outend, sizeof(cxlong)<<3); }
472
473/// parse cxullong value from string
474template<> inline
475cxullong cstrtovCStyle<cxullong>(const char* str, const char* inend, const char*& outend)
476{ return cstrtouXCStyle(str, inend, outend, sizeof(cxullong)<<3); }
477
478/// parse cxllong value from string
479template<> inline
480cxllong cstrtovCStyle<cxllong>(const char* str, const char* inend, const char*& outend)
481{ return cstrtoiXCStyle(str, inend, outend, sizeof(cxllong)<<3); }
482
483/// parse UInt128 value from string
484template<> inline
485UInt128 cstrtovCStyle<UInt128>(const char* str, const char* inend, const char*& outend)
486{ return cstrtou128CStyle(str, inend, outend); }
487
488/// parse float value from string
489template<> inline
490float cstrtovCStyle<float>(const char* str, const char* inend, const char*& outend)
491{
492    union {
493        float f;
494        uint32_t u;
495    } v;
496    v.u = cstrtofXCStyle(str, inend, outend, 8, 23);
497    return v.f;
498}
499
500/// parse double value from string
501template<> inline
502double cstrtovCStyle<double>(const char* str, const char* inend, const char*& outend)
503{
504    union {
505        double d;
506        uint64_t u;
507    } v;
508    v.u = cstrtofXCStyle(str, inend, outend, 11, 52);
509    return v.d;
510}
511
512/// parses half float formatted looks like C-style
513/** parses half floating point from str string. inend can points
514 * to end of string or can be null. Function throws ParseException when number in string
515 * is out of range, when string does not have number or inend points to string.
516 * Function accepts decimal format and binary format. Result is rounded to nearest even
517 * (if two values are equally close will be choosen a even value).
518 * Currently only IEEE-754 format is supported.
519 * \param str input string pointer
520 * \param inend pointer points to end of string or null if not end specified
521 * \param outend returns end of number in string (returned even if exception thrown)
522 * \return parsed floating point value
523 */
524cxushort cstrtohCStyle(const char* str, const char* inend, const char*& outend);
525
526/// parse half value from string
527inline cxushort cstrtohCStyle(const char* str, const char* inend, const char*& outend)
528{ return cstrtofXCStyle(str, inend, outend, 5, 10); }
529
530/// format unsigned value to string
531extern size_t uXtocstrCStyle(uint64_t value, char* str, size_t maxSize, cxuint radix,
532            cxuint width, bool prefix);
533
534/// formast signed value to string
535extern size_t iXtocstrCStyle(int64_t value, char* str, size_t maxSize, cxuint radix,
536            cxuint width, bool prefix);
537
538/// formats an integer
539/** formats an integer in C-style formatting.
540 * \param value integer value
541 * \param str output string
542 * \param maxSize max size of string (including null-character)
543 * \param radix radix of digits (2, 8, 10, 16)
544 * \param width max number of digits in number
545 * \param prefix adds required prefix if true
546 * \return length of output string (excluding null-character)
547 */
548template<typename T>
549extern size_t itocstrCStyle(T value, char* str, size_t maxSize, cxuint radix = 10,
550       cxuint width = 0, bool prefix = true);
551
552/// format cxuchar value to string
553template<> inline
554size_t itocstrCStyle<cxuchar>(cxuchar value, char* str, size_t maxSize, cxuint radix,
555       cxuint width, bool prefix)
556{ return uXtocstrCStyle(value, str, maxSize, radix, width, prefix); }
557
558/// format cxchar value to string
559template<> inline
560size_t itocstrCStyle<cxchar>(cxchar value, char* str, size_t maxSize, cxuint radix,
561       cxuint width, bool prefix)
562{ return iXtocstrCStyle(value, str, maxSize, radix, width, prefix); }
563
564/// format cxushort value to string
565template<> inline
566size_t itocstrCStyle<cxushort>(cxushort value, char* str, size_t maxSize, cxuint radix,
567       cxuint width, bool prefix)
568{ return uXtocstrCStyle(value, str, maxSize, radix, width, prefix); }
569
570/// format cxshort value to string
571template<> inline
572size_t itocstrCStyle<cxshort>(cxshort value, char* str, size_t maxSize, cxuint radix,
573       cxuint width, bool prefix)
574{ return iXtocstrCStyle(value, str, maxSize, radix, width, prefix); }
575
576/// format cxuint value to string
577template<> inline
578size_t itocstrCStyle<cxuint>(cxuint value, char* str, size_t maxSize, cxuint radix,
579       cxuint width, bool prefix)
580{ return uXtocstrCStyle(value, str, maxSize, radix, width, prefix); }
581
582/// format cxint value to string
583template<> inline
584size_t itocstrCStyle<cxint>(cxint value, char* str, size_t maxSize, cxuint radix,
585       cxuint width, bool prefix)
586{ return iXtocstrCStyle(value, str, maxSize, radix, width, prefix); }
587
588/// format cxulong value to string
589template<> inline
590size_t itocstrCStyle<cxulong>(cxulong value, char* str, size_t maxSize, cxuint radix,
591       cxuint width, bool prefix)
592{ return uXtocstrCStyle(value, str, maxSize, radix, width, prefix); }
593
594/// format cxlong value to string
595template<> inline
596size_t itocstrCStyle<cxlong>(cxlong value, char* str, size_t maxSize, cxuint radix,
597       cxuint width, bool prefix)
598{ return iXtocstrCStyle(value, str, maxSize, radix, width, prefix); }
599
600/// format cxullong value to string
601template<> inline
602size_t itocstrCStyle<cxullong>(cxullong value, char* str, size_t maxSize, cxuint radix,
603       cxuint width , bool prefix)
604{ return uXtocstrCStyle(value, str, maxSize, radix, width, prefix); }
605
606/// format cxllong value to string
607template<> inline
608size_t itocstrCStyle<cxllong>(cxllong value, char* str, size_t maxSize, cxuint radix,
609       cxuint width, bool prefix)
610{ return iXtocstrCStyle(value, str, maxSize, radix, width, prefix); }
611
612/// format float value to string
613extern size_t fXtocstrCStyle(uint64_t value, char* str, size_t maxSize,
614        bool scientific, cxuint expBits, cxuint mantisaBits);
615
616/// formats half float in C-style
617/** formats to string the half float in C-style formatting. This function handles 2 modes
618 * of printing value: human readable and scientific. Scientific mode forces form with
619 * decimal exponent.
620 * Currently only IEEE-754 format is supported.
621 * \param value float value
622 * \param str output string
623 * \param maxSize max size of string (including null-character)
624 * \param scientific enable scientific mode
625 * \return length of output string (excluding null-character)
626 */
627size_t htocstrCStyle(cxushort value, char* str, size_t maxSize,
628                            bool scientific = false);
629
630inline size_t htocstrCStyle(cxushort value, char* str, size_t maxSize, bool scientific)
631{ return fXtocstrCStyle(value, str, maxSize, scientific, 5, 10); }
632
633/// formats single float in C-style
634/** formats to string the single float in C-style formatting. This function handles 2 modes
635 * of printing value: human readable and scientific. Scientific mode forces form with
636 * decimal exponent.
637 * Currently only IEEE-754 format is supported.
638 * \param value float value
639 * \param str output string
640 * \param maxSize max size of string (including null-character)
641 * \param scientific enable scientific mode
642 * \return length of output string (excluding null-character)
643 */
644size_t ftocstrCStyle(float value, char* str, size_t maxSize,
645                            bool scientific = false);
646
647inline size_t ftocstrCStyle(float value, char* str, size_t maxSize, bool scientific)
648{
649    union {
650        float f;
651        uint32_t u;
652    } v;
653    v.f = value;
654    return fXtocstrCStyle(v.u, str, maxSize, scientific, 8, 23);
655}
656
657/// formats double float in C-style
658/** formats to string the double float in C-style formatting. This function handles 2 modes
659 * of printing value: human readable and scientific. Scientific mode forces form with
660 * decimal exponent.
661 * Currently only IEEE-754 format is supported.
662 * \param value float value
663 * \param str output string
664 * \param maxSize max size of string (including null-character)
665 * \param scientific enable scientific mode
666 * \return length of output string (excluding null-character)
667 */
668size_t dtocstrCStyle(double value, char* str, size_t maxSize,
669                            bool scientific = false);
670
671inline size_t dtocstrCStyle(double value, char* str, size_t maxSize, bool scientific)
672{
673    union {
674        double d;
675        uint64_t u;
676    } v;
677    v.d = value;
678    return fXtocstrCStyle(v.u, str, maxSize, scientific, 11, 52);
679}
680
681/* file system utilities */
682
683/// returns true if path refers to directory
684extern bool isDirectory(const char* path);
685/// returns true if file exists
686extern bool isFileExists(const char* path);
687
688/// load data from file (any regular or pipe or device)
689/**
690 * \param filename filename
691 * \return array of data (can be greater than size of data from file)
692 */
693extern Array<cxbyte> loadDataFromFile(const char* filename);
694
695/// convert to filesystem from unified path (with slashes)
696extern void filesystemPath(char* path);
697/// convert to filesystem from unified path (with slashes)
698extern void filesystemPath(std::string& path);
699
700/// join two paths
701extern std::string joinPaths(const std::string& path1, const std::string& path2);
702
703/// get file timestamp in nanosecond since Unix epoch
704extern uint64_t getFileTimestamp(const char* filename);
705
706/// get user's home directory
707extern std::string getHomeDir();
708/// create directory
709extern void makeDir(const char* dirname);
710/// run executable with output, returns array of output
711extern Array<cxbyte> runExecWithOutput(const char* program, const char** argv);
712
713/// find amdocl library, returns path if found, otherwise returns empty string
714extern std::string findAmdOCL();
715
716/// find Mesa OpenCL library, returns path if found, otherwise returns empty string
717extern std::string findMesaOCL();
718
719/// find LLVM config, returns path if found, otherwise returns empty string
720extern std::string findLLVMConfig();
721
722/*
723 * Reference support
724 */
725
726/// reference countable object
727class RefCountable
728{
729private:
730    mutable std::atomic<size_t> refCount;
731public:
732    /// constructor
733    RefCountable() : refCount(1)
734    { }
735   
736    /// reference object
737    void reference() const
738    {
739        refCount.fetch_add(1);
740    }
741   
742    /// unreference object (returns true if no reference count)
743    bool unreference() const
744    {
745        return (refCount.fetch_sub(1) == 1);
746    }
747};
748
749/// reference countable object (only for single threading usage)
750class FastRefCountable
751{
752private:
753    mutable size_t refCount;
754public:
755    /// constructor
756    FastRefCountable() : refCount(1)
757    { }
758   
759    /// reference object
760    void reference() const
761    {
762        refCount++;
763    }
764   
765    /// unreference object (returns true if no reference count)
766    bool unreference() const
767    {
768        return (--refCount == 0);
769    }
770};
771
772/// reference pointer based on Glibmm refptr
773template<typename T>
774class RefPtr
775{
776private:
777    T* ptr;
778public:
779    /// empty constructor
780    RefPtr(): ptr(nullptr)
781    { }
782   
783    /// constructor from pointer
784    explicit RefPtr(T* inputPtr) : ptr(inputPtr)
785    { }
786   
787    /// copy constructor
788    RefPtr(const RefPtr<T>& refPtr) : ptr(refPtr.ptr)
789    {
790        if (ptr != nullptr)
791            ptr->reference();
792    }
793   
794    /// move constructor
795    RefPtr(RefPtr<T>&& refPtr) : ptr(refPtr.ptr)
796    { refPtr.ptr = nullptr; }
797   
798    /// destructor
799    ~RefPtr()
800    {
801        if (ptr != nullptr)
802            if (ptr->unreference())
803                delete ptr;
804    }
805   
806    /// copy constructor
807    RefPtr<T>& operator=(const RefPtr<T>& refPtr)
808    {
809        if (ptr != nullptr)
810            if (ptr->unreference())
811                delete ptr;
812        if (refPtr.ptr != nullptr)
813            refPtr.ptr->reference();
814        ptr = refPtr.ptr;
815        return *this;
816    }
817    /// move constructor
818    RefPtr<T>& operator=(RefPtr<T>&& refPtr)
819    {
820        if (ptr != nullptr)
821            if (ptr->unreference())
822                delete ptr;
823        ptr = refPtr.ptr;
824        refPtr.ptr = nullptr;
825        return *this;
826    }
827   
828    /// equality operator
829    bool operator==(const RefPtr<T>& refPtr) const
830    { return ptr == refPtr.ptr; }
831    /// unequality operator
832    bool operator!=(const RefPtr<T>& refPtr) const
833    { return ptr != refPtr.ptr; }
834   
835    /// return true if not null
836    operator bool() const
837    { return ptr!=nullptr; }
838   
839    /// return true if null
840    bool operator!() const
841    { return ptr==nullptr; }
842   
843    /// get elem from pointer
844    T* operator->() const
845    { return ptr; }
846   
847    /// reset refpointer
848    void reset()
849    {
850        if (ptr != nullptr)
851            if (ptr->unreference())
852                delete ptr;
853        ptr = nullptr;
854    }
855   
856    /// swap between refpointers
857    void swap(RefPtr<T>& refPtr)
858    {
859        T* tmp = ptr;
860        ptr = refPtr.ptr;
861        refPtr.ptr = tmp;
862    }
863   
864    /// const cast
865    template<typename DestType>
866    RefPtr<DestType> constCast() const
867    {
868        DestType* p = const_cast<DestType*>(ptr);
869        if (p != nullptr)
870            p->reference();
871        return RefPtr<DestType>(p);
872    }
873    /// static cast
874    template<typename DestType>
875    RefPtr<DestType> staticCast() const
876    {
877        DestType* p = static_cast<DestType*>(ptr);
878        if (p != nullptr)
879            p->reference();
880        return RefPtr<DestType>(p);
881    }
882    /// dynamic cast
883    template<typename DestType>
884    RefPtr<DestType> dynamicCast() const
885    {
886        DestType* p = dynamic_cast<DestType*>(ptr);
887        if (p != nullptr)
888            p->reference();
889        return RefPtr<DestType>(p);
890    }
891};
892
893/// convert character to lowercase
894inline char toLower(char c);
895
896inline char toLower(char c)
897{ return  (c >= 'A' &&  c <= 'Z') ? c - 'A' + 'a' : c; }
898
899/// convert string to lowercase
900inline void toLowerString(std::string& string);
901
902inline void toLowerString(std::string& string)
903{ std::transform(string.begin(), string.end(), string.begin(), toLower); }
904
905/// convert string to lowercase
906inline void toLowerString(char* cstr);
907
908inline void toLowerString(char* cstr)
909{
910    for (; *cstr!=0; cstr++)
911        *cstr = toLower(*cstr);
912}
913
914/// convert string to lowercase
915inline void toLowerString(CString& string);
916
917inline void toLowerString(CString& string)
918{ if (!string.empty())
919    toLowerString(string.begin()); }
920
921/// convert character to uppercase
922inline char toUpper(char c);
923
924inline char toUpper(char c)
925{ return  (c >= 'a' &&  c <= 'z') ? c - 'a' + 'A' : c; }
926
927/// convert string to uppercase
928inline void toUpperString(std::string& string);
929
930inline void toUpperString(std::string& string)
931{ std::transform(string.begin(), string.end(), string.begin(), toUpper); }
932
933/// convert string to uppercase
934inline void toUpperString(char* cstr);
935
936inline void toUpperString(char* cstr)
937{
938    for (; *cstr!=0; cstr++)
939        *cstr = toUpper(*cstr);
940}
941
942/// convert string to uppercase
943inline void toUpperString(CString& string);
944
945inline void toUpperString(CString& string)
946{ if (!string.empty())
947    toUpperString(string.begin()); }
948
949/* CALL once */
950
951#ifdef HAVE_CALL_ONCE
952typedef std::once_flag OnceFlag;
953
954template<class Callable, class... Args>
955inline void callOnce(std::once_flag& flag, Callable&& f, Args&&... args)
956{ std::call_once(flag, f, args...); }
957#else
958struct OnceFlag: std::atomic<int>
959{   // force zero initialization
960    OnceFlag(): std::atomic<int>(0)
961    { }
962};
963
964template<class Callable, class... Args>
965inline void callOnce(OnceFlag& flag, Callable&& f, Args&&... args)
966{
967    if (flag.exchange(1) == 0)
968        f(args...);
969}
970#endif
971
972};
973
974#endif
Note: See TracBrowser for help on using the repository browser.