Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Start transition from tinyformat to fmt/std::format -- multi-stage #2076

Merged
merged 1 commit into from
Nov 27, 2018

Commits on Nov 27, 2018

  1. Start transition from tinyformat to fmt/std::format -- multi-stage

    For many years we have used Chris Foster's magnificent "tinyformat"
    package to do a lot of the heavy lifting for our type-safe string
    formatting with printf-like notation, which we use for Strutil::format,
    nearly every error reporting facility in the major classes, etc. Thanks,
    Chris!
    
    The C++ committee has finally caught up to Chris, advancing drafts of a
    "string formatting" proposal that now seems very likely to be part of
    C++20. The best implementation at this point is the {fmt} package.
    
    Unfortunately, {fmt} and the C++ draft papers differ from tinyformat in
    that rather than traditional C printf notation for formatting, they use
    a notation very similar to Python string formatting, e.g.,
    
        format ("%d %.3f", 1, 23.4)  -->  format ("{} {.3f}", 1, 23.4)
    
    This compatibility break is one reason I've stayed away from {fmt},
    despite that (no slight to Chris) it's at least twice twice the speed of
    tinyformat.
    
    But knowing that this is almost certainly the shape of the future C++
    standard, I am confident that the best long-term path is to migrate to
    its conventions. And it will be nice to reuse the same cognitive
    machinery whether we're programming in C++ or Python, and get the speed
    boost.
    
    But how to do this migration without breaking every string format
    operation in OIIO, and additionally in all the packages that call OIIO
    and use any of its string formatting or error reporting facilities (and
    indeed, we use it extensively in OSL)? This PR is the first step of
    implementing the transition, which will occur over a couple major
    releases. Here we go:
    
    1. Introduce Strutil::sprintf(), ustring::sprintf(), and various
       errorf(), warningf(), etc., functions as needed that now and forever
       will use the printf notation (and for now are still implemented
       primarily with tinyformat, but that's not a detail you need to worry
       about).
    
       Neary all internal uses of the format() commands within OIIO internals
       have switched to sprintf().
    
       Calling apps that make use of OIIO's string formatting can therefore
       also change their calls from format() to sprintf() and everything
       will continue working for the forseeable future.
    
    2. Introduce, in a namespace, Strutil::fmt::format() and certain
       fmterror(), etc., that use the NEW Python-like notation, implemented
       underneath with fmt::format().
    
       Calling apps may start using these now if they prefer the Python
       notation...
    
       But BEWARE! I have discovered that the fmt library does not correctly
       implement the promised locale-inedependent formatting for floating
       point values (it does for integers), and so could cause problems for
       those of you who might have apps running on platforms wth certain
       locales that, for example, use ',' as the decimal (sheesh). This is a
       known problem with fmt, will be fixed soon, and as soon as it does,
       I'll update our embedded copy of fmt and give you the all clear to go
       nuts with the new python style formatting directives.
    
    3. For OIIO 2.0, Strutil::format, ustring::format, and the various error()
       functions will behave identically to sprintf (C printf notation), but
       for OIIO 2.1, I am planning on having them all switch to to the new
       python (a.k.a. C++20-ish std::format()) format designations.
    
    So, the upshot is that NOTHING should break for your existing code's
    format()/error() calls when switching from OIIO 1.x to 2.0.
    (Proof: OSL master compiles against it and passes all tests, without a
    single change.)
    
    But after you upgrade to 2.0 and before 2.1 is released (I'm assuming in
    the latter half of 2019 at the earliest), you'll want to either switch
    all those calls to Strutil::sprintf()/errorf() and stick to the
    printf-style formatting *OR* change them to
    Strutil::fmt::format()/fmterror() using the new formatting specs.
    Pretty much all of the OIIO internals (error calls, etc.) have been
    changed to use the explicit printf-like forms. So they seem safe.
    
    After 2.1, then, the old names format()/error() will be the new behavior
    and you can switch back to those if you want. And by the time C++20
    comes out, we'll all be on the same page, and some day OIIO won't even
    need to use the fmt library because it can rely on std::format.
    
    There you go. Here is the PR that implements the first phase.
    
    We have put the relevant parts of fmt library in
    include/OpenImageIO/fmt.  We are currently using commit 01640f44, with
    one fix by me on top of it that fixes a Windows compile issue. We will
    update the version of fmt as fixes and improvements come.
    
    Sorry for such a weird change in the middle of the beta period. But
    sometimes a looming deadline of a code freeze and major release (after
    which I wouldn't want to introduce this kind of disrupction) really
    makes one focus about doing it right now instead of having to wait
    potentially an additional year.
    lgritz committed Nov 27, 2018
    Configuration menu
    Copy the full SHA
    39e98c8 View commit details
    Browse the repository at this point in the history