+// Copy not null terminated char array to null terminated string.
+// Replace non-ascii characters. Remove leading and trailing blanks.
+const char * format_char_array(char * str, int strsize, const char * chr, int chrsize);
+
+// Version for fixed size buffers.
+template<size_t STRSIZE, size_t CHRSIZE>
+inline const char * format_char_array(char (& str)[STRSIZE], const char (& chr)[CHRSIZE])
+ { return format_char_array(str, (int)STRSIZE, chr, (int)CHRSIZE); }
+
+// Format integer with thousands separator
+const char * format_with_thousands_sep(char * str, int strsize, uint64_t val,
+ const char * thousands_sep = 0);
+
+// Format capacity with SI prefixes
+const char * format_capacity(char * str, int strsize, uint64_t val,
+ const char * decimal_point = 0);
+
+// Wrapper class for a raw data buffer
+class raw_buffer
+{
+public:
+ explicit raw_buffer(unsigned sz, unsigned char val = 0)
+ : m_data(new unsigned char[sz]),
+ m_size(sz)
+ { memset(m_data, val, m_size); }
+
+ ~raw_buffer()
+ { delete [] m_data; }
+
+ unsigned size() const
+ { return m_size; }
+
+ unsigned char * data()
+ { return m_data; }
+ const unsigned char * data() const
+ { return m_data; }
+
+private:
+ unsigned char * m_data;
+ unsigned m_size;
+
+ raw_buffer(const raw_buffer &);
+ void operator=(const raw_buffer &);
+};
+
+/// Wrapper class for FILE *.
+class stdio_file
+{
+public:
+ explicit stdio_file(FILE * f = 0, bool owner = false)
+ : m_file(f), m_owner(owner) { }
+
+ stdio_file(const char * name, const char * mode)
+ : m_file(fopen(name, mode)), m_owner(true) { }
+
+ ~stdio_file()
+ {
+ if (m_file && m_owner)
+ fclose(m_file);
+ }
+
+ bool open(const char * name, const char * mode)
+ {
+ if (m_file && m_owner)
+ fclose(m_file);
+ m_file = fopen(name, mode);
+ m_owner = true;
+ return !!m_file;
+ }
+
+ void open(FILE * f, bool owner = false)
+ {
+ if (m_file && m_owner)
+ fclose(m_file);
+ m_file = f;
+ m_owner = owner;
+ }
+
+ bool close()
+ {
+ if (!m_file)
+ return true;
+ bool ok = !ferror(m_file);
+ if (fclose(m_file))
+ ok = false;
+ m_file = 0;
+ return ok;
+ }
+
+ operator FILE * ()
+ { return m_file; }
+
+ bool operator!() const
+ { return !m_file; }
+
+private:
+ FILE * m_file;
+ bool m_owner;
+
+ stdio_file(const stdio_file &);
+ void operator=(const stdio_file &);
+};
+
+/// Wrapper class for regex(3).
+/// Supports copy & assignment and is compatible with STL containers.
+class regular_expression
+{
+public:
+ // Construction & assignment
+ regular_expression();
+
+ regular_expression(const char * pattern, int flags,
+ bool throw_on_error = true);
+
+ ~regular_expression();
+
+ regular_expression(const regular_expression & x);
+
+ regular_expression & operator=(const regular_expression & x);
+
+ /// Set and compile new pattern, return false on error.
+ bool compile(const char * pattern, int flags);
+
+ // Get pattern from last compile().
+ const char * get_pattern() const
+ { return m_pattern.c_str(); }
+
+ /// Get error message from last compile().
+ const char * get_errmsg() const
+ { return m_errmsg.c_str(); }
+
+ // Return true if pattern is not set or bad.
+ bool empty() const
+ { return (m_pattern.empty() || !m_errmsg.empty()); }
+
+ /// Return true if substring matches pattern
+ bool match(const char * str, int flags = 0) const
+ { return !regexec(&m_regex_buf, str, 0, (regmatch_t*)0, flags); }
+
+ /// Return true if full string matches pattern
+ bool full_match(const char * str, int flags = 0) const
+ {
+ regmatch_t range;
+ return ( !regexec(&m_regex_buf, str, 1, &range, flags)
+ && range.rm_so == 0 && range.rm_eo == (int)strlen(str));
+ }
+
+ /// Return true if substring matches pattern, fill regmatch_t array.
+ bool execute(const char * str, unsigned nmatch, regmatch_t * pmatch, int flags = 0) const
+ { return !regexec(&m_regex_buf, str, nmatch, pmatch, flags); }
+
+private:
+ std::string m_pattern;
+ int m_flags;
+ regex_t m_regex_buf;
+ std::string m_errmsg;
+
+ void free_buf();
+ void copy(const regular_expression & x);
+ bool compile();
+};
+
+#ifdef _WIN32
+// Get exe directory
+//(implemented in os_win32.cpp)
+std::string get_exe_dir();
+#endif