Git Product home page Git Product logo

fmt's People

Contributors

0x8000-0000 avatar alabuzhev avatar alexezeder avatar brevzin avatar carterli avatar chronoxor avatar danielae avatar dean0x7d avatar denchat avatar dependabot[bot] avatar dimztimz avatar eliaskosunen avatar foonathan avatar gsjaardema avatar hazardyknusperkeks avatar jgopel avatar jk-jeon avatar joycebrum avatar luncliff avatar medithe avatar mwinterb avatar neheb avatar nioshd avatar orivej avatar pauldreik avatar phprus avatar rimathia avatar shawnzhong avatar vertexwahn avatar vitaut avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fmt's Issues

Improve error reporting

Formatters need a more consistent approach to error reporting. Currently there are three ways to report a format error:

  1. Throw FormatError immediately.
  2. Set FormatterBase::error_ which is checked at the end of formatting and FormatError is thrown if it is set.
  3. Use report_error_ (BasicFormatter only).

An important question is whether we want to report errors as soon as they are found or have the ability to override an earlier error with a later, but more important one. The first case is simpler, we just throw FormatError as soon as an error is found. The second case requires keeping track of an error which complicates the logic.

It seems that Python's str.format uses the first approach. The only case I found were a later error seem to override an earlier one is the case of unbalanced braces, for example:

>>> '{-1:'.format(42)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: unmatched '{' in format

However, this is probably because str.format processes nested arguments first, so it's not really an exception from the rule.

The printf function has rudimentary error checking. For example, neither of the following is reported as an error:

  printf("%s")
  printf("%d", "a");

A rare case of an error caught by printf:

 printf("%10000000000d", 0);

This sets errno to EOVERFLOW which gives generic error message "Value too large for defined data type".

Considering that

  • pretty much any error reporting is an improvement on printf's
  • format strings are usually small which makes it easy to locate errors

I think it makes sense to go with option 1 which is the simplest.

32bit performance

64bit build:

1: Converting 14 long long with 10 base-10 digits (no sign) to buffer 300 bytes
1: sizeof(short, int, long, long long): 2 4 8 8
1: Run tests #1 #2 #3 #4 #5 Results: 
1:                       (!) fmt::FormatInt [avg:26419050 var:0.0692767% ms:26 runs:50 conv_ops:49999600]
1:             (+183%) boost::spirit::karma [avg:74907132 var:0.162081% ms:74 runs:50 conv_ops:49999600]

32bit build:

1: Converting 14 long long with 10 base-10 digits (no sign) to buffer 300 bytes
1: sizeof(short, int, long, long long): 2 4 4 8
1: Run tests #1 #2 #3 #4 #5 Results: 
1:                       (!) fmt::FormatInt [avg:115024795 var:0.554144% ms:115 runs:50 conv_ops:49999600]
1:              (+98%) boost::spirit::karma [avg:228828029 var:0.15578% ms:228 runs:50 conv_ops:49999600]

In some cases boost::karma works better:

1: Converting 25 int with 4 base-10 digits to buffer 300 bytes
1: sizeof(short, int, long, long long): 2 4 4 8
1: Run tests #1 #2 #3 #4 #5 Results: 
1:                    (+75%) fmt::FormatInt [avg:45775614 var:0.0263464% ms:45 runs:50 conv_ops:50000000]
1:                 (!) boost::spirit::karma [avg:26063573 var:1.59616% ms:26 runs:50 conv_ops:50000000]

It's probably because every type converting to uint64_t. May be template parameter is more appropriate?

32bit: https://s3.amazonaws.com/archive.travis-ci.org/jobs/19018932/log.txt
64bit: https://s3.amazonaws.com/archive.travis-ci.org/jobs/19018934/log.txt

error C2039: 'Format' : is not a member of 'fmt::BasicWriter<Char>'

I have tried this code from the examples
fmt::Writer out;
out << "The answer is " << 42 << "\n";
out.Format("({:+f}, {:+f})") << -3.14 << 3.14;

it gives the error:

