/////////////////////////////////////////////////////////////////////// // // NAMESPACE SV // // * Operate on string_view or just characters. // * Do not allocate memory. // * Do not copy strings. // // NAMESPACE UTIL // // * General purpose utility functions. // * Sort of a catch-all. // /////////////////////////////////////////////////////////////////////// #ifndef UTIL_HPP #define UTIL_HPP #include "wrap-string.hpp" #include "wrap-set.hpp" #include "wrap-map.hpp" #include "wrap-vector.hpp" #include "wrap-sstream.hpp" #include #include #include #include #include #include "luastack.hpp" #include "spookyv2.hpp" namespace sv { // Bring this into our namespace. using string_view = std::string_view; // Test character class, ignoring current locale and unicode issues. inline bool ascii_isupper(char c) { return (c >= 'A') && (c <= 'Z'); } inline bool ascii_islower(char c) { return (c >= 'a') && (c <= 'z'); } inline bool ascii_isdigit(char c) { return (c >= '0') && (c <= '9'); } inline bool ascii_isalpha(char c) { return ascii_isupper(c) || ascii_islower(c); } inline bool ascii_isalnum(char c) { return ascii_isalpha(c) || ascii_isdigit(c); } inline bool ascii_isspace(char c) { return (c==' ')||(c=='\t')||(c=='\r')||(c=='\n')||(c=='\f')||(c=='\v'); } // Check for the null string_view // // Note that the null string view is an empty string, // but not every empty string is the null string view. // inline bool isnull(string_view v) { return v.data() == nullptr; } // Check if numbers can be parsed as int64/double bool valid_double(string_view v); bool valid_int64(string_view v); bool valid_hex64(string_view v); // Parse numbers as int32, int64, or double. Returns errval on failure. double to_double(string_view v, double errval = std::numeric_limits::quiet_NaN()); int64_t to_int64(string_view v, int64_t errval = std::numeric_limits::min()); uint64_t to_hex64(string_view v, uint64_t errval = std::numeric_limits::max()); // Trim whitspace from a string_view. string_view ltrim(string_view v); string_view rtrim(string_view v); string_view trim(string_view v); // Trim specific character (all occurrences) from a string_view. string_view ltrim(string_view v, char c); string_view rtrim(string_view v, char c); string_view trim(string_view v, char c); // Return true if the string has the specified prefix or suffix. bool has_prefix(string_view s, string_view prefix); bool has_suffix(string_view s, string_view suffix); // Return the length of the common prefix of A and B. int common_prefix_length(string_view a, string_view b); // Return true if the string is a lua identifier. bool is_lua_id(string_view s); // Return true if the line of code is a lua comment. bool is_lua_comment(string_view s); // Return the first character, but if the view is empty, // return zero. inline char zfront(string_view &s) { return s.empty() ? char(0) : s.front(); } // Read from a string_view until separator is reached. // // If the separator appears in the source, returns everything // before the separator, and updates the source to everything // after the separator. // // If the separator doesn't appear in the source, returns // the entire source, and replaces source with the null string_view. // string_view read_to_sep(string_view &source, char sep); // Read from a string_view until newline is reached. // // If there's a line-break in the source (newline or CRLF), // returns the text before the line-break, and updates the // source to the text after the line-break. // // If there's no line-break in the source, returns the entire source, // and updates source to the null string_view. // string_view read_to_line(string_view &source); // Read from a string_view until whitespace is reached. // // If there's any whitespace in the source, returns the text // before the whitespace, and update the source to the text // after the whitespace. // // If there's no whitespace in the source, returns the entire // source, and updates the source to the null string_view. // string_view read_to_space(string_view &source); // Read up to nbytes from a string_view. // string_view read_nbytes(string_view &source, int nbytes); // Return true if the string is valid utf-8. bool valid_utf8(string_view s); } // namespace sv namespace util { enum WorldType { WORLD_TYPE_STANDALONE, WORLD_TYPE_C_SYNC, WORLD_TYPE_S_SYNC, WORLD_TYPE_MASTER, }; enum MessageType { MSG_NULL, MSG_DIFF, MSG_ACK, MSG_INVOKE, }; using StringVec = eng::vector; using StringPair = std::pair; using StringSet = eng::set; using LuaSourceVec = eng::vector; using LuaSourcePtr = std::unique_ptr; using HashValue = std::pair; using IdVector = eng::vector; // Ascii uppercase and lowercase. eng::string ascii_tolower(std::string_view c); eng::string ascii_toupper(std::string_view c); // Return seconds elapsed, for profiling purposes. double profiling_clock(); // Output a string to a stream using Lua string escaping and quoting. void quote_string(const eng::string &str, std::ostream *os); // ID vector quick create. IdVector id_vector_create(int64_t id1=-1, int64_t id2=-1, int64_t id3=-1, int64_t id4=-1); // ID vector debug string. eng::string id_vector_debug_string(const IdVector &idv); // Unions and sorts two ID vectors. IdVector sort_union_id_vectors(const IdVector &v1, const IdVector &v2); // Get a 128-bit hashvalue for a string. HashValue hash_string(const eng::string &str); // Get a 128-bit hashvalue for an ID vector. HashValue hash_id_vector(const IdVector &idv); // Convert a 128-bit hash to a hexadecimal string. eng::string hash_to_hex(const HashValue &hash); // Hash four integers together to 64 bits. // This is a good hash, but not cryptographically good. uint64_t hash_ints(uint64_t n1, uint64_t n2, uint64_t n3, uint64_t n4); // Convert a 64-bit hash value into a floating point number between 0 and 1. double hash_to_double(uint64_t hash); // Split a string into multiple strings StringVec split(const eng::string &s, char sep); // Split a string into multiple strings using \r or \n StringVec split_lines(const eng::string &s); // Split a string into multiple lines using |, remove any leading blank line. StringVec split_docstring(const eng::string &s); // Join multiple strings into one string eng::string join(const StringVec &strs, eng::string sep); // Return N repetitions of string A eng::string repeat_string(const eng::string &a, int n); // String to lowercase/uppercase. Ascii only, no unicode. eng::string tolower(eng::string input); eng::string toupper(eng::string input); // Calculate distance between two points double distance_squared(double x1, double y1, double x2, double y2); // Return true if a world type is authoritative. bool world_type_authoritative(util::WorldType wt); // Make a LuaSourceVec with one element, for unit testing. LuaSourcePtr make_lua_source(const eng::string &code); // Remove nullptrs from a vector of unique pointers. template void remove_nullptrs(eng::vector> &vec) { std::unique_ptr nullp; auto iter = std::remove(vec.begin(), vec.end(), nullp); vec.erase(iter, vec.end()); } // An XYZ coordinate, general purpose. struct XYZ { float x, y, z; XYZ() { x=0; y=0; z=0; } XYZ(float ix, float iy, float iz) { x=ix; y=iy; z=iz; } bool operator ==(const XYZ &o) const { return x==o.x && y == o.y && z==o.z; } bool operator !=(const XYZ &o) const { return x!=o.x || y != o.y || z!=o.z; } eng::string debug_string() const; }; // These are formatting directives that can be sent to a std::ostream. class hex64 {}; class hex32 {}; class hex16 {}; class hex8 {}; class NullStreamBuffer : public std::streambuf { public: int overflow(int c) { return c; } }; // send_to_stream: send all arguments to the specified stream. inline void send_to_stream(std::ostream &os) {} template inline void send_to_stream(std::ostream &os, ARG arg, REST & ... rest) { os << arg; send_to_stream(os, rest...); } // ss: convert all arguments to a string by sending them to a stringstream. template inline eng::string ss(ARGS & ... args) { eng::ostringstream oss; send_to_stream(oss, args...); return oss.str(); } } // namespace util std::ostream &operator<<(std::ostream &oss, const util::hex64 &v); std::ostream &operator<<(std::ostream &oss, const util::hex32 &v); std::ostream &operator<<(std::ostream &oss, const util::hex16 &v); std::ostream &operator<<(std::ostream &oss, const util::hex8 &v); #endif // UTIL_HPP