util.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644
  1. // ECOin - Copyright (c) - 2014/2022 - GPLv3 - epsylon@riseup.net (https://03c8.net)
  2. #ifndef ECOIN_UTIL_H
  3. #define ECOIN_UTIL_H
  4. #include "uint256.h"
  5. #ifndef WIN32
  6. #include <sys/types.h>
  7. #include <sys/time.h>
  8. #include <sys/resource.h>
  9. #endif
  10. #include <map>
  11. #include <vector>
  12. #include <string>
  13. #include <boost/thread.hpp>
  14. #include <boost/filesystem.hpp>
  15. #include <boost/filesystem/path.hpp>
  16. #include <boost/date_time/gregorian/gregorian_types.hpp>
  17. #include <boost/date_time/posix_time/posix_time_types.hpp>
  18. #include <openssl/sha.h>
  19. #include <openssl/ripemd.h>
  20. #include "netbase.h" // for AddTimeData
  21. typedef long long int64;
  22. typedef unsigned long long uint64;
  23. static const int64 COIN = 1000000;
  24. static const int64 CENT = 10000;
  25. #define BEGIN(a) ((char*)&(a))
  26. #define END(a) ((char*)&((&(a))[1]))
  27. #define UBEGIN(a) ((unsigned char*)&(a))
  28. #define UEND(a) ((unsigned char*)&((&(a))[1]))
  29. #define ARRAYLEN(array) (sizeof(array)/sizeof((array)[0]))
  30. #define UVOIDBEGIN(a) ((void*)&(a))
  31. #define CVOIDBEGIN(a) ((const void*)&(a))
  32. #define UINTBEGIN(a) ((uint32_t*)&(a))
  33. #define CUINTBEGIN(a) ((const uint32_t*)&(a))
  34. #ifndef PRI64d
  35. #if defined(_MSC_VER) || defined(__MSVCRT__)
  36. #define PRI64d "I64d"
  37. #define PRI64u "I64u"
  38. #define PRI64x "I64x"
  39. #else
  40. #define PRI64d "lld"
  41. #define PRI64u "llu"
  42. #define PRI64x "llx"
  43. #endif
  44. #endif
  45. #ifndef THROW_WITH_STACKTRACE
  46. #define THROW_WITH_STACKTRACE(exception) \
  47. { \
  48. LogStackTrace(); \
  49. throw (exception); \
  50. }
  51. void LogStackTrace();
  52. #endif
  53. /* Format characters for (s)size_t and ptrdiff_t */
  54. #if defined(_MSC_VER) || defined(__MSVCRT__)
  55. /* (s)size_t and ptrdiff_t have the same size specifier in MSVC:
  56. http://msdn.microsoft.com/en-us/library/tcxf1dw6%28v=vs.100%29.aspx
  57. */
  58. #define PRIszx "Ix"
  59. #define PRIszu "Iu"
  60. #define PRIszd "Id"
  61. #define PRIpdx "Ix"
  62. #define PRIpdu "Iu"
  63. #define PRIpdd "Id"
  64. #else /* C99 standard */
  65. #define PRIszx "zx"
  66. #define PRIszu "zu"
  67. #define PRIszd "zd"
  68. #define PRIpdx "tx"
  69. #define PRIpdu "tu"
  70. #define PRIpdd "td"
  71. #endif
  72. // This is needed because the foreach macro can't get over the comma in pair<t1, t2>
  73. #define PAIRTYPE(t1, t2) std::pair<t1, t2>
  74. // Align by increasing pointer, must have extra space at end of buffer
  75. template <size_t nBytes, typename T>
  76. T* alignup(T* p)
  77. {
  78. union
  79. {
  80. T* ptr;
  81. size_t n;
  82. } u;
  83. u.ptr = p;
  84. u.n = (u.n + (nBytes-1)) & ~(nBytes-1);
  85. return u.ptr;
  86. }
  87. #ifdef WIN32
  88. #define MSG_NOSIGNAL 0
  89. #define MSG_DONTWAIT 0
  90. #ifndef S_IRUSR
  91. #define S_IRUSR 0400
  92. #define S_IWUSR 0200
  93. #endif
  94. #else
  95. #define MAX_PATH 1024
  96. inline void Sleep(int64 n)
  97. {
  98. /*Boost has a year 2038 problem— if the request sleep time is past epoch+2^31 seconds the sleep returns instantly.
  99. So we clamp our sleeps here to 10 years and hope that boost is fixed by 2028.*/
  100. boost::thread::sleep(boost::get_system_time() + boost::posix_time::milliseconds(n>315576000000LL?315576000000LL:n));
  101. }
  102. #endif
  103. /* This GNU C extension enables the compiler to check the format string against the parameters provided.
  104. * X is the number of the "format string" parameter, and Y is the number of the first variadic parameter.
  105. * Parameters count from 1.
  106. */
  107. #ifdef __GNUC__
  108. #define ATTR_WARN_PRINTF(X,Y) __attribute__((format(printf,X,Y)))
  109. #else
  110. #define ATTR_WARN_PRINTF(X,Y)
  111. #endif
  112. extern std::map<std::string, std::string> mapArgs;
  113. extern std::map<std::string, std::vector<std::string> > mapMultiArgs;
  114. extern bool fDebug;
  115. extern bool fDebugNet;
  116. extern bool fPrintToConsole;
  117. extern bool fPrintToDebugger;
  118. extern bool fRequestShutdown;
  119. extern bool fShutdown;
  120. extern bool fDaemon;
  121. extern bool fServer;
  122. extern bool fCommandLine;
  123. extern std::string strMiscWarning;
  124. extern bool fTestNet;
  125. extern bool fNoListen;
  126. extern bool fLogTimestamps;
  127. extern bool fReopenDebugLog;
  128. void RandAddSeed();
  129. void RandAddSeedPerfmon();
  130. int ATTR_WARN_PRINTF(1,2) OutputDebugStringF(const char* pszFormat, ...);
  131. /*
  132. Rationale for the real_strprintf / strprintf construction:
  133. It is not allowed to use va_start with a pass-by-reference argument.
  134. (C++ standard, 18.7, paragraph 3). Use a dummy argument to work around this, and use a
  135. macro to keep similar semantics.
  136. */
  137. /** Overload strprintf for char*, so that GCC format type warnings can be given */
  138. std::string ATTR_WARN_PRINTF(1,3) real_strprintf(const char *format, int dummy, ...);
  139. /** Overload strprintf for std::string, to be able to use it with _ (translation).
  140. * This will not support GCC format type warnings (-Wformat) so be careful.
  141. */
  142. std::string real_strprintf(const std::string &format, int dummy, ...);
  143. #define strprintf(format, ...) real_strprintf(format, 0, __VA_ARGS__)
  144. std::string vstrprintf(const char *format, va_list ap);
  145. bool ATTR_WARN_PRINTF(1,2) error(const char *format, ...);
  146. /* Redefine printf so that it directs output to debug.log
  147. *
  148. * Do this *after* defining the other printf-like functions, because otherwise the
  149. * __attribute__((format(printf,X,Y))) gets expanded to __attribute__((format(OutputDebugStringF,X,Y)))
  150. * which confuses gcc.
  151. */
  152. #define printf OutputDebugStringF
  153. void LogException(std::exception* pex, const char* pszThread);
  154. void PrintException(std::exception* pex, const char* pszThread);
  155. void PrintExceptionContinue(std::exception* pex, const char* pszThread);
  156. void ParseString(const std::string& str, char c, std::vector<std::string>& v);
  157. std::string FormatMoney(int64 n, bool fPlus=false);
  158. bool ParseMoney(const std::string& str, int64& nRet);
  159. bool ParseMoney(const char* pszIn, int64& nRet);
  160. std::vector<unsigned char> ParseHex(const char* psz);
  161. std::vector<unsigned char> ParseHex(const std::string& str);
  162. bool IsHex(const std::string& str);
  163. std::vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid = NULL);
  164. std::string DecodeBase64(const std::string& str);
  165. std::string EncodeBase64(const unsigned char* pch, size_t len);
  166. std::string EncodeBase64(const std::string& str);
  167. std::vector<unsigned char> DecodeBase32(const char* p, bool* pfInvalid = NULL);
  168. std::string DecodeBase32(const std::string& str);
  169. std::string EncodeBase32(const unsigned char* pch, size_t len);
  170. std::string EncodeBase32(const std::string& str);
  171. void ParseParameters(int argc, const char*const argv[]);
  172. bool WildcardMatch(const char* psz, const char* mask);
  173. bool WildcardMatch(const std::string& str, const std::string& mask);
  174. void FileCommit(FILE *fileout);
  175. int GetFilesize(FILE* file);
  176. bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest);
  177. boost::filesystem::path GetDefaultDataDir();
  178. const boost::filesystem::path &GetDataDir(bool fNetSpecific = true);
  179. boost::filesystem::path GetConfigFile();
  180. boost::filesystem::path GetPidFile();
  181. #ifndef WIN32
  182. void CreatePidFile(const boost::filesystem::path &path, pid_t pid);
  183. #endif
  184. void ReadConfigFile(std::map<std::string, std::string>& mapSettingsRet, std::map<std::string, std::vector<std::string> >& mapMultiSettingsRet);
  185. #ifdef WIN32
  186. boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate = true);
  187. #endif
  188. void ShrinkDebugFile();
  189. int GetRandInt(int nMax);
  190. uint64 GetRand(uint64 nMax);
  191. uint256 GetRandHash();
  192. long ConvertLong(const char* cHex);
  193. int64 GetTime();
  194. void SetMockTime(int64 nMockTimeIn);
  195. int64 GetAdjustedTime();
  196. int64 GetTimeOffset();
  197. std::string FormatFullVersion();
  198. std::string FormatSubVersion(const std::string& name, int nClientVersion, const std::vector<std::string>& comments);
  199. void AddTimeData(const CNetAddr& ip, int64 nTime);
  200. void runCommand(std::string strCommand);
  201. inline std::string i64tostr(int64 n)
  202. {
  203. return strprintf("%" PRI64d, n);
  204. }
  205. inline std::string itostr(int n)
  206. {
  207. return strprintf("%d", n);
  208. }
  209. inline int64 atoi64(const char* psz)
  210. {
  211. #ifdef _MSC_VER
  212. return _atoi64(psz);
  213. #else
  214. return strtoll(psz, NULL, 10);
  215. #endif
  216. }
  217. inline int64 atoi64(const std::string& str)
  218. {
  219. #ifdef _MSC_VER
  220. return _atoi64(str.c_str());
  221. #else
  222. return strtoll(str.c_str(), NULL, 10);
  223. #endif
  224. }
  225. inline int atoi(const std::string& str)
  226. {
  227. return atoi(str.c_str());
  228. }
  229. inline int roundint(double d)
  230. {
  231. return (int)(d > 0 ? d + 0.5 : d - 0.5);
  232. }
  233. inline int64 roundint64(double d)
  234. {
  235. return (int64)(d > 0 ? d + 0.5 : d - 0.5);
  236. }
  237. inline int64 abs64(int64 n)
  238. {
  239. return (n >= 0 ? n : -n);
  240. }
  241. inline std::string leftTrim(std::string src, char chr)
  242. {
  243. std::string::size_type pos = src.find_first_not_of(chr, 0);
  244. if(pos > 0)
  245. src.erase(0, pos);
  246. return src;
  247. }
  248. template<typename T>
  249. std::string HexStr(const T itbegin, const T itend, bool fSpaces=false)
  250. {
  251. std::string rv;
  252. static const char hexmap[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
  253. '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
  254. rv.reserve((itend-itbegin)*3);
  255. for(T it = itbegin; it < itend; ++it)
  256. {
  257. unsigned char val = (unsigned char)(*it);
  258. if(fSpaces && it != itbegin)
  259. rv.push_back(' ');
  260. rv.push_back(hexmap[val>>4]);
  261. rv.push_back(hexmap[val&15]);
  262. }
  263. return rv;
  264. }
  265. inline std::string HexStr(const std::vector<unsigned char>& vch, bool fSpaces=false)
  266. {
  267. return HexStr(vch.begin(), vch.end(), fSpaces);
  268. }
  269. template<typename T>
  270. void PrintHex(const T pbegin, const T pend, const char* pszFormat="%s", bool fSpaces=true)
  271. {
  272. printf(pszFormat, HexStr(pbegin, pend, fSpaces).c_str());
  273. }
  274. inline void PrintHex(const std::vector<unsigned char>& vch, const char* pszFormat="%s", bool fSpaces=true)
  275. {
  276. printf(pszFormat, HexStr(vch, fSpaces).c_str());
  277. }
  278. inline int64 GetPerformanceCounter()
  279. {
  280. int64 nCounter = 0;
  281. #ifdef WIN32
  282. QueryPerformanceCounter((LARGE_INTEGER*)&nCounter);
  283. #else
  284. timeval t;
  285. gettimeofday(&t, NULL);
  286. nCounter = (int64) t.tv_sec * 1000000 + t.tv_usec;
  287. #endif
  288. return nCounter;
  289. }
  290. inline int64 GetTimeMillis()
  291. {
  292. return (boost::posix_time::ptime(boost::posix_time::microsec_clock::universal_time()) -
  293. boost::posix_time::ptime(boost::gregorian::date(1970,1,1))).total_milliseconds();
  294. }
  295. inline std::string DateTimeStrFormat(const char* pszFormat, int64 nTime)
  296. {
  297. time_t n = nTime;
  298. struct tm* ptmTime = gmtime(&n);
  299. char pszTime[200];
  300. strftime(pszTime, sizeof(pszTime), pszFormat, ptmTime);
  301. return pszTime;
  302. }
  303. static const std::string strTimestampFormat = "%Y-%m-%d %H:%M:%S UTC";
  304. inline std::string DateTimeStrFormat(int64 nTime)
  305. {
  306. return DateTimeStrFormat(strTimestampFormat.c_str(), nTime);
  307. }
  308. template<typename T>
  309. void skipspaces(T& it)
  310. {
  311. while (isspace(*it))
  312. ++it;
  313. }
  314. inline bool IsSwitchChar(char c)
  315. {
  316. #ifdef WIN32
  317. return c == '-' || c == '/';
  318. #else
  319. return c == '-';
  320. #endif
  321. }
  322. /**
  323. * Return string argument or default value
  324. *
  325. * @param strArg Argument to get (e.g. "-foo")
  326. * @param default (e.g. "1")
  327. * @return command-line argument or default value
  328. */
  329. std::string GetArg(const std::string& strArg, const std::string& strDefault);
  330. /**
  331. * Return integer argument or default value
  332. *
  333. * @param strArg Argument to get (e.g. "-foo")
  334. * @param default (e.g. 1)
  335. * @return command-line argument (0 if invalid number) or default value
  336. */
  337. int64 GetArg(const std::string& strArg, int64 nDefault);
  338. /**
  339. * Return boolean argument or default value
  340. *
  341. * @param strArg Argument to get (e.g. "-foo")
  342. * @param default (true or false)
  343. * @return command-line argument or default value
  344. */
  345. bool GetBoolArg(const std::string& strArg, bool fDefault=false);
  346. /**
  347. * Set an argument if it doesn't already have a value
  348. *
  349. * @param strArg Argument to set (e.g. "-foo")
  350. * @param strValue Value (e.g. "1")
  351. * @return true if argument gets set, false if it already had a value
  352. */
  353. bool SoftSetArg(const std::string& strArg, const std::string& strValue);
  354. /**
  355. * Set a boolean argument if it doesn't already have a value
  356. *
  357. * @param strArg Argument to set (e.g. "-foo")
  358. * @param fValue Value (e.g. false)
  359. * @return true if argument gets set, false if it already had a value
  360. */
  361. bool SoftSetBoolArg(const std::string& strArg, bool fValue);
  362. template<typename T1>
  363. inline uint256 Hash(const T1 pbegin, const T1 pend)
  364. {
  365. static unsigned char pblank[1];
  366. uint256 hash1;
  367. SHA256((pbegin == pend ? pblank : (unsigned char*)&pbegin[0]), (pend - pbegin) * sizeof(pbegin[0]), (unsigned char*)&hash1);
  368. uint256 hash2;
  369. SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2);
  370. return hash2;
  371. }
  372. class CHashWriter
  373. {
  374. private:
  375. SHA256_CTX ctx;
  376. public:
  377. int nType;
  378. int nVersion;
  379. void Init() {
  380. SHA256_Init(&ctx);
  381. }
  382. CHashWriter(int nTypeIn, int nVersionIn) : nType(nTypeIn), nVersion(nVersionIn) {
  383. Init();
  384. }
  385. CHashWriter& write(const char *pch, size_t size) {
  386. SHA256_Update(&ctx, pch, size);
  387. return (*this);
  388. }
  389. // invalidates the object
  390. uint256 GetHash() {
  391. uint256 hash1;
  392. SHA256_Final((unsigned char*)&hash1, &ctx);
  393. uint256 hash2;
  394. SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2);
  395. return hash2;
  396. }
  397. template<typename T>
  398. CHashWriter& operator<<(const T& obj) {
  399. // Serialize to this stream
  400. ::Serialize(*this, obj, nType, nVersion);
  401. return (*this);
  402. }
  403. };
  404. template<typename T1, typename T2>
  405. inline uint256 Hash(const T1 p1begin, const T1 p1end,
  406. const T2 p2begin, const T2 p2end)
  407. {
  408. static unsigned char pblank[1];
  409. uint256 hash1;
  410. SHA256_CTX ctx;
  411. SHA256_Init(&ctx);
  412. SHA256_Update(&ctx, (p1begin == p1end ? pblank : (unsigned char*)&p1begin[0]), (p1end - p1begin) * sizeof(p1begin[0]));
  413. SHA256_Update(&ctx, (p2begin == p2end ? pblank : (unsigned char*)&p2begin[0]), (p2end - p2begin) * sizeof(p2begin[0]));
  414. SHA256_Final((unsigned char*)&hash1, &ctx);
  415. uint256 hash2;
  416. SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2);
  417. return hash2;
  418. }
  419. template<typename T1, typename T2, typename T3>
  420. inline uint256 Hash(const T1 p1begin, const T1 p1end,
  421. const T2 p2begin, const T2 p2end,
  422. const T3 p3begin, const T3 p3end)
  423. {
  424. static unsigned char pblank[1];
  425. uint256 hash1;
  426. SHA256_CTX ctx;
  427. SHA256_Init(&ctx);
  428. SHA256_Update(&ctx, (p1begin == p1end ? pblank : (unsigned char*)&p1begin[0]), (p1end - p1begin) * sizeof(p1begin[0]));
  429. SHA256_Update(&ctx, (p2begin == p2end ? pblank : (unsigned char*)&p2begin[0]), (p2end - p2begin) * sizeof(p2begin[0]));
  430. SHA256_Update(&ctx, (p3begin == p3end ? pblank : (unsigned char*)&p3begin[0]), (p3end - p3begin) * sizeof(p3begin[0]));
  431. SHA256_Final((unsigned char*)&hash1, &ctx);
  432. uint256 hash2;
  433. SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2);
  434. return hash2;
  435. }
  436. template<typename T>
  437. uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL_VERSION)
  438. {
  439. CHashWriter ss(nType, nVersion);
  440. ss << obj;
  441. return ss.GetHash();
  442. }
  443. inline uint160 Hash160(const std::vector<unsigned char>& vch)
  444. {
  445. uint256 hash1;
  446. SHA256(&vch[0], vch.size(), (unsigned char*)&hash1);
  447. uint160 hash2;
  448. RIPEMD160((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2);
  449. return hash2;
  450. }
  451. /**
  452. * Timing-attack-resistant comparison.
  453. * Takes time proportional to length
  454. * of first argument.
  455. */
  456. template <typename T>
  457. bool TimingResistantEqual(const T& a, const T& b)
  458. {
  459. if (b.size() == 0) return a.size() == 0;
  460. size_t accumulator = a.size() ^ b.size();
  461. for (size_t i = 0; i < a.size(); i++)
  462. accumulator |= a[i] ^ b[i%b.size()];
  463. return accumulator == 0;
  464. }
  465. /** Median filter over a stream of values.
  466. * Returns the median of the last N numbers
  467. */
  468. template <typename T> class CMedianFilter
  469. {
  470. private:
  471. std::vector<T> vValues;
  472. std::vector<T> vSorted;
  473. unsigned int nSize;
  474. public:
  475. CMedianFilter(unsigned int size, T initial_value):
  476. nSize(size)
  477. {
  478. vValues.reserve(size);
  479. vValues.push_back(initial_value);
  480. vSorted = vValues;
  481. }
  482. void input(T value)
  483. {
  484. if(vValues.size() == nSize)
  485. {
  486. vValues.erase(vValues.begin());
  487. }
  488. vValues.push_back(value);
  489. vSorted.resize(vValues.size());
  490. std::copy(vValues.begin(), vValues.end(), vSorted.begin());
  491. std::sort(vSorted.begin(), vSorted.end());
  492. }
  493. T median() const
  494. {
  495. int size = vSorted.size();
  496. assert(size>0);
  497. if(size & 1) // Odd number of elements
  498. {
  499. return vSorted[size/2];
  500. }
  501. else // Even number of elements
  502. {
  503. return (vSorted[size/2-1] + vSorted[size/2]) / 2;
  504. }
  505. }
  506. int size() const
  507. {
  508. return vValues.size();
  509. }
  510. std::vector<T> sorted () const
  511. {
  512. return vSorted;
  513. }
  514. };
  515. bool NewThread(void(*pfn)(void*), void* parg);
  516. #ifdef WIN32
  517. inline void SetThreadPriority(int nPriority)
  518. {
  519. SetThreadPriority(GetCurrentThread(), nPriority);
  520. }
  521. #else
  522. #define THREAD_PRIORITY_LOWEST PRIO_MAX
  523. #define THREAD_PRIORITY_BELOW_NORMAL 2
  524. #define THREAD_PRIORITY_NORMAL 0
  525. #define THREAD_PRIORITY_ABOVE_NORMAL 0
  526. inline void SetThreadPriority(int nPriority)
  527. {
  528. // It's unclear if it's even possible to change thread priorities on Linux,
  529. // but we really and truly need it for the generation threads.
  530. #ifdef PRIO_THREAD
  531. setpriority(PRIO_THREAD, 0, nPriority);
  532. #else
  533. setpriority(PRIO_PROCESS, 0, nPriority);
  534. #endif
  535. }
  536. inline void ExitThread(size_t nExitCode)
  537. {
  538. pthread_exit((void*)nExitCode);
  539. }
  540. #endif
  541. void RenameThread(const char* name);
  542. inline uint32_t ByteReverse(uint32_t value)
  543. {
  544. value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8);
  545. return (value<<16) | (value>>16);
  546. }
  547. #endif