m:\mmgit\mmcyb\src\mm\cmmaxes.cpp(307): error C2039: 'Format' : is not a member of 'fmt::BasicWriter'
3> with
3> [
3> Char=char
3> ]

Xcode 6 beta 6 util-test crash

Here's how to reproduce:

  1. mkdir build && cd build && cmake -G Xcode ..
  2. Open Xcode build project, and run util-test target.

Here's the crash report:

Process:         util-test [99663]
Path:            /Users/USER/Desktop/*/util-test
Identifier:      util-test
Version:         0
Code Type:       X86-64 (Native)
Parent Process:  util-test [99660]
Responsible:     Xcode [99349]
User ID:         501

Date/Time:       2014-08-21 08:49:37.471 -0700
OS Version:      Mac OS X 10.9.4 (13E28)
Report Version:  11
Anonymous UUID:  A313BD1C-E57C-0B66-D31B-15AC4B26A391

Sleep/Wake UUID: 8804A7BB-AD23-4561-B5BC-CE0436895581

Crashed Thread:  0  Dispatch queue: com.apple.main-thread

Exception Type:  EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000

Application Specific Information:
crashed on child side of fork pre-exec

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libsystem_kernel.dylib          0x00007fff8a95d866 __pthread_kill + 10
1   libsystem_pthread.dylib         0x00007fff93e7235c pthread_kill + 92
2   libsystem_c.dylib               0x00007fff8fb48b1a abort + 125
3   libsystem_c.dylib               0x00007fff8fb1298e __assert_rtn + 272
4   util-test                       0x000000010005681f fmt::internal::StrError(int, char*&, unsigned long) + 111 (format.cc:263)
5   util-test                       0x00000001000020a4 UtilTest_StrError_Test::TestBody() + 580 (util-test.cc:141)
6   util-test                       0x000000010004bf13 void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) + 131 (gtest.cc:2090)
7   util-test                       0x0000000100038267 void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) + 119 (gtest.cc:2126)
8   util-test                       0x000000010001e475 testing::Test::Run() + 197 (gtest.cc:2161)
9   util-test                       0x000000010001f5ab testing::TestInfo::Run() + 219 (gtest.cc:2338)
10  util-test                       0x0000000100020387 testing::TestCase::Run() + 231 (gtest.cc:2444)
11  util-test                       0x00000001000276ee testing::internal::UnitTestImpl::RunAllTests() + 926 (gtest.cc:4236)
12  util-test                       0x0000000100048c53 bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) + 131 (gtest.cc:2090)
13  util-test                       0x000000010003a9e7 bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) + 119 (gtest.cc:2126)
14  util-test                       0x0000000100027334 testing::UnitTest::Run() + 100 (gtest.cc:3871)
15  util-test                       0x0000000100013a33 main + 51 (test-main.cc:43)
16  libdyld.dylib                   0x00007fff954985fd start + 1

Compile error when using WStringRef with <<bool

Hi, thanks for your library! I'm just evaluating it for logging purposes and came across one problem. When trying wide char version of the format string:

auto x = fmt::str(fmt::Format(L"{}") << true);
or
std::wstring xx = fmt::str(fmt::Format(L"{}") << std::wstring(L"wstring"));

I got compile time error (VC2010), complaining that:

  void Write(const std::basic_string<char> &s, ...) doesn't accept std::basic_string<wchar_t>

works fine once I changed Write method to this:

  template <typename Char>
  void Write(const std::basic_string<Char> &s, const FormatSpec &spec) {
    FormatString(s.data(), s.size(), spec);
  }

The library looks exactly what I was looking for: replacement-based API (without a need to specify type in format string), type-safe, super fast and small.
For logging purposes, however, it would be nice to be able to turn-off exceptions (replaced by debug assert() + "bad format" result?) instead of try/catch the fmt::Format calls. Have you considered header-only version?
Thanks again
Filip Jerabek

Warnings when compiling in Visual Studio 2012

Hi,

Firstly thanks for the library, it will help me produce better error messages!

I am very new to C++ in general so I may be doing something very wrong but after adding the header and the code file I get 47 warnings all of the types:

Warning 1 warning C4521: 'fmt::BasicFormatter' : multiple copy constructors specified d:\light bot\code\lightbot\lightbot\3rdparty\format\format.h 1015 1 LightBot
Warning 2 warning C4521: 'fmt::Formatter<>' : multiple copy constructors specified d:\light bot\code\lightbot\lightbot\3rdparty\format\format.h 1138 1 LightBot
Warning 3 warning C4521: 'fmt::BasicFormatter' : multiple copy constructors specified d:\light bot\code\lightbot\lightbot\3rdparty\format\format.h 1015 1 LightBot
Warning 4 warning C4521: 'fmt::Formatter<Action,Char>' : multiple copy constructors specified d:\light bot\code\lightbot\lightbot\3rdparty\format\format.h 1138 1 LightBot

I don't believe I am doing something wrong? Additionally is the library cross platform?

Missing initializer_list header in VS2012 (Update 4)

VS 2012 (Update 4) doesn't have the initializer_list header and fails to compile because of the FMT_USE_INITIALIZER_LIST test.

There's a workaround for VS2012, but it's still in some alpha stage. I'd suggest changing the minimum version to 1800 (VS 2013).

Printf like checks

some compilers (gcc,clang) can check printf like functions
in Os X it works like this

int printf(const char * __restrict, ...) __printflike(1, 2);

int sprintf(char * __restrict, const char * __restrict, ...) __printflike(2, 3);
int sscanf(const char * __restrict, const char * __restrict, ...) __scanflike(2, 3);
int vsprintf(char * __restrict, const char * __restrict, va_list) __printflike(2, 0);

int snprintf(char * __restrict, size_t, const char * __restrict, ...) __printflike(3, 4);
int vsnprintf(char * __restrict, size_t, const char * __restrict, va_list) __printflike(3, 0);

define __printflike(fmtarg, firstvararg) \

    __attribute__((__format__ (__printf__, fmtarg, firstvararg)))

i fink it good idea to add something similar to your library

you can take some additional information here https://mail-index.netbsd.org/tech-userlevel/2012/03/04/msg006197.html

Terminate character

Current version of FormatInt class set terminating '\0' character automatically. I think it's better to follow principle don't pay for what you don't use and let user set '\0' when he really wants it.

Latest version of format package does not compile with C++98

/format.h: In function 'fmt::Formatter<fmt::NoAction, char> fmt::Format(fmt::StringRef)':
/format.h:1112: error: 'fmt::Formatter<Action, Char>::Formatter(const fmt::Formatter<Action, Char>&) [with Action = fmt::NoAction, Char = char]' is private
/format.h:1226: error: within this context
/format.h: In function 'fmt::Formatter<fmt::NoAction, wchar_t> fmt::Format(fmt::WStringRef)':
/format.h:1112: error: 'fmt::Formatter<Action, Char>::Formatter(const fmt::Formatter<Action, Char>&) [with Action = fmt::NoAction, Char = wchar_t]' is private
/format.h:1230: error: within this context
/format.h: In function 'fmt::Formatter<fmt::Write, char> fmt::Print(fmt::StringRef)':
/format.h:1112: error: 'fmt::Formatter<Action, Char>::Formatter(const fmt::Formatter<Action, Char>&) [with Action = fmt::Write, Char = char]' is private
/format.h:1246: error: within this context
In file included from /format.cc:34:
/format.h: In function 'fmt::Formatter<fmt::NoAction, char> fmt::Format(fmt::StringRef)':
/format.h:1112: error: 'fmt::Formatter<Action, Char>::Formatter(const fmt::Formatter<Action, Char>&) [with Action = fmt::NoAction, Char = char]' is private
/format.h:1226: error: within this context
/format.h: In function 'fmt::Formatter<fmt::NoAction, wchar_t> fmt::Format(fmt::WStringRef)':
/format.h:1112: error: 'fmt::Formatter<Action, Char>::Formatter(const fmt::Formatter<Action, Char>&) [with Action = fmt::NoAction, Char = wchar_t]' is private
/format.h:1230: error: within this context
/format.h: In function 'fmt::Formatter<fmt::Write, char> fmt::Print(fmt::StringRef)':
/format.h:1112: error: 'fmt::Formatter<Action, Char>::Formatter(const fmt::Formatter<Action, Char>&) [with Action = fmt::Write, Char = char]' is private
/format.h:1246: error: within this context

Exception in FromatDouble if buffer.capacity == offset

// Format using snprintf.
Char fill = static_cast<Char>(spec.fill());
for (;;) {
    std::size_t size = buffer_.capacity() - offset;
    Char *start = &buffer_[offset];
    int n = internal::CharTraits<Char>::FormatFloat(start, size, format, width_for_sprintf, precision, value);

It is possible for size to be equal 0.
As a workaround , I added GrowBuffer(1000) and recalculated size again.

Uppercase versions of base prefixes 0X and 0B

Clarify in the documentation that '#' used together with 'X' adds prefix "0X" (note uppercase 'X') to the output value. Similarly 'B' specifier that adds prefix '0B' should be added. See also #4

Benchmark against Karma needed

Hi,

I've found the speed-test below on another library page where a guy compared "format" (not a unique name btw.) against Boost Karma, among others. And Karma generally was either as fast as format or even faster.

I would love to see how you benchmark this and how you explain this. Thanks in advance.

------------------------------------snip--------------------------------------
Well, README.md of project https://github.com/vitaut/format
reference to spirit.karma, but I don't have any speed test results, so
I've cloned your project and find only one test called int-generator.
I've tested it on Visual Studio 2013 x64 compiler with full optimization (/Ox):

cl /c /W3 /WX- /Ox /Ob2 /D WIN32 /D _WINDOWS /D NDEBUG /D HAVE_BOOST /D "CMAKE_INTDIR="Release"" /D _MBCS /Gm- /EHsc /MD /GS /fp:precise /Zc:wchar_t /Zc:forScope /GR /Fo"format.dir\Release" /Fd"format.dir\Release\vc120.pdb" /Gd /TP /errorReport:prompt ..\format.cc

cl /c /W3 /WX- /Ox /Ob2 /D WIN32 /D _WINDOWS /D NDEBUG /D HAVE_BOOST /D "CMAKE_INTDIR="Release"" /D _MBCS /Gm- /EHsc /MD /GS /fp:precise /Zc:wchar_t /Zc:forScope /GR /Fo"int-generator.dir\Release" /Fd"int-generator.dir\Release\vc120.pdb" /Gd /TP /errorReport:prompt "....\format-benchmark\int_generator.cpp"

Results (MAX_ITERATION = 1e8):

ltoa: 12.3518 [s]
sprintf: 23.7584 [s]
sprintf+std::string: 25.3529 [s]
std::stringstream: 71.6845 [s]
std::to_string: 28.8839 [s]
boost::lexical_cast: 14.7594 [s]
karma::generate: 4.68553 [s]
karma::generate+std::string: 6.09963 [s]
fmt::Writer: 3.75357 [s]
fmt::Writer+std::string: 6.60581 [s]
fmt::Format: 10.4957 [s]
fmt::Format+std::string: 13.3467 [s]
fmt::FormatInt: 3.61697 [s]
cppx::decimal_from: 3.82345 [s]

As you can see boost libraries lexical_cast and karma are "among the slickest and fastest".
lexical_cast is twice faster then c-style sprintf and STL-style stringstream and to_string
and only ~20% slower then c-style ltoa.

Boost.karma already works better then fmt::* with std::string:

karma::generate+std::string: 6.09963 [s]
fmt::Writer+std::string: 6.60581 [s]
fmt::Format+std::string: 13.3467 [s]

Boost.karma works about twice faster than fmt::Format:
karma::generate: 4.68553 [s]
fmt::Format: 10.4957 [s]

FormatInt is not working with int64 type (ostringstream, to_string, boost.karma and boost.lexical_cast works fine).

So only fmt::Writer is rest:
karma::generate: 4.68553 [s]
fmt::Writer: 3.75357 [s]

Let's test it with little numbers. Patched fill function:

struct random_fill {
int operator()() const {
int scale = std::rand() / 100 + 1;

  •  return ((std::rand() \* std::rand()) / scale);
    
  •  return ((std::rand() \* std::rand()) / scale) % 100;
    
    }
    };

Voila!

karma::generate: 1.35417 [s]
fmt::Writer: 1.88881 [s]

And modulus 10:

struct random_fill {
int operator()() const {
int scale = std::rand() / 100 + 1;

  •  return ((std::rand() \* std::rand()) / scale) % 10;
    
  •  return ((std::rand() \* std::rand()) / scale);
    
    }
    };

Result (karma twice faster!):
karma::generate: 0.855458 [s]
fmt::Writer: 1.61517 [s]

Support char as number

This should return 0x61, but instead fails saying it needs a numeric type instead of a character type.

fmt::format("0x{0:02X}", 'a'); // Crashes

This, however, succeeds:

fmt::format("0x{0:02X}\n", (int)'a'); // Returns 0x61

cppformat usage for localization

I'm going to add localization in the project https://github.com/HarpyWar/pvpgn, and I find your library is well suited for this purpose.

Now I use code like this:

fmt::Formatter<> localize(t_connection c, const char *format)
{
    // localization stuff here (t_connection is needed to get user language)
    ...
    fmt::Formatter<> f(format);
    return f;
}

std::string text = str(localize(c, "Account {} has been muted.") << username);

Is there way to avoid additional str wrapper? I'm not a good C++ programmer and I just want to make sure that I do it correctly, and there is no a better/shorter way like this:

std::string text = localize(c, "Account {} has been muted.") << username;
   or
std::string text = localize(c, "Account {} has been muted.", username);

Support for {0:02X}, 'y'

I'm still getting an error here when calling fmt::format("{0:02X}", 'x'); and I think it's because it's not liking the number alignment, but... 'x' is a number in this case.

    // format.cc:444
    if (spec_.align_ == ALIGN_NUMERIC || spec_.flags_ != 0)
      throw FormatError("invalid format specifier for char");

C++11 support

Hello

Is an upgrade using new C++11 features si to be expected ? I believe some parts of the code could be replaced by new standard templates, particularly regarding the traits (IsDouble and things like that).

A compile-time parsing of the format strings using constexpr features could be done, but that is a more tricky part.

Inconsistency in the Writer class?

I tried this with today's master:

fmt::Writer wo;
wo.write ("The answer in hexadecimal is {}", fmt::hex (1337) );
wo << "The answer in hexadecimal is (" << fmt::hex (1337) << ")";

The streaming example with the << operator worked fine, but the wo.write() failed. Shouldn't both be possible? And if not, for what reason?

build error with intel c compiler (c++11)

I've been trying to compile your library with intel c compiler and -std=c++11 flag enabled:

format.cc(55): error: more than one instance of overloaded function "signbit" matches the argument list:
function "signbit(double)"
function "std::signbit(double)"
argument types are: (double)
return signbit(value);
^

compilation aborted for format.cc (code 2)

$ icc -v
$ icc version 14.0.2 (gcc version 4.6.0 compatibility)

with -std=gnu++98 (default) everything is good.

Add support for printf format specification

Currently the C++ Format library uses format string syntax based on Python's str.format. It should be pretty easy to add support for printf's string syntax for legacy code.

Buffer full behaviour under Visual Studio with formatDouble

sprintf_s calls the invalid_parameter_handler function if the buffer size does not fit the input, instead of directly returning the written count.
A fix could be to use instead _vsnprintf_s with _TRUNCATE to get an error return value.

Small test is:

fmt::Writer writer;
int i = 0;
while ( i++ < 130 )
{
  std::cout << i << std::endl;
  writer << 1.01;
}

This fails with Visual Studio.

Are all tests supposed to be "passed"?

I just built everything from the master today on Win8.1-64 with mingw64 GCC4.9 and running the test EXEs produced a number of "failed" tests. Are they supposed to fail or should all be green and "passed"?

Compiling errors VC2010 , QT4.8

Not sure what is causing this error or what compilerbut a similar problem is described here:
http://heifner.blogspot.co.uk/2008/02/stdmin-and-stdmax.html.

I have manage to get it to compile by:
using namespace std;
and changing std::max to max on line 106 and 662 of format.h.

Here's the original compile error. there are also warnings shown with this fix.

M:\mmgit\mmcyb\inc\format.h(106): error C2589: '(' : illegal token on right side of '::'
1> M:\mmgit\mmcyb\inc\format.h(105) : while compiling class template member function 'void fmt::internal::Array<T,SIZE>::Grow(size_t)'
1> with
1> [
1> T=char,
1> SIZE=500
1> ]
1> M:\mmgit\mmcyb\inc\format.h(425) : see reference to class template instantiation 'fmt::internal::Array<T,SIZE>' being compiled
1> with
1> [
1> T=char,
1> SIZE=500
1> ]
1> M:\mmgit\mmcyb\inc\format.h(872) : see reference to class template instantiation 'fmt::BasicWriter' being compiled
1> with
1> [
1> Char=char
1> ]
1> M:\mmgit\mmcyb\inc\format.h(1128) : see reference to class template instantiation 'fmt::BasicFormatter' being compiled
1> with
1> [
1> Char=char
1> ]
1>M:\mmgit\mmcyb\inc\format.h(106): error C2059: syntax error : '::'
1>M:\mmgit\mmcyb\inc\format.h(106): error C2589: '(' : illegal token on right side of '::'
1> M:\mmgit\mmcyb\inc\format.h(105) : while compiling class template member function 'void fmt::internal::Array<T,SIZE>::Grow(size_t)'
1> with
1> [
1> T=const fmt::BasicFormatter::Arg *,
1> SIZE=10
1> ]
1> M:\mmgit\mmcyb\inc\format.h(979) : see reference to class template instantiation 'fmt::internal::Array<T,SIZE>' being compiled
1> with
1> [
1> T=const fmt::BasicFormatter::Arg *,
1> SIZE=10
1> ]
1>M:\mmgit\mmcyb\inc\format.h(106): error C2059: syntax error : '::'
1>
1>Build FAILED.
1>
1>Time Elapsed 00:00:00.98

Missing support for std::wstring in BasicFormatter::Arg

BasicFormatter::Arg has a constructor from a std::string, but not a constructor from a std::wstring; this leads to std::wstring being treated as a custom type.

Arg(const std::string &value) : type(STRING), formatter(0) {
      string.value = value.c_str();
      string.size = value.size();
    }

I'm not sure if the correct solution is to add a second constructor for std::wstring:

Arg(const std::wstring &value) : type(STRING), formatter(0) {
      string.value = value.c_str();
      string.size = value.size();
    }

Or whether to use std::basic_string (which will automatically add the correct type of STL constructor based on the current char type of the formatter):

Arg(const std::basic_string<Char> &value) : type(STRING), formatter(0) {
      string.value = value.c_str();
      string.size = value.size();
    }

However both worked when I tried them.

Small issues in docs

Hi, interesting to set yet another take on this problem :)

I had a look at the docs out of curiosity and have a few comments (maybe I am
just expecting too much, since this library seems to be only a few hours old!)

Support for user-defined types

I wanted to see how you achieved this, but I can't see that it works as
expected. For instance, the following is a compile error:

format::Print("a string: {0}\n") << std::string("asdf");

I thought about implementing positional arguments in tinyformat, and the best
solution I came up with involved a type of variant class as follows:

class Arg
{
    public:
        virtual void print(std::ostream& out) = 0;
};

template<typename T>
class ArgT : public Arg
{
    const T& m_value;
    public:
        virtual void print(std::ostream& out)
        {
            out << m_value;
        }
};

You'd then construct a std::vector<Arg*> as you sweep through the arguments,
creating an ArgT for the Nth argument. (The could be stack-allocated
in the tinyformat case, though unfortunately not with the << based interface.)
Reordering can then be achived simply using indexing.

In the end I didn't do it because I didn't need the functionality and it would
introduce some extra complexity to tinyformat, which is alreay a lot less tiny
than I would like ;-) It also means a virtual function call per argument which
is less than ideal...

i18n in printf
posix printf does have a notation to support positional arguments for i18n,
and this is implemented in glibc even though it's not in C99. For example,
try out:

printf("%2$s  %1$s\n", "first_arg", "second_arg");

Good luck with your implementation!
~Chris

Support for variadic version of the Format function

The stream operator << dosen't work as expected, based on the use being equivalent to std::ostream.

fmt::Formatter<> msg = fmt::Format(format);
msg << arg1;
msg << arg2;
...
msg << argN;
result = fmt::str(msg);

throws exception, to many formatting tokens on the second line, as it immediately attempts to format the string, but not all arguments have been passed.

P.S. I need to use this method as my code is actually

template<typename... Args> inline std::string const & Format(std::string const &format,Args const & ... args) {
        fmt::Formatter<> msg = fmt::Format(format);
        RescursiveFormat(msg,args...);
        return *new std::string(fmt::str(msg)); }

Where RescursiveFormat(msg,args...); reduce to (by template meta programing, and compiler optimization)

msg << arg1;
msg << arg2;
...
msg << argN;

For however may arguments are passed.

This allows formatting to be done by
Format(<format_string>,...) i.e. like sprintf, by type-safe, and using format as the underlining formatting method.

How to use this library?

Is there an example how to use this library? I have downloaded 0.9.0 release, add two files in my vs2013 project solution: format.h and format.cc, then #include format.h in my program.
But I receive a lot of compile errors.
Should I use cmake before or it is not necessary?

Warning 1   warning C4627: '#include "format.h"': skipped when looking for precompiled header use   m:\projects\test\format.cс 34  1   test
Warning 2   warning C4603: '_CRT_SECURE_NO_WARNINGS' : macro is not defined or definition is different after precompiled header use m:\projects\test\format.cс 30  1   test
Warning 3   warning C4603: '_SCL_SECURE_NO_WARNINGS' : macro is not defined or definition is different after precompiled header use m:\projects\test\format.cс 32  1   test
Error   4   error C2653: 'fmt' : is not a class or namespace name   m:\projects\test\format.cс 52  1   test
Error   5   error C2873: 'ULongLong' : symbol cannot be used in a using-declaration m:\projects\test\format.cс 52  1   test
Error   6   error C3861: '_ecvt_s': identifier not found    m:\projects\test\format.cс 90  1   test
Error   7   error C3861: '_finite': identifier not found    m:\projects\test\format.cс 94  1   test
Error   8   error C2653: 'fmt' : is not a class or namespace name   m:\projects\test\format.cс 108 1   test
Error   9   error C2065: 'Writer' : undeclared identifier   m:\projects\test\format.cс 108 1   test
Error   10  error C2059: syntax error : ',' m:\projects\test\format.cс 108 1   test
Error   11  error C2065: 'FormatFunc' : undeclared identifier   m:\projects\test\format.cс 110 1   test
Error   12  error C2146: syntax error : missing ')' before identifier 'func'    m:\projects\test\format.cс 110 1   test
Error   13  error C2182: 'ReportError' : illegal use of type 'void' m:\projects\test\format.cс 110 1   test
Error   14  error C2653: 'fmt' : is not a class or namespace name   m:\projects\test\format.cс 111 1   test
Error   15  error C2059: syntax error : ')' m:\projects\test\format.cс 111 1   test
Error   16  error C2143: syntax error : missing ';' before '{'  m:\projects\test\format.cс 111 1   test
Error   17  error C2447: '{' : missing function header (old-style formal list?) m:\projects\test\format.cс 111 1   test
Error   18  error C2653: 'fmt' : is not a class or namespace name   m:\projects\test\format.cс 122 1   test
Error   19  error C2143: syntax error : missing ';' before '<'  m:\projects\test\format.cс 122 1   test
Error   20  error C2988: unrecognizable template declaration/definition m:\projects\test\format.cс 122 1   test
Error   21  error C2059: syntax error : '<' m:\projects\test\format.cс 122 1   test
Error   22  error C2039: 'FormatFloat' : is not a member of '`global namespace''    m:\projects\test\format.cс 122 1   test
Error   23  error C2039: 'size_t' : is not a member of 'std'    m:\projects\test\format.cс 123 1   test
Error   24  error C2653: 'fmt' : is not a class or namespace name   m:\projects\test\format.cс 136 1   test
Error   25  error C2039: 'FormatFloat' : is not a member of '`global namespace''    m:\projects\test\format.cс 136 1   test
Error   26  error C2039: 'size_t' : is not a member of 'std'    m:\projects\test\format.cс 137 1   test
Error   27  error C2143: syntax error : missing ';' before '{'  m:\projects\test\format.cс 138 1   test
Error   28  error C2447: '{' : missing function header (old-style formal list?) m:\projects\test\format.cс 138 1   test
Error   29  error C2653: 'fmt' : is not a class or namespace name   m:\projects\test\format.cс 149 1   test
Error   30  error C4430: missing type specifier - int assumed. Note: C++ does not support default-int   m:\projects\test\format.cс 167 1   test
Error   31  error C2653: 'fmt' : is not a class or namespace name   m:\projects\test\format.cс 167 1   test
Error   32  error C2146: syntax error : missing ';' before identifier 'POWERS_OF_10_32' m:\projects\test\format.cс 167 1   test
Error   33  error C4430: missing type specifier - int assumed. Note: C++ does not support default-int   m:\projects\test\format.cс 168 1   test
Error   34  error C2653: 'fmt' : is not a class or namespace name   m:\projects\test\format.cс 168 1   test
Error   35  error C2146: syntax error : missing ';' before identifier 'POWERS_OF_10_64' m:\projects\test\format.cс 168 1   test
Error   36  error C3861: 'ULongLong': identifier not found  m:\projects\test\format.cс 171 1   test
Error   37  error C1903: unable to recover from previous error(s); stopping compilation m:\projects\test\format.cс 171 1   test

Add support for formatting via variadic templates where possible

I feel that C++11 variadic templates would provide a nice alternative to the streaming syntax that format uses by default.

I've implemented a version of this for my own project, and have had a go at rolling it back into format itself in a more generic form.

The change can be found here: https://github.com/jdale88/format/commit/5a2eb12a783246f87c1a0d1b5355fe8df22ec6d2

At present, the syntax for using that change is as follows (it will accept any number of parameters after the initial format string):

std::string str = fmt::VariadicFormat<fmt::Formatter<>>("Hello {0}", "World");
std::wstring wstr = fmt::VariadicFormat<fmt::Formatter<fmt::NoAction, wchar_t>>(L"Hello {0}", L"World");

I felt it best to discuss this feature before submitting a pull request, as it might be completely unsuitable, or you might want to approach it differently. This bug is really just to open up a discussion about it.

Thanks.

EDIT:
I improved upon that initial commit a bit.

std::string str = fmt::Format("Hello {0}", "World");
std::wstring wstr = fmt::Format(L"Hello {0}", L"World");

Improve function naming consistency.

Currently there is an inconsistency in function naming. Some functions are named according to Google C++ Style Guide:

  • Format
  • Print
  • Clear
  • ReportSystemError
    ...

Other follow standard library conventions:

  • c_str
  • str
  • clear
  • resize
  • reserve
  • printf
  • sprintf
    ...

The names should be unified before the version 1.0 of the API is released. This is pretty arbitrary, but it's probably better to follow standard library conventions for public API for consistency with printf and because its done already for most functions.

Inconsistent naming of action classes

Action classes are named inconsistently:

  • NoAction
  • Write
  • ColorWriter

Also there should be clear distinction between writer and action classes.

As the action classes are rarely used explicitly, their names can be fairly verbose, e.g. EmptyAction, FileWriteAction, ColoredWriteAction or something like that.

Warnings on older GCC

/home/travis/build/cppformat/format/format.h:91:19: warning: ISO C++ 1998 does not support ‘long long’ [-Wlong-long]
/home/travis/build/cppformat/format/format.h:92:19: warning: ISO C++ 1998 does not support ‘long long’ [-Wlong-long]

https://travis-ci.org/cppformat/format

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.