1 /**********************************************\
2 *
3 *  Simple Viewer GL edition
4 *  by Andrey A. Ugolnik
5 *  http://www.ugolnik.info
6 *  andrey@ugolnik.info
7 *
8 \**********************************************/
9 
10 #include "helpers.h"
11 
12 #include <cmath>
13 #include <cstring>
14 #include <ctime>
15 #include <string>
16 
17 namespace helpers
18 {
read_uint16(const uint8_t * p)19     uint16_t read_uint16(const uint8_t* p)
20     {
21         return ((uint16_t)p[0] << 8) | p[1];
22     }
23 
read_uint32(const uint8_t * p)24     uint32_t read_uint32(const uint8_t* p)
25     {
26         return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) | ((uint32_t)p[2] << 8) | (uint32_t)p[3];
27     }
28 
swap_uint32s(uint8_t * p,uint32_t size)29     void swap_uint32s(uint8_t* p, uint32_t size)
30     {
31         const uint32_t items = size / 4;
32         for (uint32_t i = 0; i < items; i++)
33         {
34             *((uint32_t*)p) = read_uint32(p);
35             p += 4;
36         }
37     }
38 
swap_uint16s(uint8_t * p,uint32_t size)39     void swap_uint16s(uint8_t* p, uint32_t size)
40     {
41         const uint32_t items = size / 2;
42         for (uint32_t i = 0; i < items; i++)
43         {
44             *((uint16_t*)p) = read_uint16(p);
45             p += 2;
46         }
47     }
48 
trimRightSpaces(char * buf)49     void trimRightSpaces(char* buf)
50     {
51         char* s = buf - 1;
52         for (; *buf; ++buf)
53         {
54             if (*buf != ' ')
55             {
56                 s = buf;
57             }
58         }
59         *++s = 0; // nul terminate the string on the first of the final spaces
60     }
61 
nextPot(uint32_t n)62     uint32_t nextPot(uint32_t n)
63     {
64         n = n - 1;
65         n = n | (n >> 1);
66         n = n | (n >> 2);
67         n = n | (n >> 4);
68         n = n | (n >> 8);
69         n = n | (n >> 16);
70         return n + 1;
71     }
72 
calculatePitch(uint32_t width,uint32_t bpp)73     uint32_t calculatePitch(uint32_t width, uint32_t bpp)
74     {
75         // texture pitch should be multiple by 4
76         return (uint32_t)::ceilf(width * (bpp / 8) / 4.0f) * 4;
77     }
78 
getTime()79     uint64_t getTime()
80     {
81         timespec now;
82         clock_gettime(CLOCK_REALTIME, &now);
83         return now.tv_sec * 1000000000 + now.tv_nsec;
84     }
85 
replaceAll(std::string & subject,const std::string & search,const std::string & replace)86     void replaceAll(std::string& subject, const std::string& search, const std::string& replace)
87     {
88         const size_t searchLen = search.length();
89 
90         size_t index = 0;
91         while (true)
92         {
93             index = subject.find(search, index);
94             if (index == std::string::npos)
95             {
96                 break;
97             }
98 
99             subject.replace(index, searchLen, replace);
100             index += replace.length();
101         }
102     }
103 
memfind(const char * buf,size_t size,const char * tofind)104     char* memfind(const char* buf, size_t size, const char* tofind)
105     {
106         const auto findlen = ::strlen(tofind);
107         if (findlen > size)
108         {
109             return nullptr;
110         }
111 
112         if (size < 1)
113         {
114             return (char*)buf;
115         }
116 
117         {
118             const char* bufend = &buf[size - findlen + 1];
119             const char* c = buf;
120             for (; c < bufend; c++)
121             {
122                 if (*c == *tofind)
123                 { // first letter matches
124                     if (::memcmp(c + 1, tofind + 1, findlen - 1) == 0)
125                     { // found
126                         return (char*)c;
127                     }
128                 }
129             }
130         }
131 
132         return nullptr;
133     }
134 
base64decode(const char * input,size_t in_len,Buffer & out)135     bool base64decode(const char* input, size_t in_len, Buffer& out)
136     {
137         static constexpr uint8_t LookupTable[] = {
138             64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
139             64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
140             64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
141             52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
142             64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
143             15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
144             64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
145             41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
146             64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
147             64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
148             64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
149             64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
150             64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
151             64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
152             64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
153             64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
154         };
155 
156         if (in_len % 4 != 0)
157         {
158             return false; // "Input data size is not a multiple of 4"
159         }
160 
161         size_t out_len = in_len / 4 * 3;
162         if (input[in_len - 1] == '=')
163         {
164             out_len--;
165         }
166         if (input[in_len - 2] == '=')
167         {
168             out_len--;
169         }
170 
171         out.resize(out_len);
172 
173         for (size_t i = 0, j = 0; i < in_len;)
174         {
175             uint32_t a = input[i] == '=' ? 0 & i++ : LookupTable[(int)input[i++]];
176             uint32_t b = input[i] == '=' ? 0 & i++ : LookupTable[(int)input[i++]];
177             uint32_t c = input[i] == '=' ? 0 & i++ : LookupTable[(int)input[i++]];
178             uint32_t d = input[i] == '=' ? 0 & i++ : LookupTable[(int)input[i++]];
179 
180             uint32_t triple = (a << 3 * 6) + (b << 2 * 6) + (c << 1 * 6) + (d << 0 * 6);
181 
182             if (j < out_len)
183             {
184                 out[j++] = (triple >> 2 * 8) & 0xFF;
185             }
186             if (j < out_len)
187             {
188                 out[j++] = (triple >> 1 * 8) & 0xFF;
189             }
190             if (j < out_len)
191             {
192                 out[j++] = (triple >> 0 * 8) & 0xFF;
193             }
194         }
195 
196         return true;
197     }
198 } // namespace helpers
199