| 
									
										
										
										
											2012-12-07 08:31:09 -08:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2012-12-12 07:44:41 -08:00
										 |  |  |  String formatting library for C++ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  Copyright (c) 2012, 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. | 
					
						
							| 
									
										
										
										
											2012-12-07 08:31:09 -08:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-16 15:06:31 -08:00
										 |  |  | // Disable useless MSVC warnings.
 | 
					
						
							| 
									
										
										
										
											2012-12-17 15:41:00 -08:00
										 |  |  | #undef _CRT_SECURE_NO_WARNINGS
 | 
					
						
							| 
									
										
										
										
											2012-12-16 15:06:31 -08:00
										 |  |  | #define _CRT_SECURE_NO_WARNINGS
 | 
					
						
							| 
									
										
										
										
											2012-12-21 15:02:25 -08:00
										 |  |  | #undef _SCL_SECURE_NO_WARNINGS
 | 
					
						
							|  |  |  | #define _SCL_SECURE_NO_WARNINGS
 | 
					
						
							| 
									
										
										
										
											2012-12-16 15:06:31 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-14 15:16:20 -08:00
										 |  |  | #include "format.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-12 09:17:28 -08:00
										 |  |  | #include <cctype>
 | 
					
						
							| 
									
										
										
										
											2013-09-07 10:15:08 -07:00
										 |  |  | #include <cmath>
 | 
					
						
							| 
									
										
										
										
											2013-12-27 08:00:10 -08:00
										 |  |  | #include <cstdarg>
 | 
					
						
							| 
									
										
										
										
											2013-09-07 10:15:08 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef _MSC_VER
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | inline int SignBit(double value) { | 
					
						
							|  |  |  |   // When compiled in C++11 mode signbit is no longer a macro but a function
 | 
					
						
							|  |  |  |   // defined in namespace std and the macro is undefined.
 | 
					
						
							|  |  |  |   using namespace std; | 
					
						
							|  |  |  |   return signbit(value); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | inline int IsInf(double x) { | 
					
						
							|  |  |  | #ifdef isinf
 | 
					
						
							|  |  |  |   return isinf(x); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |   return std::isinf(x); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define FMT_SNPRINTF snprintf
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-27 08:00:10 -08:00
										 |  |  | #else  // _MSC_VER
 | 
					
						
							| 
									
										
										
										
											2013-09-07 10:15:08 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | inline int SignBit(double value) { | 
					
						
							|  |  |  |   if (value < 0) return 1; | 
					
						
							|  |  |  |   if (value == value) return 0; | 
					
						
							|  |  |  |   int dec = 0, sign = 0; | 
					
						
							|  |  |  |   char buffer[2];  // The buffer size must be >= 2 or _ecvt_s will fail.
 | 
					
						
							|  |  |  |   _ecvt_s(buffer, sizeof(buffer), value, 0, &dec, &sign); | 
					
						
							|  |  |  |   return sign; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | inline int IsInf(double x) { return !_finite(x); } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-27 08:00:10 -08:00
										 |  |  | 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; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2013-09-07 10:15:08 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | #endif  // _MSC_VER
 | 
					
						
							| 
									
										
										
										
											2013-09-09 22:21:40 -07:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2013-09-07 10:15:08 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-09 22:21:40 -07:00
										 |  |  | template <typename T> | 
					
						
							|  |  |  | int fmt::internal::CharTraits<char>::FormatFloat( | 
					
						
							|  |  |  |     char *buffer, std::size_t size, const char *format, | 
					
						
							|  |  |  |     unsigned width, int precision, T value) { | 
					
						
							|  |  |  |   if (width == 0) { | 
					
						
							| 
									
										
										
										
											2013-09-07 10:15:08 -07:00
										 |  |  |     return precision < 0 ? | 
					
						
							| 
									
										
										
										
											2013-09-09 22:21:40 -07:00
										 |  |  |         FMT_SNPRINTF(buffer, size, format, value) : | 
					
						
							|  |  |  |         FMT_SNPRINTF(buffer, size, format, precision, value); | 
					
						
							| 
									
										
										
										
											2013-09-07 10:15:08 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2013-09-09 22:21:40 -07:00
										 |  |  |   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>::FormatFloat( | 
					
						
							|  |  |  |     wchar_t *buffer, std::size_t size, const wchar_t *format, | 
					
						
							|  |  |  |     unsigned width, int precision, T value) { | 
					
						
							|  |  |  |   if (width == 0) { | 
					
						
							| 
									
										
										
										
											2013-09-07 10:15:08 -07:00
										 |  |  |     return precision < 0 ? | 
					
						
							| 
									
										
										
										
											2013-09-09 22:21:40 -07:00
										 |  |  |         swprintf(buffer, size, format, value) : | 
					
						
							|  |  |  |         swprintf(buffer, size, format, precision, value); | 
					
						
							| 
									
										
										
										
											2013-09-07 10:15:08 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2013-09-09 22:21:40 -07:00
										 |  |  |   return precision < 0 ? | 
					
						
							|  |  |  |       swprintf(buffer, size, format, width, value) : | 
					
						
							|  |  |  |       swprintf(buffer, size, format, width, precision, value); | 
					
						
							| 
									
										
										
										
											2013-09-09 06:51:03 -07:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2012-12-12 09:29:50 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-09 06:51:03 -07:00
										 |  |  | const char fmt::internal::DIGITS[] = | 
					
						
							| 
									
										
										
										
											2013-01-26 16:07:28 -08:00
										 |  |  |     "0001020304050607080910111213141516171819" | 
					
						
							|  |  |  |     "2021222324252627282930313233343536373839" | 
					
						
							|  |  |  |     "4041424344454647484950515253545556575859" | 
					
						
							|  |  |  |     "6061626364656667686970717273747576777879" | 
					
						
							|  |  |  |     "8081828384858687888990919293949596979899"; | 
					
						
							| 
									
										
										
										
											2013-01-08 09:56:05 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-26 16:07:28 -08:00
										 |  |  | void fmt::internal::ReportUnknownType(char code, const char *type) { | 
					
						
							| 
									
										
										
										
											2013-01-08 09:56:05 -08:00
										 |  |  |   if (std::isprint(static_cast<unsigned char>(code))) { | 
					
						
							|  |  |  |     throw fmt::FormatError(fmt::str( | 
					
						
							| 
									
										
										
										
											2013-01-26 16:07:28 -08:00
										 |  |  |         fmt::Format("unknown format code '{}' for {}") << code << type)); | 
					
						
							| 
									
										
										
										
											2013-01-08 09:56:05 -08:00
										 |  |  |   } | 
					
						
							|  |  |  |   throw fmt::FormatError( | 
					
						
							| 
									
										
										
										
											2013-01-26 16:07:28 -08:00
										 |  |  |       fmt::str(fmt::Format("unknown format code '\\x{:02x}' for {}") | 
					
						
							| 
									
										
										
										
											2013-01-08 09:56:05 -08:00
										 |  |  |         << static_cast<unsigned>(code) << type)); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Fills the padding around the content and returns the pointer to the
 | 
					
						
							|  |  |  | // content area.
 | 
					
						
							|  |  |  | template <typename Char> | 
					
						
							| 
									
										
										
										
											2013-09-08 13:07:04 -07:00
										 |  |  | typename fmt::BasicWriter<Char>::CharPtr | 
					
						
							|  |  |  |   fmt::BasicWriter<Char>::FillPadding(CharPtr buffer, | 
					
						
							|  |  |  |     unsigned total_size, std::size_t content_size, wchar_t fill) { | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |   std::size_t padding = total_size - content_size; | 
					
						
							|  |  |  |   std::size_t left_padding = padding / 2; | 
					
						
							| 
									
										
										
										
											2013-09-08 13:47:06 -07:00
										 |  |  |   Char fill_char = static_cast<Char>(fill); | 
					
						
							|  |  |  |   std::fill_n(buffer, left_padding, fill_char); | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |   buffer += left_padding; | 
					
						
							|  |  |  |   CharPtr content = buffer; | 
					
						
							| 
									
										
										
										
											2013-09-08 13:47:06 -07:00
										 |  |  |   std::fill_n(buffer + content_size, padding - left_padding, fill_char); | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |   return content; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <typename Char> | 
					
						
							|  |  |  | void fmt::BasicWriter<Char>::FormatDecimal( | 
					
						
							|  |  |  |     CharPtr buffer, uint64_t value, unsigned num_digits) { | 
					
						
							|  |  |  |   --num_digits; | 
					
						
							|  |  |  |   while (value >= 100) { | 
					
						
							|  |  |  |     // Integer division is slow so do it for a group of two digits instead
 | 
					
						
							|  |  |  |     // of for every digit. The idea comes from the talk by Alexandrescu
 | 
					
						
							|  |  |  |     // "Three Optimization Tips for C++". See speed-test for a comparison.
 | 
					
						
							|  |  |  |     unsigned index = (value % 100) * 2; | 
					
						
							|  |  |  |     value /= 100; | 
					
						
							| 
									
										
										
										
											2013-09-09 06:51:03 -07:00
										 |  |  |     buffer[num_digits] = internal::DIGITS[index + 1]; | 
					
						
							|  |  |  |     buffer[num_digits - 1] = internal::DIGITS[index]; | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |     num_digits -= 2; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (value < 10) { | 
					
						
							|  |  |  |     *buffer = static_cast<char>('0' + value); | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   unsigned index = static_cast<unsigned>(value * 2); | 
					
						
							| 
									
										
										
										
											2013-09-09 06:51:03 -07:00
										 |  |  |   buffer[1] = internal::DIGITS[index + 1]; | 
					
						
							|  |  |  |   buffer[0] = internal::DIGITS[index]; | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <typename Char> | 
					
						
							|  |  |  | typename fmt::BasicWriter<Char>::CharPtr | 
					
						
							|  |  |  |   fmt::BasicWriter<Char>::PrepareFilledBuffer( | 
					
						
							| 
									
										
										
										
											2014-01-28 12:47:37 -08:00
										 |  |  |     unsigned size, const AlignSpec &spec, char sign) { | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |   unsigned width = spec.width(); | 
					
						
							|  |  |  |   if (width <= size) { | 
					
						
							|  |  |  |     CharPtr p = GrowBuffer(size); | 
					
						
							|  |  |  |     *p = sign; | 
					
						
							|  |  |  |     return p + size - 1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   CharPtr p = GrowBuffer(width); | 
					
						
							|  |  |  |   CharPtr end = p + width; | 
					
						
							|  |  |  |   Alignment align = spec.align(); | 
					
						
							| 
									
										
										
										
											2014-01-08 08:17:38 -08:00
										 |  |  |   // TODO: error if fill is not convertible to Char
 | 
					
						
							| 
									
										
										
										
											2013-09-08 13:47:06 -07:00
										 |  |  |   Char fill = static_cast<Char>(spec.fill()); | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |   if (align == ALIGN_LEFT) { | 
					
						
							|  |  |  |     *p = sign; | 
					
						
							|  |  |  |     p += size; | 
					
						
							| 
									
										
										
										
											2013-09-08 13:47:06 -07:00
										 |  |  |     std::fill(p, end, fill); | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |   } else if (align == ALIGN_CENTER) { | 
					
						
							| 
									
										
										
										
											2013-09-08 13:47:06 -07:00
										 |  |  |     p = FillPadding(p, width, size, fill); | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |     *p = sign; | 
					
						
							|  |  |  |     p += size; | 
					
						
							|  |  |  |   } else { | 
					
						
							|  |  |  |     if (align == ALIGN_NUMERIC) { | 
					
						
							|  |  |  |       if (sign) { | 
					
						
							|  |  |  |         *p++ = sign; | 
					
						
							|  |  |  |         --size; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       *(end - size) = sign; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2013-09-08 13:47:06 -07:00
										 |  |  |     std::fill(p, end - size, fill); | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |     p = end; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return p - 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <typename Char> | 
					
						
							|  |  |  | template <typename T> | 
					
						
							|  |  |  | void fmt::BasicWriter<Char>::FormatDouble( | 
					
						
							| 
									
										
										
										
											2014-01-28 12:47:37 -08:00
										 |  |  |     T value, const FormatSpec &spec, int precision) { | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |   // Check type.
 | 
					
						
							|  |  |  |   char type = spec.type(); | 
					
						
							|  |  |  |   bool upper = false; | 
					
						
							|  |  |  |   switch (type) { | 
					
						
							|  |  |  |   case 0: | 
					
						
							|  |  |  |     type = 'g'; | 
					
						
							|  |  |  |     break; | 
					
						
							|  |  |  |   case 'e': case 'f': case 'g': | 
					
						
							|  |  |  |     break; | 
					
						
							|  |  |  |   case 'F': | 
					
						
							|  |  |  | #ifdef _MSC_VER
 | 
					
						
							|  |  |  |     // MSVC's printf doesn't support 'F'.
 | 
					
						
							|  |  |  |     type = 'f'; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     // Fall through.
 | 
					
						
							|  |  |  |   case 'E': case 'G': | 
					
						
							|  |  |  |     upper = true; | 
					
						
							|  |  |  |     break; | 
					
						
							|  |  |  |   default: | 
					
						
							|  |  |  |     internal::ReportUnknownType(type, "double"); | 
					
						
							|  |  |  |     break; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   char sign = 0; | 
					
						
							|  |  |  |   // Use SignBit instead of value < 0 because the latter is always
 | 
					
						
							|  |  |  |   // false for NaN.
 | 
					
						
							| 
									
										
										
										
											2013-09-07 10:15:08 -07:00
										 |  |  |   if (SignBit(value)) { | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |     sign = '-'; | 
					
						
							|  |  |  |     value = -value; | 
					
						
							|  |  |  |   } else if (spec.sign_flag()) { | 
					
						
							|  |  |  |     sign = spec.plus_flag() ? '+' : ' '; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (value != value) { | 
					
						
							|  |  |  |     // Format NaN ourselves because sprintf's output is not consistent
 | 
					
						
							|  |  |  |     // across platforms.
 | 
					
						
							|  |  |  |     std::size_t size = 4; | 
					
						
							|  |  |  |     const char *nan = upper ? " NAN" : " nan"; | 
					
						
							|  |  |  |     if (!sign) { | 
					
						
							|  |  |  |       --size; | 
					
						
							|  |  |  |       ++nan; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     CharPtr out = FormatString(nan, size, spec); | 
					
						
							|  |  |  |     if (sign) | 
					
						
							|  |  |  |       *out = sign; | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-07 10:15:08 -07:00
										 |  |  |   if (IsInf(value)) { | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |     // Format infinity ourselves because sprintf's output is not consistent
 | 
					
						
							|  |  |  |     // across platforms.
 | 
					
						
							|  |  |  |     std::size_t size = 4; | 
					
						
							|  |  |  |     const char *inf = upper ? " INF" : " inf"; | 
					
						
							|  |  |  |     if (!sign) { | 
					
						
							|  |  |  |       --size; | 
					
						
							|  |  |  |       ++inf; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     CharPtr out = FormatString(inf, size, spec); | 
					
						
							|  |  |  |     if (sign) | 
					
						
							|  |  |  |       *out = sign; | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   std::size_t offset = buffer_.size(); | 
					
						
							|  |  |  |   unsigned width = spec.width(); | 
					
						
							|  |  |  |   if (sign) { | 
					
						
							|  |  |  |     buffer_.reserve(buffer_.size() + (std::max)(width, 1u)); | 
					
						
							|  |  |  |     if (width > 0) | 
					
						
							|  |  |  |       --width; | 
					
						
							|  |  |  |     ++offset; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Build format string.
 | 
					
						
							|  |  |  |   enum { MAX_FORMAT_SIZE = 10}; // longest format: %#-*.*Lg
 | 
					
						
							|  |  |  |   Char format[MAX_FORMAT_SIZE]; | 
					
						
							|  |  |  |   Char *format_ptr = format; | 
					
						
							|  |  |  |   *format_ptr++ = '%'; | 
					
						
							|  |  |  |   unsigned width_for_sprintf = width; | 
					
						
							|  |  |  |   if (spec.hash_flag()) | 
					
						
							|  |  |  |     *format_ptr++ = '#'; | 
					
						
							|  |  |  |   if (spec.align() == ALIGN_CENTER) { | 
					
						
							|  |  |  |     width_for_sprintf = 0; | 
					
						
							|  |  |  |   } else { | 
					
						
							|  |  |  |     if (spec.align() == ALIGN_LEFT) | 
					
						
							|  |  |  |       *format_ptr++ = '-'; | 
					
						
							|  |  |  |     if (width != 0) | 
					
						
							|  |  |  |       *format_ptr++ = '*'; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (precision >= 0) { | 
					
						
							|  |  |  |     *format_ptr++ = '.'; | 
					
						
							|  |  |  |     *format_ptr++ = '*'; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (internal::IsLongDouble<T>::VALUE) | 
					
						
							|  |  |  |     *format_ptr++ = 'L'; | 
					
						
							|  |  |  |   *format_ptr++ = type; | 
					
						
							|  |  |  |   *format_ptr = '\0'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Format using snprintf.
 | 
					
						
							| 
									
										
										
										
											2013-09-08 13:30:14 -07:00
										 |  |  |   Char fill = static_cast<Char>(spec.fill()); | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |   for (;;) { | 
					
						
							|  |  |  |     std::size_t size = buffer_.capacity() - offset; | 
					
						
							|  |  |  |     Char *start = &buffer_[offset]; | 
					
						
							| 
									
										
										
										
											2013-09-09 22:21:40 -07:00
										 |  |  |     int n = internal::CharTraits<Char>::FormatFloat( | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |         start, size, format, width_for_sprintf, precision, value); | 
					
						
							|  |  |  |     if (n >= 0 && offset + n < buffer_.capacity()) { | 
					
						
							|  |  |  |       if (sign) { | 
					
						
							|  |  |  |         if ((spec.align() != ALIGN_RIGHT && spec.align() != ALIGN_DEFAULT) || | 
					
						
							|  |  |  |             *start != ' ') { | 
					
						
							|  |  |  |           *(start - 1) = sign; | 
					
						
							|  |  |  |           sign = 0; | 
					
						
							|  |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2013-09-08 13:30:14 -07:00
										 |  |  |           *(start - 1) = fill; | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |         } | 
					
						
							|  |  |  |         ++n; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (spec.align() == ALIGN_CENTER && | 
					
						
							|  |  |  |           spec.width() > static_cast<unsigned>(n)) { | 
					
						
							|  |  |  |         unsigned width = spec.width(); | 
					
						
							|  |  |  |         CharPtr p = GrowBuffer(width); | 
					
						
							|  |  |  |         std::copy(p, p + n, p + (width - n) / 2); | 
					
						
							| 
									
										
										
										
											2013-09-08 13:30:14 -07:00
										 |  |  |         FillPadding(p, spec.width(), n, fill); | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |         return; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (spec.fill() != ' ' || sign) { | 
					
						
							|  |  |  |         while (*start == ' ') | 
					
						
							| 
									
										
										
										
											2013-09-08 13:30:14 -07:00
										 |  |  |           *start++ = fill; | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |         if (sign) | 
					
						
							|  |  |  |           *(start - 1) = sign; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       GrowBuffer(n); | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     buffer_.reserve(n >= 0 ? offset + n + 1 : 2 * buffer_.capacity()); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Throws Exception(message) if format contains '}', otherwise throws
 | 
					
						
							|  |  |  | // FormatError reporting unmatched '{'. The idea is that unmatched '{'
 | 
					
						
							|  |  |  | // should override other errors.
 | 
					
						
							|  |  |  | template <typename Char> | 
					
						
							|  |  |  | void fmt::BasicFormatter<Char>::ReportError( | 
					
						
							|  |  |  |     const Char *s, StringRef message) const { | 
					
						
							|  |  |  |   for (int num_open_braces = num_open_braces_; *s; ++s) { | 
					
						
							|  |  |  |     if (*s == '{') { | 
					
						
							|  |  |  |       ++num_open_braces; | 
					
						
							|  |  |  |     } else if (*s == '}') { | 
					
						
							|  |  |  |       if (--num_open_braces == 0) | 
					
						
							|  |  |  |         throw fmt::FormatError(message); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   throw fmt::FormatError("unmatched '{' in format"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Parses an unsigned integer advancing s to the end of the parsed input.
 | 
					
						
							|  |  |  | // This function assumes that the first character of s is a digit.
 | 
					
						
							|  |  |  | template <typename Char> | 
					
						
							|  |  |  | unsigned fmt::BasicFormatter<Char>::ParseUInt(const Char *&s) const { | 
					
						
							|  |  |  |   assert('0' <= *s && *s <= '9'); | 
					
						
							|  |  |  |   unsigned value = 0; | 
					
						
							|  |  |  |   do { | 
					
						
							|  |  |  |     unsigned new_value = value * 10 + (*s++ - '0'); | 
					
						
							|  |  |  |     if (new_value < value)  // Check if value wrapped around.
 | 
					
						
							|  |  |  |       ReportError(s, "number is too big in format"); | 
					
						
							|  |  |  |     value = new_value; | 
					
						
							|  |  |  |   } while ('0' <= *s && *s <= '9'); | 
					
						
							|  |  |  |   return value; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <typename Char> | 
					
						
							|  |  |  | inline const typename fmt::BasicFormatter<Char>::Arg | 
					
						
							|  |  |  |     &fmt::BasicFormatter<Char>::ParseArgIndex(const Char *&s) { | 
					
						
							|  |  |  |   unsigned arg_index = 0; | 
					
						
							|  |  |  |   if (*s < '0' || *s > '9') { | 
					
						
							|  |  |  |     if (*s != '}' && *s != ':') | 
					
						
							|  |  |  |       ReportError(s, "invalid argument index in format string"); | 
					
						
							|  |  |  |     if (next_arg_index_ < 0) { | 
					
						
							|  |  |  |       ReportError(s, | 
					
						
							|  |  |  |           "cannot switch from manual to automatic argument indexing"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     arg_index = next_arg_index_++; | 
					
						
							|  |  |  |   } else { | 
					
						
							|  |  |  |     if (next_arg_index_ > 0) { | 
					
						
							|  |  |  |       ReportError(s, | 
					
						
							|  |  |  |           "cannot switch from automatic to manual argument indexing"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     next_arg_index_ = -1; | 
					
						
							|  |  |  |     arg_index = ParseUInt(s); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (arg_index >= args_.size()) | 
					
						
							|  |  |  |     ReportError(s, "argument index is out of range in format"); | 
					
						
							|  |  |  |   return *args_[arg_index]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <typename Char> | 
					
						
							|  |  |  | void fmt::BasicFormatter<Char>::CheckSign(const Char *&s, const Arg &arg) { | 
					
						
							| 
									
										
										
										
											2013-12-10 08:01:08 -08:00
										 |  |  |   char sign = static_cast<char>(*s); | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |   if (arg.type > LAST_NUMERIC_TYPE) { | 
					
						
							|  |  |  |     ReportError(s, | 
					
						
							| 
									
										
										
										
											2013-12-07 08:12:03 -08:00
										 |  |  |         Format("format specifier '{}' requires numeric argument") << sign); | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2013-11-21 09:11:58 -08:00
										 |  |  |   if (arg.type == UINT || arg.type == ULONG || arg.type == ULONG_LONG) { | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |     ReportError(s, | 
					
						
							| 
									
										
										
										
											2013-12-07 08:12:03 -08:00
										 |  |  |         Format("format specifier '{}' requires signed argument") << sign); | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |   } | 
					
						
							|  |  |  |   ++s; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template <typename Char> | 
					
						
							|  |  |  | void fmt::BasicFormatter<Char>::DoFormat() { | 
					
						
							|  |  |  |   const Char *start = format_; | 
					
						
							|  |  |  |   format_ = 0; | 
					
						
							|  |  |  |   next_arg_index_ = 0; | 
					
						
							|  |  |  |   const Char *s = start; | 
					
						
							|  |  |  |   BasicWriter<Char> &writer = *writer_; | 
					
						
							|  |  |  |   while (*s) { | 
					
						
							| 
									
										
										
										
											2013-09-07 12:52:52 -07:00
										 |  |  |     Char c = *s++; | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |     if (c != '{' && c != '}') continue; | 
					
						
							|  |  |  |     if (*s == c) { | 
					
						
							|  |  |  |       writer.buffer_.append(start, s); | 
					
						
							|  |  |  |       start = ++s; | 
					
						
							|  |  |  |       continue; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (c == '}') | 
					
						
							|  |  |  |       throw FormatError("unmatched '}' in format"); | 
					
						
							|  |  |  |     num_open_braces_= 1; | 
					
						
							|  |  |  |     writer.buffer_.append(start, s - 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const Arg &arg = ParseArgIndex(s); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-28 12:47:37 -08:00
										 |  |  |     FormatSpec spec; | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |     int precision = -1; | 
					
						
							|  |  |  |     if (*s == ':') { | 
					
						
							|  |  |  |       ++s; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Parse fill and alignment.
 | 
					
						
							| 
									
										
										
										
											2013-09-07 12:52:52 -07:00
										 |  |  |       if (Char c = *s) { | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |         const Char *p = s + 1; | 
					
						
							|  |  |  |         spec.align_ = ALIGN_DEFAULT; | 
					
						
							|  |  |  |         do { | 
					
						
							|  |  |  |           switch (*p) { | 
					
						
							|  |  |  |           case '<': | 
					
						
							|  |  |  |             spec.align_ = ALIGN_LEFT; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           case '>': | 
					
						
							|  |  |  |             spec.align_ = ALIGN_RIGHT; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           case '=': | 
					
						
							|  |  |  |             spec.align_ = ALIGN_NUMERIC; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           case '^': | 
					
						
							|  |  |  |             spec.align_ = ALIGN_CENTER; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           if (spec.align_ != ALIGN_DEFAULT) { | 
					
						
							|  |  |  |             if (p != s) { | 
					
						
							|  |  |  |               if (c == '}') break; | 
					
						
							|  |  |  |               if (c == '{') | 
					
						
							|  |  |  |                 ReportError(s, "invalid fill character '{'"); | 
					
						
							|  |  |  |               s += 2; | 
					
						
							|  |  |  |               spec.fill_ = c; | 
					
						
							|  |  |  |             } else ++s; | 
					
						
							|  |  |  |             if (spec.align_ == ALIGN_NUMERIC && arg.type > LAST_NUMERIC_TYPE) | 
					
						
							|  |  |  |               ReportError(s, "format specifier '=' requires numeric argument"); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } while (--p >= s); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Parse sign.
 | 
					
						
							|  |  |  |       switch (*s) { | 
					
						
							|  |  |  |       case '+': | 
					
						
							|  |  |  |         CheckSign(s, arg); | 
					
						
							|  |  |  |         spec.flags_ |= SIGN_FLAG | PLUS_FLAG; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       case '-': | 
					
						
							|  |  |  |         CheckSign(s, arg); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       case ' ': | 
					
						
							|  |  |  |         CheckSign(s, arg); | 
					
						
							|  |  |  |         spec.flags_ |= SIGN_FLAG; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (*s == '#') { | 
					
						
							|  |  |  |         if (arg.type > LAST_NUMERIC_TYPE) | 
					
						
							|  |  |  |           ReportError(s, "format specifier '#' requires numeric argument"); | 
					
						
							|  |  |  |         spec.flags_ |= HASH_FLAG; | 
					
						
							|  |  |  |         ++s; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Parse width and zero flag.
 | 
					
						
							|  |  |  |       if ('0' <= *s && *s <= '9') { | 
					
						
							|  |  |  |         if (*s == '0') { | 
					
						
							|  |  |  |           if (arg.type > LAST_NUMERIC_TYPE) | 
					
						
							|  |  |  |             ReportError(s, "format specifier '0' requires numeric argument"); | 
					
						
							|  |  |  |           spec.align_ = ALIGN_NUMERIC; | 
					
						
							|  |  |  |           spec.fill_ = '0'; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         // Zero may be parsed again as a part of the width, but it is simpler
 | 
					
						
							|  |  |  |         // and more efficient than checking if the next char is a digit.
 | 
					
						
							|  |  |  |         unsigned value = ParseUInt(s); | 
					
						
							|  |  |  |         if (value > INT_MAX) | 
					
						
							|  |  |  |           ReportError(s, "number is too big in format"); | 
					
						
							|  |  |  |         spec.width_ = value; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Parse precision.
 | 
					
						
							|  |  |  |       if (*s == '.') { | 
					
						
							|  |  |  |         ++s; | 
					
						
							|  |  |  |         precision = 0; | 
					
						
							|  |  |  |         if ('0' <= *s && *s <= '9') { | 
					
						
							|  |  |  |           unsigned value = ParseUInt(s); | 
					
						
							|  |  |  |           if (value > INT_MAX) | 
					
						
							|  |  |  |             ReportError(s, "number is too big in format"); | 
					
						
							|  |  |  |           precision = value; | 
					
						
							|  |  |  |         } else if (*s == '{') { | 
					
						
							|  |  |  |           ++s; | 
					
						
							|  |  |  |           ++num_open_braces_; | 
					
						
							|  |  |  |           const Arg &precision_arg = ParseArgIndex(s); | 
					
						
							| 
									
										
										
										
											2013-12-06 07:12:38 -08:00
										 |  |  |           ULongLong value = 0; | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |           switch (precision_arg.type) { | 
					
						
							|  |  |  |           case INT: | 
					
						
							|  |  |  |             if (precision_arg.int_value < 0) | 
					
						
							|  |  |  |               ReportError(s, "negative precision in format"); | 
					
						
							|  |  |  |             value = precision_arg.int_value; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           case UINT: | 
					
						
							|  |  |  |             value = precision_arg.uint_value; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           case LONG: | 
					
						
							|  |  |  |             if (precision_arg.long_value < 0) | 
					
						
							|  |  |  |               ReportError(s, "negative precision in format"); | 
					
						
							|  |  |  |             value = precision_arg.long_value; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           case ULONG: | 
					
						
							|  |  |  |             value = precision_arg.ulong_value; | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2013-11-22 07:45:43 -08:00
										 |  |  |           case LONG_LONG: | 
					
						
							|  |  |  |             if (precision_arg.long_long_value < 0) | 
					
						
							|  |  |  |               ReportError(s, "negative precision in format"); | 
					
						
							|  |  |  |             value = precision_arg.long_long_value; | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2013-11-21 09:11:58 -08:00
										 |  |  |           case ULONG_LONG: | 
					
						
							| 
									
										
										
										
											2013-11-18 22:58:39 -08:00
										 |  |  |             value = precision_arg.ulong_long_value; | 
					
						
							| 
									
										
										
										
											2013-11-21 09:11:58 -08:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |           default: | 
					
						
							|  |  |  |             ReportError(s, "precision is not integer"); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           if (value > INT_MAX) | 
					
						
							|  |  |  |             ReportError(s, "number is too big in format"); | 
					
						
							| 
									
										
										
										
											2013-11-18 22:58:39 -08:00
										 |  |  |           precision = static_cast<int>(value); | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |           if (*s++ != '}') | 
					
						
							|  |  |  |             throw FormatError("unmatched '{' in format"); | 
					
						
							|  |  |  |           --num_open_braces_; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |           ReportError(s, "missing precision in format"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (arg.type != DOUBLE && arg.type != LONG_DOUBLE) { | 
					
						
							|  |  |  |           ReportError(s, | 
					
						
							|  |  |  |               "precision specifier requires floating-point argument"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Parse type.
 | 
					
						
							|  |  |  |       if (*s != '}' && *s) | 
					
						
							| 
									
										
										
										
											2013-09-07 12:52:52 -07:00
										 |  |  |         spec.type_ = static_cast<char>(*s++); | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (*s++ != '}') | 
					
						
							|  |  |  |       throw FormatError("unmatched '{' in format"); | 
					
						
							|  |  |  |     start = s; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Format argument.
 | 
					
						
							|  |  |  |     switch (arg.type) { | 
					
						
							|  |  |  |     case INT: | 
					
						
							| 
									
										
										
										
											2013-12-31 09:43:32 -08:00
										 |  |  |       FormatInt(arg.int_value, spec); | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |       break; | 
					
						
							|  |  |  |     case UINT: | 
					
						
							| 
									
										
										
										
											2013-12-31 09:43:32 -08:00
										 |  |  |       FormatInt(arg.uint_value, spec); | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |       break; | 
					
						
							|  |  |  |     case LONG: | 
					
						
							| 
									
										
										
										
											2013-12-31 09:43:32 -08:00
										 |  |  |       FormatInt(arg.long_value, spec); | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |       break; | 
					
						
							|  |  |  |     case ULONG: | 
					
						
							| 
									
										
										
										
											2013-12-31 09:43:32 -08:00
										 |  |  |       FormatInt(arg.ulong_value, spec); | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |       break; | 
					
						
							| 
									
										
										
										
											2013-11-22 07:45:43 -08:00
										 |  |  |     case LONG_LONG: | 
					
						
							| 
									
										
										
										
											2013-12-31 09:43:32 -08:00
										 |  |  |       FormatInt(arg.long_long_value, spec); | 
					
						
							| 
									
										
										
										
											2013-11-22 07:45:43 -08:00
										 |  |  |       break; | 
					
						
							| 
									
										
										
										
											2013-11-21 09:11:58 -08:00
										 |  |  |     case ULONG_LONG: | 
					
						
							| 
									
										
										
										
											2013-12-31 09:43:32 -08:00
										 |  |  |       FormatInt(arg.ulong_long_value, spec); | 
					
						
							| 
									
										
										
										
											2013-11-21 09:11:58 -08:00
										 |  |  |       break; | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |     case DOUBLE: | 
					
						
							|  |  |  |       writer.FormatDouble(arg.double_value, spec, precision); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case LONG_DOUBLE: | 
					
						
							|  |  |  |       writer.FormatDouble(arg.long_double_value, spec, precision); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case CHAR: { | 
					
						
							|  |  |  |       if (spec.type_ && spec.type_ != 'c') | 
					
						
							|  |  |  |         internal::ReportUnknownType(spec.type_, "char"); | 
					
						
							|  |  |  |       typedef typename BasicWriter<Char>::CharPtr CharPtr; | 
					
						
							|  |  |  |       CharPtr out = CharPtr(); | 
					
						
							|  |  |  |       if (spec.width_ > 1) { | 
					
						
							| 
									
										
										
										
											2013-09-08 14:25:22 -07:00
										 |  |  |         Char fill = static_cast<Char>(spec.fill()); | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |         out = writer.GrowBuffer(spec.width_); | 
					
						
							|  |  |  |         if (spec.align_ == ALIGN_RIGHT) { | 
					
						
							| 
									
										
										
										
											2013-09-08 14:25:22 -07:00
										 |  |  |           std::fill_n(out, spec.width_ - 1, fill); | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |           out += spec.width_ - 1; | 
					
						
							|  |  |  |         } else if (spec.align_ == ALIGN_CENTER) { | 
					
						
							| 
									
										
										
										
											2013-09-08 14:25:22 -07:00
										 |  |  |           out = writer.FillPadding(out, spec.width_, 1, fill); | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2013-09-08 14:25:22 -07:00
										 |  |  |           std::fill_n(out + 1, spec.width_ - 1, fill); | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |         } | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         out = writer.GrowBuffer(1); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       *out = arg.int_value; | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case STRING: { | 
					
						
							|  |  |  |       if (spec.type_ && spec.type_ != 's') | 
					
						
							|  |  |  |         internal::ReportUnknownType(spec.type_, "string"); | 
					
						
							|  |  |  |       const Char *str = arg.string.value; | 
					
						
							|  |  |  |       std::size_t size = arg.string.size; | 
					
						
							|  |  |  |       if (size == 0) { | 
					
						
							|  |  |  |         if (!str) | 
					
						
							|  |  |  |           throw FormatError("string pointer is null"); | 
					
						
							|  |  |  |         if (*str) | 
					
						
							|  |  |  |           size = std::char_traits<Char>::length(str); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       writer.FormatString(str, size, spec); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case POINTER: | 
					
						
							|  |  |  |       if (spec.type_ && spec.type_ != 'p') | 
					
						
							|  |  |  |         internal::ReportUnknownType(spec.type_, "pointer"); | 
					
						
							|  |  |  |       spec.flags_= HASH_FLAG; | 
					
						
							|  |  |  |       spec.type_ = 'x'; | 
					
						
							| 
									
										
										
										
											2013-12-31 09:43:32 -08:00
										 |  |  |       FormatInt(reinterpret_cast<uintptr_t>(arg.pointer_value), spec); | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  |       break; | 
					
						
							|  |  |  |     case CUSTOM: | 
					
						
							|  |  |  |       if (spec.type_) | 
					
						
							|  |  |  |         internal::ReportUnknownType(spec.type_, "object"); | 
					
						
							|  |  |  |       arg.custom.format(writer, arg.custom.value, spec); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |       assert(false); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   writer.buffer_.append(start, s); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-07 10:15:08 -07:00
										 |  |  | // Explicit instantiations for char.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  | template void fmt::BasicWriter<char>::FormatDouble<double>( | 
					
						
							| 
									
										
										
										
											2014-01-28 12:47:37 -08:00
										 |  |  |     double value, const FormatSpec &spec, int precision); | 
					
						
							| 
									
										
										
										
											2013-09-07 10:15:08 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  | template void fmt::BasicWriter<char>::FormatDouble<long double>( | 
					
						
							| 
									
										
										
										
											2014-01-28 12:47:37 -08:00
										 |  |  |     long double value, const FormatSpec &spec, int precision); | 
					
						
							| 
									
										
										
										
											2013-09-07 10:15:08 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-08 13:07:04 -07:00
										 |  |  | template fmt::BasicWriter<char>::CharPtr | 
					
						
							|  |  |  |   fmt::BasicWriter<char>::FillPadding(CharPtr buffer, | 
					
						
							|  |  |  |     unsigned total_size, std::size_t content_size, wchar_t fill); | 
					
						
							| 
									
										
										
										
											2013-09-07 10:15:08 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  | template void fmt::BasicWriter<char>::FormatDecimal( | 
					
						
							|  |  |  |     CharPtr buffer, uint64_t value, unsigned num_digits); | 
					
						
							| 
									
										
										
										
											2013-09-07 10:15:08 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  | template fmt::BasicWriter<char>::CharPtr | 
					
						
							|  |  |  |   fmt::BasicWriter<char>::PrepareFilledBuffer( | 
					
						
							| 
									
										
										
										
											2014-01-28 12:47:37 -08:00
										 |  |  |     unsigned size, const AlignSpec &spec, char sign); | 
					
						
							| 
									
										
										
										
											2013-09-07 10:15:08 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  | template void fmt::BasicFormatter<char>::ReportError( | 
					
						
							|  |  |  |     const char *s, StringRef message) const; | 
					
						
							| 
									
										
										
										
											2013-09-07 10:15:08 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  | template unsigned fmt::BasicFormatter<char>::ParseUInt(const char *&s) const; | 
					
						
							| 
									
										
										
										
											2013-09-07 10:15:08 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  | template const fmt::BasicFormatter<char>::Arg | 
					
						
							|  |  |  |     &fmt::BasicFormatter<char>::ParseArgIndex(const char *&s); | 
					
						
							| 
									
										
										
										
											2013-09-07 10:15:08 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  | template void fmt::BasicFormatter<char>::CheckSign( | 
					
						
							|  |  |  |     const char *&s, const Arg &arg); | 
					
						
							| 
									
										
										
										
											2013-09-07 10:15:08 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  | template void fmt::BasicFormatter<char>::DoFormat(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-07 10:15:08 -07:00
										 |  |  | // Explicit instantiations for wchar_t.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  | template void fmt::BasicWriter<wchar_t>::FormatDouble<double>( | 
					
						
							| 
									
										
										
										
											2014-01-28 12:47:37 -08:00
										 |  |  |     double value, const FormatSpec &spec, int precision); | 
					
						
							| 
									
										
										
										
											2013-09-07 10:15:08 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  | template void fmt::BasicWriter<wchar_t>::FormatDouble<long double>( | 
					
						
							| 
									
										
										
										
											2014-01-28 12:47:37 -08:00
										 |  |  |     long double value, const FormatSpec &spec, int precision); | 
					
						
							| 
									
										
										
										
											2013-09-07 10:15:08 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  | template fmt::BasicWriter<wchar_t>::CharPtr | 
					
						
							| 
									
										
										
										
											2013-09-08 13:07:04 -07:00
										 |  |  |   fmt::BasicWriter<wchar_t>::FillPadding(CharPtr buffer, | 
					
						
							|  |  |  |       unsigned total_size, std::size_t content_size, wchar_t fill); | 
					
						
							| 
									
										
										
										
											2013-09-07 10:15:08 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  | template void fmt::BasicWriter<wchar_t>::FormatDecimal( | 
					
						
							|  |  |  |     CharPtr buffer, uint64_t value, unsigned num_digits); | 
					
						
							| 
									
										
										
										
											2013-09-07 10:15:08 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  | template fmt::BasicWriter<wchar_t>::CharPtr | 
					
						
							|  |  |  |   fmt::BasicWriter<wchar_t>::PrepareFilledBuffer( | 
					
						
							| 
									
										
										
										
											2014-01-28 12:47:37 -08:00
										 |  |  |     unsigned size, const AlignSpec &spec, char sign); | 
					
						
							| 
									
										
										
										
											2013-09-07 10:15:08 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  | template void fmt::BasicFormatter<wchar_t>::ReportError( | 
					
						
							|  |  |  |     const wchar_t *s, StringRef message) const; | 
					
						
							| 
									
										
										
										
											2013-09-07 10:15:08 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  | template unsigned fmt::BasicFormatter<wchar_t>::ParseUInt( | 
					
						
							|  |  |  |     const wchar_t *&s) const; | 
					
						
							| 
									
										
										
										
											2013-09-07 10:15:08 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  | template const fmt::BasicFormatter<wchar_t>::Arg | 
					
						
							|  |  |  |     &fmt::BasicFormatter<wchar_t>::ParseArgIndex(const wchar_t *&s); | 
					
						
							| 
									
										
										
										
											2013-09-07 10:15:08 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  | template void fmt::BasicFormatter<wchar_t>::CheckSign( | 
					
						
							|  |  |  |     const wchar_t *&s, const Arg &arg); | 
					
						
							| 
									
										
										
										
											2013-09-07 10:15:08 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-06 20:23:42 -07:00
										 |  |  | template void fmt::BasicFormatter<wchar_t>::DoFormat(); |