#include "util/util.h" #include <cmath> namespace nasal::util { bool is_windows() { #if defined(_WIN32) || defined(_WIN64) return true; #else return false; #endif } bool is_linux() { #if defined __linux__ return true; #else return false; #endif } bool is_macos() { #if defined __APPLE__ return true; #else return false; #endif } bool is_x86() { #if defined(__i386__) || defined(_M_IX86) return true; #else return false; #endif } bool is_amd64() { #if defined(__amd64__) || defined(_M_X64) return true; #else return false; #endif } bool is_x86_64() { return is_amd64(); } bool is_arm() { #if defined(__arm__) || defined(_M_ARM) return true; #else return false; #endif } bool is_aarch64() { #if defined(__aarch64__) || defined(_M_ARM64) return true; #else return false; #endif } bool is_ia64() { #if defined(__ia64__) return true; #else return false; #endif } bool is_powerpc() { #if defined(__powerpc__) return true; #else return false; #endif } bool is_superh() { #if defined(__sh__) return true; #else return false; #endif } const char* get_platform() { if (is_windows()) { return "windows"; } else if (is_linux()) { return "linux"; } else if (is_macos()) { return "macOS"; } return "unknown"; } const char* get_arch() { if (is_x86()) { return "x86"; } else if (is_x86_64()) { return "x86-64"; } else if (is_amd64()) { return "amd64"; } else if (is_arm()) { return "arm"; } else if (is_aarch64()) { return "aarch64"; } else if (is_ia64()) { return "ia64"; } else if (is_powerpc()) { return "powerpc"; } else if (is_superh()) { return "superh"; } return "unknown"; } u32 utf8_hdchk(const char head) { // RFC-2279 but now we use RFC-3629 so nbytes is less than 4 const auto c = static_cast<u8>(head); if ((c>>5)==0x06) { // 110x xxxx (10xx xxxx)^1 return 1; } if ((c>>4)==0x0e) { // 1110 xxxx (10xx xxxx)^2 return 2; } if ((c>>3)==0x1e) { // 1111 0xxx (10xx xxxx)^3 return 3; } return 0; } std::string char_to_hex(const char c) { const char hextbl[] = "0123456789abcdef"; return {hextbl[(c&0xf0)>>4], hextbl[c&0x0f]}; } std::string rawstr(const std::string& str, const usize maxlen) { std::string ret(""); for(auto i : str) { // windows doesn't output unicode normally, so we output the hex if (util::is_windows() && i<=0) { ret += "\\x" + char_to_hex(i); continue; } switch(i) { case '\0': ret += "\\0"; break; case '\a': ret += "\\a"; break; case '\b': ret += "\\b"; break; case '\t': ret += "\\t"; break; case '\n': ret += "\\n"; break; case '\v': ret += "\\v"; break; case '\f': ret += "\\f"; break; case '\r': ret += "\\r"; break; case '\033':ret += "\\e"; break; case '\"': ret += "\\\""; break; case '\'': ret += "\\\'"; break; case '\\': ret += "\\\\"; break; default: ret += i; break; } } if (maxlen && ret.length()>maxlen) { ret = ret.substr(0, maxlen)+"..."; } return ret; } f64 hex_to_f64(const char* str) { f64 ret = 0; for(; *str; ++str) { if ('0'<=*str && *str<='9') { ret = ret*16+(*str-'0'); } else if ('a'<=*str && *str<='f') { ret = ret*16+(*str-'a'+10); } else if ('A'<=*str && *str<='F') { ret = ret*16+(*str-'A'+10); } else { return nan(""); } } return ret; } f64 oct_to_f64(const char* str) { f64 ret = 0; while('0'<=*str && *str<'8') { ret = ret*8+(*str++-'0'); } if (*str) { return nan(""); } return ret; } // we have the same reason not using atof here // just as andy's interpreter does. // it is not platform independent, and may have strange output. // so we write a new function here to convert str to number manually. // but this also makes 0.1+0.2==0.3, // not another result that you may get in other languages. f64 dec_to_f64(const char* str) { f64 ret = 0, num_pow = 0; bool negative = false; while('0'<=*str && *str<='9') { ret = ret*10+(*str++-'0'); } if (!*str) { return ret; } if (*str=='.') { if (!*++str) { return nan(""); } num_pow = 0.1; while('0'<=*str && *str<='9') { ret += num_pow*(*str++-'0'); num_pow *= 0.1; } if (!*str) { return ret; } } if (*str!='e' && *str!='E') { return nan(""); } if (!*++str) { return nan(""); } if (*str=='-' || *str=='+') { negative = (*str++=='-'); } if (!*str) { return nan(""); } num_pow = 0; while('0'<=*str && *str<='9') { num_pow = num_pow*10+(*str++-'0'); } if (*str) { return nan(""); } return negative? ret*std::pow(10, 1-num_pow)*0.1: ret*std::pow(10, num_pow-1)*10; } f64 str_to_num(const char* str) { bool negative = false; f64 res = 0; if (*str=='-' || *str=='+') { negative = (*str++=='-'); } if (!*str) { return nan(""); } if (str[0]=='0' && str[1]=='x') { res = hex_to_f64(str+2); } else if (str[0]=='0' && str[1]=='o') { res = oct_to_f64(str+2); } else { res = dec_to_f64(str); } return negative? -res:res; } }