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