http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/thirdparty/spdlog-0.13.0/include/spdlog/details/null_mutex.h ---------------------------------------------------------------------- diff --git a/thirdparty/spdlog-0.13.0/include/spdlog/details/null_mutex.h b/thirdparty/spdlog-0.13.0/include/spdlog/details/null_mutex.h new file mode 100644 index 0000000..67b0aee --- /dev/null +++ b/thirdparty/spdlog-0.13.0/include/spdlog/details/null_mutex.h @@ -0,0 +1,45 @@ +// +// Copyright(c) 2015 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +#pragma once + +#include <atomic> +// null, no cost dummy "mutex" and dummy "atomic" int + +namespace spdlog +{ +namespace details +{ +struct null_mutex +{ + void lock() {} + void unlock() {} + bool try_lock() + { + return true; + } +}; + +struct null_atomic_int +{ + int value; + null_atomic_int() = default; + + null_atomic_int(int val):value(val) + {} + + int load(std::memory_order) const + { + return value; + } + + void store(int val) + { + value = val; + } +}; + +} +}
http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/thirdparty/spdlog-0.13.0/include/spdlog/details/os.h ---------------------------------------------------------------------- diff --git a/thirdparty/spdlog-0.13.0/include/spdlog/details/os.h b/thirdparty/spdlog-0.13.0/include/spdlog/details/os.h new file mode 100644 index 0000000..b63ce66 --- /dev/null +++ b/thirdparty/spdlog-0.13.0/include/spdlog/details/os.h @@ -0,0 +1,406 @@ +// +// Copyright(c) 2015 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// +#pragma once + +#include <spdlog/common.h> + +#include <cstdio> +#include <ctime> +#include <functional> +#include <string> +#include <chrono> +#include <thread> +#include <stdio.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/types.h> + +#ifdef _WIN32 + +#ifndef NOMINMAX +#define NOMINMAX //prevent windows redefining min/max +#endif + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include <windows.h> +#include <process.h> // _get_pid support +#include <io.h> // _get_osfhandle support + +#ifdef __MINGW32__ +#include <share.h> +#endif + +#else // unix + +#include <unistd.h> +#include <fcntl.h> + +#ifdef __linux__ +#include <sys/syscall.h> //Use gettid() syscall under linux to get thread id + +#elif __FreeBSD__ +#include <sys/thr.h> //Use thr_self() syscall under FreeBSD to get thread id +#endif + +#endif //unix + +#ifndef __has_feature // Clang - feature checking macros. +#define __has_feature(x) 0 // Compatibility with non-clang compilers. +#endif + + +namespace spdlog +{ +namespace details +{ +namespace os +{ + +inline spdlog::log_clock::time_point now() +{ + +#if defined __linux__ && defined SPDLOG_CLOCK_COARSE + timespec ts; + ::clock_gettime(CLOCK_REALTIME_COARSE, &ts); + return std::chrono::time_point<log_clock, typename log_clock::duration>( + std::chrono::duration_cast<typename log_clock::duration>( + std::chrono::seconds(ts.tv_sec) + std::chrono::nanoseconds(ts.tv_nsec))); + + +#else + return log_clock::now(); +#endif + +} +inline std::tm localtime(const std::time_t &time_tt) +{ + +#ifdef _WIN32 + std::tm tm; + localtime_s(&tm, &time_tt); +#else + std::tm tm; + localtime_r(&time_tt, &tm); +#endif + return tm; +} + +inline std::tm localtime() +{ + std::time_t now_t = time(nullptr); + return localtime(now_t); +} + + +inline std::tm gmtime(const std::time_t &time_tt) +{ + +#ifdef _WIN32 + std::tm tm; + gmtime_s(&tm, &time_tt); +#else + std::tm tm; + gmtime_r(&time_tt, &tm); +#endif + return tm; +} + +inline std::tm gmtime() +{ + std::time_t now_t = time(nullptr); + return gmtime(now_t); +} +inline bool operator==(const std::tm& tm1, const std::tm& tm2) +{ + return (tm1.tm_sec == tm2.tm_sec && + tm1.tm_min == tm2.tm_min && + tm1.tm_hour == tm2.tm_hour && + tm1.tm_mday == tm2.tm_mday && + tm1.tm_mon == tm2.tm_mon && + tm1.tm_year == tm2.tm_year && + tm1.tm_isdst == tm2.tm_isdst); +} + +inline bool operator!=(const std::tm& tm1, const std::tm& tm2) +{ + return !(tm1 == tm2); +} + +// eol definition +#if !defined (SPDLOG_EOL) +#ifdef _WIN32 +#define SPDLOG_EOL "\r\n" +#else +#define SPDLOG_EOL "\n" +#endif +#endif + +SPDLOG_CONSTEXPR static const char* eol = SPDLOG_EOL; +SPDLOG_CONSTEXPR static int eol_size = sizeof(SPDLOG_EOL) - 1; + +inline void prevent_child_fd(FILE *f) +{ +#ifdef _WIN32 + auto file_handle = (HANDLE)_get_osfhandle(_fileno(f)); + if (!::SetHandleInformation(file_handle, HANDLE_FLAG_INHERIT, 0)) + throw spdlog_ex("SetHandleInformation failed", errno); +#else + auto fd = fileno(f); + if(fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) + throw spdlog_ex("fcntl with FD_CLOEXEC failed", errno); +#endif +} + + +//fopen_s on non windows for writing +inline int fopen_s(FILE** fp, const filename_t& filename, const filename_t& mode) +{ +#ifdef _WIN32 +#ifdef SPDLOG_WCHAR_FILENAMES + *fp = _wfsopen((filename.c_str()), mode.c_str(), _SH_DENYWR); +#else + *fp = _fsopen((filename.c_str()), mode.c_str(), _SH_DENYWR); +#endif +#else //unix + *fp = fopen((filename.c_str()), mode.c_str()); +#endif + +#ifdef SPDLOG_PREVENT_CHILD_FD + if(*fp != nullptr) + prevent_child_fd(*fp); +#endif + return *fp == nullptr; +} + + +inline int remove(const filename_t &filename) +{ +#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES) + return _wremove(filename.c_str()); +#else + return std::remove(filename.c_str()); +#endif +} + +inline int rename(const filename_t& filename1, const filename_t& filename2) +{ +#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES) + return _wrename(filename1.c_str(), filename2.c_str()); +#else + return std::rename(filename1.c_str(), filename2.c_str()); +#endif +} + + +//Return if file exists +inline bool file_exists(const filename_t& filename) +{ +#ifdef _WIN32 +#ifdef SPDLOG_WCHAR_FILENAMES + auto attribs = GetFileAttributesW(filename.c_str()); +#else + auto attribs = GetFileAttributesA(filename.c_str()); +#endif + return (attribs != INVALID_FILE_ATTRIBUTES && !(attribs & FILE_ATTRIBUTE_DIRECTORY)); +#else //common linux/unix all have the stat system call + struct stat buffer; + return (stat (filename.c_str(), &buffer) == 0); +#endif +} + + + + +//Return file size according to open FILE* object +inline size_t filesize(FILE *f) +{ + if (f == nullptr) + throw spdlog_ex("Failed getting file size. fd is null"); +#ifdef _WIN32 + int fd = _fileno(f); +#if _WIN64 //64 bits + struct _stat64 st; + if (_fstat64(fd, &st) == 0) + return st.st_size; + +#else //windows 32 bits + long ret = _filelength(fd); + if (ret >= 0) + return static_cast<size_t>(ret); +#endif + +#else // unix + int fd = fileno(f); + //64 bits(but not in osx, where fstat64 is deprecated) +#if !defined(__FreeBSD__) && !defined(__APPLE__) && (defined(__x86_64__) || defined(__ppc64__)) + struct stat64 st; + if (fstat64(fd, &st) == 0) + return static_cast<size_t>(st.st_size); +#else // unix 32 bits or osx + struct stat st; + if (fstat(fd, &st) == 0) + return static_cast<size_t>(st.st_size); +#endif +#endif + throw spdlog_ex("Failed getting file size from fd", errno); +} + + + + +//Return utc offset in minutes or throw spdlog_ex on failure +inline int utc_minutes_offset(const std::tm& tm = details::os::localtime()) +{ + +#ifdef _WIN32 +#if _WIN32_WINNT < _WIN32_WINNT_WS08 + TIME_ZONE_INFORMATION tzinfo; + auto rv = GetTimeZoneInformation(&tzinfo); +#else + DYNAMIC_TIME_ZONE_INFORMATION tzinfo; + auto rv = GetDynamicTimeZoneInformation(&tzinfo); +#endif + if (rv == TIME_ZONE_ID_INVALID) + throw spdlog::spdlog_ex("Failed getting timezone info. ", errno); + + int offset = -tzinfo.Bias; + if (tm.tm_isdst) + offset -= tzinfo.DaylightBias; + else + offset -= tzinfo.StandardBias; + return offset; +#else + +#if defined(sun) || defined(__sun) + // 'tm_gmtoff' field is BSD extension and it's missing on SunOS/Solaris + struct helper + { + static long int calculate_gmt_offset(const std::tm & localtm = details::os::localtime(), const std::tm & gmtm = details::os::gmtime()) + { + int local_year = localtm.tm_year + (1900 - 1); + int gmt_year = gmtm.tm_year + (1900 - 1); + + long int days = ( + // difference in day of year + localtm.tm_yday - gmtm.tm_yday + + // + intervening leap days + + ((local_year >> 2) - (gmt_year >> 2)) + - (local_year / 100 - gmt_year / 100) + + ((local_year / 100 >> 2) - (gmt_year / 100 >> 2)) + + // + difference in years * 365 */ + + (long int)(local_year - gmt_year) * 365 + ); + + long int hours = (24 * days) + (localtm.tm_hour - gmtm.tm_hour); + long int mins = (60 * hours) + (localtm.tm_min - gmtm.tm_min); + long int secs = (60 * mins) + (localtm.tm_sec - gmtm.tm_sec); + + return secs; + } + }; + + long int offset_seconds = helper::calculate_gmt_offset(tm); +#else + long int offset_seconds = tm.tm_gmtoff; +#endif + + return static_cast<int>(offset_seconds / 60); +#endif +} + +//Return current thread id as size_t +//It exists because the std::this_thread::get_id() is much slower(espcially under VS 2013) +inline size_t _thread_id() +{ +#ifdef _WIN32 + return static_cast<size_t>(::GetCurrentThreadId()); +#elif __linux__ +# if defined(__ANDROID__) && defined(__ANDROID_API__) && (__ANDROID_API__ < 21) +# define SYS_gettid __NR_gettid +# endif + return static_cast<size_t>(syscall(SYS_gettid)); +#elif __FreeBSD__ + long tid; + thr_self(&tid); + return static_cast<size_t>(tid); +#else //Default to standard C++11 (OSX and other Unix) + return static_cast<size_t>(std::hash<std::thread::id>()(std::this_thread::get_id())); +#endif +} + +//Return current thread id as size_t (from thread local storage) +inline size_t thread_id() +{ +#if defined(_MSC_VER) && (_MSC_VER < 1900) || defined(__clang__) && !__has_feature(cxx_thread_local) + return _thread_id(); +#else + static thread_local const size_t tid = _thread_id(); + return tid; +#endif +} + + + + +// wchar support for windows file names (SPDLOG_WCHAR_FILENAMES must be defined) +#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES) +#define SPDLOG_FILENAME_T(s) L ## s +inline std::string filename_to_str(const filename_t& filename) +{ + std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> c; + return c.to_bytes(filename); +} +#else +#define SPDLOG_FILENAME_T(s) s +inline std::string filename_to_str(const filename_t& filename) +{ + return filename; +} +#endif + + +// Return errno string (thread safe) +inline std::string errno_str(int err_num) +{ + char buf[256]; + SPDLOG_CONSTEXPR auto buf_size = sizeof(buf); + +#ifdef _WIN32 + if(strerror_s(buf, buf_size, err_num) == 0) + return std::string(buf); + else + return "Unkown error"; + +#elif defined(__FreeBSD__) || defined(__APPLE__) || defined(ANDROID) || defined(__SUNPRO_CC) || \ + ((_POSIX_C_SOURCE >= 200112L) && ! defined(_GNU_SOURCE)) // posix version + + if (strerror_r(err_num, buf, buf_size) == 0) + return std::string(buf); + else + return "Unkown error"; + +#else // gnu version (might not use the given buf, so its retval pointer must be used) + return std::string(strerror_r(err_num, buf, buf_size)); +#endif +} + +inline int pid() +{ + +#ifdef _WIN32 + return ::_getpid(); +#else + return static_cast<int>(::getpid()); +#endif + +} + +} //os +} //details +} //spdlog http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/thirdparty/spdlog-0.13.0/include/spdlog/details/pattern_formatter_impl.h ---------------------------------------------------------------------- diff --git a/thirdparty/spdlog-0.13.0/include/spdlog/details/pattern_formatter_impl.h b/thirdparty/spdlog-0.13.0/include/spdlog/details/pattern_formatter_impl.h new file mode 100644 index 0000000..70b9dc8 --- /dev/null +++ b/thirdparty/spdlog-0.13.0/include/spdlog/details/pattern_formatter_impl.h @@ -0,0 +1,670 @@ +// +// Copyright(c) 2015 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +#pragma once + +#include <spdlog/formatter.h> +#include <spdlog/details/log_msg.h> +#include <spdlog/details/os.h> +#include <spdlog/fmt/fmt.h> + +#include <chrono> +#include <ctime> +#include <memory> +#include <mutex> +#include <string> +#include <thread> +#include <utility> +#include <vector> +#include <array> + +namespace spdlog +{ +namespace details +{ +class flag_formatter +{ +public: + virtual ~flag_formatter() + {} + virtual void format(details::log_msg& msg, const std::tm& tm_time) = 0; +}; + +/////////////////////////////////////////////////////////////////////// +// name & level pattern appenders +/////////////////////////////////////////////////////////////////////// +namespace +{ +class name_formatter:public flag_formatter +{ + void format(details::log_msg& msg, const std::tm&) override + { + msg.formatted << *msg.logger_name; + } +}; +} + +// log level appender +class level_formatter:public flag_formatter +{ + void format(details::log_msg& msg, const std::tm&) override + { + msg.formatted << level::to_str(msg.level); + } +}; + +// short log level appender +class short_level_formatter:public flag_formatter +{ + void format(details::log_msg& msg, const std::tm&) override + { + msg.formatted << level::to_short_str(msg.level); + } +}; + +/////////////////////////////////////////////////////////////////////// +// Date time pattern appenders +/////////////////////////////////////////////////////////////////////// + +static const char* ampm(const tm& t) +{ + return t.tm_hour >= 12 ? "PM" : "AM"; +} + +static int to12h(const tm& t) +{ + return t.tm_hour > 12 ? t.tm_hour - 12 : t.tm_hour; +} + +//Abbreviated weekday name +using days_array = std::array<std::string, 7>; +static const days_array& days() +{ + static const days_array arr{ { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" } }; + return arr; +} +class a_formatter:public flag_formatter +{ + void format(details::log_msg& msg, const std::tm& tm_time) override + { + msg.formatted << days()[tm_time.tm_wday]; + } +}; + +//Full weekday name +static const days_array& full_days() +{ + static const days_array arr{ { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" } }; + return arr; +} +class A_formatter:public flag_formatter +{ + void format(details::log_msg& msg, const std::tm& tm_time) override + { + msg.formatted << full_days()[tm_time.tm_wday]; + } +}; + +//Abbreviated month +using months_array = std::array<std::string, 12>; +static const months_array& months() +{ + static const months_array arr{ { "Jan", "Feb", "Mar", "Apr", "May", "June", "July", "Aug", "Sept", "Oct", "Nov", "Dec" } }; + return arr; +} +class b_formatter:public flag_formatter +{ + void format(details::log_msg& msg, const std::tm& tm_time) override + { + msg.formatted << months()[tm_time.tm_mon]; + } +}; + +//Full month name +static const months_array& full_months() +{ + static const months_array arr{ { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" } }; + return arr; +} +class B_formatter:public flag_formatter +{ + void format(details::log_msg& msg, const std::tm& tm_time) override + { + msg.formatted << full_months()[tm_time.tm_mon]; + } +}; + + +//write 2 ints seperated by sep with padding of 2 +static fmt::MemoryWriter& pad_n_join(fmt::MemoryWriter& w, int v1, int v2, char sep) +{ + w << fmt::pad(v1, 2, '0') << sep << fmt::pad(v2, 2, '0'); + return w; +} + +//write 3 ints seperated by sep with padding of 2 +static fmt::MemoryWriter& pad_n_join(fmt::MemoryWriter& w, int v1, int v2, int v3, char sep) +{ + w << fmt::pad(v1, 2, '0') << sep << fmt::pad(v2, 2, '0') << sep << fmt::pad(v3, 2, '0'); + return w; +} + + +//Date and time representation (Thu Aug 23 15:35:46 2014) +class c_formatter:public flag_formatter +{ + void format(details::log_msg& msg, const std::tm& tm_time) override + { + msg.formatted << days()[tm_time.tm_wday] << ' ' << months()[tm_time.tm_mon] << ' ' << tm_time.tm_mday << ' '; + pad_n_join(msg.formatted, tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec, ':') << ' ' << tm_time.tm_year + 1900; + } +}; + + +// year - 2 digit +class C_formatter:public flag_formatter +{ + void format(details::log_msg& msg, const std::tm& tm_time) override + { + msg.formatted << fmt::pad(tm_time.tm_year % 100, 2, '0'); + } +}; + + + +// Short MM/DD/YY date, equivalent to %m/%d/%y 08/23/01 +class D_formatter:public flag_formatter +{ + void format(details::log_msg& msg, const std::tm& tm_time) override + { + pad_n_join(msg.formatted, tm_time.tm_mon + 1, tm_time.tm_mday, tm_time.tm_year % 100, '/'); + } +}; + + +// year - 4 digit +class Y_formatter:public flag_formatter +{ + void format(details::log_msg& msg, const std::tm& tm_time) override + { + msg.formatted << tm_time.tm_year + 1900; + } +}; + +// month 1-12 +class m_formatter:public flag_formatter +{ + void format(details::log_msg& msg, const std::tm& tm_time) override + { + msg.formatted << fmt::pad(tm_time.tm_mon + 1, 2, '0'); + } +}; + +// day of month 1-31 +class d_formatter:public flag_formatter +{ + void format(details::log_msg& msg, const std::tm& tm_time) override + { + msg.formatted << fmt::pad(tm_time.tm_mday, 2, '0'); + } +}; + +// hours in 24 format 0-23 +class H_formatter:public flag_formatter +{ + void format(details::log_msg& msg, const std::tm& tm_time) override + { + msg.formatted << fmt::pad(tm_time.tm_hour, 2, '0'); + } +}; + +// hours in 12 format 1-12 +class I_formatter:public flag_formatter +{ + void format(details::log_msg& msg, const std::tm& tm_time) override + { + msg.formatted << fmt::pad(to12h(tm_time), 2, '0'); + } +}; + +// minutes 0-59 +class M_formatter:public flag_formatter +{ + void format(details::log_msg& msg, const std::tm& tm_time) override + { + msg.formatted << fmt::pad(tm_time.tm_min, 2, '0'); + } +}; + +// seconds 0-59 +class S_formatter:public flag_formatter +{ + void format(details::log_msg& msg, const std::tm& tm_time) override + { + msg.formatted << fmt::pad(tm_time.tm_sec, 2, '0'); + } +}; + +// milliseconds +class e_formatter:public flag_formatter +{ + void format(details::log_msg& msg, const std::tm&) override + { + auto duration = msg.time.time_since_epoch(); + auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() % 1000; + msg.formatted << fmt::pad(static_cast<int>(millis), 3, '0'); + } +}; + +// microseconds +class f_formatter:public flag_formatter +{ + void format(details::log_msg& msg, const std::tm&) override + { + auto duration = msg.time.time_since_epoch(); + auto micros = std::chrono::duration_cast<std::chrono::microseconds>(duration).count() % 1000000; + msg.formatted << fmt::pad(static_cast<int>(micros), 6, '0'); + } +}; + +// nanoseconds +class F_formatter:public flag_formatter +{ + void format(details::log_msg& msg, const std::tm&) override + { + auto duration = msg.time.time_since_epoch(); + auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count() % 1000000000; + msg.formatted << fmt::pad(static_cast<int>(ns), 9, '0'); + } +}; + +// AM/PM +class p_formatter:public flag_formatter +{ + void format(details::log_msg& msg, const std::tm& tm_time) override + { + msg.formatted << ampm(tm_time); + } +}; + + +// 12 hour clock 02:55:02 pm +class r_formatter:public flag_formatter +{ + void format(details::log_msg& msg, const std::tm& tm_time) override + { + pad_n_join(msg.formatted, to12h(tm_time), tm_time.tm_min, tm_time.tm_sec, ':') << ' ' << ampm(tm_time); + } +}; + +// 24-hour HH:MM time, equivalent to %H:%M +class R_formatter:public flag_formatter +{ + void format(details::log_msg& msg, const std::tm& tm_time) override + { + pad_n_join(msg.formatted, tm_time.tm_hour, tm_time.tm_min, ':'); + } +}; + +// ISO 8601 time format (HH:MM:SS), equivalent to %H:%M:%S +class T_formatter:public flag_formatter +{ + void format(details::log_msg& msg, const std::tm& tm_time) override + { + pad_n_join(msg.formatted, tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec, ':'); + } +}; + + +// ISO 8601 offset from UTC in timezone (+-HH:MM) +class z_formatter:public flag_formatter +{ +public: + const std::chrono::seconds cache_refresh = std::chrono::seconds(5); + + z_formatter():_last_update(std::chrono::seconds(0)) + {} + z_formatter(const z_formatter&) = delete; + z_formatter& operator=(const z_formatter&) = delete; + + void format(details::log_msg& msg, const std::tm& tm_time) override + { +#ifdef _WIN32 + int total_minutes = get_cached_offset(msg, tm_time); +#else + // No need to chache under gcc, + // it is very fast (already stored in tm.tm_gmtoff) + int total_minutes = os::utc_minutes_offset(tm_time); +#endif + bool is_negative = total_minutes < 0; + char sign; + if (is_negative) + { + total_minutes = -total_minutes; + sign = '-'; + } + else + { + sign = '+'; + } + + int h = total_minutes / 60; + int m = total_minutes % 60; + msg.formatted << sign; + pad_n_join(msg.formatted, h, m, ':'); + } +private: + log_clock::time_point _last_update; + int _offset_minutes; + std::mutex _mutex; + + int get_cached_offset(const log_msg& msg, const std::tm& tm_time) + { + using namespace std::chrono; + std::lock_guard<std::mutex> l(_mutex); + if (msg.time - _last_update >= cache_refresh) + { + _offset_minutes = os::utc_minutes_offset(tm_time); + _last_update = msg.time; + } + return _offset_minutes; + } +}; + + + +// Thread id +class t_formatter:public flag_formatter +{ + void format(details::log_msg& msg, const std::tm&) override + { + msg.formatted << msg.thread_id; + } +}; + +// Current pid +class pid_formatter:public flag_formatter +{ + void format(details::log_msg& msg, const std::tm&) override + { + msg.formatted << details::os::pid(); + } +}; + + +class v_formatter:public flag_formatter +{ + void format(details::log_msg& msg, const std::tm&) override + { + msg.formatted << fmt::StringRef(msg.raw.data(), msg.raw.size()); + } +}; + +class ch_formatter:public flag_formatter +{ +public: + explicit ch_formatter(char ch): _ch(ch) + {} + void format(details::log_msg& msg, const std::tm&) override + { + msg.formatted << _ch; + } +private: + char _ch; +}; + + +//aggregate user chars to display as is +class aggregate_formatter:public flag_formatter +{ +public: + aggregate_formatter() + {} + void add_ch(char ch) + { + _str += ch; + } + void format(details::log_msg& msg, const std::tm&) override + { + msg.formatted << _str; + } +private: + std::string _str; +}; + +// Full info formatter +// pattern: [%Y-%m-%d %H:%M:%S.%e] [%n] [%l] %v +class full_formatter:public flag_formatter +{ + void format(details::log_msg& msg, const std::tm& tm_time) override + { +#ifndef SPDLOG_NO_DATETIME + auto duration = msg.time.time_since_epoch(); + auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() % 1000; + + /* Slower version(while still very fast - about 3.2 million lines/sec under 10 threads), + msg.formatted.write("[{:d}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}.{:03d}] [{}] [{}] {} ", + tm_time.tm_year + 1900, + tm_time.tm_mon + 1, + tm_time.tm_mday, + tm_time.tm_hour, + tm_time.tm_min, + tm_time.tm_sec, + static_cast<int>(millis), + msg.logger_name, + level::to_str(msg.level), + msg.raw.str());*/ + + + // Faster (albeit uglier) way to format the line (5.6 million lines/sec under 10 threads) + msg.formatted << '[' << static_cast<unsigned int>(tm_time.tm_year + 1900) << '-' + << fmt::pad(static_cast<unsigned int>(tm_time.tm_mon + 1), 2, '0') << '-' + << fmt::pad(static_cast<unsigned int>(tm_time.tm_mday), 2, '0') << ' ' + << fmt::pad(static_cast<unsigned int>(tm_time.tm_hour), 2, '0') << ':' + << fmt::pad(static_cast<unsigned int>(tm_time.tm_min), 2, '0') << ':' + << fmt::pad(static_cast<unsigned int>(tm_time.tm_sec), 2, '0') << '.' + << fmt::pad(static_cast<unsigned int>(millis), 3, '0') << "] "; + + //no datetime needed +#else + (void)tm_time; +#endif + +#ifndef SPDLOG_NO_NAME + msg.formatted << '[' << *msg.logger_name << "] "; +#endif + + msg.formatted << '[' << level::to_str(msg.level) << "] "; + msg.formatted << fmt::StringRef(msg.raw.data(), msg.raw.size()); + } +}; + + + +} +} +/////////////////////////////////////////////////////////////////////////////// +// pattern_formatter inline impl +/////////////////////////////////////////////////////////////////////////////// +inline spdlog::pattern_formatter::pattern_formatter(const std::string& pattern) +{ + compile_pattern(pattern); +} + +inline void spdlog::pattern_formatter::compile_pattern(const std::string& pattern) +{ + auto end = pattern.end(); + std::unique_ptr<details::aggregate_formatter> user_chars; + for (auto it = pattern.begin(); it != end; ++it) + { + if (*it == '%') + { + if (user_chars) //append user chars found so far + _formatters.push_back(std::move(user_chars)); + + if (++it != end) + handle_flag(*it); + else + break; + } + else // chars not following the % sign should be displayed as is + { + if (!user_chars) + user_chars = std::unique_ptr<details::aggregate_formatter>(new details::aggregate_formatter()); + user_chars->add_ch(*it); + } + } + if (user_chars) //append raw chars found so far + { + _formatters.push_back(std::move(user_chars)); + } + +} +inline void spdlog::pattern_formatter::handle_flag(char flag) +{ + switch (flag) + { + // logger name + case 'n': + _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::name_formatter())); + break; + + case 'l': + _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::level_formatter())); + break; + + case 'L': + _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::short_level_formatter())); + break; + + case('t'): + _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::t_formatter())); + break; + + case('v'): + _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::v_formatter())); + break; + + case('a'): + _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::a_formatter())); + break; + + case('A'): + _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::A_formatter())); + break; + + case('b'): + case('h'): + _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::b_formatter())); + break; + + case('B'): + _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::B_formatter())); + break; + case('c'): + _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::c_formatter())); + break; + + case('C'): + _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::C_formatter())); + break; + + case('Y'): + _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::Y_formatter())); + break; + + case('D'): + case('x'): + + _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::D_formatter())); + break; + + case('m'): + _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::m_formatter())); + break; + + case('d'): + _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::d_formatter())); + break; + + case('H'): + _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::H_formatter())); + break; + + case('I'): + _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::I_formatter())); + break; + + case('M'): + _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::M_formatter())); + break; + + case('S'): + _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::S_formatter())); + break; + + case('e'): + _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::e_formatter())); + break; + + case('f'): + _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::f_formatter())); + break; + case('F'): + _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::F_formatter())); + break; + + case('p'): + _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::p_formatter())); + break; + + case('r'): + _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::r_formatter())); + break; + + case('R'): + _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::R_formatter())); + break; + + case('T'): + case('X'): + _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::T_formatter())); + break; + + case('z'): + _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::z_formatter())); + break; + + case ('+'): + _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::full_formatter())); + break; + + case ('P'): + _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::pid_formatter())); + break; + + default: //Unkown flag appears as is + _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::ch_formatter('%'))); + _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::ch_formatter(flag))); + break; + } +} + + +inline void spdlog::pattern_formatter::format(details::log_msg& msg) +{ + +#ifndef SPDLOG_NO_DATETIME + auto tm_time = details::os::localtime(log_clock::to_time_t(msg.time)); +#else + std::tm tm_time; +#endif + for (auto &f : _formatters) + { + f->format(msg, tm_time); + } + //write eol + msg.formatted.write(details::os::eol, details::os::eol_size); +} http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/thirdparty/spdlog-0.13.0/include/spdlog/details/registry.h ---------------------------------------------------------------------- diff --git a/thirdparty/spdlog-0.13.0/include/spdlog/details/registry.h b/thirdparty/spdlog-0.13.0/include/spdlog/details/registry.h new file mode 100644 index 0000000..ee14adf --- /dev/null +++ b/thirdparty/spdlog-0.13.0/include/spdlog/details/registry.h @@ -0,0 +1,185 @@ +// +// Copyright(c) 2015 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +#pragma once + +// Loggers registy of unique name->logger pointer +// An attempt to create a logger with an already existing name will be ignored +// If user requests a non existing logger, nullptr will be returned +// This class is thread safe + +#include <spdlog/details/null_mutex.h> +#include <spdlog/logger.h> +#include <spdlog/async_logger.h> +#include <spdlog/common.h> + +#include <chrono> +#include <functional> +#include <memory> +#include <mutex> +#include <string> +#include <unordered_map> + +namespace spdlog +{ +namespace details +{ +template <class Mutex> class registry_t +{ +public: + + void register_logger(std::shared_ptr<logger> logger) + { + std::lock_guard<Mutex> lock(_mutex); + auto logger_name = logger->name(); + throw_if_exists(logger_name); + _loggers[logger_name] = logger; + } + + + std::shared_ptr<logger> get(const std::string& logger_name) + { + std::lock_guard<Mutex> lock(_mutex); + auto found = _loggers.find(logger_name); + return found == _loggers.end() ? nullptr : found->second; + } + + template<class It> + std::shared_ptr<logger> create(const std::string& logger_name, const It& sinks_begin, const It& sinks_end) + { + std::lock_guard<Mutex> lock(_mutex); + throw_if_exists(logger_name); + std::shared_ptr<logger> new_logger; + if (_async_mode) + new_logger = std::make_shared<async_logger>(logger_name, sinks_begin, sinks_end, _async_q_size, _overflow_policy, _worker_warmup_cb, _flush_interval_ms, _worker_teardown_cb); + else + new_logger = std::make_shared<logger>(logger_name, sinks_begin, sinks_end); + + if (_formatter) + new_logger->set_formatter(_formatter); + + if (_err_handler) + new_logger->set_error_handler(_err_handler); + + new_logger->set_level(_level); + + + //Add to registry + _loggers[logger_name] = new_logger; + return new_logger; + } + + void apply_all(std::function<void(std::shared_ptr<logger>)> fun) + { + std::lock_guard<Mutex> lock(_mutex); + for (auto &l : _loggers) + fun(l.second); + } + + void drop(const std::string& logger_name) + { + std::lock_guard<Mutex> lock(_mutex); + _loggers.erase(logger_name); + } + + void drop_all() + { + std::lock_guard<Mutex> lock(_mutex); + _loggers.clear(); + } + std::shared_ptr<logger> create(const std::string& logger_name, sinks_init_list sinks) + { + return create(logger_name, sinks.begin(), sinks.end()); + } + + std::shared_ptr<logger> create(const std::string& logger_name, sink_ptr sink) + { + return create(logger_name, { sink }); + } + + + void formatter(formatter_ptr f) + { + std::lock_guard<Mutex> lock(_mutex); + _formatter = f; + for (auto& l : _loggers) + l.second->set_formatter(_formatter); + } + + void set_pattern(const std::string& pattern) + { + std::lock_guard<Mutex> lock(_mutex); + _formatter = std::make_shared<pattern_formatter>(pattern); + for (auto& l : _loggers) + l.second->set_formatter(_formatter); + } + + void set_level(level::level_enum log_level) + { + std::lock_guard<Mutex> lock(_mutex); + for (auto& l : _loggers) + l.second->set_level(log_level); + _level = log_level; + } + + void set_error_handler(log_err_handler handler) + { + for (auto& l : _loggers) + l.second->set_error_handler(handler); + _err_handler = handler; + } + + void set_async_mode(size_t q_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function<void()>& worker_teardown_cb) + { + std::lock_guard<Mutex> lock(_mutex); + _async_mode = true; + _async_q_size = q_size; + _overflow_policy = overflow_policy; + _worker_warmup_cb = worker_warmup_cb; + _flush_interval_ms = flush_interval_ms; + _worker_teardown_cb = worker_teardown_cb; + } + + void set_sync_mode() + { + std::lock_guard<Mutex> lock(_mutex); + _async_mode = false; + } + + static registry_t<Mutex>& instance() + { + static registry_t<Mutex> s_instance; + return s_instance; + } + +private: + registry_t<Mutex>() {} + registry_t<Mutex>(const registry_t<Mutex>&) = delete; + registry_t<Mutex>& operator=(const registry_t<Mutex>&) = delete; + + void throw_if_exists(const std::string &logger_name) + { + if (_loggers.find(logger_name) != _loggers.end()) + throw spdlog_ex("logger with name '" + logger_name + "' already exists"); + } + Mutex _mutex; + std::unordered_map <std::string, std::shared_ptr<logger>> _loggers; + formatter_ptr _formatter; + level::level_enum _level = level::info; + log_err_handler _err_handler; + bool _async_mode = false; + size_t _async_q_size = 0; + async_overflow_policy _overflow_policy = async_overflow_policy::block_retry; + std::function<void()> _worker_warmup_cb = nullptr; + std::chrono::milliseconds _flush_interval_ms; + std::function<void()> _worker_teardown_cb = nullptr; +}; +#ifdef SPDLOG_NO_REGISTRY_MUTEX +typedef registry_t<spdlog::details::null_mutex> registry; +#else +typedef registry_t<std::mutex> registry; +#endif +} +} http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/thirdparty/spdlog-0.13.0/include/spdlog/details/spdlog_impl.h ---------------------------------------------------------------------- diff --git a/thirdparty/spdlog-0.13.0/include/spdlog/details/spdlog_impl.h b/thirdparty/spdlog-0.13.0/include/spdlog/details/spdlog_impl.h new file mode 100644 index 0000000..79d3ac4 --- /dev/null +++ b/thirdparty/spdlog-0.13.0/include/spdlog/details/spdlog_impl.h @@ -0,0 +1,245 @@ +// +// Copyright(c) 2015 Gabi Melman. +// Distributed under the MIT License (http://opensource.org/licenses/MIT) +// + +#pragma once + +// +// Global registry functions +// +#include <spdlog/spdlog.h> +#include <spdlog/details/registry.h> +#include <spdlog/sinks/file_sinks.h> +#include <spdlog/sinks/stdout_sinks.h> +#ifdef SPDLOG_ENABLE_SYSLOG +#include <spdlog/sinks/syslog_sink.h> +#endif + +#ifdef _WIN32 +#include <spdlog/sinks/wincolor_sink.h> +#else +#include <spdlog/sinks/ansicolor_sink.h> +#endif + + +#ifdef __ANDROID__ +#include <spdlog/sinks/android_sink.h> +#endif + +#include <chrono> +#include <functional> +#include <memory> +#include <string> + +inline void spdlog::register_logger(std::shared_ptr<logger> logger) +{ + return details::registry::instance().register_logger(logger); +} + +inline std::shared_ptr<spdlog::logger> spdlog::get(const std::string& name) +{ + return details::registry::instance().get(name); +} + +inline void spdlog::drop(const std::string &name) +{ + details::registry::instance().drop(name); +} + +// Create multi/single threaded simple file logger +inline std::shared_ptr<spdlog::logger> spdlog::basic_logger_mt(const std::string& logger_name, const filename_t& filename, bool truncate) +{ + return create<spdlog::sinks::simple_file_sink_mt>(logger_name, filename, truncate); +} + +inline std::shared_ptr<spdlog::logger> spdlog::basic_logger_st(const std::string& logger_name, const filename_t& filename, bool truncate) +{ + return create<spdlog::sinks::simple_file_sink_st>(logger_name, filename, truncate); +} + +// Create multi/single threaded rotating file logger +inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_mt(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files) +{ + return create<spdlog::sinks::rotating_file_sink_mt>(logger_name, filename, max_file_size, max_files); +} + +inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_st(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files) +{ + return create<spdlog::sinks::rotating_file_sink_st>(logger_name, filename, max_file_size, max_files); +} + +// Create file logger which creates new file at midnight): +inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_mt(const std::string& logger_name, const filename_t& filename, int hour, int minute) +{ + return create<spdlog::sinks::daily_file_sink_mt>(logger_name, filename, hour, minute); +} + +inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_st(const std::string& logger_name, const filename_t& filename, int hour, int minute) +{ + return create<spdlog::sinks::daily_file_sink_st>(logger_name, filename, hour, minute); +} + + +// +// stdout/stderr loggers +// +inline std::shared_ptr<spdlog::logger> spdlog::stdout_logger_mt(const std::string& logger_name) +{ + return spdlog::details::registry::instance().create(logger_name, spdlog::sinks::stdout_sink_mt::instance()); +} + +inline std::shared_ptr<spdlog::logger> spdlog::stdout_logger_st(const std::string& logger_name) +{ + return spdlog::details::registry::instance().create(logger_name, spdlog::sinks::stdout_sink_st::instance()); +} + +inline std::shared_ptr<spdlog::logger> spdlog::stderr_logger_mt(const std::string& logger_name) +{ + return spdlog::details::registry::instance().create(logger_name, spdlog::sinks::stderr_sink_mt::instance()); +} + +inline std::shared_ptr<spdlog::logger> spdlog::stderr_logger_st(const std::string& logger_name) +{ + return spdlog::details::registry::instance().create(logger_name, spdlog::sinks::stderr_sink_st::instance()); +} + +// +// stdout/stderr color loggers +// +#ifdef _WIN32 +inline std::shared_ptr<spdlog::logger> spdlog::stdout_color_mt(const std::string& logger_name) +{ + auto sink = std::make_shared<spdlog::sinks::wincolor_stdout_sink_mt>(); + return spdlog::details::registry::instance().create(logger_name, sink); +} + +inline std::shared_ptr<spdlog::logger> spdlog::stdout_color_st(const std::string& logger_name) +{ + auto sink = std::make_shared<spdlog::sinks::wincolor_stdout_sink_st>(); + return spdlog::details::registry::instance().create(logger_name, sink); +} + +inline std::shared_ptr<spdlog::logger> spdlog::stderr_color_mt(const std::string& logger_name) +{ + auto sink = std::make_shared<spdlog::sinks::wincolor_stderr_sink_mt>(); + return spdlog::details::registry::instance().create(logger_name, sink); +} + + +inline std::shared_ptr<spdlog::logger> spdlog::stderr_color_st(const std::string& logger_name) +{ + auto sink = std::make_shared<spdlog::sinks::wincolor_stderr_sink_st>(); + return spdlog::details::registry::instance().create(logger_name, sink); +} + +#else //ansi terminal colors + +inline std::shared_ptr<spdlog::logger> spdlog::stdout_color_mt(const std::string& logger_name) +{ + auto sink = std::make_shared<spdlog::sinks::ansicolor_sink>(spdlog::sinks::stdout_sink_mt::instance()); + return spdlog::details::registry::instance().create(logger_name, sink); +} + +inline std::shared_ptr<spdlog::logger> spdlog::stdout_color_st(const std::string& logger_name) +{ + auto sink = std::make_shared<spdlog::sinks::ansicolor_sink>(spdlog::sinks::stdout_sink_st::instance()); + return spdlog::details::registry::instance().create(logger_name, sink); +} + +inline std::shared_ptr<spdlog::logger> spdlog::stderr_color_mt(const std::string& logger_name) +{ + auto sink = std::make_shared<spdlog::sinks::ansicolor_sink>(spdlog::sinks::stderr_sink_mt::instance()); + return spdlog::details::registry::instance().create(logger_name, sink); +} + +inline std::shared_ptr<spdlog::logger> spdlog::stderr_color_st(const std::string& logger_name) +{ + auto sink = std::make_shared<spdlog::sinks::ansicolor_sink>(spdlog::sinks::stderr_sink_st::instance()); + return spdlog::details::registry::instance().create(logger_name, sink); +} +#endif + +#ifdef SPDLOG_ENABLE_SYSLOG +// Create syslog logger +inline std::shared_ptr<spdlog::logger> spdlog::syslog_logger(const std::string& logger_name, const std::string& syslog_ident, int syslog_option) +{ + return create<spdlog::sinks::syslog_sink>(logger_name, syslog_ident, syslog_option); +} +#endif + +#ifdef __ANDROID__ +inline std::shared_ptr<spdlog::logger> spdlog::android_logger(const std::string& logger_name, const std::string& tag) +{ + return create<spdlog::sinks::android_sink>(logger_name, tag); +} +#endif + +// Create and register a logger a single sink +inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string& logger_name, const spdlog::sink_ptr& sink) +{ + return details::registry::instance().create(logger_name, sink); +} + +//Create logger with multiple sinks + +inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string& logger_name, spdlog::sinks_init_list sinks) +{ + return details::registry::instance().create(logger_name, sinks); +} + + +template <typename Sink, typename... Args> +inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string& logger_name, Args... args) +{ + sink_ptr sink = std::make_shared<Sink>(args...); + return details::registry::instance().create(logger_name, { sink }); +} + + +template<class It> +inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string& logger_name, const It& sinks_begin, const It& sinks_end) +{ + return details::registry::instance().create(logger_name, sinks_begin, sinks_end); +} + +inline void spdlog::set_formatter(spdlog::formatter_ptr f) +{ + details::registry::instance().formatter(f); +} + +inline void spdlog::set_pattern(const std::string& format_string) +{ + return details::registry::instance().set_pattern(format_string); +} + +inline void spdlog::set_level(level::level_enum log_level) +{ + return details::registry::instance().set_level(log_level); +} + +inline void spdlog::set_error_handler(log_err_handler handler) +{ + return details::registry::instance().set_error_handler(handler); +} + + +inline void spdlog::set_async_mode(size_t queue_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function<void()>& worker_teardown_cb) +{ + details::registry::instance().set_async_mode(queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb); +} + +inline void spdlog::set_sync_mode() +{ + details::registry::instance().set_sync_mode(); +} + +inline void spdlog::apply_all(std::function<void(std::shared_ptr<logger>)> fun) +{ + details::registry::instance().apply_all(fun); +} + +inline void spdlog::drop_all() +{ + details::registry::instance().drop_all(); +} http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/thirdparty/spdlog-0.13.0/include/spdlog/dummy.cpp ---------------------------------------------------------------------- diff --git a/thirdparty/spdlog-0.13.0/include/spdlog/dummy.cpp b/thirdparty/spdlog-0.13.0/include/spdlog/dummy.cpp new file mode 100644 index 0000000..6b2d4ab --- /dev/null +++ b/thirdparty/spdlog-0.13.0/include/spdlog/dummy.cpp @@ -0,0 +1,22 @@ +/** + * @file dummy.cpp + * MiNiFiMain implementation + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Dummy CPP file to work around Cmake limitation on header only libraries + http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/73ecc667/thirdparty/spdlog-0.13.0/include/spdlog/fmt/bundled/format.cc ---------------------------------------------------------------------- diff --git a/thirdparty/spdlog-0.13.0/include/spdlog/fmt/bundled/format.cc b/thirdparty/spdlog-0.13.0/include/spdlog/fmt/bundled/format.cc new file mode 100644 index 0000000..2bd774e --- /dev/null +++ b/thirdparty/spdlog-0.13.0/include/spdlog/fmt/bundled/format.cc @@ -0,0 +1,940 @@ +/* + Formatting library for C++ + + Copyright (c) 2012 - 2016, Victor Zverovich + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "format.h" + +#include <string.h> + +#include <cctype> +#include <cerrno> +#include <climits> +#include <cmath> +#include <cstdarg> +#include <cstddef> // for std::ptrdiff_t + +#if defined(_WIN32) && defined(__MINGW32__) +# include <cstring> +#endif + +#if FMT_USE_WINDOWS_H +# if defined(NOMINMAX) || defined(FMT_WIN_MINMAX) +# include <windows.h> +# else +# define NOMINMAX +# include <windows.h> +# undef NOMINMAX +# endif +#endif + +using fmt::internal::Arg; + +#if FMT_EXCEPTIONS +# define FMT_TRY try +# define FMT_CATCH(x) catch (x) +#else +# define FMT_TRY if (true) +# define FMT_CATCH(x) if (false) +#endif + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4127) // conditional expression is constant +# pragma warning(disable: 4702) // unreachable code +// Disable deprecation warning for strerror. The latter is not called but +// MSVC fails to detect it. +# pragma warning(disable: 4996) +#endif + +// Dummy implementations of strerror_r and strerror_s called if corresponding +// system functions are not available. +static inline fmt::internal::Null<> strerror_r(int, char *, ...) { + return fmt::internal::Null<>(); +} +static inline fmt::internal::Null<> strerror_s(char *, std::size_t, ...) { + return fmt::internal::Null<>(); +} + +namespace fmt { + +FMT_FUNC internal::RuntimeError::~RuntimeError() throw() {} +FMT_FUNC FormatError::~FormatError() throw() {} +FMT_FUNC SystemError::~SystemError() throw() {} + +namespace { + +#ifndef _MSC_VER +# define FMT_SNPRINTF snprintf +#else // _MSC_VER +inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) { + va_list args; + va_start(args, format); + int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args); + va_end(args); + return result; +} +# define FMT_SNPRINTF fmt_snprintf +#endif // _MSC_VER + +#if defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT) +# define FMT_SWPRINTF snwprintf +#else +# define FMT_SWPRINTF swprintf +#endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT) + +// Checks if a value fits in int - used to avoid warnings about comparing +// signed and unsigned integers. +template <bool IsSigned> +struct IntChecker { + template <typename T> + static bool fits_in_int(T value) { + unsigned max = INT_MAX; + return value <= max; + } + static bool fits_in_int(bool) { return true; } +}; + +template <> +struct IntChecker<true> { + template <typename T> + static bool fits_in_int(T value) { + return value >= INT_MIN && value <= INT_MAX; + } + static bool fits_in_int(int) { return true; } +}; + +const char RESET_COLOR[] = "\x1b[0m"; + +typedef void (*FormatFunc)(Writer &, int, StringRef); + +// Portable thread-safe version of strerror. +// Sets buffer to point to a string describing the error code. +// This can be either a pointer to a string stored in buffer, +// or a pointer to some static immutable string. +// Returns one of the following values: +// 0 - success +// ERANGE - buffer is not large enough to store the error message +// other - failure +// Buffer should be at least of size 1. +int safe_strerror( + int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT { + FMT_ASSERT(buffer != 0 && buffer_size != 0, "invalid buffer"); + + class StrError { + private: + int error_code_; + char *&buffer_; + std::size_t buffer_size_; + + // A noop assignment operator to avoid bogus warnings. + void operator=(const StrError &) {} + + // Handle the result of XSI-compliant version of strerror_r. + int handle(int result) { + // glibc versions before 2.13 return result in errno. + return result == -1 ? errno : result; + } + + // Handle the result of GNU-specific version of strerror_r. + int handle(char *message) { + // If the buffer is full then the message is probably truncated. + if (message == buffer_ && strlen(buffer_) == buffer_size_ - 1) + return ERANGE; + buffer_ = message; + return 0; + } + + // Handle the case when strerror_r is not available. + int handle(internal::Null<>) { + return fallback(strerror_s(buffer_, buffer_size_, error_code_)); + } + + // Fallback to strerror_s when strerror_r is not available. + int fallback(int result) { + // If the buffer is full then the message is probably truncated. + return result == 0 && strlen(buffer_) == buffer_size_ - 1 ? + ERANGE : result; + } + + // Fallback to strerror if strerror_r and strerror_s are not available. + int fallback(internal::Null<>) { + errno = 0; + buffer_ = strerror(error_code_); + return errno; + } + + public: + StrError(int err_code, char *&buf, std::size_t buf_size) + : error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {} + + int run() { + strerror_r(0, 0, ""); // Suppress a warning about unused strerror_r. + return handle(strerror_r(error_code_, buffer_, buffer_size_)); + } + }; + return StrError(error_code, buffer, buffer_size).run(); +} + +void format_error_code(Writer &out, int error_code, + StringRef message) FMT_NOEXCEPT { + // Report error code making sure that the output fits into + // INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential + // bad_alloc. + out.clear(); + static const char SEP[] = ": "; + static const char ERROR_STR[] = "error "; + // Subtract 2 to account for terminating null characters in SEP and ERROR_STR. + std::size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2; + typedef internal::IntTraits<int>::MainType MainType; + MainType abs_value = static_cast<MainType>(error_code); + if (internal::is_negative(error_code)) { + abs_value = 0 - abs_value; + ++error_code_size; + } + error_code_size += internal::count_digits(abs_value); + if (message.size() <= internal::INLINE_BUFFER_SIZE - error_code_size) + out << message << SEP; + out << ERROR_STR << error_code; + assert(out.size() <= internal::INLINE_BUFFER_SIZE); +} + +void report_error(FormatFunc func, int error_code, + StringRef message) FMT_NOEXCEPT { + MemoryWriter full_message; + func(full_message, error_code, message); + // Use Writer::data instead of Writer::c_str to avoid potential memory + // allocation. + std::fwrite(full_message.data(), full_message.size(), 1, stderr); + std::fputc('\n', stderr); +} + +// IsZeroInt::visit(arg) returns true iff arg is a zero integer. +class IsZeroInt : public ArgVisitor<IsZeroInt, bool> { + public: + template <typename T> + bool visit_any_int(T value) { return value == 0; } +}; + +// Checks if an argument is a valid printf width specifier and sets +// left alignment if it is negative. +class WidthHandler : public ArgVisitor<WidthHandler, unsigned> { + private: + FormatSpec &spec_; + + FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler); + + public: + explicit WidthHandler(FormatSpec &spec) : spec_(spec) {} + + void report_unhandled_arg() { + FMT_THROW(FormatError("width is not integer")); + } + + template <typename T> + unsigned visit_any_int(T value) { + typedef typename internal::IntTraits<T>::MainType UnsignedType; + UnsignedType width = static_cast<UnsignedType>(value); + if (internal::is_negative(value)) { + spec_.align_ = ALIGN_LEFT; + width = 0 - width; + } + if (width > INT_MAX) + FMT_THROW(FormatError("number is too big")); + return static_cast<unsigned>(width); + } +}; + +class PrecisionHandler : public ArgVisitor<PrecisionHandler, int> { + public: + void report_unhandled_arg() { + FMT_THROW(FormatError("precision is not integer")); + } + + template <typename T> + int visit_any_int(T value) { + if (!IntChecker<std::numeric_limits<T>::is_signed>::fits_in_int(value)) + FMT_THROW(FormatError("number is too big")); + return static_cast<int>(value); + } +}; + +template <typename T, typename U> +struct is_same { + enum { value = 0 }; +}; + +template <typename T> +struct is_same<T, T> { + enum { value = 1 }; +}; + +// An argument visitor that converts an integer argument to T for printf, +// if T is an integral type. If T is void, the argument is converted to +// corresponding signed or unsigned type depending on the type specifier: +// 'd' and 'i' - signed, other - unsigned) +template <typename T = void> +class ArgConverter : public ArgVisitor<ArgConverter<T>, void> { + private: + internal::Arg &arg_; + wchar_t type_; + + FMT_DISALLOW_COPY_AND_ASSIGN(ArgConverter); + + public: + ArgConverter(internal::Arg &arg, wchar_t type) + : arg_(arg), type_(type) {} + + void visit_bool(bool value) { + if (type_ != 's') + visit_any_int(value); + } + + template <typename U> + void visit_any_int(U value) { + bool is_signed = type_ == 'd' || type_ == 'i'; + using internal::Arg; + typedef typename internal::Conditional< + is_same<T, void>::value, U, T>::type TargetType; + if (sizeof(TargetType) <= sizeof(int)) { + // Extra casts are used to silence warnings. + if (is_signed) { + arg_.type = Arg::INT; + arg_.int_value = static_cast<int>(static_cast<TargetType>(value)); + } else { + arg_.type = Arg::UINT; + typedef typename internal::MakeUnsigned<TargetType>::Type Unsigned; + arg_.uint_value = static_cast<unsigned>(static_cast<Unsigned>(value)); + } + } else { + if (is_signed) { + arg_.type = Arg::LONG_LONG; + // glibc's printf doesn't sign extend arguments of smaller types: + // std::printf("%lld", -42); // prints "4294967254" + // but we don't have to do the same because it's a UB. + arg_.long_long_value = static_cast<LongLong>(value); + } else { + arg_.type = Arg::ULONG_LONG; + arg_.ulong_long_value = + static_cast<typename internal::MakeUnsigned<U>::Type>(value); + } + } + } +}; + +// Converts an integer argument to char for printf. +class CharConverter : public ArgVisitor<CharConverter, void> { + private: + internal::Arg &arg_; + + FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter); + + public: + explicit CharConverter(internal::Arg &arg) : arg_(arg) {} + + template <typename T> + void visit_any_int(T value) { + arg_.type = internal::Arg::CHAR; + arg_.int_value = static_cast<char>(value); + } +}; +} // namespace + +namespace internal { + +template <typename Char> +class PrintfArgFormatter : + public ArgFormatterBase<PrintfArgFormatter<Char>, Char> { + + void write_null_pointer() { + this->spec().type_ = 0; + this->write("(nil)"); + } + + typedef ArgFormatterBase<PrintfArgFormatter<Char>, Char> Base; + + public: + PrintfArgFormatter(BasicWriter<Char> &w, FormatSpec &s) + : ArgFormatterBase<PrintfArgFormatter<Char>, Char>(w, s) {} + + void visit_bool(bool value) { + FormatSpec &fmt_spec = this->spec(); + if (fmt_spec.type_ != 's') + return this->visit_any_int(value); + fmt_spec.type_ = 0; + this->write(value); + } + + void visit_char(int value) { + const FormatSpec &fmt_spec = this->spec(); + BasicWriter<Char> &w = this->writer(); + if (fmt_spec.type_ && fmt_spec.type_ != 'c') + w.write_int(value, fmt_spec); + typedef typename BasicWriter<Char>::CharPtr CharPtr; + CharPtr out = CharPtr(); + if (fmt_spec.width_ > 1) { + Char fill = ' '; + out = w.grow_buffer(fmt_spec.width_); + if (fmt_spec.align_ != ALIGN_LEFT) { + std::fill_n(out, fmt_spec.width_ - 1, fill); + out += fmt_spec.width_ - 1; + } else { + std::fill_n(out + 1, fmt_spec.width_ - 1, fill); + } + } else { + out = w.grow_buffer(1); + } + *out = static_cast<Char>(value); + } + + void visit_cstring(const char *value) { + if (value) + Base::visit_cstring(value); + else if (this->spec().type_ == 'p') + write_null_pointer(); + else + this->write("(null)"); + } + + void visit_pointer(const void *value) { + if (value) + return Base::visit_pointer(value); + this->spec().type_ = 0; + write_null_pointer(); + } + + void visit_custom(Arg::CustomValue c) { + BasicFormatter<Char> formatter(ArgList(), this->writer()); + const Char format_str[] = {'}', 0}; + const Char *format = format_str; + c.format(&formatter, c.value, &format); + } +}; +} // namespace internal +} // namespace fmt + +FMT_FUNC void fmt::SystemError::init( + int err_code, CStringRef format_str, ArgList args) { + error_code_ = err_code; + MemoryWriter w; + internal::format_system_error(w, err_code, format(format_str, args)); + std::runtime_error &base = *this; + base = std::runtime_error(w.str()); +} + +template <typename T> +int fmt::internal::CharTraits<char>::format_float( + char *buffer, std::size_t size, const char *format, + unsigned width, int precision, T value) { + if (width == 0) { + return precision < 0 ? + FMT_SNPRINTF(buffer, size, format, value) : + FMT_SNPRINTF(buffer, size, format, precision, value); + } + return precision < 0 ? + FMT_SNPRINTF(buffer, size, format, width, value) : + FMT_SNPRINTF(buffer, size, format, width, precision, value); +} + +template <typename T> +int fmt::internal::CharTraits<wchar_t>::format_float( + wchar_t *buffer, std::size_t size, const wchar_t *format, + unsigned width, int precision, T value) { + if (width == 0) { + return precision < 0 ? + FMT_SWPRINTF(buffer, size, format, value) : + FMT_SWPRINTF(buffer, size, format, precision, value); + } + return precision < 0 ? + FMT_SWPRINTF(buffer, size, format, width, value) : + FMT_SWPRINTF(buffer, size, format, width, precision, value); +} + +template <typename T> +const char fmt::internal::BasicData<T>::DIGITS[] = + "0001020304050607080910111213141516171819" + "2021222324252627282930313233343536373839" + "4041424344454647484950515253545556575859" + "6061626364656667686970717273747576777879" + "8081828384858687888990919293949596979899"; + +#define FMT_POWERS_OF_10(factor) \ + factor * 10, \ + factor * 100, \ + factor * 1000, \ + factor * 10000, \ + factor * 100000, \ + factor * 1000000, \ + factor * 10000000, \ + factor * 100000000, \ + factor * 1000000000 + +template <typename T> +const uint32_t fmt::internal::BasicData<T>::POWERS_OF_10_32[] = { + 0, FMT_POWERS_OF_10(1) +}; + +template <typename T> +const uint64_t fmt::internal::BasicData<T>::POWERS_OF_10_64[] = { + 0, + FMT_POWERS_OF_10(1), + FMT_POWERS_OF_10(fmt::ULongLong(1000000000)), + // Multiply several constants instead of using a single long long constant + // to avoid warnings about C++98 not supporting long long. + fmt::ULongLong(1000000000) * fmt::ULongLong(1000000000) * 10 +}; + +FMT_FUNC void fmt::internal::report_unknown_type(char code, const char *type) { + (void)type; + if (std::isprint(static_cast<unsigned char>(code))) { + FMT_THROW(fmt::FormatError( + fmt::format("unknown format code '{}' for {}", code, type))); + } + FMT_THROW(fmt::FormatError( + fmt::format("unknown format code '\\x{:02x}' for {}", + static_cast<unsigned>(code), type))); +} + +#if FMT_USE_WINDOWS_H + +FMT_FUNC fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s) { + static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16"; + if (s.size() > INT_MAX) + FMT_THROW(WindowsError(ERROR_INVALID_PARAMETER, ERROR_MSG)); + int s_size = static_cast<int>(s.size()); + int length = MultiByteToWideChar( + CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, 0, 0); + if (length == 0) + FMT_THROW(WindowsError(GetLastError(), ERROR_MSG)); + buffer_.resize(length + 1); + length = MultiByteToWideChar( + CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, &buffer_[0], length); + if (length == 0) + FMT_THROW(WindowsError(GetLastError(), ERROR_MSG)); + buffer_[length] = 0; +} + +FMT_FUNC fmt::internal::UTF16ToUTF8::UTF16ToUTF8(fmt::WStringRef s) { + if (int error_code = convert(s)) { + FMT_THROW(WindowsError(error_code, + "cannot convert string from UTF-16 to UTF-8")); + } +} + +FMT_FUNC int fmt::internal::UTF16ToUTF8::convert(fmt::WStringRef s) { + if (s.size() > INT_MAX) + return ERROR_INVALID_PARAMETER; + int s_size = static_cast<int>(s.size()); + int length = WideCharToMultiByte(CP_UTF8, 0, s.data(), s_size, 0, 0, 0, 0); + if (length == 0) + return GetLastError(); + buffer_.resize(length + 1); + length = WideCharToMultiByte( + CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, 0, 0); + if (length == 0) + return GetLastError(); + buffer_[length] = 0; + return 0; +} + +FMT_FUNC void fmt::WindowsError::init( + int err_code, CStringRef format_str, ArgList args) { + error_code_ = err_code; + MemoryWriter w; + internal::format_windows_error(w, err_code, format(format_str, args)); + std::runtime_error &base = *this; + base = std::runtime_error(w.str()); +} + +FMT_FUNC void fmt::internal::format_windows_error( + fmt::Writer &out, int error_code, + fmt::StringRef message) FMT_NOEXCEPT { + FMT_TRY { + MemoryBuffer<wchar_t, INLINE_BUFFER_SIZE> buffer; + buffer.resize(INLINE_BUFFER_SIZE); + for (;;) { + wchar_t *system_message = &buffer[0]; + int result = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + 0, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + system_message, static_cast<uint32_t>(buffer.size()), 0); + if (result != 0) { + UTF16ToUTF8 utf8_message; + if (utf8_message.convert(system_message) == ERROR_SUCCESS) { + out << message << ": " << utf8_message; + return; + } + break; + } + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) + break; // Can't get error message, report error code instead. + buffer.resize(buffer.size() * 2); + } + } FMT_CATCH(...) {} + fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32. +} + +#endif // FMT_USE_WINDOWS_H + +FMT_FUNC void fmt::internal::format_system_error( + fmt::Writer &out, int error_code, + fmt::StringRef message) FMT_NOEXCEPT { + FMT_TRY { + MemoryBuffer<char, INLINE_BUFFER_SIZE> buffer; + buffer.resize(INLINE_BUFFER_SIZE); + for (;;) { + char *system_message = &buffer[0]; + int result = safe_strerror(error_code, system_message, buffer.size()); + if (result == 0) { + out << message << ": " << system_message; + return; + } + if (result != ERANGE) + break; // Can't get error message, report error code instead. + buffer.resize(buffer.size() * 2); + } + } FMT_CATCH(...) {} + fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32. +} + +template <typename Char> +void fmt::internal::ArgMap<Char>::init(const ArgList &args) { + if (!map_.empty()) + return; + typedef internal::NamedArg<Char> NamedArg; + const NamedArg *named_arg = 0; + bool use_values = + args.type(ArgList::MAX_PACKED_ARGS - 1) == internal::Arg::NONE; + if (use_values) { + for (unsigned i = 0;/*nothing*/; ++i) { + internal::Arg::Type arg_type = args.type(i); + switch (arg_type) { + case internal::Arg::NONE: + return; + case internal::Arg::NAMED_ARG: + named_arg = static_cast<const NamedArg*>(args.values_[i].pointer); + map_.push_back(Pair(named_arg->name, *named_arg)); + break; + default: + /*nothing*/; + } + } + return; + } + for (unsigned i = 0; i != ArgList::MAX_PACKED_ARGS; ++i) { + internal::Arg::Type arg_type = args.type(i); + if (arg_type == internal::Arg::NAMED_ARG) { + named_arg = static_cast<const NamedArg*>(args.args_[i].pointer); + map_.push_back(Pair(named_arg->name, *named_arg)); + } + } + for (unsigned i = ArgList::MAX_PACKED_ARGS;/*nothing*/; ++i) { + switch (args.args_[i].type) { + case internal::Arg::NONE: + return; + case internal::Arg::NAMED_ARG: + named_arg = static_cast<const NamedArg*>(args.args_[i].pointer); + map_.push_back(Pair(named_arg->name, *named_arg)); + break; + default: + /*nothing*/; + } + } +} + +template <typename Char> +void fmt::internal::FixedBuffer<Char>::grow(std::size_t) { + FMT_THROW(std::runtime_error("buffer overflow")); +} + +FMT_FUNC Arg fmt::internal::FormatterBase::do_get_arg( + unsigned arg_index, const char *&error) { + Arg arg = args_[arg_index]; + switch (arg.type) { + case Arg::NONE: + error = "argument index out of range"; + break; + case Arg::NAMED_ARG: + arg = *static_cast<const internal::Arg*>(arg.pointer); + break; + default: + /*nothing*/; + } + return arg; +} + +template <typename Char> +void fmt::internal::PrintfFormatter<Char>::parse_flags( + FormatSpec &spec, const Char *&s) { + for (;;) { + switch (*s++) { + case '-': + spec.align_ = ALIGN_LEFT; + break; + case '+': + spec.flags_ |= SIGN_FLAG | PLUS_FLAG; + break; + case '0': + spec.fill_ = '0'; + break; + case ' ': + spec.flags_ |= SIGN_FLAG; + break; + case '#': + spec.flags_ |= HASH_FLAG; + break; + default: + --s; + return; + } + } +} + +template <typename Char> +Arg fmt::internal::PrintfFormatter<Char>::get_arg( + const Char *s, unsigned arg_index) { + (void)s; + const char *error = 0; + Arg arg = arg_index == UINT_MAX ? + next_arg(error) : FormatterBase::get_arg(arg_index - 1, error); + if (error) + FMT_THROW(FormatError(!*s ? "invalid format string" : error)); + return arg; +} + +template <typename Char> +unsigned fmt::internal::PrintfFormatter<Char>::parse_header( + const Char *&s, FormatSpec &spec) { + unsigned arg_index = UINT_MAX; + Char c = *s; + if (c >= '0' && c <= '9') { + // Parse an argument index (if followed by '$') or a width possibly + // preceded with '0' flag(s). + unsigned value = parse_nonnegative_int(s); + if (*s == '$') { // value is an argument index + ++s; + arg_index = value; + } else { + if (c == '0') + spec.fill_ = '0'; + if (value != 0) { + // Nonzero value means that we parsed width and don't need to + // parse it or flags again, so return now. + spec.width_ = value; + return arg_index; + } + } + } + parse_flags(spec, s); + // Parse width. + if (*s >= '0' && *s <= '9') { + spec.width_ = parse_nonnegative_int(s); + } else if (*s == '*') { + ++s; + spec.width_ = WidthHandler(spec).visit(get_arg(s)); + } + return arg_index; +} + +template <typename Char> +void fmt::internal::PrintfFormatter<Char>::format( + BasicWriter<Char> &writer, BasicCStringRef<Char> format_str) { + const Char *start = format_str.c_str(); + const Char *s = start; + while (*s) { + Char c = *s++; + if (c != '%') continue; + if (*s == c) { + write(writer, start, s); + start = ++s; + continue; + } + write(writer, start, s - 1); + + FormatSpec spec; + spec.align_ = ALIGN_RIGHT; + + // Parse argument index, flags and width. + unsigned arg_index = parse_header(s, spec); + + // Parse precision. + if (*s == '.') { + ++s; + if ('0' <= *s && *s <= '9') { + spec.precision_ = static_cast<int>(parse_nonnegative_int(s)); + } else if (*s == '*') { + ++s; + spec.precision_ = PrecisionHandler().visit(get_arg(s)); + } + } + + Arg arg = get_arg(s, arg_index); + if (spec.flag(HASH_FLAG) && IsZeroInt().visit(arg)) + spec.flags_ &= ~to_unsigned<int>(HASH_FLAG); + if (spec.fill_ == '0') { + if (arg.type <= Arg::LAST_NUMERIC_TYPE) + spec.align_ = ALIGN_NUMERIC; + else + spec.fill_ = ' '; // Ignore '0' flag for non-numeric types. + } + + // Parse length and convert the argument to the required type. + switch (*s++) { + case 'h': + if (*s == 'h') + ArgConverter<signed char>(arg, *++s).visit(arg); + else + ArgConverter<short>(arg, *s).visit(arg); + break; + case 'l': + if (*s == 'l') + ArgConverter<fmt::LongLong>(arg, *++s).visit(arg); + else + ArgConverter<long>(arg, *s).visit(arg); + break; + case 'j': + ArgConverter<intmax_t>(arg, *s).visit(arg); + break; + case 'z': + ArgConverter<std::size_t>(arg, *s).visit(arg); + break; + case 't': + ArgConverter<std::ptrdiff_t>(arg, *s).visit(arg); + break; + case 'L': + // printf produces garbage when 'L' is omitted for long double, no + // need to do the same. + break; + default: + --s; + ArgConverter<void>(arg, *s).visit(arg); + } + + // Parse type. + if (!*s) + FMT_THROW(FormatError("invalid format string")); + spec.type_ = static_cast<char>(*s++); + if (arg.type <= Arg::LAST_INTEGER_TYPE) { + // Normalize type. + switch (spec.type_) { + case 'i': case 'u': + spec.type_ = 'd'; + break; + case 'c': + // TODO: handle wchar_t + CharConverter(arg).visit(arg); + break; + } + } + + start = s; + + // Format argument. + internal::PrintfArgFormatter<Char>(writer, spec).visit(arg); + } + write(writer, start, s); +} + +FMT_FUNC void fmt::report_system_error( + int error_code, fmt::StringRef message) FMT_NOEXCEPT { + // 'fmt::' is for bcc32. + fmt::report_error(internal::format_system_error, error_code, message); +} + +#if FMT_USE_WINDOWS_H +FMT_FUNC void fmt::report_windows_error( + int error_code, fmt::StringRef message) FMT_NOEXCEPT { + // 'fmt::' is for bcc32. + fmt::report_error(internal::format_windows_error, error_code, message); +} +#endif + +FMT_FUNC void fmt::print(std::FILE *f, CStringRef format_str, ArgList args) { + MemoryWriter w; + w.write(format_str, args); + std::fwrite(w.data(), 1, w.size(), f); +} + +FMT_FUNC void fmt::print(CStringRef format_str, ArgList args) { + print(stdout, format_str, args); +} + +FMT_FUNC void fmt::print_colored(Color c, CStringRef format, ArgList args) { + char escape[] = "\x1b[30m"; + escape[3] = static_cast<char>('0' + c); + std::fputs(escape, stdout); + print(format, args); + std::fputs(RESET_COLOR, stdout); +} + +FMT_FUNC int fmt::fprintf(std::FILE *f, CStringRef format, ArgList args) { + MemoryWriter w; + printf(w, format, args); + std::size_t size = w.size(); + return std::fwrite(w.data(), 1, size, f) < size ? -1 : static_cast<int>(size); +} + +#ifndef FMT_HEADER_ONLY + +template struct fmt::internal::BasicData<void>; + +// Explicit instantiations for char. + +template void fmt::internal::FixedBuffer<char>::grow(std::size_t); + +template void fmt::internal::ArgMap<char>::init(const fmt::ArgList &args); + +template void fmt::internal::PrintfFormatter<char>::format( + BasicWriter<char> &writer, CStringRef format); + +template int fmt::internal::CharTraits<char>::format_float( + char *buffer, std::size_t size, const char *format, + unsigned width, int precision, double value); + +template int fmt::internal::CharTraits<char>::format_float( + char *buffer, std::size_t size, const char *format, + unsigned width, int precision, long double value); + +// Explicit instantiations for wchar_t. + +template void fmt::internal::FixedBuffer<wchar_t>::grow(std::size_t); + +template void fmt::internal::ArgMap<wchar_t>::init(const fmt::ArgList &args); + +template void fmt::internal::PrintfFormatter<wchar_t>::format( + BasicWriter<wchar_t> &writer, WCStringRef format); + +template int fmt::internal::CharTraits<wchar_t>::format_float( + wchar_t *buffer, std::size_t size, const wchar_t *format, + unsigned width, int precision, double value); + +template int fmt::internal::CharTraits<wchar_t>::format_float( + wchar_t *buffer, std::size_t size, const wchar_t *format, + unsigned width, int precision, long double value); + +#endif // FMT_HEADER_ONLY + +#ifdef _MSC_VER +# pragma warning(pop) +#endif
