├── .appveyor.yml ├── .codecov.yml ├── .gitattributes ├── .github └── workflows │ └── ci.yml ├── CMakeLists.txt ├── LICENSE ├── README.md ├── benchmark ├── Jamfile ├── bench_format.cpp └── results.txt ├── build.jam ├── doc ├── choices.html └── format.html ├── example ├── Jamfile.v2 ├── sample_advanced.cpp ├── sample_formats.cpp ├── sample_new_features.cpp └── sample_userType.cpp ├── include └── boost │ ├── format.hpp │ └── format │ ├── alt_sstream.hpp │ ├── alt_sstream_impl.hpp │ ├── detail │ ├── compat_workarounds.hpp │ ├── config_macros.hpp │ ├── msvc_disambiguater.hpp │ ├── unset_macros.hpp │ ├── workarounds_gcc-2_95.hpp │ └── workarounds_stlport.hpp │ ├── exceptions.hpp │ ├── feed_args.hpp │ ├── format_class.hpp │ ├── format_fwd.hpp │ ├── format_implementation.hpp │ ├── free_funcs.hpp │ ├── group.hpp │ ├── internals.hpp │ ├── internals_fwd.hpp │ └── parsing.hpp ├── index.html ├── meta └── libraries.json ├── test ├── Jamfile.v2 ├── cmake_test │ ├── CMakeLists.txt │ └── main.cpp ├── format_test1.cpp ├── format_test2.cpp ├── format_test3.cpp ├── format_test_enum.cpp ├── format_test_exceptions.cpp └── format_test_wstring.cpp └── tools ├── Jamfile.v2 └── format_matrix.cpp /.appveyor.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2016, 2017 Peter Dimov 2 | # Copyright 2017 - 2019 James E. King III 3 | # Copyright 2019 - 2021 Alexander Grund 4 | # Distributed under the Boost Software License, Version 1.0. 5 | # (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) 6 | 7 | # 8 | # Generic Appveyor build script for boostorg repositories 9 | # See: https://github.com/boostorg/boost-ci/ 10 | # 11 | # Instructions for customizing this script for your library: 12 | # 13 | # 1. Customize the compilers and language levels you want. 14 | # 2. If you have more than include/, src/, test/, example/, examples/, 15 | # benchmark/ or tools/ directories, set the environment variable DEPINST. 16 | # For example if your build uses code in "bench/" and "fog/" directories: 17 | # - DEPINST: --include bench --include fog 18 | # 3. Enable pull request builds in your boostorg/ account. 19 | # 20 | # That's it - the script will do everything else for you. 21 | # 22 | 23 | version: 1.0.{build}-{branch} 24 | 25 | shallow_clone: true 26 | 27 | branches: 28 | only: 29 | - master 30 | - develop 31 | - /bugfix\/.*/ 32 | - /feature\/.*/ 33 | - /fix\/.*/ 34 | - /pr\/.*/ 35 | 36 | skip_commits: 37 | files: 38 | - LICENSE 39 | - meta/* 40 | - README.md 41 | 42 | matrix: 43 | fast_finish: false 44 | # Adding MAYFAIL to any matrix job allows it to fail but the build stays green: 45 | allow_failures: 46 | - MAYFAIL: true 47 | 48 | environment: 49 | global: 50 | B2_CI_VERSION: 1 51 | GIT_FETCH_JOBS: 4 52 | # see: http://www.boost.org/build/doc/html/bbv2/overview/invocation.html#bbv2.overview.invocation.properties 53 | # to use the default for a given environment, comment it out; recommend you build debug and release however: 54 | # on Windows it is important to exercise all the possibilities, especially shared vs static, however most 55 | # libraries that care about this exercise it in their Jamfiles... 56 | B2_ADDRESS_MODEL: 32,64 57 | B2_LINK: shared,static 58 | # B2_THREADING: threading=multi,single 59 | B2_VARIANT: release 60 | 61 | matrix: 62 | - FLAVOR: Visual Studio 2017 C++2a Strict 63 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 64 | B2_CXXFLAGS: -permissive- 65 | B2_CXXSTD: 2a 66 | B2_TOOLSET: msvc-14.1 67 | 68 | - FLAVOR: Visual Studio 2017 C++14/17 69 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 70 | B2_CXXSTD: 14,17 71 | B2_TOOLSET: msvc-14.1 72 | 73 | - FLAVOR: cygwin (32-bit) 74 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 75 | ADDPATH: C:\cygwin\bin; 76 | B2_ADDRESS_MODEL: 32 77 | B2_CXXSTD: 11,14,1z 78 | B2_TOOLSET: gcc 79 | 80 | - FLAVOR: cygwin (64-bit) 81 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 82 | ADDPATH: C:\cygwin64\bin; 83 | B2_ADDRESS_MODEL: 64 84 | B2_CXXSTD: 11,14,1z 85 | B2_TOOLSET: gcc 86 | 87 | install: 88 | - git clone --depth 1 https://github.com/boostorg/boost-ci.git C:\boost-ci-cloned 89 | # Copy ci folder if not testing Boost.CI 90 | - if NOT "%APPVEYOR_PROJECT_NAME%" == "boost-ci" xcopy /s /e /q /i /y C:\boost-ci-cloned\ci .\ci 91 | - rmdir /s /q C:\boost-ci-cloned 92 | - ci\appveyor\install.bat 93 | 94 | build: off 95 | 96 | test_script: ci\build.bat 97 | 98 | -------------------------------------------------------------------------------- /.codecov.yml: -------------------------------------------------------------------------------- 1 | # Copyright 2019 - 2021 Alexander Grund 2 | # Distributed under the Boost Software License, Version 1.0. 3 | # (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) 4 | # 5 | # Sample codecov configuration file. Edit as required 6 | 7 | codecov: 8 | max_report_age: off 9 | require_ci_to_pass: yes 10 | notify: 11 | # Increase this if you have multiple coverage collection jobs 12 | after_n_builds: 2 13 | wait_for_ci: yes 14 | 15 | # Change how pull request comments look 16 | comment: 17 | layout: "reach,diff,flags,files,footer" 18 | 19 | # Ignore specific files or folders. Glob patterns are supported. 20 | # See https://docs.codecov.com/docs/ignoring-paths 21 | ignore: 22 | - libs/format/test/ 23 | - test/ 24 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto !eol svneol=native#text/plain 2 | *.gitattributes text svneol=native#text/plain 3 | 4 | # Scriptish formats 5 | *.bat text svneol=native#text/plain 6 | *.bsh text svneol=native#text/x-beanshell 7 | *.cgi text svneol=native#text/plain 8 | *.cmd text svneol=native#text/plain 9 | *.js text svneol=native#text/javascript 10 | *.php text svneol=native#text/x-php 11 | *.pl text svneol=native#text/x-perl 12 | *.pm text svneol=native#text/x-perl 13 | *.py text svneol=native#text/x-python 14 | *.sh eol=lf svneol=LF#text/x-sh 15 | configure eol=lf svneol=LF#text/x-sh 16 | 17 | # Image formats 18 | *.bmp binary svneol=unset#image/bmp 19 | *.gif binary svneol=unset#image/gif 20 | *.ico binary svneol=unset#image/ico 21 | *.jpeg binary svneol=unset#image/jpeg 22 | *.jpg binary svneol=unset#image/jpeg 23 | *.png binary svneol=unset#image/png 24 | *.tif binary svneol=unset#image/tiff 25 | *.tiff binary svneol=unset#image/tiff 26 | *.svg text svneol=native#image/svg%2Bxml 27 | 28 | # Data formats 29 | *.pdf binary svneol=unset#application/pdf 30 | *.avi binary svneol=unset#video/avi 31 | *.doc binary svneol=unset#application/msword 32 | *.dsp text svneol=crlf#text/plain 33 | *.dsw text svneol=crlf#text/plain 34 | *.eps binary svneol=unset#application/postscript 35 | *.gz binary svneol=unset#application/gzip 36 | *.mov binary svneol=unset#video/quicktime 37 | *.mp3 binary svneol=unset#audio/mpeg 38 | *.ppt binary svneol=unset#application/vnd.ms-powerpoint 39 | *.ps binary svneol=unset#application/postscript 40 | *.psd binary svneol=unset#application/photoshop 41 | *.rdf binary svneol=unset#text/rdf 42 | *.rss text svneol=unset#text/xml 43 | *.rtf binary svneol=unset#text/rtf 44 | *.sln text svneol=native#text/plain 45 | *.swf binary svneol=unset#application/x-shockwave-flash 46 | *.tgz binary svneol=unset#application/gzip 47 | *.vcproj text svneol=native#text/xml 48 | *.vcxproj text svneol=native#text/xml 49 | *.vsprops text svneol=native#text/xml 50 | *.wav binary svneol=unset#audio/wav 51 | *.xls binary svneol=unset#application/vnd.ms-excel 52 | *.zip binary svneol=unset#application/zip 53 | 54 | # Text formats 55 | .htaccess text svneol=native#text/plain 56 | *.bbk text svneol=native#text/xml 57 | *.cmake text svneol=native#text/plain 58 | *.css text svneol=native#text/css 59 | *.dtd text svneol=native#text/xml 60 | *.htm text svneol=native#text/html 61 | *.html text svneol=native#text/html 62 | *.ini text svneol=native#text/plain 63 | *.log text svneol=native#text/plain 64 | *.mak text svneol=native#text/plain 65 | *.qbk text svneol=native#text/plain 66 | *.rst text svneol=native#text/plain 67 | *.sql text svneol=native#text/x-sql 68 | *.txt text svneol=native#text/plain 69 | *.xhtml text svneol=native#text/xhtml%2Bxml 70 | *.xml text svneol=native#text/xml 71 | *.xsd text svneol=native#text/xml 72 | *.xsl text svneol=native#text/xml 73 | *.xslt text svneol=native#text/xml 74 | *.xul text svneol=native#text/xul 75 | *.yml text svneol=native#text/plain 76 | boost-no-inspect text svneol=native#text/plain 77 | CHANGES text svneol=native#text/plain 78 | COPYING text svneol=native#text/plain 79 | INSTALL text svneol=native#text/plain 80 | Jamfile text svneol=native#text/plain 81 | Jamroot text svneol=native#text/plain 82 | Jamfile.v2 text svneol=native#text/plain 83 | Jamrules text svneol=native#text/plain 84 | Makefile* text svneol=native#text/plain 85 | README text svneol=native#text/plain 86 | TODO text svneol=native#text/plain 87 | 88 | # Code formats 89 | *.c text svneol=native#text/plain 90 | *.cpp text svneol=native#text/plain 91 | *.h text svneol=native#text/plain 92 | *.hpp text svneol=native#text/plain 93 | *.ipp text svneol=native#text/plain 94 | *.tpp text svneol=native#text/plain 95 | *.jam text svneol=native#text/plain 96 | *.java text svneol=native#text/plain 97 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Generated by `boostdep --cmake format` 2 | # Copyright 2020, 2021 Peter Dimov 3 | # Distributed under the Boost Software License, Version 1.0. 4 | # https://www.boost.org/LICENSE_1_0.txt 5 | 6 | cmake_minimum_required(VERSION 3.8...3.20) 7 | 8 | project(boost_format VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX) 9 | 10 | add_library(boost_format INTERFACE) 11 | add_library(Boost::format ALIAS boost_format) 12 | 13 | target_include_directories(boost_format INTERFACE include) 14 | 15 | target_link_libraries(boost_format 16 | INTERFACE 17 | Boost::assert 18 | Boost::config 19 | Boost::core 20 | Boost::optional 21 | Boost::smart_ptr 22 | Boost::throw_exception 23 | Boost::utility 24 | ) 25 | 26 | target_compile_features(boost_format INTERFACE cxx_std_11) 27 | 28 | if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt") 29 | 30 | add_subdirectory(test) 31 | 32 | endif() 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Boost Software License - Version 1.0 - August 17th, 2003 2 | 3 | Permission is hereby granted, free of charge, to any person or organization 4 | obtaining a copy of the software and accompanying documentation covered by 5 | this license (the "Software") to use, reproduce, display, distribute, 6 | execute, and transmit the Software, and to prepare derivative works of the 7 | Software, and to permit third-parties to whom the Software is furnished to 8 | do so, all subject to the following: 9 | 10 | The copyright notices in the Software and this entire statement, including 11 | the above license grant, this restriction and the following disclaimer, 12 | must be included in all copies of the Software, in whole or in part, and 13 | all derivative works of the Software, unless such copies or derivative 14 | works are solely in the form of machine-executable object code generated by 15 | a source language processor. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 20 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 21 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 22 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Format, part of the collection of [Boost C++ Libraries](https://github.com/boostorg), provides a type-safe mechanism for formatting arguments according to a printf-like format-string. User-defined types are supported by providing a `std::ostream operator <<` implementation for them. 2 | 3 | ### License 4 | 5 | Distributed under the [Boost Software License, Version 1.0](https://www.boost.org/LICENSE_1_0.txt). 6 | 7 | ### Properties 8 | 9 | * C++11 10 | * Header-only 11 | 12 | ### Build Status 13 | 14 | 15 | | Branch | GHA CI | Appveyor | Coverity Scan | codecov.io | Deps | Docs | Tests | 16 | | :-------------: | ------ | -------- | ------------- | ---------- | ---- | ---- | ----- | 17 | | [`master`](https://github.com/boostorg/format/tree/master) | [![Build Status](https://github.com/boostorg/format/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/boostorg/format/actions?query=branch:master) | [![Build status](https://ci.appveyor.com/api/projects/status/aeg8obnkb0mrgqvd/branch/master?svg=true)](https://ci.appveyor.com/project/cppalliance/format/branch/master) | [![Coverity Scan Build Status](https://scan.coverity.com/projects/14007/badge.svg)](https://scan.coverity.com/projects/boostorg-format) | [![codecov](https://codecov.io/gh/boostorg/format/branch/master/graph/badge.svg?token=)](https://codecov.io/gh/boostorg/format/tree/master) | [![Deps](https://img.shields.io/badge/deps-master-brightgreen.svg)](https://pdimov.github.io/boostdep-report/master/format.html) | [![Documentation](https://img.shields.io/badge/docs-master-brightgreen.svg)](https://www.boost.org/doc/libs/master/libs/format) | [![Enter the Matrix](https://img.shields.io/badge/matrix-master-brightgreen.svg)](https://www.boost.org/development/tests/master/developer/format.html) 18 | | [`develop`](https://github.com/boostorg/format/tree/develop) | [![Build Status](https://github.com/boostorg/format/actions/workflows/ci.yml/badge.svg?branch=develop)](https://github.com/boostorg/format/actions?query=branch:develop) | [![Build status](https://ci.appveyor.com/api/projects/status/aeg8obnkb0mrgqvd/branch/develop?svg=true)](https://ci.appveyor.com/project/cppalliance/format/branch/develop) | [![Coverity Scan Build Status](https://scan.coverity.com/projects/14007/badge.svg)](https://scan.coverity.com/projects/boostorg-format) | [![codecov](https://codecov.io/gh/boostorg/format/branch/develop/graph/badge.svg?token=)](https://codecov.io/gh/boostorg/format/tree/develop) | [![Deps](https://img.shields.io/badge/deps-develop-brightgreen.svg)](https://pdimov.github.io/boostdep-report/develop/format.html) | [![Documentation](https://img.shields.io/badge/docs-develop-brightgreen.svg)](https://www.boost.org/doc/libs/develop/libs/format) | [![Enter the Matrix](https://img.shields.io/badge/matrix-develop-brightgreen.svg)](https://www.boost.org/development/tests/develop/developer/format.html) 19 | 20 | ### Directories 21 | 22 | | Name | Purpose | 23 | | ----------- | ------------------------------ | 24 | | `benchmark` | benchmark tool | 25 | | `doc` | documentation | 26 | | `examples` | use case examples | 27 | | `include` | headers | 28 | | `test` | unit tests | 29 | | `tools` | development tools | 30 | 31 | ### More information 32 | 33 | * [Ask questions](https://stackoverflow.com/questions/ask?tags=c%2B%2B,boost,boost-format): Be sure to read the documentation first as Boost.Format, like any other string formatting library, has its own rules. 34 | * [Report bugs](https://github.com/boostorg/format/issues): Be sure to mention Boost version, platform and compiler you're using. A small compilable code sample to reproduce the problem is always good as well. 35 | * [Submit Pull Requests](https://github.com/boostorg/format/pulls) against the **develop** branch. Note that by submitting patches you agree to license your modifications under the [Boost Software License, Version 1.0](https://www.boost.org/LICENSE_1_0.txt). Be sure to include tests proving your changes work properly. 36 | * Discussions about the library are held on the [Boost developers mailing list](https://www.boost.org/community/groups.html#main). Be sure to read the [discussion policy](https://www.boost.org/community/policy.html) before posting and add the `[format]` tag at the beginning of the subject line. 37 | 38 | -------------------------------------------------------------------------------- /benchmark/Jamfile: -------------------------------------------------------------------------------- 1 | # Boost.Format Library benchmark Jamfile 2 | # 3 | # Copyright (c) 2003 Samuel Krempp 4 | # 5 | # Distributed under the Boost Software License, Version 1.0. 6 | # See www.boost.org/LICENSE_1_0.txt 7 | # 8 | 9 | project 10 | : requirements 11 | /boost/format//boost_format 12 | /boost/timer//boost_timer 13 | msvc:_CRT_SECURE_NO_WARNINGS 14 | ; 15 | 16 | exe bench_format_no_locale 17 | : bench_format.cpp 18 | /boost/timer//boost_timer 19 | : BOOST_NO_STD_LOCALE no_locale 20 | ; 21 | 22 | exe bench_format_normal 23 | : bench_format.cpp 24 | /boost/timer//boost_timer 25 | : normal 26 | ; 27 | 28 | exe bench_format_no_reuse_stream 29 | : bench_format.cpp 30 | /boost/timer//boost_timer 31 | : alts BOOST_FORMAT_NO_OSS_MEMBER no_reuse_stream 32 | ; 33 | -------------------------------------------------------------------------------- /benchmark/bench_format.cpp: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | // Boost general library 'format' --------------------------- 3 | // See http://www.boost.org for updates, documentation, and revision history. 4 | 5 | // Copyright (c) 2001 Samuel Krempp 6 | // krempp@crans.ens-cachan.fr 7 | // Distributed under the Boost Software License, Version 1.0. (See 8 | // accompanying file LICENSE_1_0.txt or copy at 9 | // http://www.boost.org/LICENSE_1_0.txt) 10 | 11 | // several suggestions from Jens Maurer 12 | 13 | // ------------------------------------------------------------------------------ 14 | // bench_variants.cc : do the same task, with sprintf, stream, and format 15 | // and compare their times. 16 | 17 | // This benchmark is provided purely for information. 18 | // It might not even compile as-is, 19 | // or not give any sensible results. 20 | // (e.g., it expects sprintf to be POSIX compliant) 21 | 22 | // ------------------------------------------------------------------------------ 23 | 24 | 25 | #include 26 | #include 27 | #include // sprintf 28 | #include 29 | #include 30 | #include // floor 31 | #include 32 | #include 33 | 34 | #include 35 | 36 | // portable /dev/null stream equivalent, by James Kanze, http://www.gabi-soft.de 37 | class NulStreambuf : public std::streambuf 38 | { 39 | public: 40 | NulStreambuf() { 41 | setp( dummyBuffer , dummyBuffer + 64 ) ; 42 | } 43 | virtual int overflow( int c ); 44 | virtual int underflow(); 45 | private: 46 | char dummyBuffer[ 64 ] ; 47 | } ; 48 | 49 | class NulStream : public std::basic_ostream > 50 | { 51 | public: 52 | NulStream(); 53 | virtual ~NulStream(); 54 | NulStreambuf* rdbuf() { 55 | return static_cast< NulStreambuf* >( 56 | ((std::basic_ostream > *) this) -> rdbuf() ) ; 57 | } 58 | } ; 59 | 60 | 61 | //------------------------------------------------------------------------------------- 62 | // NulStream implementation 63 | 64 | NulStream::NulStream() : std::basic_ostream > (NULL) { 65 | init( new NulStreambuf ) ; 66 | } 67 | 68 | NulStream::~NulStream() { 69 | delete rdbuf() ; 70 | } 71 | 72 | int NulStreambuf::underflow(){ return std::ios::traits_type::eof(); 73 | } 74 | 75 | int NulStreambuf::overflow( int c ){ 76 | setp( dummyBuffer , dummyBuffer + 64 ) ; 77 | return (c == std::ios::traits_type::eof()) ? '\0' : c ; 78 | } 79 | 80 | 81 | 82 | // ------------------------------------------------------------------------------------- 83 | 84 | namespace benchmark { 85 | 86 | static int NTests = 300000; 87 | 88 | //static std::stringstream nullStream; 89 | static NulStream nullStream; 90 | static boost::timer::nanosecond_type tstream, tpf; 91 | //static const std::string fstring="%3$#x %1$20.10E %2$g %3$d \n"; 92 | static const std::string fstring="%3$0#6x %1$20.10E %2$g %3$0+5d \n"; 93 | static const double arg1=45.23; 94 | static const double arg2=12.34; 95 | static const int arg3=23; 96 | static const std::string res = 97 | "0x0017 4.5230000000E+01 12.34 +0023 \n"; 98 | //static const std::string res = "23.0000 4.5230000000E+01 12.34 23 \n"; 99 | 100 | void test_sprintf(); 101 | void test_nullstream(); 102 | void test_opti_nullstream(); 103 | void test_parsed_once_format(); 104 | void test_reused_format(); 105 | void test_format(); 106 | void test_try1(); 107 | void test_try2(); 108 | 109 | void test_sprintf() 110 | { 111 | using namespace std; 112 | 113 | vector bufr; 114 | bufr.reserve(4000); 115 | char *buf = &bufr[0]; 116 | 117 | // Check that sprintf is Unix98 compatible on the platform : 118 | sprintf(buf, fstring.c_str(), arg1, arg2, arg3); 119 | if( strncmp( buf, res.c_str(), res.size()) != 0 ) { 120 | cerr << endl << buf; 121 | } 122 | // time the loop : 123 | boost::timer::cpu_timer chrono; 124 | for(int i=0; i oss; 135 | oss << boost::format(fstring) % arg1 % arg2 % arg3; 136 | boost::timer::cpu_timer chrono; 137 | size_t dummy=0; 138 | for(int i=0; i oss; 190 | 191 | { 192 | do_stream(oss); 193 | if(oss.str() != res ) { 194 | cerr << endl << oss.str() ; 195 | } 196 | } 197 | 198 | for(int i=0; i oss; 223 | //static const std::string fstring="%3$#x %1$20.10E %2$g %3$d \n"; 224 | 225 | std::ios_base::fmtflags f0 = oss.flags(), f1, f2; 226 | streamsize p0 = oss.precision(); 227 | { 228 | oss << hex << showbase; 229 | f1 = oss.flags(); 230 | oss << arg3; 231 | 232 | oss.flags(f0); 233 | oss << " " << scientific << setw(20) << setprecision(10) << uppercase; 234 | f2 = oss.flags(); 235 | oss << arg1; 236 | 237 | oss.flags(f0); oss.precision(p0); 238 | oss << " " << arg2 << " " << arg3 << " \n" ; 239 | 240 | if(oss.str() != res ) { 241 | cerr << endl << oss.str() ; 242 | } 243 | } 244 | 245 | for(int i=0; i oss; 268 | oss << boost::format(fmter) % arg1 % arg2 % arg3 ; 269 | if( oss.str() != res ) { 270 | cerr << endl << oss.str(); 271 | } 272 | 273 | // not only is the format-string parsed once, 274 | // but also the buffer of the internal stringstream is already allocated. 275 | 276 | boost::timer::cpu_timer chrono; 277 | for(int i=0; i oss; 290 | oss << boost::format(fstring) % arg1 % arg2 % arg3; 291 | if(oss.str() != res ) { 292 | cerr << endl << oss.str(); 293 | } 294 | 295 | boost::timer::cpu_timer chrono; 296 | boost::format fmter; 297 | for(int i=0; i oss; 310 | oss << boost::format(fstring) % arg1 % arg2 % arg3; 311 | if(oss.str() != res ) { 312 | cerr << endl << oss.str(); 313 | } 314 | 315 | boost::timer::cpu_timer chrono; 316 | for(int i=0; iinclude 20 | ; 21 | 22 | explicit 23 | [ alias boost_format : : : : $(boost_dependencies) ] 24 | [ alias all 25 | : boost_format 26 | benchmark 27 | example 28 | test 29 | tools 30 | : pedantic 31 | on 32 | ] 33 | ; 34 | 35 | call-if : boost-library format 36 | ; 37 | 38 | -------------------------------------------------------------------------------- /doc/choices.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Type-safe 'printf-like' format class 9 | 10 | 11 | 12 |

boost.png (6897 bytes)Type-safe 'printf-like' format 14 | class

15 | 16 |

Choices made

17 | 18 |

"Le pourquoi du comment" ( - "the why of the how")

19 |
20 | 21 |

The syntax of the format-string

22 | 23 |

Format is a new library. One of its goal is to provide a replacement for 24 | printf, that means format can parse a format-string designed for printf, 25 | apply it to the given arguments, and produce the same result as printf 26 | would have.
27 | With this constraint, there were roughly 3 possible choices for the syntax 28 | of the format-string :

29 | 30 |
    31 |
  1. Use the exact same syntax of printf. It's well known by many 32 | experienced users, and fits almost all needs. But with C++ streams, the 33 | type-conversion character, crucial to determine the end of a directive, 34 | is only useful to set some associated formatting options, in a C++ 35 | streams context (%x for setting hexa, etc..) It would be better to make 36 | this obligatory type-conversion character, with modified meaning, 37 | optional.
  2. 38 | 39 |
  3. extend printf syntax while maintaining compatibility, by using 40 | characters and constructs not yet valid as printf syntax. e.g. : "%1%", 41 | "%[1]", "%|1$d|", .. Using begin / end marks, all sort of extension can 42 | be considered.
  4. 43 | 44 |
  5. Provide a non-legacy mode, in parallel of the printf-compatible one, 45 | that can be designed to fit other objectives without constraints of 46 | compatibilty with the existing printf syntax.
    47 | But Designing a replacement to printf's syntax, that would be clearly 48 | better, and as much powerful, is yet another task than building a format 49 | class. When such a syntax is designed, we should consider splitting 50 | Boost.format into 2 separate libraries : one working hand in hand with 51 | this new syntax, and another supporting the legacy syntax (possibly a 52 | fast version, built with safety improvement above snprintf or the 53 | like).
  6. 54 |
In the absence of a full, clever, new syntax clearly better adapted to 55 | C++ streams than printf, the second approach was chosen. Boost.format uses 56 | printf's syntax, with extensions (tabulations, centered alignements) that 57 | can be expressed using extensions to this syntax.
58 | And alternate compatible notations are provided to address the weaknesses 59 | of printf's : 60 | 61 |
    62 |
  • "%N%" as a simpler positional, typeless and optionless 63 | notation.
  • 64 | 65 |
  • %|spec| as a way to encapsulate printf directive in movre 66 | visually evident structures, at the same time making printf's 67 | 'type-conversion character' optional.
  • 68 |
69 |
70 | 71 |

Why are arguments passed through an operator rather than a function 72 | call ?


73 | The inconvenience of the operator approach (for some people) is that it 74 | might be confusing. It's a usual warning that too much of overloading 75 | operators gets people real confused.
76 | Since the use of format objects will be in specific contexts ( most often 77 | right after a "cout << ") and look like a formatting string followed 78 | by arguments indeed : 79 | 80 |
81 |
 82 | format(" %s at %s  with %s\n") % x % y % z;
 83 | 
84 |
we can hope it wont confuse people that much. 85 | 86 |

An other fear about operators, is precedence problems. What if I someday 87 | write format("%s") % x+y
88 | instead of format("%s") % (x+y) ??
89 | It will make a mistake at compile-time, so the error will be immediately 90 | detected.
91 | indeed, this line calls tmp = operator%( format("%s"), x)
92 | and then operator+(tmp, y)
93 | tmp will be a format object, for which no implicit conversion is defined, 94 | and thus the call to operator+ will fail. (except if you define such an 95 | operator, of course). So you can safely assume precedence mistakes will be 96 | noticed at compilation.

97 | 98 |


99 | On the other hand, the function approach has a true inconvenience. It needs 100 | to define lots of template function like :

101 | 102 |
103 |
104 | template <class T1, class T2,  .., class TN> 
105 | string format(string s,  const T1& x1, .... , const T1& xN);
106 | 
107 | 
108 |
and even if we define those for N up to 500, that is still a 109 | limitation, that C's printf does not have.
110 | Also, since format somehow emulates printf in some cases, but is far from 111 | being fully equivalent to printf, it's best to use a radically different 112 | appearance, and using operator calls succeeds very well in that ! 113 | 114 |


115 | Anyhow, if we actually chose the formal function call templates system, it 116 | would only be able to print Classes T for which there is an

117 | 118 |
119 |
120 | operator<< ( stream,   const T&)
121 | 
122 |
Because allowing both const and non const produces a 123 | combinatorics explosion - if we go up to 10 arguments, we need 2^10 124 | functions.
125 | (providing overloads on T& / const T& is at the frontier of defects 126 | of the C++ standard, and thus is far from guaranteed to be supported. But 127 | right now several compilers support those overloads)
128 | There is a lot of chances that a class which only provides the non-const 129 | equivalent is badly designed, but yet it is another unjustified restriction 130 | to the user.
131 | Also, some manipulators are functions, and can not be passed as const 132 | references. The function call approach thus does not support manipulators 133 | well. 134 | 135 |

In conclusion, using a dedicated binary operator is the simplest, most 136 | robust, and least restrictive mechanism to pass arguments when you can't 137 | know the number of arguments at compile-time.

138 |
139 | 140 |

Why operator% rather than a member function 'with(..)' 141 | ??

technically, 142 | 143 |
144 |
145 | format(fstr) % x1 % x2 % x3;
146 | 
147 |
has the same structure as 148 | 149 |
150 |
151 | format(fstr).with( x1 ).with( x2 ).with( x3 );
152 | 
153 |
which does not have any precedence problem. The only drawback, 154 | is it's harder for the eye to catch what is done in this line, than when we 155 | are using operators. calling .with(..), it looks just like any other line 156 | of code. So it may be a better solution, depending on tastes. The extra 157 | characters, and overall cluttered aspect of the line of code using 158 | 'with(..)' were enough for me to opt for a true operator. 159 |
160 | 161 |

Why operator% rather than usual formatting operator<< ??

162 | 163 |
    164 |
  • because passing arguments to a format object is *not* the same as 165 | sending variables, sequentially, into a stream, and because a format 166 | object is not a stream, nor a manipulator.
    167 | We use an operator to pass arguments. format will use them as a 168 | function would, it simply takes arguments one by one.
    169 | format objects can not provide stream-like behaviour. When you try to 170 | implement a format object that acts like a manipulator, returning a 171 | stream, you make the user beleive it is completely like a 172 | stream-manipulator. And sooner or later, the user is deceived by this 173 | point of view.
    174 | The most obvious example of that difference in behaviour is 175 | 176 |
    177 |
    178 | cout << format("%s %s ") << x;
    179 | cout << y ;  // uh-oh, format is not really a stream manipulator
    180 | 
    181 |
    182 |
  • 183 | 184 |
  • precedence of % is higher than that of <<. It can be viewd as a 185 | problem, because + and - thus needs to be grouped inside parentheses, 186 | while it is not necessary with '<<'. But if the user forgets, the 187 | mistake is catched at compilation, and hopefully he won't forget 188 | again.
    189 | On the other hand, the higher precedence makes format's behaviour very 190 | straight-forward. 191 | 192 |
    193 |
    194 | cout << format("%s %s ") % x % y << endl;
    195 | 
    196 |
    is treated exaclt like : 197 | 198 |
    199 |
    200 | cout << ( format("%s %s ") % x % y ) << endl;
    201 | 
    202 |
    So using %, the life of a format object does not interfere 203 | with the surrounding stream context. This is the simplest possible 204 | behaviour, and thus the user is able to continue using the stream after 205 | the format object.
    206 |
    207 | With operator<<, things are much more problematic in this 208 | situation. This line : 209 | 210 |
    211 |
    212 | cout << format("%s %s ") <<  x  <<  y << endl;
    213 | 
    214 |
    is understood as : 215 | 216 |
    217 |
    218 | ( ( ( cout << format("%s %s ") ) << x ) <<  y ) << endl;
    219 | 
    220 |
    Several alternative implementations chose 221 | operator<<, and there is only one way to make it work :
    222 | the first call to 223 | 224 |
    225 |
    226 | operator<<( ostream&, format const&)
    227 | 
    228 |
    returns a proxy, encapsulating both the final destination 229 | (cout) and the format-string information
    230 | Passing arguments to format, or to the final destination after 231 | completion of the format are indistinguishable. This is a problem. 232 | 233 |

    I examined several possible implementations, and none is completely 234 | satsifying.
    235 | E.g. : In order to catch users mistake, it makes sense to raise 236 | exceptions when the user passes too many arguments. But in this 237 | context, supplementary arguments are most certainly aimed at the final 238 | destination. There are several choices here :

    239 | 240 |
      241 |
    • You can give-up detection of arity excess, and have the proxy's 242 | template member operator<<( const T&) simply forward all 243 | supplementary arguments to cout.
    • 244 | 245 |
    • Require the user to close the format arguments with a special 246 | manipulator, 'endf', in this way : 247 | 248 |
      249 |
      250 | cout << format("%s %s ") <<  x  <<  y << endf << endl;
      251 | 
      252 |
      You can define endf to be a function that returns the 253 | final destination stored inside the proxy. Then it's okay, after 254 | endf the user is calling << on cout again. 255 |
    • 256 | 257 |
    • An intermediate solution, is to adress the most frequent use, 258 | where the user simply wants to output one more manipulator item to 259 | cout (a std::flush, or endl, ..) 260 | 261 |
      262 |
      263 | cout << format("%s %s \n") <<  x  <<  y << flush ;
      264 | 
      265 |
      Then, the solution is to overload the operator<< 266 | for manipulators. This way You don't need endf, but outputting a 267 | non-manipulator item right after the format arguments is a mistake. 268 |
    • 269 |

    270 | The most complete solution is the one with the endf manipualtor. With 271 | operator%, there is no need for this end-format function, plus you 272 | instantly see which arguments are going into the format object, and 273 | which are going to the stream. 274 |
  • 275 | 276 |
  • Esthetically : '%' is the same letter as used inside the 277 | format-string. That is quite nice to have the same letter used for 278 | passing each argument. '<<' is 2 letters, '%' is one. '%' is also 279 | smaller in size. It overall improves visualisation (we see what goes with 280 | what) : 281 | 282 |
    283 |
    284 | cout << format("%s %s %s") %x %y %z << "And  avg is" << format("%s\n") %avg;
    285 | 
    286 |
    compared to : 287 | 288 |
    289 |
    290 | cout << format("%s %s %s") << x << y << z << endf <<"And avg is" << format("%s\n") << avg;
    291 | 
    292 |
    "<<" misleadingly puts the arguments at the same 293 | level as any object passed to the stream. 294 |
  • 295 | 296 |
  • python also uses % for formatting, so you see it's not so "unheard 297 | of" ;-)
  • 298 |
299 |
300 | 301 |

Why operator% rather than operator(), or operator[] ??

302 | 303 |

operator() has the merit of being the natural way to send an argument 304 | into a function. And some think that operator[] 's meaning apply well to 305 | the usage in format.
306 | They're as good as operator% technically, but quite ugly. (that's a matter 307 | of taste)
308 | And deepd down, using operator% for passing arguments that were referred to 309 | by "%" in the format string seems much more natural to me than using those 310 | operators.

311 |
312 | 313 |

Valid HTML 4.01 Transitional

316 | 317 |

Revised 318 | 02 December, 2006

319 | 320 |

Copyright © 2001 Samuel Krempp

321 | 322 |

Distributed under the Boost Software License, Version 1.0. (See 323 | accompanying file LICENSE_1_0.txt or 324 | copy at http://www.boost.org/LICENSE_1_0.txt)

326 | 327 | 328 | -------------------------------------------------------------------------------- /example/Jamfile.v2: -------------------------------------------------------------------------------- 1 | # Boost.Format Library example Jamfile 2 | # 3 | # Copyright (c) 2003 Samuel Krempp 4 | # 5 | # Distributed under the Boost Software License, Version 1.0. (See accompany- 6 | # ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | import testing ; 9 | 10 | project : requirements /boost/format//boost_format ; 11 | 12 | test-suite "format-examples" 13 | : [ run sample_advanced.cpp ] 14 | [ run sample_formats.cpp ] 15 | [ run sample_new_features.cpp ] 16 | [ run sample_userType.cpp : : : /boost/numeric_conversion//boost_numeric_conversion ] 17 | ; 18 | 19 | -------------------------------------------------------------------------------- /example/sample_advanced.cpp: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // sample_advanced.cc : examples of adanced usage of format 3 | // ---------------------------------------------------------------------------- 4 | 5 | // Copyright Samuel Krempp 2003. Use, modification, and distribution are 6 | // subject to the Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | // See http://www.boost.org/libs/format for library home page 10 | 11 | // ---------------------------------------------------------------------------- 12 | 13 | #include 14 | #include 15 | 16 | #include "boost/format.hpp" 17 | 18 | 19 | namespace MyNS_ForOutput { 20 | using std::cout; using std::cerr; 21 | using std::string; 22 | using std::endl; using std::flush; 23 | 24 | using boost::format; 25 | using boost::io::group; 26 | } 27 | 28 | namespace MyNS_Manips { 29 | using std::setfill; 30 | using std::setw; 31 | using std::hex ; 32 | using std::dec ; 33 | using std::showbase ; 34 | using std::left ; 35 | using std::right ; 36 | using std::internal ; 37 | } 38 | 39 | int main(){ 40 | using namespace MyNS_ForOutput; 41 | using namespace MyNS_Manips; 42 | 43 | std::string s; 44 | 45 | //------------------------------------------------------------------------ 46 | // storing the parsed format-string in a 'formatter' : 47 | // format objects are regular objects that can be copied, assigned, 48 | // fed arguments, dumped to a stream, re-fed arguments, etc... 49 | // So users can use them the way they like. 50 | 51 | format fmter("%1% %2% %3% %1% \n"); 52 | fmter % 10 % 20 % 30; 53 | cout << fmter; 54 | // prints "10 20 30 10 \n" 55 | 56 | // note that once the fmter got all its arguments, 57 | // the formatted string stays available (until next call to '%') 58 | // The result is available via function str() or stream's << : 59 | cout << fmter; 60 | // prints the same string again. 61 | 62 | 63 | // once you call operator% again, arguments are cleared inside the object 64 | // and it is an error to ask for the conversion string before feeding all arguments : 65 | fmter % 1001; 66 | try { cout << fmter; } 67 | catch (boost::io::too_few_args& exc) { 68 | cout << exc.what() << "***Dont worry, that was planned\n"; 69 | } 70 | 71 | // we just need to feed the last two arguments, and it will be ready for output again : 72 | cout << fmter % 1002 % 1003; 73 | // prints "1001 1002 1003 1001 \n" 74 | 75 | cout << fmter % 10 % 1 % 2; 76 | // prints "10 1 2 10 \n" 77 | 78 | 79 | 80 | //--------------------------------------------------------------- 81 | // using format objects 82 | 83 | // modify the formatting options for a given directive : 84 | fmter = format("%1% %2% %3% %2% %1% \n"); 85 | fmter.modify_item(4, group(setfill('_'), hex, showbase, setw(5)) ); 86 | cout << fmter % 1 % 2 % 3; 87 | // prints "1 2 3 __0x2 1 \n" 88 | 89 | // bind one of the argumets : 90 | fmter.bind_arg(1, 18); 91 | cout << fmter % group(hex, showbase, 20) % 30; // %2 is 20, and 20 == 0x14 92 | // prints "18 0x14 30 _0x14 18 \n" 93 | 94 | 95 | fmter.modify_item(4, setw(0)); // cancels previous width-5 96 | fmter.bind_arg(1, 77); // replace 18 with 77 for first argument. 97 | cout << fmter % 10 % 20; 98 | // prints "77 10 20 0xa 77 \n" 99 | 100 | try 101 | { 102 | cout << fmter % 6 % 7 % 8; // Aye ! too many args, because arg1 is bound already 103 | } 104 | catch (boost::io::too_many_args& exc) 105 | { 106 | cout << exc.what() << "***Dont worry, that was planned\n"; 107 | } 108 | 109 | // clear regular arguments, but not bound arguments : 110 | fmter.clear(); 111 | cout << fmter % 2 % 3; 112 | // prints "77 2 3 0x2 77 \n" 113 | 114 | // clear_binds() clears both regular AND bound arguments : 115 | fmter.clear_binds(); 116 | cout << fmter % 1 % 2 % 3; 117 | // prints "1 2 3 0x2 1 \n" 118 | 119 | 120 | // setting desired exceptions : 121 | fmter.exceptions( boost::io::all_error_bits ^( boost::io::too_many_args_bit ) ); 122 | cout << fmter % 1 % 2 % 3 % 4 % 5 % 6 ; 123 | 124 | 125 | // ----------------------------------------------------------- 126 | // misc: 127 | 128 | // unsupported printf directives %n and asterisk-fields are purely ignored. 129 | // do *NOT* provide an argument for them, it is an error. 130 | cout << format("|%5d| %n") % 7 << endl; 131 | // prints "| 7| " 132 | cout << format("|%*.*d|") % 7 << endl; 133 | // prints "|7|" 134 | 135 | 136 | // truncations of strings : 137 | cout << format("%|.2s| %|8c|.\n") % "root" % "user"; 138 | // prints "ro u.\n" 139 | 140 | 141 | // manipulators conflicting with format-string : manipulators win. 142 | cout << format("%2s") % group(setfill('0'), setw(6), 1) << endl; 143 | // prints "000001" 144 | cout << format("%2$5s %1% %2$3s\n") % 1 % group(setfill('X'), setw(4), 2) ; 145 | // prints "XXX2 1 XXX2\n" 146 | // width is 4, as set by manip, not the format-string. 147 | 148 | // nesting : 149 | cout << format("%2$014x [%1%] %2$05s\n") % (format("%05s / %s") % -18 % 7) 150 | % group(showbase, -100); 151 | // prints "0x0000ffffff9c [-0018 / 7] -0100\n" 152 | 153 | 154 | cout << "\n\nEverything went OK, exiting. \n"; 155 | return 0; 156 | } 157 | -------------------------------------------------------------------------------- /example/sample_formats.cpp: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // sample_formats.cpp : example of basic usage of format 3 | // ---------------------------------------------------------------------------- 4 | 5 | // Copyright Samuel Krempp 2003. Use, modification, and distribution are 6 | // subject to the Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | // See http://www.boost.org/libs/format for library home page 10 | // ---------------------------------------------------------------------------- 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include "boost/format.hpp" 17 | 18 | // 2 custom namespaces, to bring in a few useful names : 19 | 20 | namespace MyNS_ForOutput { 21 | using std::cout; using std::cerr; 22 | using std::string; 23 | using std::endl; using std::flush; 24 | 25 | using boost::format; 26 | using boost::io::group; 27 | } 28 | 29 | namespace MyNS_Manips { 30 | using std::setfill; 31 | using std::setw; 32 | using std::hex ; 33 | using std::dec ; 34 | // gcc-2.95 doesnt define the next ones 35 | // using std::showbase ; 36 | // using std::left ; 37 | // using std::right ; 38 | // using std::internal ; 39 | } 40 | 41 | int main(){ 42 | using namespace MyNS_ForOutput; 43 | using namespace MyNS_Manips; 44 | 45 | std::cout << format("%|1$1| %|2$3|") % "Hello" % 3 << std::endl; 46 | 47 | // Reordering : 48 | cout << format("%1% %2% %3% %2% %1% \n") % "o" % "oo" % "O"; // 'simple' style. 49 | // prints "o oo O oo o \n" 50 | cout << format("(x,y) = (%1$+5d,%2$+5d) \n") % -23 % 35; // Posix-Printf style 51 | 52 | 53 | // No reordering : 54 | cout << format("writing %s, x=%s : %d-th step \n") % "toto" % 40.23 % 50; 55 | // prints "writing toto, x=40.23 : 50-th step \n" 56 | 57 | cout << format("(x,y) = (%+5d,%+5d) \n") % -23 % 35; 58 | cout << format("(x,y) = (%|+5|,%|+5|) \n") % -23 % 35; 59 | cout << format("(x,y) = (%|1$+5|,%|2$+5|) \n") % -23 % 35; 60 | // all those are the same, it prints "(x,y) = ( -23, +35) \n" 61 | 62 | 63 | 64 | // Using manipulators, via 'group' : 65 | cout << format("%2% %1% %2%\n") % 1 % group(setfill('X'), hex, setw(4), 16+3) ; 66 | // prints "XX13 1 XX13\n" 67 | 68 | 69 | // printf directives's type-flag can be used to pass formatting options : 70 | cout << format("_%1$4d_ is : _%1$#4x_, _%1$#4o_, and _%1$s_ by default\n") % 18; 71 | // prints "_ 18_ is : _0x12_, _ 022_, and _18_ by default\n" 72 | 73 | // Taking the string value : 74 | std::string s; 75 | s= str( format(" %d %d ") % 11 % 22 ); 76 | assert( s == " 11 22 "); 77 | 78 | 79 | // ----------------------------------------------- 80 | // %% prints '%' 81 | 82 | cout << format("%%##%#x ") % 20 << endl; 83 | // prints "%##0x14 " 84 | 85 | 86 | // ----------------------------------------------- 87 | // Enforcing the right number of arguments 88 | 89 | // Too much arguments will throw an exception when feeding the unwanted argument : 90 | try { 91 | format(" %1% %1% ") % 101 % 102; 92 | // the format-string refers to ONE argument, twice. not 2 arguments. 93 | // thus giving 2 arguments is an error 94 | } 95 | catch (boost::io::too_many_args& exc) { 96 | cerr << exc.what() << "\n\t\t***Dont worry, that was planned\n"; 97 | } 98 | 99 | 100 | // Too few arguments when requesting the result will also throw an exception : 101 | try { 102 | cerr << format(" %|3$| ") % 101; 103 | // even if %1$ and %2$ are not used, you should have given 3 arguments 104 | } 105 | catch (boost::io::too_few_args& exc) { 106 | cerr << exc.what() << "\n\t\t***Dont worry, that was planned\n"; 107 | } 108 | 109 | 110 | cerr << "\n\nEverything went OK, exiting. \n"; 111 | return 0; 112 | } 113 | -------------------------------------------------------------------------------- /example/sample_new_features.cpp: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // sample_new_features.cpp : demonstrate features added to printf's syntax 3 | // ---------------------------------------------------------------------------- 4 | 5 | // Copyright Samuel Krempp 2003. Use, modification, and distribution are 6 | // subject to the Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | // See http://www.boost.org/libs/format for library home page 10 | 11 | // ---------------------------------------------------------------------------- 12 | 13 | #include 14 | #include 15 | 16 | #include "boost/format.hpp" 17 | 18 | int main(){ 19 | using namespace std; 20 | using boost::format; 21 | using boost::io::group; 22 | 23 | // ------------------------------------------------------------------------ 24 | // Simple style of reordering : 25 | cout << format("%1% %2% %3% %2% %1% \n") % "o" % "oo" % "O"; 26 | // prints "o oo O oo o \n" 27 | 28 | 29 | // ------------------------------------------------------------------------ 30 | // Centered alignment : flag '=' 31 | cout << format("_%|=6|_") % 1 << endl; 32 | // prints "_ 1 _" : 3 spaces are padded before, and 2 after. 33 | 34 | 35 | 36 | // ------------------------------------------------------------------------ 37 | // Tabulations : "%|Nt|" => tabulation of N spaces. 38 | // "%|NTf|" => tabulation of N times the character . 39 | // are useful when printing lines with several fields whose width can vary a lot 40 | // but we'd like to print some fields at the same place when possible : 41 | vector names(1, "Marc-François Michel"), 42 | surname(1,"Durand"), 43 | tel(1, "+33 (0) 123 456 789"); 44 | 45 | names.push_back("Jean"); 46 | surname.push_back("de Lattre de Tassigny"); 47 | tel.push_back("+33 (0) 987 654 321"); 48 | 49 | for(unsigned int i=0; i 15 | #include 16 | #include "boost/format.hpp" 17 | #include 18 | 19 | #if !(BOOST_WORKAROUND(__GNUC__, < 3) && defined(__STL_CONFIG_H) ) 20 | // not for broken gcc stdlib 21 | #include 22 | 23 | #else 24 | // not as complete, but compatible with gcc-2.95 : 25 | 26 | void copyfmt(ios& left, const ios& right) { 27 | left.fill(right.fill()); 28 | left.flags(right.flags() ); 29 | left.exceptions(right.exceptions()); 30 | left.width(right.width()); 31 | left.precision(right.precision()); 32 | } 33 | 34 | namespace boost { namespace io { 35 | class ios_all_saver { 36 | std::basic_ios ios_; 37 | std::ios & target_r; 38 | public: 39 | ios_all_saver(std::ios& right) : ios_(0), target_r(right) { 40 | copyfmt(ios_, right); 41 | } 42 | ~ios_all_saver() { 43 | copyfmt(target_r, ios_); 44 | } 45 | }; 46 | 47 | } } // N.S. boost::io 48 | 49 | 50 | // define showpos and noshowpos : 51 | class ShowPos { 52 | public: 53 | bool showpos_; 54 | ShowPos(bool v) : showpos_(v) {} 55 | }; 56 | std::ostream& operator<<(std::ostream& os, const ShowPos& x) { 57 | if(x.showpos_) 58 | os.setf(ios_base:: showpos); 59 | else 60 | os.unsetf(ios_base:: showpos); 61 | return os; 62 | } 63 | ShowPos noshowpos(false); 64 | ShowPos showpos(true); 65 | 66 | #endif // -end gcc-2.95 workarounds 67 | 68 | 69 | 70 | //---------------------------------------------------------------------------// 71 | // *** an exemple of UDT : a Rational class **** 72 | class Rational { 73 | public: 74 | Rational(int n, unsigned int d) : n_(n), d_(d) {} 75 | Rational(int n, int d); // convert denominator to unsigned 76 | friend std::ostream& operator<<(std::ostream&, const Rational&); 77 | private: 78 | int n_; // numerator 79 | unsigned int d_; // denominator 80 | }; 81 | 82 | Rational::Rational(int n, int d) : n_(n) 83 | { 84 | if(d < 0) { n_ = -n_; d=-d; } // make the denominator always non-negative. 85 | d_ = static_cast(d); 86 | } 87 | 88 | std::ostream& operator<<(std::ostream& os, const Rational& r) { 89 | using namespace std; 90 | streamsize n, s1, s2, s3; 91 | streamsize w = os.width(0); // width has to be zeroed before saving state. 92 | // boost::io::ios_all_saver bia_saver (os); 93 | 94 | boost::io::basic_oaltstringstream oss; 95 | oss.copyfmt(os ); 96 | oss << r.n_; 97 | s1 = oss.size(); 98 | oss << "/" << noshowpos; // a rational number needs only one sign ! 99 | s2 = oss.size(); 100 | oss << r.d_ ; 101 | s3 = oss.size(); 102 | 103 | n = w - s3; 104 | if(n <= 0) { 105 | os.write(oss.begin(), oss.size()); 106 | } 107 | else if(os.flags() & std::ios_base::internal) { 108 | std::streamsize n1 = w/2, n2 = w - n1, t; 109 | t = (s3-s1) - n2; // is 2d part '/nnn' bigger than 1/2 w ? 110 | if(t > 0) { 111 | n1 = w -(s3-s1); // put all paddings on first part. 112 | n2 = 0; // minimal width (s3-s2) 113 | } 114 | else { 115 | n2 -= s2-s1; // adjust for '/', n2 is still w/2. 116 | } 117 | os << setw(n1) << r.n_ << "/" << noshowpos << setw(n2) << r.d_; 118 | } 119 | else { 120 | if(! (os.flags() & std::ios_base::left)) { 121 | // -> right align. (right bit is set, or no bit is set) 122 | os << string(boost::numeric_cast(n), ' '); 123 | } 124 | os.write(oss.begin(), s3); 125 | if( os.flags() & std::ios_base::left ) { 126 | os << string(boost::numeric_cast(n), ' '); 127 | } 128 | } 129 | 130 | return os; 131 | } 132 | 133 | 134 | 135 | int main(){ 136 | using namespace std; 137 | using boost::format; 138 | using boost::io::group; 139 | using boost::io::str; 140 | string s; 141 | 142 | Rational r(16, 9); 143 | 144 | cout << "bonjour ! " << endl; 145 | // "bonjour !" 146 | 147 | cout << r << endl; 148 | // "16/9" 149 | 150 | cout << showpos << r << ", " << 5 << endl; 151 | // "+16/9, +5" 152 | 153 | cout << format("%02d : [%0+9d] \n") % 1 % r ; 154 | // "01 : [+016 / 0009]" 155 | 156 | cout << format("%02d : [%_+9d] \n") % 2 % Rational(9,160); 157 | // "02 : [+9 / 160]" 158 | 159 | cout << format("%02d : [%_+9d] \n") % 3 % r; 160 | // "03 : [+16 / 9]" 161 | 162 | cout << format("%02d : [%_9d] \n") % 4 % Rational(8,1234); 163 | // "04 : [8 / 1234]" 164 | 165 | cout << format("%02d : [%_9d] \n") % 5 % Rational(1234,8); 166 | // "05 : [1234 / 8]" 167 | 168 | cout << format("%02d : [%09d] \n") % 6 % Rational(8,1234); 169 | // "06 : [0008 / 1234]" 170 | 171 | cout << format("%02d : [%0+9d] \n") % 7 % Rational(1234,8); 172 | // "07 : [+1234 / 008]" 173 | 174 | cout << format("%02d : [%0+9d] \n") % 8 % Rational(7,12345); 175 | // "08 : [+07 / 12345]" 176 | 177 | 178 | cerr << "\n\nEverything went OK, exiting. \n"; 179 | return 0; 180 | } 181 | -------------------------------------------------------------------------------- /include/boost/format.hpp: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // format.hpp : primary header 3 | // ---------------------------------------------------------------------------- 4 | 5 | // Copyright Samuel Krempp 2003. Use, modification, and distribution are 6 | // subject to the Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | // See http://www.boost.org/libs/format for library home page 10 | 11 | 12 | // ---------------------------------------------------------------------------- 13 | 14 | #ifndef BOOST_FORMAT_HPP 15 | #define BOOST_FORMAT_HPP 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #ifndef BOOST_NO_STD_LOCALE 23 | #include 24 | #endif 25 | 26 | // *** Compatibility framework 27 | #include 28 | 29 | #ifdef BOOST_NO_LOCALE_ISDIGIT 30 | #include // we'll use the non-locale 's std::isdigit(int) 31 | #endif 32 | 33 | // **** Forward declarations ---------------------------------- 34 | #include // basic_format, and other frontends 35 | #include // misc forward declarations for internal use 36 | 37 | // **** Auxiliary structs (stream_format_state , and format_item ) 38 | #include 39 | 40 | // **** Format class interface -------------------------------- 41 | #include 42 | 43 | // **** Exceptions ----------------------------------------------- 44 | #include 45 | 46 | // **** Implementation ------------------------------------------- 47 | #include // member functions 48 | #include // class for grouping arguments 49 | #include // argument-feeding functions 50 | #include // format-string parsing (member-)functions 51 | 52 | // **** Implementation of the free functions ---------------------- 53 | #include 54 | 55 | 56 | // *** Undefine 'local' macros : 57 | #include 58 | 59 | #endif // BOOST_FORMAT_HPP 60 | -------------------------------------------------------------------------------- /include/boost/format/alt_sstream.hpp: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // alt_sstream.hpp : alternative stringstream 3 | // ---------------------------------------------------------------------------- 4 | 5 | // Copyright Samuel Krempp 2003. Use, modification, and distribution are 6 | // subject to the Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | // See http://www.boost.org/libs/format for library home page 10 | 11 | // ---------------------------------------------------------------------------- 12 | 13 | 14 | 15 | #ifndef BOOST_SK_ALT_SSTREAM_HPP 16 | #define BOOST_SK_ALT_SSTREAM_HPP 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | namespace boost { 27 | namespace io { 28 | 29 | template, 30 | class Alloc=::std::allocator > 31 | class basic_altstringbuf; 32 | 33 | template, 34 | class Alloc=::std::allocator > 35 | class basic_oaltstringstream; 36 | 37 | 38 | template 39 | class basic_altstringbuf 40 | : public ::std::basic_streambuf 41 | { 42 | typedef ::std::basic_streambuf streambuf_t; 43 | typedef typename CompatAlloc::compatible_type compat_allocator_type; 44 | typedef typename CompatTraits::compatible_type compat_traits_type; 45 | public: 46 | typedef Ch char_type; 47 | typedef Tr traits_type; 48 | typedef typename compat_traits_type::int_type int_type; 49 | typedef typename compat_traits_type::pos_type pos_type; 50 | typedef typename compat_traits_type::off_type off_type; 51 | typedef Alloc allocator_type; 52 | typedef ::std::basic_string string_type; 53 | typedef typename string_type::size_type size_type; 54 | 55 | typedef ::std::streamsize streamsize; 56 | 57 | 58 | explicit basic_altstringbuf(std::ios_base::openmode mode 59 | = std::ios_base::in | std::ios_base::out) 60 | : putend_(NULL), is_allocated_(false), mode_(mode) 61 | {} 62 | explicit basic_altstringbuf(const string_type& s, 63 | ::std::ios_base::openmode mode 64 | = ::std::ios_base::in | ::std::ios_base::out) 65 | : putend_(NULL), is_allocated_(false), mode_(mode) 66 | { dealloc(); str(s); } 67 | virtual ~basic_altstringbuf() BOOST_NOEXCEPT_OR_NOTHROW 68 | { dealloc(); } 69 | using streambuf_t::pbase; 70 | using streambuf_t::pptr; 71 | using streambuf_t::epptr; 72 | using streambuf_t::eback; 73 | using streambuf_t::gptr; 74 | using streambuf_t::egptr; 75 | 76 | void clear_buffer(); 77 | void str(const string_type& s); 78 | 79 | // 0-copy access : 80 | Ch * begin() const; 81 | size_type size() const; 82 | size_type cur_size() const; // stop at current pointer 83 | Ch * pend() const // the highest position reached by pptr() since creation 84 | { return ((putend_ < pptr()) ? pptr() : putend_); } 85 | size_type pcount() const 86 | { return static_cast( pptr() - pbase()) ;} 87 | 88 | // copy buffer to string : 89 | string_type str() const 90 | { return string_type(begin(), size()); } 91 | string_type cur_str() const 92 | { return string_type(begin(), cur_size()); } 93 | protected: 94 | explicit basic_altstringbuf (basic_altstringbuf * s, 95 | ::std::ios_base::openmode mode 96 | = ::std::ios_base::in | ::std::ios_base::out) 97 | : putend_(NULL), is_allocated_(false), mode_(mode) 98 | { dealloc(); str(s); } 99 | 100 | virtual pos_type seekoff(off_type off, ::std::ios_base::seekdir way, 101 | ::std::ios_base::openmode which 102 | = ::std::ios_base::in | ::std::ios_base::out); 103 | virtual pos_type seekpos (pos_type pos, 104 | ::std::ios_base::openmode which 105 | = ::std::ios_base::in | ::std::ios_base::out); 106 | virtual int_type underflow(); 107 | virtual int_type pbackfail(int_type meta = compat_traits_type::eof()); 108 | virtual int_type overflow(int_type meta = compat_traits_type::eof()); 109 | void dealloc(); 110 | private: 111 | enum { alloc_min = 256}; // minimum size of allocations 112 | 113 | Ch *putend_; // remembers (over seeks) the highest value of pptr() 114 | bool is_allocated_; 115 | ::std::ios_base::openmode mode_; 116 | compat_allocator_type alloc_; // the allocator object 117 | }; 118 | 119 | 120 | // --- class basic_oaltstringstream ---------------------------------------- 121 | template 122 | class basic_oaltstringstream 123 | : private base_from_member< shared_ptr< basic_altstringbuf< Ch, Tr, Alloc> > >, 124 | public ::std::basic_ostream 125 | { 126 | class No_Op { 127 | // used as no-op deleter for (not-owner) shared_pointers 128 | public: 129 | template 130 | const T & operator()(const T & arg) { return arg; } 131 | }; 132 | typedef ::std::basic_ostream stream_t; 133 | typedef boost::base_from_member > > 135 | pbase_type; 136 | typedef ::std::basic_string string_type; 137 | typedef typename string_type::size_type size_type; 138 | typedef basic_altstringbuf stringbuf_t; 139 | public: 140 | typedef Alloc allocator_type; 141 | basic_oaltstringstream() 142 | : pbase_type(new stringbuf_t), stream_t(pbase_type::member.get()) 143 | { } 144 | basic_oaltstringstream(::boost::shared_ptr buf) 145 | : pbase_type(buf), stream_t(pbase_type::member.get()) 146 | { } 147 | basic_oaltstringstream(stringbuf_t * buf) 148 | : pbase_type(buf, No_Op() ), stream_t(pbase_type::member.get()) 149 | { } 150 | stringbuf_t * rdbuf() const 151 | { return pbase_type::member.get(); } 152 | void clear_buffer() 153 | { rdbuf()->clear_buffer(); } 154 | 155 | // 0-copy access : 156 | Ch * begin() const 157 | { return rdbuf()->begin(); } 158 | size_type size() const 159 | { return rdbuf()->size(); } 160 | size_type cur_size() const // stops at current position 161 | { return rdbuf()->cur_size(); } 162 | 163 | // copy buffer to string : 164 | string_type str() const // [pbase, epptr[ 165 | { return rdbuf()->str(); } 166 | string_type cur_str() const // [pbase, pptr[ 167 | { return rdbuf()->cur_str(); } 168 | void str(const string_type& s) 169 | { rdbuf()->str(s); } 170 | }; 171 | 172 | } // N.S. io 173 | } // N.S. boost 174 | 175 | #include 176 | 177 | #endif // include guard 178 | 179 | -------------------------------------------------------------------------------- /include/boost/format/alt_sstream_impl.hpp: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // alt_sstream_impl.hpp : alternative stringstream, templates implementation 3 | // ---------------------------------------------------------------------------- 4 | 5 | // Copyright Samuel Krempp 2003. Use, modification, and distribution are 6 | // subject to the Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | // See http://www.boost.org/libs/format for library home page 10 | 11 | // ---------------------------------------------------------------------------- 12 | 13 | #ifndef BOOST_SK_ALT_SSTREAM_IMPL_HPP 14 | #define BOOST_SK_ALT_SSTREAM_IMPL_HPP 15 | 16 | namespace boost { 17 | namespace io { 18 | // --- Implementation ------------------------------------------------------// 19 | 20 | template 21 | void basic_altstringbuf:: 22 | clear_buffer () { 23 | const Ch * p = pptr(); 24 | const Ch * b = pbase(); 25 | if(p != NULL && p != b) { 26 | seekpos(0, ::std::ios_base::out); 27 | } 28 | p = gptr(); 29 | b = eback(); 30 | if(p != NULL && p != b) { 31 | seekpos(0, ::std::ios_base::in); 32 | } 33 | } 34 | 35 | template 36 | void basic_altstringbuf:: 37 | str (const string_type& s) { 38 | size_type sz=s.size(); 39 | if(sz != 0 && mode_ & (::std::ios_base::in | ::std::ios_base::out) ) { 40 | #ifdef _RWSTD_NO_CLASS_PARTIAL_SPEC 41 | void *vd_ptr = boost::allocator_allocate(alloc_, sz, is_allocated_? eback() : 0); 42 | Ch *new_ptr = static_cast(vd_ptr); 43 | #else 44 | Ch *new_ptr = boost::allocator_allocate(alloc_, sz, is_allocated_? eback() : 0); 45 | #endif 46 | // if this didnt throw, we're safe, update the buffer 47 | dealloc(); 48 | sz = s.copy(new_ptr, sz); 49 | putend_ = new_ptr + sz; 50 | if(mode_ & ::std::ios_base::in) 51 | streambuf_t::setg(new_ptr, new_ptr, new_ptr + sz); 52 | if(mode_ & ::std::ios_base::out) { 53 | streambuf_t::setp(new_ptr, new_ptr + sz); 54 | if(mode_ & (::std::ios_base::app | ::std::ios_base::ate)) 55 | streambuf_t::pbump(static_cast(sz)); 56 | if(gptr() == NULL) 57 | streambuf_t::setg(new_ptr, NULL, new_ptr); 58 | } 59 | is_allocated_ = true; 60 | } 61 | else 62 | dealloc(); 63 | } 64 | template 65 | Ch* basic_altstringbuf:: 66 | begin () const { 67 | if(mode_ & ::std::ios_base::out && pptr() != NULL) 68 | return pbase(); 69 | else if(mode_ & ::std::ios_base::in && gptr() != NULL) 70 | return eback(); 71 | return NULL; 72 | } 73 | 74 | template 75 | typename std::basic_string::size_type 76 | basic_altstringbuf:: 77 | size () const { 78 | if(mode_ & ::std::ios_base::out && pptr()) 79 | return static_cast(pend() - pbase()); 80 | else if(mode_ & ::std::ios_base::in && gptr()) 81 | return static_cast(egptr() - eback()); 82 | else 83 | return 0; 84 | } 85 | 86 | template 87 | typename std::basic_string::size_type 88 | basic_altstringbuf:: 89 | cur_size () const { 90 | if(mode_ & ::std::ios_base::out && pptr()) 91 | return static_cast( pptr() - pbase()); 92 | else if(mode_ & ::std::ios_base::in && gptr()) 93 | return static_cast( gptr() - eback()); 94 | else 95 | return 0; 96 | } 97 | 98 | template 99 | typename basic_altstringbuf::pos_type 100 | basic_altstringbuf:: 101 | seekoff (off_type off, ::std::ios_base::seekdir way, ::std::ios_base::openmode which) { 102 | if(pptr() != NULL && putend_ < pptr()) 103 | putend_ = pptr(); 104 | if(which & ::std::ios_base::in && gptr() != NULL) { 105 | // get area 106 | if(way == ::std::ios_base::end) 107 | off += static_cast(putend_ - gptr()); 108 | else if(way == ::std::ios_base::beg) 109 | off += static_cast(eback() - gptr()); 110 | else if(way != ::std::ios_base::cur || (which & ::std::ios_base::out) ) 111 | // (altering in&out is only supported if way is beg or end, not cur) 112 | return pos_type(off_type(-1)); 113 | if(eback() <= off+gptr() && off+gptr() <= putend_ ) { 114 | // set gptr 115 | streambuf_t::gbump(static_cast(off)); 116 | if(which & ::std::ios_base::out && pptr() != NULL) 117 | // update pptr to match gptr 118 | streambuf_t::pbump(static_cast(gptr()-pptr())); 119 | } 120 | else 121 | off = off_type(-1); 122 | } 123 | else if(which & ::std::ios_base::out && pptr() != NULL) { 124 | // put area 125 | if(way == ::std::ios_base::end) 126 | off += static_cast(putend_ - pptr()); 127 | else if(way == ::std::ios_base::beg) 128 | off += static_cast(pbase() - pptr()); 129 | else 130 | return pos_type(off_type(-1)); 131 | if(pbase() <= off+pptr() && off+pptr() <= putend_) 132 | // set pptr 133 | streambuf_t::pbump(static_cast(off)); 134 | else 135 | off = off_type(-1); 136 | } 137 | else // neither in nor out 138 | off = off_type(-1); 139 | return (pos_type(off)); 140 | } 141 | //- end seekoff(..) 142 | 143 | 144 | template 145 | typename basic_altstringbuf::pos_type 146 | basic_altstringbuf:: 147 | seekpos (pos_type pos, ::std::ios_base::openmode which) { 148 | off_type off = off_type(pos); // operation guaranteed by fpos.operations table 127 149 | if(pptr() != NULL && putend_ < pptr()) 150 | putend_ = pptr(); 151 | if(off != off_type(-1)) { 152 | if(which & ::std::ios_base::in && gptr() != NULL) { 153 | // get area 154 | if(0 <= off && off <= putend_ - eback()) { 155 | streambuf_t::gbump(static_cast(eback() - gptr() + off)); 156 | if(which & ::std::ios_base::out && pptr() != NULL) { 157 | // update pptr to match gptr 158 | streambuf_t::pbump(static_cast(gptr()-pptr())); 159 | } 160 | } 161 | else 162 | off = off_type(-1); 163 | } 164 | else if(which & ::std::ios_base::out && pptr() != NULL) { 165 | // put area 166 | if(0 <= off && off <= putend_ - eback()) 167 | streambuf_t::pbump(static_cast(eback() - pptr() + off)); 168 | else 169 | off = off_type(-1); 170 | } 171 | else // neither in nor out 172 | off = off_type(-1); 173 | return (pos_type(off)); 174 | } 175 | else { 176 | BOOST_ASSERT(0); // fpos.operations allows undefined-behaviour here 177 | return pos_type(off_type(-1)); 178 | } 179 | } 180 | // -end seekpos(..) 181 | 182 | 183 | template 184 | typename basic_altstringbuf::int_type 185 | basic_altstringbuf:: 186 | underflow () { 187 | if(gptr() == NULL) // no get area -> nothing to get. 188 | return (compat_traits_type::eof()); 189 | else if(gptr() < egptr()) // ok, in buffer 190 | return (compat_traits_type::to_int_type(*gptr())); 191 | else if(mode_ & ::std::ios_base::in && pptr() != NULL 192 | && (gptr() < pptr() || gptr() < putend_) ) 193 | { // expand get area 194 | if(putend_ < pptr()) 195 | putend_ = pptr(); // remember pptr reached this far 196 | streambuf_t::setg(eback(), gptr(), putend_); 197 | return (compat_traits_type::to_int_type(*gptr())); 198 | } 199 | else // couldnt get anything. EOF. 200 | return (compat_traits_type::eof()); 201 | } 202 | // -end underflow(..) 203 | 204 | 205 | template 206 | typename basic_altstringbuf::int_type 207 | basic_altstringbuf:: 208 | pbackfail (int_type meta) { 209 | if(gptr() != NULL && (eback() < gptr()) 210 | && (mode_ & (::std::ios_base::out) 211 | || compat_traits_type::eq_int_type(compat_traits_type::eof(), meta) 212 | || compat_traits_type::eq(compat_traits_type::to_char_type(meta), gptr()[-1]) ) ) { 213 | streambuf_t::gbump(-1); // back one character 214 | if(!compat_traits_type::eq_int_type(compat_traits_type::eof(), meta)) 215 | // put-back meta into get area 216 | *gptr() = compat_traits_type::to_char_type(meta); 217 | return (compat_traits_type::not_eof(meta)); 218 | } 219 | else 220 | return (compat_traits_type::eof()); // failed putback 221 | } 222 | // -end pbackfail(..) 223 | 224 | 225 | template 226 | typename basic_altstringbuf::int_type 227 | basic_altstringbuf:: 228 | overflow (int_type meta) { 229 | #ifdef BOOST_MSVC 230 | #pragma warning(push) 231 | #pragma warning(disable:4996) 232 | #endif 233 | if(compat_traits_type::eq_int_type(compat_traits_type::eof(), meta)) 234 | return compat_traits_type::not_eof(meta); // nothing to do 235 | else if(pptr() != NULL && pptr() < epptr()) { 236 | streambuf_t::sputc(compat_traits_type::to_char_type(meta)); 237 | return meta; 238 | } 239 | else if(! (mode_ & ::std::ios_base::out)) 240 | // no write position, and cant make one 241 | return compat_traits_type::eof(); 242 | else { // make a write position available 243 | std::size_t prev_size = pptr() == NULL ? 0 : epptr() - eback(); 244 | std::size_t new_size = prev_size; 245 | // exponential growth : size *= 1.5 246 | std::size_t add_size = new_size / 2; 247 | if(add_size < alloc_min) 248 | add_size = alloc_min; 249 | Ch * newptr = NULL, *oldptr = eback(); 250 | 251 | // make sure adding add_size wont overflow size_t 252 | while (0 < add_size && ((std::numeric_limits::max)() 253 | - add_size < new_size) ) 254 | add_size /= 2; 255 | if(0 < add_size) { 256 | new_size += add_size; 257 | #ifdef _RWSTD_NO_CLASS_PARTIAL_SPEC 258 | void *vdptr = boost::allocator_allocate(alloc_, new_size, is_allocated_? oldptr : 0); 259 | newptr = static_cast(vdptr); 260 | #else 261 | newptr = boost::allocator_allocate(alloc_, new_size, is_allocated_? oldptr : 0); 262 | #endif 263 | } 264 | 265 | if(0 < prev_size) 266 | compat_traits_type::copy(newptr, oldptr, prev_size); 267 | if(is_allocated_) 268 | alloc_.deallocate(oldptr, prev_size); 269 | is_allocated_=true; 270 | 271 | if(prev_size == 0) { // first allocation 272 | putend_ = newptr; 273 | streambuf_t::setp(newptr, newptr + new_size); 274 | if(mode_ & ::std::ios_base::in) 275 | streambuf_t::setg(newptr, newptr, newptr + 1); 276 | else 277 | streambuf_t::setg(newptr, 0, newptr); 278 | } 279 | else { // update pointers 280 | putend_ = putend_ - oldptr + newptr; 281 | int pptr_count = static_cast(pptr()-pbase()); 282 | int gptr_count = static_cast(gptr()-eback()); 283 | streambuf_t::setp(pbase() - oldptr + newptr, newptr + new_size); 284 | streambuf_t::pbump(pptr_count); 285 | if(mode_ & ::std::ios_base::in) 286 | streambuf_t::setg(newptr, newptr + gptr_count, pptr() + 1); 287 | else 288 | streambuf_t::setg(newptr, 0, newptr); 289 | } 290 | streambuf_t::sputc(compat_traits_type::to_char_type(meta)); 291 | return meta; 292 | } 293 | #ifdef BOOST_MSVC 294 | #pragma warning(pop) 295 | #endif 296 | } 297 | // -end overflow(..) 298 | 299 | template 300 | void basic_altstringbuf:: dealloc() { 301 | if(is_allocated_) 302 | alloc_.deallocate(eback(), (pptr() != NULL ? epptr() : egptr()) - eback()); 303 | is_allocated_ = false; 304 | streambuf_t::setg(0, 0, 0); 305 | streambuf_t::setp(0, 0); 306 | putend_ = NULL; 307 | } 308 | 309 | }// N.S. io 310 | } // N.S. boost 311 | 312 | #endif // include guard 313 | 314 | -------------------------------------------------------------------------------- /include/boost/format/detail/compat_workarounds.hpp: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // compat_workarounds : general framework for non-conformance workarounds 3 | // ---------------------------------------------------------------------------- 4 | 5 | // Copyright Samuel Krempp 2003. Use, modification, and distribution are 6 | // subject to the Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | // see http://www.boost.org/libs/format for library home page 10 | 11 | // ---------------------------------------------------------------------------- 12 | 13 | 14 | // this file defines wrapper classes to hide non-conforming 15 | // std::char_traits<> and std::allocator<> traits 16 | // and Includes : config_macros.hpp (defines config macros 17 | // and compiler-specific switches) 18 | 19 | // Non-conformant Std-libs fail to supply conformant traits (std::char_traits, 20 | // std::allocator) and/or the std::string doesnt support them. 21 | // We don't want to have hundreds of #ifdef workarounds, so we define 22 | // replacement traits. 23 | // But both char_traits and allocator traits are visible in the interface, 24 | // (inside the final string type), thus we need to keep both 25 | // the replacement type (typedefed to 'compatible_type') for real use, 26 | // and the original stdlib type (typedef to 'type_for_string') for interface 27 | // visibility. This is what Compat* classes do (as well as be transparent 28 | // when good allocator and char traits are present) 29 | 30 | #ifndef BOOST_FORMAT_COMPAT_WORKAROUNDS_HPP 31 | #define BOOST_FORMAT_COMPAT_WORKAROUNDS_HPP 32 | 33 | namespace boost { 34 | namespace io { 35 | 36 | // gcc-2.95 char traits (non-conformantly named string_char_traits) 37 | // lack several functions so we extend them in a replacement class. 38 | template 39 | class CompatTraits; 40 | 41 | // std::allocator in gcc-2.95 is ok, but basic_string only works 42 | // with plain 'std::alloc' still, alt_stringbuf requires a functionnal 43 | // alloc template argument, so we need a replacement allocator 44 | template 45 | class CompatAlloc; 46 | } // N.S. io 47 | }// N.S. boost 48 | 49 | 50 | #include 51 | // sets-up macros and load compiler-specific workarounds headers. 52 | 53 | #if !defined(BOOST_FORMAT_STREAMBUF_DEFINED) 54 | // workarounds-gcc-2.95 might have defined own streambuf 55 | #include 56 | #endif 57 | 58 | #if !defined(BOOST_FORMAT_OSTREAM_DEFINED) 59 | // workarounds-gcc-2.95 might already have included 60 | #include 61 | #endif 62 | 63 | 64 | 65 | namespace boost { 66 | namespace io { 67 | 68 | // **** CompatTraits general definitions : ---------------------------- 69 | template 70 | class CompatTraits 71 | { // general case : be transparent 72 | public: 73 | typedef Tr compatible_type; 74 | }; 75 | 76 | // **** CompatAlloc general definitions : ----------------------------- 77 | template 78 | class CompatAlloc 79 | { // general case : be transparent 80 | public: 81 | typedef Alloc compatible_type; 82 | }; 83 | 84 | } //N.S. io 85 | } // N.S. boost 86 | #endif // include guard 87 | -------------------------------------------------------------------------------- /include/boost/format/detail/config_macros.hpp: -------------------------------------------------------------------------------- 1 | // -*- C++ -*- 2 | // ---------------------------------------------------------------------------- 3 | // config_macros.hpp : configuration macros for the format library 4 | // only BOOST_IO_STD is absolutely needed (it should be 'std::' in general) 5 | // others are compiler-specific workaround macros used in #ifdef switches 6 | // ---------------------------------------------------------------------------- 7 | 8 | // Copyright Samuel Krempp 2003. Use, modification, and distribution are 9 | // subject to the Boost Software License, Version 1.0. (See accompanying 10 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 11 | 12 | // see http://www.boost.org/libs/format for library home page 13 | 14 | 15 | // ---------------------------------------------------------------------------- 16 | 17 | #ifndef BOOST_FORMAT_CONFIG_MACROS_HPP 18 | #define BOOST_FORMAT_CONFIG_MACROS_HPP 19 | 20 | #include 21 | #include 22 | 23 | // make sure our local macros wont override something : 24 | #if defined(BOOST_NO_LOCALE_ISDIGIT) || defined(BOOST_OVERLOAD_FOR_NON_CONST) \ 25 | || defined(BOOST_IO_STD) || defined( BOOST_IO_NEEDS_USING_DECLARATION ) \ 26 | || defined(BOOST_NO_TEMPLATE_STD_STREAM) \ 27 | || defined(BOOST_FORMAT_STREAMBUF_DEFINED) || defined(BOOST_FORMAT_OSTREAM_DEFINED) 28 | #error "boost::format uses a local macro that is already defined." 29 | #endif 30 | 31 | // specific workarounds. each header can define BOOS_IO_STD if it 32 | // needs. (e.g. because of IO_NEEDS_USING_DECLARATION) 33 | #include 34 | #include 35 | 36 | #ifndef BOOST_IO_STD 37 | # define BOOST_IO_STD ::std:: 38 | #endif 39 | 40 | #if defined(BOOST_NO_STD_LOCALE) || \ 41 | ( BOOST_WORKAROUND(BOOST_BORLANDC, <= 0x564) \ 42 | || BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT( 0x570 ) ) ) 43 | // some future BOOST_BORLANDC >0x564 versions might not need this 44 | // 0x570 is Borland's kylix branch 45 | #define BOOST_NO_LOCALE_ISDIGIT 46 | #endif 47 | 48 | #if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x570) ) || BOOST_WORKAROUND( BOOST_MSVC, BOOST_TESTED_AT(1300)) 49 | #define BOOST_NO_OVERLOAD_FOR_NON_CONST 50 | #endif 51 | 52 | // **** Workaround for io streams, stlport and msvc. 53 | #ifdef BOOST_IO_NEEDS_USING_DECLARATION 54 | namespace boost { 55 | using std::char_traits; 56 | using std::basic_ostream; 57 | namespace io { 58 | using std::basic_ostream; 59 | namespace detail { 60 | using std::basic_ios; 61 | using std::basic_ostream; 62 | } 63 | } 64 | #if ! defined(BOOST_NO_STD_LOCALE) 65 | using std::locale; 66 | namespace io { 67 | using std::locale; 68 | namespace detail { 69 | using std::locale; 70 | } 71 | } 72 | #endif // locale 73 | } 74 | // -end N.S. boost 75 | #endif // needs_using_declaration 76 | 77 | #if ! defined(BOOST_NO_STD_LOCALE) 78 | #include 79 | #endif 80 | 81 | 82 | // *** hide std::locale if it doesnt exist. 83 | // this typedef is either std::locale or int, avoids placing ifdefs everywhere 84 | namespace boost { namespace io { namespace detail { 85 | #if ! defined(BOOST_NO_STD_LOCALE) 86 | typedef BOOST_IO_STD locale locale_t; 87 | #else 88 | typedef int locale_t; 89 | #endif 90 | } } } 91 | 92 | 93 | // ---------------------------------------------------------------------------- 94 | 95 | #endif // BOOST_FORMAT_MACROS_DEFAULT_HPP 96 | -------------------------------------------------------------------------------- /include/boost/format/detail/msvc_disambiguater.hpp: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // msvc_disambiguater.hpp : msvc workarounds. (for put_{head|last} overloads) 3 | // the trick was described in boost's list by Aleksey Gurtovoy 4 | // ---------------------------------------------------------------------------- 5 | 6 | // Copyright Samuel Krempp 2003. Use, modification, and distribution are 7 | // subject to the Boost Software License, Version 1.0. (See accompanying 8 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 | 10 | // see http://www.boost.org/libs/format for library home page 11 | 12 | // ---------------------------------------------------------------------------- 13 | 14 | #ifndef BOOST_MSVC_DISAMBIGUATER_HPP 15 | #define BOOST_MSVC_DISAMBIGUATER_HPP 16 | 17 | #if BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590042)) 18 | 19 | #include 20 | #include 21 | 22 | namespace boost { 23 | namespace io { 24 | namespace detail { 25 | 26 | template< class Ch, class Tr, class T > 27 | struct disambiguater 28 | { 29 | template< typename U > 30 | static void put_head(BOOST_IO_STD basic_ostream& os, group1 const& x, long) 31 | { 32 | os << group_head(x.a1_); 33 | } 34 | static void put_head(BOOST_IO_STD basic_ostream& os, T const& x, int) 35 | { 36 | } 37 | template< typename U > 38 | static void put_last(BOOST_IO_STD basic_ostream& os, group1 const& x, long) 39 | { 40 | os << group_last(x.a1_); 41 | } 42 | static void put_last(BOOST_IO_STD basic_ostream& os, T const& x, int) 43 | { 44 | os << x; 45 | } 46 | }; 47 | 48 | } // namespace detail 49 | } // namespace io 50 | } // namespace boost 51 | 52 | #endif // -__DECCXX_VER 53 | 54 | #endif // -BOOST_MSVC_DISAMBIGUATER_HPP 55 | -------------------------------------------------------------------------------- /include/boost/format/detail/unset_macros.hpp: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // unset_macros.hpp 3 | // ---------------------------------------------------------------------------- 4 | 5 | // Copyright Samuel Krempp 2003. Use, modification, and distribution are 6 | // subject to the Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | // See http://www.boost.org/libs/format for library home page 10 | 11 | // ---------------------------------------------------------------------------- 12 | 13 | // *** Undefine 'local' macros : 14 | #ifdef BOOST_NO_OVERLOAD_FOR_NON_CONST 15 | #undef BOOST_NO_OVERLOAD_FOR_NON_CONST 16 | #endif 17 | #ifdef BOOST_NO_LOCALE_ISDIGIT 18 | #undef BOOST_NO_LOCALE_ISDIGIT 19 | #endif 20 | #ifdef BOOST_IO_STD 21 | #undef BOOST_IO_STD 22 | #endif 23 | #ifdef BOOST_IO_NEEDS_USING_DECLARATION 24 | #undef BOOST_IO_NEEDS_USING_DECLARATION 25 | #endif 26 | #ifdef BOOST_NO_TEMPLATE_STD_STREAM 27 | #undef BOOST_NO_TEMPLATE_STD_STREAM 28 | #endif 29 | #ifdef BOOST_FORMAT_STREAMBUF_DEFINED 30 | #undef BOOST_FORMAT_STREAMBUF_DEFINED 31 | #endif 32 | #ifdef BOOST_FORMAT_OSTREAM_DEFINED 33 | #undef BOOST_FORMAT_OSTREAM_DEFINED 34 | #endif 35 | -------------------------------------------------------------------------------- /include/boost/format/detail/workarounds_gcc-2_95.hpp: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // workarounds for gcc < 3.0. 3 | // ---------------------------------------------------------------------------- 4 | 5 | // Copyright Samuel Krempp 2003. Use, modification, and distribution are 6 | // subject to the Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | // See http://www.boost.org/libs/format for library home page 10 | 11 | 12 | // ---------------------------------------------------------------------------- 13 | 14 | // There's a lot to do, the stdlib shipped with gcc prior to 3.x 15 | // was terribly non-conforming. 16 | // . defines macros switches 17 | // . supplies template classes basic_foo where gcc only supplies foo. 18 | // i.e : 19 | // - basic_ios from ios 20 | // - basic_ostream from ostream 21 | // - basic_srteambuf from streambuf 22 | // these can be used transparently. (it obviously does not work for wchar_t) 23 | // . specialise CompatAlloc and CompatTraits to wrap gcc-2.95's 24 | // string_char_traits and std::alloc 25 | 26 | #if BOOST_WORKAROUND(__GNUC__, < 3) && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION) 27 | // only for gcc-2.95's native stdlib 28 | 29 | #ifndef BOOST_FORMAT_WORKAROUNDS_GCC295_H 30 | #define BOOST_FORMAT_WORKAROUNDS_GCC295_H 31 | 32 | // SGI STL doesnt have and others, so we need iostream. 33 | #include 34 | #define BOOST_FORMAT_OSTREAM_DEFINED 35 | 36 | #include 37 | #define BOOST_FORMAT_STREAMBUF_DEFINED 38 | 39 | #define BOOST_NO_TEMPLATE_STD_STREAM 40 | 41 | #ifndef BOOST_IO_STD 42 | # define BOOST_IO_STD std:: 43 | #endif 44 | 45 | 46 | 47 | // *** 48 | // gcc's simple classes turned into standard-like template classes : 49 | 50 | namespace std { 51 | 52 | 53 | // gcc has string_char_traits, it's incomplete. 54 | // we declare a std::char_traits, and specialize CompatTraits<..> on it 55 | // to do what is required 56 | template 57 | class char_traits; // no definition here, we will just use it as a tag. 58 | 59 | template 60 | class basic_streambuf; 61 | 62 | template 63 | class basic_streambuf : public streambuf { 64 | }; 65 | 66 | template > 67 | class basic_ios; 68 | 69 | template 70 | class basic_ios : public ostream { 71 | public: 72 | basic_ios(streambuf * p) : ostream(p) {}; 73 | char fill() const { return ios::fill(); } // gcc returns wchar.. 74 | char fill(char c) { return ios::fill(c); } // gcc takes wchar.. 75 | char widen(char c) { return c; } 76 | char narrow(char c, char def) { return c; } 77 | basic_ios& copyfmt(const ios& right) { 78 | fill(right.fill()); 79 | flags(right.flags() ); 80 | exceptions(right.exceptions()); 81 | width(right.width()); 82 | precision(right.precision()); 83 | return *this; 84 | } 85 | }; 86 | 87 | 88 | typedef ios ios_base; 89 | 90 | template 91 | class basic_ostream; 92 | 93 | template 94 | class basic_ostream : public basic_ios 95 | { 96 | public: 97 | basic_ostream(streambuf * p) : basic_ios (p) {} 98 | }; 99 | 100 | } // namespace std 101 | 102 | 103 | namespace boost { 104 | namespace io { 105 | 106 | 107 | // ** CompatTraits gcc2.95 specialisations ---------------------------- 108 | template 109 | class CompatTraits< ::std::string_char_traits > 110 | : public ::std::string_char_traits 111 | { 112 | public: 113 | typedef CompatTraits compatible_type; 114 | 115 | typedef Ch char_type; 116 | typedef int int_type; 117 | typedef ::std::streampos pos_type; 118 | typedef ::std::streamoff off_type; 119 | 120 | static char_type 121 | to_char_type(const int_type& meta) { 122 | return static_cast(meta); } 123 | static int_type 124 | to_int_type(const char_type& ch) { 125 | return static_cast(static_cast(ch) );} 126 | static bool 127 | eq_int_type(const int_type& left, const int_type& right) { 128 | return left == right; } 129 | static int_type 130 | eof() { 131 | return static_cast(EOF); 132 | } 133 | static int_type 134 | not_eof(const int_type& meta) { 135 | return (meta == eof()) ? 0 : meta; 136 | } 137 | }; 138 | 139 | template 140 | class CompatTraits< ::std::char_traits > { 141 | public: 142 | typedef CompatTraits< ::std::string_char_traits > compatible_type; 143 | }; 144 | 145 | // ** CompatAlloc gcc-2.95 specialisations --------------------------- 146 | template<> 147 | class CompatAlloc< ::std::alloc> 148 | { 149 | public: 150 | typedef ::std::allocator compatible_type; 151 | }; 152 | 153 | } // N.S. io 154 | } // N.S. boost 155 | 156 | 157 | 158 | 159 | 160 | #endif // include guard 161 | 162 | #endif // if workaround 163 | -------------------------------------------------------------------------------- /include/boost/format/detail/workarounds_stlport.hpp: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // workarounds_stlport.hpp : workaround STLport issues 3 | // ---------------------------------------------------------------------------- 4 | 5 | // Copyright Samuel Krempp 2003. Use, modification, and distribution are 6 | // subject to the Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | // see http://www.boost.org/libs/format for library home page 10 | 11 | // ---------------------------------------------------------------------------- 12 | 13 | #ifndef BOOST_MACROS_STLPORT_HPP 14 | #define BOOST_MACROS_STLPORT_HPP 15 | 16 | // *** This should go to "boost/config/stdlib/stlport.hpp". 17 | 18 | // If the streams are not native and there are problems with using templates 19 | // accross namespaces, we define some macros to enable a workaround for this. 20 | 21 | // STLport 4.5 22 | #if !defined(_STLP_OWN_IOSTREAMS) && defined(_STLP_USE_NAMESPACES) && defined(BOOST_NO_USING_TEMPLATE) 23 | # define BOOST_IO_STD 24 | # define BOOST_IO_NEEDS_USING_DECLARATION 25 | #endif 26 | 27 | // STLport 4.0 28 | #if !defined(__SGI_STL_OWN_IOSTREAMS) && defined(__STL_USE_OWN_NAMESPACE) && defined(BOOST_NO_USING_TEMPLATE) 29 | # define BOOST_IO_STD 30 | # define BOOST_IO_NEEDS_USING_DECLARATION 31 | #endif 32 | 33 | 34 | // ---------------------------------------------------------------------------- 35 | 36 | #endif // BOOST_MACROS_STLPORT_HPP 37 | -------------------------------------------------------------------------------- /include/boost/format/exceptions.hpp: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // boost/format/exceptions.hpp 3 | // ---------------------------------------------------------------------------- 4 | 5 | // Copyright Samuel Krempp 2003. 6 | // 7 | // Distributed under the Boost Software License, Version 1.0. 8 | // (See accompanying file LICENSE_1_0.txt or copy at 9 | // http://www.boost.org/LICENSE_1_0.txt) 10 | // 11 | // 12 | // See http://www.boost.org/libs/format/ for library home page 13 | 14 | // ---------------------------------------------------------------------------- 15 | 16 | #ifndef BOOST_FORMAT_EXCEPTIONS_HPP 17 | #define BOOST_FORMAT_EXCEPTIONS_HPP 18 | 19 | 20 | #include 21 | #include 22 | 23 | 24 | namespace boost { 25 | 26 | namespace io { 27 | 28 | // **** exceptions ----------------------------------------------- 29 | 30 | class format_error : public std::exception 31 | { 32 | public: 33 | format_error() {} 34 | virtual const char *what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE { 35 | return "boost::format_error: " 36 | "format generic failure"; 37 | } 38 | }; 39 | 40 | class bad_format_string : public format_error 41 | { 42 | std::size_t pos_, next_; 43 | public: 44 | bad_format_string(std::size_t pos, std::size_t size) 45 | : pos_(pos), next_(size) {} 46 | std::size_t get_pos() const { return pos_; } 47 | std::size_t get_next() const { return next_; } 48 | virtual const char *what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE { 49 | return "boost::bad_format_string: format-string is ill-formed"; 50 | } 51 | }; 52 | 53 | class too_few_args : public format_error 54 | { 55 | std::size_t cur_, expected_; 56 | public: 57 | too_few_args(std::size_t cur, std::size_t expected) 58 | : cur_(cur), expected_(expected) {} 59 | std::size_t get_cur() const { return cur_; } 60 | std::size_t get_expected() const { return expected_; } 61 | virtual const char *what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE { 62 | return "boost::too_few_args: " 63 | "format-string referred to more arguments than were passed"; 64 | } 65 | }; 66 | 67 | class too_many_args : public format_error 68 | { 69 | std::size_t cur_, expected_; 70 | public: 71 | too_many_args(std::size_t cur, std::size_t expected) 72 | : cur_(cur), expected_(expected) {} 73 | std::size_t get_cur() const { return cur_; } 74 | std::size_t get_expected() const { return expected_; } 75 | virtual const char *what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE { 76 | return "boost::too_many_args: " 77 | "format-string referred to fewer arguments than were passed"; 78 | } 79 | }; 80 | 81 | 82 | class out_of_range : public format_error 83 | { 84 | int index_, beg_, end_; // range is [ beg, end [ 85 | public: 86 | out_of_range(int index, int beg, int end) 87 | : index_(index), beg_(beg), end_(end) {} 88 | int get_index() const { return index_; } 89 | int get_beg() const { return beg_; } 90 | int get_end() const { return end_; } 91 | virtual const char *what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE { 92 | return "boost::out_of_range: " 93 | "tried to refer to an argument (or item) number which" 94 | " is out of range, according to the format string"; 95 | } 96 | }; 97 | 98 | 99 | } // namespace io 100 | 101 | } // namespace boost 102 | 103 | 104 | #endif // BOOST_FORMAT_EXCEPTIONS_HPP 105 | -------------------------------------------------------------------------------- /include/boost/format/feed_args.hpp: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // feed_args.hpp : functions for processing each argument 3 | // (feed, feed_manip, and distribute) 4 | // ---------------------------------------------------------------------------- 5 | 6 | // Copyright Samuel Krempp 2003. Use, modification, and distribution are 7 | // subject to the Boost Software License, Version 1.0. (See accompanying 8 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 | 10 | // See http://www.boost.org/libs/format for library home page 11 | 12 | // ---------------------------------------------------------------------------- 13 | 14 | #ifndef BOOST_FORMAT_FEED_ARGS_HPP 15 | #define BOOST_FORMAT_FEED_ARGS_HPP 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | namespace boost { 26 | namespace io { 27 | namespace detail { 28 | 29 | template 30 | void mk_str( std::basic_string & res, 31 | const Ch * beg, 32 | typename std::basic_string::size_type size, 33 | std::streamsize w, 34 | const Ch fill_char, 35 | std::ios_base::fmtflags f, 36 | const Ch prefix_space, // 0 if no space-padding 37 | bool center) 38 | // applies centered/left/right padding to the string [beg, beg+size[ 39 | // Effects : the result is placed in res. 40 | { 41 | typedef typename std::basic_string::size_type size_type; 42 | res.resize(0); 43 | if(w<=0 || static_cast(w) <=size) { 44 | // no need to pad. 45 | res.reserve(size + !!prefix_space); 46 | if(prefix_space) 47 | res.append(1, prefix_space); 48 | if (size) 49 | res.append(beg, size); 50 | } 51 | else { 52 | std::streamsize n=static_cast(w-size-!!prefix_space); 53 | std::streamsize n_after = 0, n_before = 0; 54 | res.reserve(static_cast(w)); // allocate once for the 2 inserts 55 | if(center) 56 | n_after = n/2, n_before = n - n_after; 57 | else 58 | if(f & std::ios_base::left) 59 | n_after = n; 60 | else 61 | n_before = n; 62 | // now make the res string : 63 | if(n_before) res.append(static_cast(n_before), fill_char); 64 | if(prefix_space) 65 | res.append(1, prefix_space); 66 | if (size) 67 | res.append(beg, size); 68 | if(n_after) res.append(static_cast(n_after), fill_char); 69 | } 70 | } // -mk_str(..) 71 | 72 | 73 | #if BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590042)) 74 | // __DECCXX needs to be tricked to disambiguate this simple overload.. 75 | // the trick is in "boost/format/msvc_disambiguater.hpp" 76 | 77 | template< class Ch, class Tr, class T> inline 78 | void put_head (BOOST_IO_STD basic_ostream & os, const T& x ) { 79 | disambiguater::put_head(os, x, 1L); 80 | } 81 | template< class Ch, class Tr, class T> inline 82 | void put_last (BOOST_IO_STD basic_ostream & os, const T& x ) { 83 | disambiguater::put_last(os, x, 1L); 84 | } 85 | 86 | #else 87 | 88 | template< class Ch, class Tr, class T> inline 89 | void put_head (BOOST_IO_STD basic_ostream &, const T& ) { 90 | } 91 | 92 | template< class Ch, class Tr, class T> inline 93 | void put_head( BOOST_IO_STD basic_ostream & os, const group1& x ) { 94 | os << group_head(x.a1_); // send the first N-1 items, not the last 95 | } 96 | 97 | template< class Ch, class Tr, class T> inline 98 | void put_last( BOOST_IO_STD basic_ostream & os, const T& x ) { 99 | os << x ; 100 | } 101 | 102 | template< class Ch, class Tr, class T> inline 103 | void put_last( BOOST_IO_STD basic_ostream & os, const group1& x ) { 104 | os << group_last(x.a1_); // this selects the last element 105 | } 106 | 107 | #ifndef BOOST_NO_OVERLOAD_FOR_NON_CONST 108 | template< class Ch, class Tr, class T> inline 109 | void put_head( BOOST_IO_STD basic_ostream &, T& ) { 110 | } 111 | 112 | template< class Ch, class Tr, class T> inline 113 | void put_last( BOOST_IO_STD basic_ostream & os, T& x) { 114 | os << x ; 115 | } 116 | #endif 117 | #endif // -__DECCXX workaround 118 | 119 | template< class Ch, class Tr, class T> 120 | void call_put_head(BOOST_IO_STD basic_ostream & os, const void* x) { 121 | put_head(os, *(static_cast(x))); 122 | } 123 | 124 | template< class Ch, class Tr, class T> 125 | void call_put_last(BOOST_IO_STD basic_ostream & os, const void* x) { 126 | put_last(os, *(static_cast(x))); 127 | } 128 | 129 | template< class Ch, class Tr> 130 | struct put_holder { 131 | template 132 | put_holder(T& t) 133 | : arg(&t), 134 | put_head(&call_put_head), 135 | put_last(&call_put_last) 136 | {} 137 | const void* arg; 138 | void (*put_head)(BOOST_IO_STD basic_ostream & os, const void* x); 139 | void (*put_last)(BOOST_IO_STD basic_ostream & os, const void* x); 140 | }; 141 | 142 | template< class Ch, class Tr> inline 143 | void put_head( BOOST_IO_STD basic_ostream & os, const put_holder& t) { 144 | t.put_head(os, t.arg); 145 | } 146 | 147 | template< class Ch, class Tr> inline 148 | void put_last( BOOST_IO_STD basic_ostream & os, const put_holder& t) { 149 | t.put_last(os, t.arg); 150 | } 151 | 152 | 153 | template< class Ch, class Tr, class Alloc, class T> 154 | void put( T x, 155 | const format_item& specs, 156 | typename basic_format::string_type& res, 157 | typename basic_format::internal_streambuf_t & buf, 158 | io::detail::locale_t *loc_p = NULL) 159 | { 160 | #ifdef BOOST_MSVC 161 | // If std::min or std::max are already instantiated 162 | // at this point then we get a blizzard of warning messages when we call 163 | // those templates with std::size_t as arguments. Weird and very annoyning... 164 | #pragma warning(push) 165 | #pragma warning(disable:4267) 166 | #endif 167 | // does the actual conversion of x, with given params, into a string 168 | // using the supplied stringbuf. 169 | 170 | typedef typename basic_format::string_type string_type; 171 | typedef typename basic_format::format_item_t format_item_t; 172 | typedef typename string_type::size_type size_type; 173 | 174 | basic_oaltstringstream oss( &buf); 175 | 176 | #if !defined(BOOST_NO_STD_LOCALE) 177 | if(loc_p != NULL) 178 | oss.imbue(*loc_p); 179 | #endif 180 | 181 | specs.fmtstate_.apply_on(oss, loc_p); 182 | 183 | // the stream format state can be modified by manipulators in the argument : 184 | put_head( oss, x ); 185 | // in case x is a group, apply the manip part of it, 186 | // in order to find width 187 | 188 | const std::ios_base::fmtflags fl=oss.flags(); 189 | const bool internal = (fl & std::ios_base::internal) != 0; 190 | const std::streamsize w = oss.width(); 191 | const bool two_stepped_padding= internal && (w!=0); 192 | 193 | res.resize(0); 194 | if(! two_stepped_padding) { 195 | if(w>0) // handle padding via mk_str, not natively in stream 196 | oss.width(0); 197 | put_last( oss, x); 198 | const Ch * res_beg = buf.pbase(); 199 | Ch prefix_space = 0; 200 | if(specs.pad_scheme_ & format_item_t::spacepad) 201 | if(buf.pcount()== 0 || 202 | (res_beg[0] !=oss.widen('+') && res_beg[0] !=oss.widen('-') )) 203 | prefix_space = oss.widen(' '); 204 | size_type res_size = (std::min)( 205 | (static_cast((specs.truncate_ & (std::numeric_limits::max)())) - !!prefix_space), 206 | buf.pcount() ); 207 | mk_str(res, res_beg, res_size, w, oss.fill(), fl, 208 | prefix_space, (specs.pad_scheme_ & format_item_t::centered) !=0 ); 209 | } 210 | else { // 2-stepped padding 211 | // internal can be implied by zeropad, or user-set. 212 | // left, right, and centered alignment overrule internal, 213 | // but spacepad or truncate might be mixed with internal (using manipulator) 214 | put_last( oss, x); // may pad 215 | const Ch * res_beg = buf.pbase(); 216 | size_type res_size = buf.pcount(); 217 | bool prefix_space=false; 218 | if(specs.pad_scheme_ & format_item_t::spacepad) 219 | if(buf.pcount()== 0 || 220 | (res_beg[0] !=oss.widen('+') && res_beg[0] !=oss.widen('-') )) 221 | prefix_space = true; 222 | if(res_size == static_cast(w) && w<=specs.truncate_ && !prefix_space) { 223 | // okay, only one thing was printed and padded, so res is fine 224 | res.assign(res_beg, res_size); 225 | } 226 | else { // length w exceeded 227 | // either it was multi-output with first output padding up all width.. 228 | // either it was one big arg and we are fine. 229 | // Note that res_size oss2( &buf); 236 | specs.fmtstate_.apply_on(oss2, loc_p); 237 | put_head( oss2, x ); 238 | 239 | oss2.width(0); 240 | if(prefix_space) 241 | oss2 << ' '; 242 | put_last(oss2, x ); 243 | if(buf.pcount()==0 && specs.pad_scheme_ & format_item_t::spacepad) { 244 | prefix_space =true; 245 | oss2 << ' '; 246 | } 247 | // we now have the minimal-length output 248 | const Ch * tmp_beg = buf.pbase(); 249 | size_type tmp_size = (std::min)( 250 | (static_cast(specs.truncate_ & (std::numeric_limits::max)())), 251 | buf.pcount()); 252 | 253 | if(static_cast(w) <= tmp_size) { 254 | // minimal length is already >= w, so no padding (cool!) 255 | res.assign(tmp_beg, tmp_size); 256 | } 257 | else { // hum.. we need to pad (multi_output, or spacepad present) 258 | //find where we should pad 259 | size_type sz = (std::min)(res_size + (prefix_space ? 1 : 0), tmp_size); 260 | size_type i = prefix_space; 261 | for(; i=tmp_size) i=prefix_space; 263 | res.assign(tmp_beg, i); 264 | std::streamsize d = w - static_cast(tmp_size); 265 | BOOST_ASSERT(d>0); 266 | res.append(static_cast( d ), oss2.fill()); 267 | res.append(tmp_beg+i, tmp_size-i); 268 | BOOST_ASSERT(i+(tmp_size-i)+(std::max)(d,(std::streamsize)0) 269 | == static_cast(w)); 270 | BOOST_ASSERT(res.size() == static_cast(w)); 271 | } 272 | } 273 | } 274 | buf.clear_buffer(); 275 | #ifdef BOOST_MSVC 276 | #pragma warning(pop) 277 | #endif 278 | } // end- put(..) 279 | 280 | 281 | template< class Ch, class Tr, class Alloc, class T> 282 | void distribute (basic_format& self, T x) { 283 | // call put(x, ..) on every occurrence of the current argument : 284 | if(self.cur_arg_ >= self.num_args_) { 285 | if( self.exceptions() & too_many_args_bit ) 286 | boost::throw_exception(too_many_args(self.cur_arg_, self.num_args_)); 287 | else return; 288 | } 289 | for(unsigned long i=0; i < self.items_.size(); ++i) { 290 | if(self.items_[i].argN_ == self.cur_arg_) { 291 | put (x, self.items_[i], self.items_[i].res_, 292 | self.buf_, boost::get_pointer(self.loc_) ); 293 | } 294 | } 295 | } 296 | 297 | template 298 | basic_format& 299 | feed_impl (basic_format& self, T x) { 300 | if(self.dumped_) self.clear(); 301 | distribute (self, x); 302 | ++self.cur_arg_; 303 | if(self.bound_.size() != 0) { 304 | while( self.cur_arg_ < self.num_args_ && self.bound_[self.cur_arg_] ) 305 | ++self.cur_arg_; 306 | } 307 | return self; 308 | } 309 | 310 | template inline 311 | basic_format& 312 | feed (basic_format& self, T x) { 313 | return feed_impl&>(self, put_holder(x)); 314 | } 315 | 316 | } // namespace detail 317 | } // namespace io 318 | } // namespace boost 319 | 320 | 321 | #endif // BOOST_FORMAT_FEED_ARGS_HPP 322 | -------------------------------------------------------------------------------- /include/boost/format/format_class.hpp: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // format_class.hpp : class interface 3 | // ---------------------------------------------------------------------------- 4 | 5 | // Copyright Samuel Krempp 2003. Use, modification, and distribution are 6 | // subject to the Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | // See http://www.boost.org/libs/format for library home page 10 | 11 | // ---------------------------------------------------------------------------- 12 | 13 | #ifndef BOOST_FORMAT_CLASS_HPP 14 | #define BOOST_FORMAT_CLASS_HPP 15 | 16 | 17 | #include 18 | #include 19 | 20 | #include // to store locale when needed 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | namespace boost { 28 | 29 | template 30 | class basic_format 31 | { 32 | typedef typename io::CompatTraits::compatible_type compat_traits; 33 | public: 34 | typedef Ch CharT; // borland fails in operator% if we use Ch and Tr directly 35 | typedef std::basic_string string_type; 36 | typedef typename string_type::size_type size_type; 37 | typedef io::detail::format_item format_item_t; 38 | typedef io::basic_altstringbuf internal_streambuf_t; 39 | 40 | 41 | explicit basic_format(const Ch* str=NULL); 42 | explicit basic_format(const string_type& s); 43 | basic_format(const basic_format& x); 44 | basic_format& operator= (const basic_format& x); 45 | void swap(basic_format& x); 46 | 47 | #if !defined(BOOST_NO_STD_LOCALE) 48 | explicit basic_format(const Ch* str, const std::locale & loc); 49 | explicit basic_format(const string_type& s, const std::locale & loc); 50 | #endif 51 | io::detail::locale_t getloc() const; 52 | 53 | basic_format& clear(); // empty all converted string buffers (except bound items) 54 | basic_format& clear_binds(); // unbind all bound items, and call clear() 55 | basic_format& parse(const string_type&); // resets buffers and parse a new format string 56 | 57 | // ** formatted result ** // 58 | size_type size() const; // sum of the current string pieces sizes 59 | string_type str() const; // final string 60 | 61 | // ** arguments passing ** // 62 | template 63 | basic_format& operator%(const T& x) 64 | { return io::detail::feed(*this,x); } 65 | 66 | #ifndef BOOST_NO_OVERLOAD_FOR_NON_CONST 67 | template basic_format& operator%(T& x) 68 | { return io::detail::feed(*this,x); } 69 | #endif 70 | 71 | template 72 | basic_format& operator%(volatile const T& x) 73 | { /* make a non-volatile copy */ const T v(x); 74 | /* pass the copy along */ return io::detail::feed(*this, v); } 75 | 76 | #ifndef BOOST_NO_OVERLOAD_FOR_NON_CONST 77 | template 78 | basic_format& operator%(volatile T& x) 79 | { /* make a non-volatile copy */ T v(x); 80 | /* pass the copy along */ return io::detail::feed(*this, v); } 81 | #endif 82 | 83 | #if defined(__GNUC__) 84 | // GCC can't handle anonymous enums without some help 85 | // ** arguments passing ** // 86 | basic_format& operator%(const int& x) 87 | { return io::detail::feed(*this,x); } 88 | 89 | #ifndef BOOST_NO_OVERLOAD_FOR_NON_CONST 90 | basic_format& operator%(int& x) 91 | { return io::detail::feed(*this,x); } 92 | #endif 93 | #endif 94 | 95 | // The total number of arguments expected to be passed to the format objectt 96 | int expected_args() const 97 | { return num_args_; } 98 | // The number of arguments currently bound (see bind_arg(..) ) 99 | int bound_args() const; 100 | // The number of arguments currently fed to the format object 101 | int fed_args() const; 102 | // The index (1-based) of the current argument (i.e. next to be formatted) 103 | int cur_arg() const; 104 | // The number of arguments still required to be fed 105 | int remaining_args() const; // same as expected_args() - bound_args() - fed_args() 106 | 107 | 108 | // ** object modifying **// 109 | template 110 | basic_format& bind_arg(int argN, const T& val) 111 | { return io::detail::bind_arg_body(*this, argN, val); } 112 | basic_format& clear_bind(int argN); 113 | template 114 | basic_format& modify_item(int itemN, T manipulator) 115 | { return io::detail::modify_item_body (*this, itemN, manipulator);} 116 | 117 | // Choosing which errors will throw exceptions : 118 | unsigned char exceptions() const; 119 | unsigned char exceptions(unsigned char newexcept); 120 | 121 | #if !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS ) \ 122 | && !BOOST_WORKAROUND(BOOST_BORLANDC, <= 0x570) \ 123 | && !BOOST_WORKAROUND( _CRAYC, != 0) \ 124 | && !BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590042)) 125 | // use friend templates and private members only if supported 126 | 127 | #ifndef BOOST_NO_TEMPLATE_STD_STREAM 128 | template 129 | friend std::basic_ostream & 130 | operator<<( std::basic_ostream & , 131 | const basic_format& ); 132 | #else 133 | template 134 | friend std::ostream & 135 | operator<<( std::ostream & , 136 | const basic_format& ); 137 | #endif 138 | 139 | template 140 | friend basic_format& 141 | io::detail::feed_impl (basic_format&, T); 142 | 143 | template friend 144 | void io::detail::distribute (basic_format&, T); 145 | 146 | template friend 147 | basic_format& 148 | io::detail::modify_item_body (basic_format&, int, T); 149 | 150 | template friend 151 | basic_format& 152 | io::detail::bind_arg_body (basic_format&, int, const T&); 153 | 154 | private: 155 | #endif 156 | typedef io::detail::stream_format_state stream_format_state; 157 | // flag bits, used for style_ 158 | enum style_values { ordered = 1, // set only if all directives are positional 159 | special_needs = 4 }; 160 | 161 | void make_or_reuse_data(std::size_t nbitems);// used for (re-)initialisation 162 | 163 | // member data --------------------------------------------// 164 | std::vector items_; // each '%..' directive leads to a format_item 165 | std::vector bound_; // stores which arguments were bound. size() == 0 || num_args 166 | 167 | int style_; // style of format-string : positional or not, etc 168 | int cur_arg_; // keep track of wich argument is current 169 | int num_args_; // number of expected arguments 170 | mutable bool dumped_; // true only after call to str() or << 171 | string_type prefix_; // piece of string to insert before first item 172 | unsigned char exceptions_; 173 | internal_streambuf_t buf_; // the internal stream buffer. 174 | boost::optional loc_; 175 | }; // class basic_format 176 | 177 | } // namespace boost 178 | 179 | 180 | #endif // BOOST_FORMAT_CLASS_HPP 181 | -------------------------------------------------------------------------------- /include/boost/format/format_fwd.hpp: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // format_fwd.hpp : forward declarations 3 | // ---------------------------------------------------------------------------- 4 | 5 | // Copyright Samuel Krempp 2003. Use, modification, and distribution are 6 | // subject to the Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | // See http://www.boost.org/libs/format for library home page 10 | 11 | // ---------------------------------------------------------------------------- 12 | 13 | #ifndef BOOST_FORMAT_FWD_HPP 14 | #define BOOST_FORMAT_FWD_HPP 15 | 16 | #include 17 | #include 18 | 19 | #include 20 | 21 | namespace boost { 22 | 23 | template , class Alloc = std::allocator > 25 | class basic_format; 26 | 27 | typedef basic_format format; 28 | 29 | #if !defined(BOOST_NO_STD_WSTRING) && !defined(BOOST_NO_STD_WSTREAMBUF) 30 | typedef basic_format wformat; 31 | #endif 32 | 33 | namespace io { 34 | enum format_error_bits { bad_format_string_bit = 1, 35 | too_few_args_bit = 2, too_many_args_bit = 4, 36 | out_of_range_bit = 8, 37 | all_error_bits = 255, no_error_bits=0 }; 38 | 39 | } // namespace io 40 | 41 | } // namespace boost 42 | 43 | #endif // BOOST_FORMAT_FWD_HPP 44 | -------------------------------------------------------------------------------- /include/boost/format/format_implementation.hpp: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // format_implementation.hpp Implementation of the basic_format class 3 | // ---------------------------------------------------------------------------- 4 | 5 | // Copyright Samuel Krempp 2003. Use, modification, and distribution are 6 | // subject to the Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | // See http://www.boost.org/libs/format for library home page 10 | 11 | 12 | // ---------------------------------------------------------------------------- 13 | 14 | #ifndef BOOST_FORMAT_IMPLEMENTATION_HPP 15 | #define BOOST_FORMAT_IMPLEMENTATION_HPP 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include // std::swap 22 | 23 | namespace boost { 24 | 25 | // --- basic_format implementation -----------------------------------------// 26 | 27 | template< class Ch, class Tr, class Alloc> 28 | basic_format:: basic_format(const Ch* s) 29 | : style_(0), cur_arg_(0), num_args_(0), dumped_(false), 30 | exceptions_(io::all_error_bits) 31 | { 32 | if( s) 33 | parse( s ); 34 | } 35 | 36 | #if !defined(BOOST_NO_STD_LOCALE) 37 | template< class Ch, class Tr, class Alloc> 38 | basic_format:: basic_format(const Ch* s, const std::locale & loc) 39 | : style_(0), cur_arg_(0), num_args_(0), dumped_(false), 40 | exceptions_(io::all_error_bits), loc_(loc) 41 | { 42 | if(s) parse( s ); 43 | } 44 | 45 | template< class Ch, class Tr, class Alloc> 46 | basic_format:: basic_format(const string_type& s, const std::locale & loc) 47 | : style_(0), cur_arg_(0), num_args_(0), dumped_(false), 48 | exceptions_(io::all_error_bits), loc_(loc) 49 | { 50 | parse(s); 51 | } 52 | #endif // ! BOOST_NO_STD_LOCALE 53 | template< class Ch, class Tr, class Alloc> 54 | io::detail::locale_t basic_format:: 55 | getloc() const { 56 | return loc_ ? loc_.get() : io::detail::locale_t(); 57 | } 58 | 59 | template< class Ch, class Tr, class Alloc> 60 | basic_format:: basic_format(const string_type& s) 61 | : style_(0), cur_arg_(0), num_args_(0), dumped_(false), 62 | exceptions_(io::all_error_bits) 63 | { 64 | parse(s); 65 | } 66 | 67 | template< class Ch, class Tr, class Alloc> // just don't copy the buf_ member 68 | basic_format:: basic_format(const basic_format& x) 69 | : items_(x.items_), bound_(x.bound_), style_(x.style_), 70 | cur_arg_(x.cur_arg_), num_args_(x.num_args_), dumped_(x.dumped_), 71 | prefix_(x.prefix_), exceptions_(x.exceptions_), loc_(x.loc_) 72 | { 73 | } 74 | 75 | template< class Ch, class Tr, class Alloc> // just don't copy the buf_ member 76 | basic_format& basic_format:: 77 | operator= (const basic_format& x) { 78 | if(this == &x) 79 | return *this; 80 | (basic_format(x)).swap(*this); 81 | return *this; 82 | } 83 | template< class Ch, class Tr, class Alloc> 84 | void basic_format:: 85 | swap (basic_format & x) { 86 | std::swap(exceptions_, x.exceptions_); 87 | std::swap(style_, x.style_); 88 | std::swap(cur_arg_, x.cur_arg_); 89 | std::swap(num_args_, x.num_args_); 90 | std::swap(dumped_, x.dumped_); 91 | 92 | items_.swap(x.items_); 93 | prefix_.swap(x.prefix_); 94 | bound_.swap(x.bound_); 95 | } 96 | 97 | template< class Ch, class Tr, class Alloc> 98 | unsigned char basic_format:: exceptions() const { 99 | return exceptions_; 100 | } 101 | 102 | template< class Ch, class Tr, class Alloc> 103 | unsigned char basic_format:: exceptions(unsigned char newexcept) { 104 | unsigned char swp = exceptions_; 105 | exceptions_ = newexcept; 106 | return swp; 107 | } 108 | 109 | template 110 | void basic_format:: 111 | make_or_reuse_data (std::size_t nbitems) { 112 | #if !defined(BOOST_NO_STD_LOCALE) 113 | Ch fill = ( BOOST_USE_FACET(std::ctype, getloc()) ). widen(' '); 114 | #else 115 | Ch fill = ' '; 116 | #endif 117 | if(items_.size() == 0) 118 | items_.assign( nbitems, format_item_t(fill) ); 119 | else { 120 | if(nbitems>items_.size()) 121 | items_.resize(nbitems, format_item_t(fill)); 122 | bound_.resize(0); 123 | for(std::size_t i=0; i < nbitems; ++i) 124 | items_[i].reset(fill); // strings are resized, instead of reallocated 125 | } 126 | prefix_.resize(0); 127 | } 128 | 129 | template< class Ch, class Tr, class Alloc> 130 | basic_format& basic_format:: 131 | clear () { 132 | // empty the string buffers (except bound arguments) 133 | // and make the format object ready for formatting a new set of arguments 134 | 135 | BOOST_ASSERT( bound_.size()==0 || num_args_ == static_cast(bound_.size()) ); 136 | 137 | for(unsigned long i=0; i 152 | basic_format& basic_format:: 153 | clear_binds () { 154 | // remove all binds, then clear() 155 | bound_.resize(0); 156 | clear(); 157 | return *this; 158 | } 159 | 160 | template< class Ch, class Tr, class Alloc> 161 | basic_format& basic_format:: 162 | clear_bind (int argN) { 163 | // remove the bind of ONE argument then clear() 164 | if(argN<1 || argN > num_args_ || bound_.size()==0 || !bound_[argN-1] ) { 165 | if( exceptions() & io::out_of_range_bit) 166 | boost::throw_exception(io::out_of_range(argN, 1, num_args_+1 ) ); 167 | else return *this; 168 | } 169 | bound_[argN-1]=false; 170 | clear(); 171 | return *this; 172 | } 173 | 174 | template< class Ch, class Tr, class Alloc> 175 | int basic_format:: 176 | bound_args() const { 177 | if(bound_.size()==0) 178 | return 0; 179 | int n=0; 180 | for(int i=0; i 187 | int basic_format:: 188 | fed_args() const { 189 | if(bound_.size()==0) 190 | return cur_arg_; 191 | int n=0; 192 | for(int i=0; i 199 | int basic_format:: 200 | cur_arg() const { 201 | return cur_arg_+1; } 202 | 203 | template< class Ch, class Tr, class Alloc> 204 | int basic_format:: 205 | remaining_args() const { 206 | if(bound_.size()==0) 207 | return num_args_-cur_arg_; 208 | int n=0; 209 | for(int i=cur_arg_; i 216 | typename basic_format::string_type 217 | basic_format:: 218 | str () const { 219 | if(items_.size()==0) 220 | return prefix_; 221 | if( cur_arg_ < num_args_) 222 | if( exceptions() & io::too_few_args_bit ) 223 | // not enough variables supplied 224 | boost::throw_exception(io::too_few_args(cur_arg_, num_args_)); 225 | 226 | unsigned long i; 227 | string_type res; 228 | res.reserve(size()); 229 | res += prefix_; 230 | for(i=0; i < items_.size(); ++i) { 231 | const format_item_t& item = items_[i]; 232 | res += item.res_; 233 | if( item.argN_ == format_item_t::argN_tabulation) { 234 | BOOST_ASSERT( item.pad_scheme_ & format_item_t::tabulation); 235 | if( static_cast(item.fmtstate_.width_) > res.size() ) 236 | res.append( static_cast(item.fmtstate_.width_) - res.size(), 237 | item.fmtstate_.fill_ ); 238 | } 239 | res += item.appendix_; 240 | } 241 | dumped_=true; 242 | return res; 243 | } 244 | template< class Ch, class Tr, class Alloc> 245 | typename std::basic_string::size_type basic_format:: 246 | size () const { 247 | #ifdef BOOST_MSVC 248 | // If std::min or std::max are already instantiated 249 | // at this point then we get a blizzard of warning messages when we call 250 | // those templates with std::size_t as arguments. Weird and very annoyning... 251 | #pragma warning(push) 252 | #pragma warning(disable:4267) 253 | #endif 254 | BOOST_USING_STD_MAX(); 255 | size_type sz = prefix_.size(); 256 | unsigned long i; 257 | for(i=0; i < items_.size(); ++i) { 258 | const format_item_t& item = items_[i]; 259 | sz += item.res_.size(); 260 | if( item.argN_ == format_item_t::argN_tabulation) 261 | sz = max BOOST_PREVENT_MACRO_SUBSTITUTION (sz, 262 | static_cast(item.fmtstate_.width_) ); 263 | sz += item.appendix_.size(); 264 | } 265 | return sz; 266 | #ifdef BOOST_MSVC 267 | #pragma warning(pop) 268 | #endif 269 | } 270 | 271 | namespace io { 272 | namespace detail { 273 | 274 | template 275 | basic_format& 276 | bind_arg_body (basic_format& self, int argN, const T& val) { 277 | // bind one argument to a fixed value 278 | // this is persistent over clear() calls, thus also over str() and << 279 | if(self.dumped_) 280 | self.clear(); // needed because we will modify cur_arg_ 281 | if(argN<1 || argN > self.num_args_) { 282 | if( self.exceptions() & io::out_of_range_bit ) 283 | boost::throw_exception(io::out_of_range(argN, 1, self.num_args_+1 ) ); 284 | else return self; 285 | } 286 | if(self.bound_.size()==0) 287 | self.bound_.assign(self.num_args_,false); 288 | else 289 | BOOST_ASSERT( self.num_args_ == static_cast(self.bound_.size()) ); 290 | int o_cur_arg = self.cur_arg_; 291 | self.cur_arg_ = argN-1; // arrays begin at 0 292 | 293 | self.bound_[self.cur_arg_]=false; // if already set, we unset and re-sets.. 294 | self.operator%(val); // put val at the right place, because cur_arg is set 295 | 296 | 297 | // Now re-position cur_arg before leaving : 298 | self.cur_arg_ = o_cur_arg; 299 | self.bound_[argN-1]=true; 300 | if(self.cur_arg_ == argN-1 ) { 301 | // hum, now this arg is bound, so move to next free arg 302 | while(self.cur_arg_ < self.num_args_ && self.bound_[self.cur_arg_]) 303 | ++self.cur_arg_; 304 | } 305 | // In any case, we either have all args, or are on an unbound arg : 306 | BOOST_ASSERT( self.cur_arg_ >= self.num_args_ || ! self.bound_[self.cur_arg_]); 307 | return self; 308 | } 309 | 310 | template basic_format& 311 | modify_item_body (basic_format& self, int itemN, T manipulator) { 312 | // applies a manipulator to the format_item describing a given directive. 313 | // this is a permanent change, clear or reset won't cancel that. 314 | if(itemN<1 || itemN > static_cast(self.items_.size() )) { 315 | if( self.exceptions() & io::out_of_range_bit ) 316 | boost::throw_exception(io::out_of_range(itemN, 1, static_cast(self.items_.size()) )); 317 | else return self; 318 | } 319 | self.items_[itemN-1].fmtstate_. template apply_manip ( manipulator ); 320 | return self; 321 | } 322 | 323 | } // namespace detail 324 | } // namespace io 325 | } // namespace boost 326 | 327 | 328 | 329 | #endif // BOOST_FORMAT_IMPLEMENTATION_HPP 330 | -------------------------------------------------------------------------------- /include/boost/format/free_funcs.hpp: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // free_funcs.hpp : implementation of the free functions of boost::format 3 | // ---------------------------------------------------------------------------- 4 | 5 | // Copyright Samuel Krempp 2003. Use, modification, and distribution are 6 | // subject to the Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | // See http://www.boost.org/libs/format for library home page 10 | 11 | // ---------------------------------------------------------------------------- 12 | 13 | #ifndef BOOST_FORMAT_FUNCS_HPP 14 | #define BOOST_FORMAT_FUNCS_HPP 15 | 16 | #include 17 | #include 18 | 19 | namespace boost { 20 | 21 | template inline 22 | std::basic_string str(const basic_format& f) { 23 | // adds up all pieces of strings and converted items, and return the formatted string 24 | return f.str(); 25 | } 26 | namespace io { 27 | using ::boost::str; // keep compatibility with when it was defined in this N.S. 28 | } // - namespace io 29 | 30 | #ifndef BOOST_NO_TEMPLATE_STD_STREAM 31 | template 32 | std::basic_ostream & 33 | operator<<( std::basic_ostream & os, 34 | const basic_format& f) 35 | #else 36 | template 37 | std::ostream & 38 | operator<<( std::ostream & os, 39 | const basic_format& f) 40 | #endif 41 | // effect: "return os << str(f);" but we can do it faster 42 | { 43 | typedef boost::basic_format format_t; 44 | if(f.items_.size()==0) 45 | os << f.prefix_; 46 | else { 47 | if(f.cur_arg_ < f.num_args_) 48 | if( f.exceptions() & io::too_few_args_bit ) 49 | // not enough variables supplied 50 | boost::throw_exception(io::too_few_args(f.cur_arg_, f.num_args_)); 51 | if(f.style_ & format_t::special_needs) 52 | os << f.str(); 53 | else { 54 | // else we dont have to count chars output, so we dump directly to os : 55 | os << f.prefix_; 56 | for(unsigned long i=0; i 27 | 28 | 29 | namespace boost { 30 | namespace io { 31 | 32 | 33 | namespace detail { 34 | 35 | 36 | // empty group, but useful even though. 37 | struct group0 38 | { 39 | group0() {} 40 | }; 41 | 42 | template 43 | inline 44 | BOOST_IO_STD basic_ostream& 45 | operator << ( BOOST_IO_STD basic_ostream& os, 46 | const group0& ) 47 | { 48 | return os; 49 | } 50 | 51 | template 52 | struct group1 53 | { 54 | T1 a1_; 55 | group1(T1 a1) 56 | : a1_(a1) 57 | {} 58 | group1(const group1&) = default; 59 | group1& operator=(const group1&) = delete; 60 | }; 61 | 62 | template 63 | inline 64 | BOOST_IO_STD basic_ostream& 65 | operator << (BOOST_IO_STD basic_ostream& os, 66 | const group1& x) 67 | { 68 | os << x.a1_; 69 | return os; 70 | } 71 | 72 | 73 | 74 | 75 | template 76 | struct group2 77 | { 78 | T1 a1_; 79 | T2 a2_; 80 | group2(T1 a1,T2 a2) 81 | : a1_(a1),a2_(a2) 82 | {} 83 | group2(const group2&) = default; 84 | group2& operator=(const group2&) = delete; 85 | }; 86 | 87 | template 88 | inline 89 | BOOST_IO_STD basic_ostream& 90 | operator << (BOOST_IO_STD basic_ostream& os, 91 | const group2& x) 92 | { 93 | os << x.a1_<< x.a2_; 94 | return os; 95 | } 96 | 97 | template 98 | struct group3 99 | { 100 | T1 a1_; 101 | T2 a2_; 102 | T3 a3_; 103 | group3(T1 a1,T2 a2,T3 a3) 104 | : a1_(a1),a2_(a2),a3_(a3) 105 | {} 106 | group3(const group3&) = default; 107 | group3& operator=(const group3&) = delete; 108 | }; 109 | 110 | template 111 | inline 112 | BOOST_IO_STD basic_ostream& 113 | operator << (BOOST_IO_STD basic_ostream& os, 114 | const group3& x) 115 | { 116 | os << x.a1_<< x.a2_<< x.a3_; 117 | return os; 118 | } 119 | 120 | template 121 | struct group4 122 | { 123 | T1 a1_; 124 | T2 a2_; 125 | T3 a3_; 126 | T4 a4_; 127 | group4(T1 a1,T2 a2,T3 a3,T4 a4) 128 | : a1_(a1),a2_(a2),a3_(a3),a4_(a4) 129 | {} 130 | group4(const group4&) = default; 131 | group4& operator=(const group4&) = delete; 132 | }; 133 | 134 | template 135 | inline 136 | BOOST_IO_STD basic_ostream& 137 | operator << (BOOST_IO_STD basic_ostream& os, 138 | const group4& x) 139 | { 140 | os << x.a1_<< x.a2_<< x.a3_<< x.a4_; 141 | return os; 142 | } 143 | 144 | template 145 | struct group5 146 | { 147 | T1 a1_; 148 | T2 a2_; 149 | T3 a3_; 150 | T4 a4_; 151 | T5 a5_; 152 | group5(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5) 153 | : a1_(a1),a2_(a2),a3_(a3),a4_(a4),a5_(a5) 154 | {} 155 | group5(const group5&) = default; 156 | group5& operator=(const group5&) = delete; 157 | }; 158 | 159 | template 160 | inline 161 | BOOST_IO_STD basic_ostream& 162 | operator << (BOOST_IO_STD basic_ostream& os, 163 | const group5& x) 164 | { 165 | os << x.a1_<< x.a2_<< x.a3_<< x.a4_<< x.a5_; 166 | return os; 167 | } 168 | 169 | template 170 | struct group6 171 | { 172 | T1 a1_; 173 | T2 a2_; 174 | T3 a3_; 175 | T4 a4_; 176 | T5 a5_; 177 | T6 a6_; 178 | group6(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6) 179 | : a1_(a1),a2_(a2),a3_(a3),a4_(a4),a5_(a5),a6_(a6) 180 | {} 181 | group6(const group6&) = default; 182 | group6& operator=(const group6&) = delete; 183 | }; 184 | 185 | template 186 | inline 187 | BOOST_IO_STD basic_ostream& 188 | operator << (BOOST_IO_STD basic_ostream& os, 189 | const group6& x) 190 | { 191 | os << x.a1_<< x.a2_<< x.a3_<< x.a4_<< x.a5_<< x.a6_; 192 | return os; 193 | } 194 | 195 | template 196 | struct group7 197 | { 198 | T1 a1_; 199 | T2 a2_; 200 | T3 a3_; 201 | T4 a4_; 202 | T5 a5_; 203 | T6 a6_; 204 | T7 a7_; 205 | group7(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7) 206 | : a1_(a1),a2_(a2),a3_(a3),a4_(a4),a5_(a5),a6_(a6),a7_(a7) 207 | {} 208 | group7(const group7&) = default; 209 | group7& operator=(const group7&) = delete; 210 | }; 211 | 212 | template 213 | inline 214 | BOOST_IO_STD basic_ostream& 215 | operator << (BOOST_IO_STD basic_ostream& os, 216 | const group7& x) 217 | { 218 | os << x.a1_<< x.a2_<< x.a3_<< x.a4_<< x.a5_<< x.a6_<< x.a7_; 219 | return os; 220 | } 221 | 222 | template 223 | struct group8 224 | { 225 | T1 a1_; 226 | T2 a2_; 227 | T3 a3_; 228 | T4 a4_; 229 | T5 a5_; 230 | T6 a6_; 231 | T7 a7_; 232 | T8 a8_; 233 | group8(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7,T8 a8) 234 | : a1_(a1),a2_(a2),a3_(a3),a4_(a4),a5_(a5),a6_(a6),a7_(a7),a8_(a8) 235 | {} 236 | group8(const group8&) = default; 237 | group8& operator=(const group8&) = delete; 238 | }; 239 | 240 | template 241 | inline 242 | BOOST_IO_STD basic_ostream& 243 | operator << (BOOST_IO_STD basic_ostream& os, 244 | const group8& x) 245 | { 246 | os << x.a1_<< x.a2_<< x.a3_<< x.a4_<< x.a5_<< x.a6_<< x.a7_<< x.a8_; 247 | return os; 248 | } 249 | 250 | template 251 | struct group9 252 | { 253 | T1 a1_; 254 | T2 a2_; 255 | T3 a3_; 256 | T4 a4_; 257 | T5 a5_; 258 | T6 a6_; 259 | T7 a7_; 260 | T8 a8_; 261 | T9 a9_; 262 | group9(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7,T8 a8,T9 a9) 263 | : a1_(a1),a2_(a2),a3_(a3),a4_(a4),a5_(a5),a6_(a6),a7_(a7),a8_(a8),a9_(a9) 264 | {} 265 | group9(const group9&) = default; 266 | group9& operator=(const group9&) = delete; 267 | }; 268 | 269 | template 270 | inline 271 | BOOST_IO_STD basic_ostream& 272 | operator << (BOOST_IO_STD basic_ostream& os, 273 | const group9& x) 274 | { 275 | os << x.a1_<< x.a2_<< x.a3_<< x.a4_<< x.a5_<< x.a6_<< x.a7_<< x.a8_<< x.a9_; 276 | return os; 277 | } 278 | 279 | template 280 | struct group10 281 | { 282 | T1 a1_; 283 | T2 a2_; 284 | T3 a3_; 285 | T4 a4_; 286 | T5 a5_; 287 | T6 a6_; 288 | T7 a7_; 289 | T8 a8_; 290 | T9 a9_; 291 | T10 a10_; 292 | group10(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7,T8 a8,T9 a9,T10 a10) 293 | : a1_(a1),a2_(a2),a3_(a3),a4_(a4),a5_(a5),a6_(a6),a7_(a7),a8_(a8),a9_(a9),a10_(a10) 294 | {} 295 | group10(const group10&) = default; 296 | group10& operator=(const group10&) = delete; 297 | }; 298 | 299 | template 300 | inline 301 | BOOST_IO_STD basic_ostream& 302 | operator << (BOOST_IO_STD basic_ostream& os, 303 | const group10& x) 304 | { 305 | os << x.a1_<< x.a2_<< x.a3_<< x.a4_<< x.a5_<< x.a6_<< x.a7_<< x.a8_<< x.a9_<< x.a10_; 306 | return os; 307 | } 308 | 309 | 310 | 311 | 312 | template 313 | inline 314 | group1 315 | group_head( group2 const& x) 316 | { 317 | return group1 (x.a1_); 318 | } 319 | 320 | template 321 | inline 322 | group1 323 | group_last( group2 const& x) 324 | { 325 | return group1 (x.a2_); 326 | } 327 | 328 | 329 | 330 | template 331 | inline 332 | group2 333 | group_head( group3 const& x) 334 | { 335 | return group2 (x.a1_,x.a2_); 336 | } 337 | 338 | template 339 | inline 340 | group1 341 | group_last( group3 const& x) 342 | { 343 | return group1 (x.a3_); 344 | } 345 | 346 | 347 | 348 | template 349 | inline 350 | group3 351 | group_head( group4 const& x) 352 | { 353 | return group3 (x.a1_,x.a2_,x.a3_); 354 | } 355 | 356 | template 357 | inline 358 | group1 359 | group_last( group4 const& x) 360 | { 361 | return group1 (x.a4_); 362 | } 363 | 364 | 365 | 366 | template 367 | inline 368 | group4 369 | group_head( group5 const& x) 370 | { 371 | return group4 (x.a1_,x.a2_,x.a3_,x.a4_); 372 | } 373 | 374 | template 375 | inline 376 | group1 377 | group_last( group5 const& x) 378 | { 379 | return group1 (x.a5_); 380 | } 381 | 382 | 383 | 384 | template 385 | inline 386 | group5 387 | group_head( group6 const& x) 388 | { 389 | return group5 (x.a1_,x.a2_,x.a3_,x.a4_,x.a5_); 390 | } 391 | 392 | template 393 | inline 394 | group1 395 | group_last( group6 const& x) 396 | { 397 | return group1 (x.a6_); 398 | } 399 | 400 | 401 | 402 | template 403 | inline 404 | group6 405 | group_head( group7 const& x) 406 | { 407 | return group6 (x.a1_,x.a2_,x.a3_,x.a4_,x.a5_,x.a6_); 408 | } 409 | 410 | template 411 | inline 412 | group1 413 | group_last( group7 const& x) 414 | { 415 | return group1 (x.a7_); 416 | } 417 | 418 | 419 | 420 | template 421 | inline 422 | group7 423 | group_head( group8 const& x) 424 | { 425 | return group7 (x.a1_,x.a2_,x.a3_,x.a4_,x.a5_,x.a6_,x.a7_); 426 | } 427 | 428 | template 429 | inline 430 | group1 431 | group_last( group8 const& x) 432 | { 433 | return group1 (x.a8_); 434 | } 435 | 436 | 437 | 438 | template 439 | inline 440 | group8 441 | group_head( group9 const& x) 442 | { 443 | return group8 (x.a1_,x.a2_,x.a3_,x.a4_,x.a5_,x.a6_,x.a7_,x.a8_); 444 | } 445 | 446 | template 447 | inline 448 | group1 449 | group_last( group9 const& x) 450 | { 451 | return group1 (x.a9_); 452 | } 453 | 454 | 455 | 456 | template 457 | inline 458 | group9 459 | group_head( group10 const& x) 460 | { 461 | return group9 (x.a1_,x.a2_,x.a3_,x.a4_,x.a5_,x.a6_,x.a7_,x.a8_,x.a9_); 462 | } 463 | 464 | template 465 | inline 466 | group1 467 | group_last( group10 const& x) 468 | { 469 | return group1 (x.a10_); 470 | } 471 | 472 | 473 | 474 | 475 | 476 | } // namespace detail 477 | 478 | 479 | 480 | // helper functions 481 | 482 | 483 | inline detail::group1< detail::group0 > 484 | group() { return detail::group1< detail::group0 > ( detail::group0() ); } 485 | 486 | template 487 | inline 488 | detail::group1< detail::group2 > 489 | group(T1 a1, Var const& var) 490 | { 491 | return detail::group1< detail::group2 > 492 | ( detail::group2 493 | (a1, var) 494 | ); 495 | } 496 | 497 | template 498 | inline 499 | detail::group1< detail::group3 > 500 | group(T1 a1,T2 a2, Var const& var) 501 | { 502 | return detail::group1< detail::group3 > 503 | ( detail::group3 504 | (a1,a2, var) 505 | ); 506 | } 507 | 508 | template 509 | inline 510 | detail::group1< detail::group4 > 511 | group(T1 a1,T2 a2,T3 a3, Var const& var) 512 | { 513 | return detail::group1< detail::group4 > 514 | ( detail::group4 515 | (a1,a2,a3, var) 516 | ); 517 | } 518 | 519 | template 520 | inline 521 | detail::group1< detail::group5 > 522 | group(T1 a1,T2 a2,T3 a3,T4 a4, Var const& var) 523 | { 524 | return detail::group1< detail::group5 > 525 | ( detail::group5 526 | (a1,a2,a3,a4, var) 527 | ); 528 | } 529 | 530 | template 531 | inline 532 | detail::group1< detail::group6 > 533 | group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5, Var const& var) 534 | { 535 | return detail::group1< detail::group6 > 536 | ( detail::group6 537 | (a1,a2,a3,a4,a5, var) 538 | ); 539 | } 540 | 541 | template 542 | inline 543 | detail::group1< detail::group7 > 544 | group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6, Var const& var) 545 | { 546 | return detail::group1< detail::group7 > 547 | ( detail::group7 548 | (a1,a2,a3,a4,a5,a6, var) 549 | ); 550 | } 551 | 552 | template 553 | inline 554 | detail::group1< detail::group8 > 555 | group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7, Var const& var) 556 | { 557 | return detail::group1< detail::group8 > 558 | ( detail::group8 559 | (a1,a2,a3,a4,a5,a6,a7, var) 560 | ); 561 | } 562 | 563 | template 564 | inline 565 | detail::group1< detail::group9 > 566 | group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7,T8 a8, Var const& var) 567 | { 568 | return detail::group1< detail::group9 > 569 | ( detail::group9 570 | (a1,a2,a3,a4,a5,a6,a7,a8, var) 571 | ); 572 | } 573 | 574 | template 575 | inline 576 | detail::group1< detail::group10 > 577 | group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7,T8 a8,T9 a9, Var const& var) 578 | { 579 | return detail::group1< detail::group10 > 580 | ( detail::group10 581 | (a1,a2,a3,a4,a5,a6,a7,a8,a9, var) 582 | ); 583 | } 584 | 585 | 586 | #ifndef BOOST_NO_OVERLOAD_FOR_NON_CONST 587 | 588 | template 589 | inline 590 | detail::group1< detail::group2 > 591 | group(T1 a1, Var& var) 592 | { 593 | return detail::group1< detail::group2 > 594 | ( detail::group2 595 | (a1, var) 596 | ); 597 | } 598 | 599 | template 600 | inline 601 | detail::group1< detail::group3 > 602 | group(T1 a1,T2 a2, Var& var) 603 | { 604 | return detail::group1< detail::group3 > 605 | ( detail::group3 606 | (a1,a2, var) 607 | ); 608 | } 609 | 610 | template 611 | inline 612 | detail::group1< detail::group4 > 613 | group(T1 a1,T2 a2,T3 a3, Var& var) 614 | { 615 | return detail::group1< detail::group4 > 616 | ( detail::group4 617 | (a1,a2,a3, var) 618 | ); 619 | } 620 | 621 | template 622 | inline 623 | detail::group1< detail::group5 > 624 | group(T1 a1,T2 a2,T3 a3,T4 a4, Var& var) 625 | { 626 | return detail::group1< detail::group5 > 627 | ( detail::group5 628 | (a1,a2,a3,a4, var) 629 | ); 630 | } 631 | 632 | template 633 | inline 634 | detail::group1< detail::group6 > 635 | group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5, Var& var) 636 | { 637 | return detail::group1< detail::group6 > 638 | ( detail::group6 639 | (a1,a2,a3,a4,a5, var) 640 | ); 641 | } 642 | 643 | template 644 | inline 645 | detail::group1< detail::group7 > 646 | group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6, Var& var) 647 | { 648 | return detail::group1< detail::group7 > 649 | ( detail::group7 650 | (a1,a2,a3,a4,a5,a6, var) 651 | ); 652 | } 653 | 654 | template 655 | inline 656 | detail::group1< detail::group8 > 657 | group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7, Var& var) 658 | { 659 | return detail::group1< detail::group8 > 660 | ( detail::group8 661 | (a1,a2,a3,a4,a5,a6,a7, var) 662 | ); 663 | } 664 | 665 | template 666 | inline 667 | detail::group1< detail::group9 > 668 | group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7,T8 a8, Var& var) 669 | { 670 | return detail::group1< detail::group9 > 671 | ( detail::group9 672 | (a1,a2,a3,a4,a5,a6,a7,a8, var) 673 | ); 674 | } 675 | 676 | template 677 | inline 678 | detail::group1< detail::group10 > 679 | group(T1 a1,T2 a2,T3 a3,T4 a4,T5 a5,T6 a6,T7 a7,T8 a8,T9 a9, Var& var) 680 | { 681 | return detail::group1< detail::group10 > 682 | ( detail::group10 683 | (a1,a2,a3,a4,a5,a6,a7,a8,a9, var) 684 | ); 685 | } 686 | 687 | 688 | #endif // - BOOST_NO_OVERLOAD_FOR_NON_CONST 689 | 690 | 691 | } // namespace io 692 | 693 | } // namespace boost 694 | 695 | 696 | #endif // BOOST_FORMAT_GROUP_HPP 697 | -------------------------------------------------------------------------------- /include/boost/format/internals.hpp: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // internals.hpp : internal structs : stream_format_state, format_item. 3 | // included by format.hpp 4 | // ---------------------------------------------------------------------------- 5 | 6 | // Copyright Samuel Krempp 2003. Use, modification, and distribution are 7 | // subject to the Boost Software License, Version 1.0. (See accompanying 8 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 | 10 | // See http://www.boost.org/libs/format for library home page 11 | 12 | // ---------------------------------------------------------------------------- 13 | 14 | #ifndef BOOST_FORMAT_INTERNALS_HPP 15 | #define BOOST_FORMAT_INTERNALS_HPP 16 | 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include // used as a dummy stream 25 | 26 | namespace boost { 27 | namespace io { 28 | namespace detail { 29 | 30 | 31 | //---- stream_format_state --------------------------------------------------// 32 | 33 | // set of params that define the format state of a stream 34 | template 35 | struct stream_format_state 36 | { 37 | typedef BOOST_IO_STD basic_ios basic_ios; 38 | 39 | stream_format_state(Ch fill) { reset(fill); } 40 | // stream_format_state(const basic_ios& os) { set_by_stream(os); } 41 | 42 | void reset(Ch fill); //- sets to default state. 43 | void set_by_stream(const basic_ios& os); //- sets to os's state. 44 | void apply_on(basic_ios & os, //- applies format_state to the stream 45 | boost::io::detail::locale_t * loc_default = 0) const; 46 | template 47 | void apply_manip(T manipulator) //- modifies state by applying manipulator 48 | { apply_manip_body( *this, manipulator) ; } 49 | 50 | // --- data --- 51 | std::streamsize width_; 52 | std::streamsize precision_; 53 | Ch fill_; 54 | std::ios_base::fmtflags flags_; 55 | std::ios_base::iostate rdstate_; 56 | std::ios_base::iostate exceptions_; 57 | boost::optional loc_; 58 | }; 59 | 60 | 61 | //---- format_item ---------------------------------------------------------// 62 | 63 | // stores all parameters that can be specified in format strings 64 | template 65 | struct format_item 66 | { 67 | enum pad_values { zeropad = 1, spacepad =2, centered=4, tabulation = 8 }; 68 | // 1. if zeropad is set, all other bits are not, 69 | // 2. if tabulation is set, all others are not. 70 | // centered and spacepad can be mixed freely. 71 | enum arg_values { argN_no_posit = -1, // non-positional directive. will set argN later 72 | argN_tabulation = -2, // tabulation directive. (no argument read) 73 | argN_ignored = -3 // ignored directive. (no argument read) 74 | }; 75 | typedef BOOST_IO_STD basic_ios basic_ios; 76 | typedef detail::stream_format_state stream_format_state; 77 | typedef ::std::basic_string string_type; 78 | 79 | format_item(Ch fill) :argN_(argN_no_posit), fmtstate_(fill), 80 | truncate_(max_streamsize()), pad_scheme_(0) {} 81 | void reset(Ch fill); 82 | void compute_states(); // sets states according to truncate and pad_scheme. 83 | 84 | static std::streamsize max_streamsize() { 85 | return (std::numeric_limits::max)(); 86 | } 87 | 88 | // --- data --- 89 | int argN_; //- argument number (starts at 0, eg : %1 => argN=0) 90 | // negative values for items that don't process an argument 91 | string_type res_; //- result of the formatting of this item 92 | string_type appendix_; //- piece of string between this item and the next 93 | 94 | stream_format_state fmtstate_;// set by parsing, is only affected by modify_item 95 | 96 | std::streamsize truncate_;//- is set for directives like %.5s that ask truncation 97 | unsigned int pad_scheme_;//- several possible padding schemes can mix. see pad_values 98 | }; 99 | 100 | 101 | 102 | //--- Definitions ------------------------------------------------------------ 103 | 104 | // - stream_format_state:: ------------------------------------------------- 105 | template 106 | void stream_format_state:: apply_on (basic_ios & os, 107 | boost::io::detail::locale_t * loc_default) const { 108 | // If a locale is available, set it first. "os.fill(fill_);" may chrash otherwise. 109 | #if !defined(BOOST_NO_STD_LOCALE) 110 | if(loc_) 111 | os.imbue(loc_.get()); 112 | else if(loc_default) 113 | os.imbue(*loc_default); 114 | #else 115 | ignore_unused(loc_default); 116 | #endif 117 | // set the state of this stream according to our params 118 | if(width_ != -1) 119 | os.width(width_); 120 | if(precision_ != -1) 121 | os.precision(precision_); 122 | if(fill_ != 0) 123 | os.fill(fill_); 124 | os.flags(flags_); 125 | os.clear(rdstate_); 126 | os.exceptions(exceptions_); 127 | } 128 | 129 | template 130 | void stream_format_state:: set_by_stream(const basic_ios& os) { 131 | // set our params according to the state of this stream 132 | flags_ = os.flags(); 133 | width_ = os.width(); 134 | precision_ = os.precision(); 135 | fill_ = os.fill(); 136 | rdstate_ = os.rdstate(); 137 | exceptions_ = os.exceptions(); 138 | } 139 | 140 | 141 | template 142 | void apply_manip_body( stream_format_state& self, 143 | T manipulator) { 144 | // modify our params according to the manipulator 145 | basic_oaltstringstream ss; 146 | self.apply_on( ss ); 147 | ss << manipulator; 148 | self.set_by_stream( ss ); 149 | } 150 | 151 | template inline 152 | void stream_format_state:: reset(Ch fill) { 153 | // set our params to standard's default state. cf 27.4.4.1 of the C++ norm 154 | width_=0; precision_=6; 155 | fill_=fill; // default is widen(' '), but we cant compute it without the locale 156 | flags_ = std::ios_base::dec | std::ios_base::skipws; 157 | // the adjust_field part is left equal to 0, which means right. 158 | exceptions_ = std::ios_base::goodbit; 159 | rdstate_ = std::ios_base::goodbit; 160 | } 161 | 162 | 163 | // --- format_item:: -------------------------------------------------------- 164 | 165 | template 166 | void format_item:: 167 | reset (Ch fill) { 168 | argN_=argN_no_posit; truncate_ = max_streamsize(); pad_scheme_ =0; 169 | res_.resize(0); appendix_.resize(0); 170 | fmtstate_.reset(fill); 171 | } 172 | 173 | template 174 | void format_item:: 175 | compute_states() { 176 | // reflect pad_scheme_ on fmt_state_ 177 | // because some pad_schemes has complex consequences on several state params. 178 | if(pad_scheme_ & zeropad) { 179 | // ignore zeropad in left alignment : 180 | if(fmtstate_.flags_ & std::ios_base::left) { 181 | BOOST_ASSERT(!(fmtstate_.flags_ &(std::ios_base::adjustfield ^std::ios_base::left))); 182 | // only left bit might be set. (not right, nor internal) 183 | pad_scheme_ = pad_scheme_ & (~zeropad); 184 | } 185 | else { 186 | pad_scheme_ &= ~spacepad; // printf ignores spacepad when zeropadding 187 | fmtstate_.fill_='0'; 188 | fmtstate_.flags_ = (fmtstate_.flags_ & ~std::ios_base::adjustfield) 189 | | std::ios_base::internal; 190 | // removes all adjustfield bits, and adds internal. 191 | } 192 | } 193 | if(pad_scheme_ & spacepad) { 194 | if(fmtstate_.flags_ & std::ios_base::showpos) 195 | pad_scheme_ &= ~spacepad; 196 | } 197 | } 198 | 199 | 200 | } } } // namespaces boost :: io :: detail 201 | 202 | 203 | #endif // BOOST_FORMAT_INTERNALS_HPP 204 | -------------------------------------------------------------------------------- /include/boost/format/internals_fwd.hpp: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // internals_fwd.hpp : forward declarations, for internal headers 3 | // ---------------------------------------------------------------------------- 4 | 5 | // Copyright Samuel Krempp 2003. Use, modification, and distribution are 6 | // subject to the Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | // See http://www.boost.org/libs/format for library home page 10 | 11 | // ---------------------------------------------------------------------------- 12 | 13 | #ifndef BOOST_FORMAT_INTERNAL_FWD_HPP 14 | #define BOOST_FORMAT_INTERNAL_FWD_HPP 15 | 16 | #include 17 | #include 18 | 19 | 20 | namespace boost { 21 | namespace io { 22 | 23 | namespace detail { 24 | template struct stream_format_state; 25 | template struct format_item; 26 | 27 | 28 | // these functions were intended as methods, 29 | // but MSVC have problems with template member functions : 30 | // defined in format_implementation.hpp : 31 | template 32 | basic_format& 33 | modify_item_body (basic_format& self, 34 | int itemN, T manipulator); 35 | 36 | template 37 | basic_format& 38 | bind_arg_body (basic_format& self, 39 | int argN, const T& val); 40 | 41 | // in internals.hpp : 42 | template 43 | void apply_manip_body (stream_format_state& self, 44 | T manipulator); 45 | 46 | // argument feeding (defined in feed_args.hpp ) : 47 | template 48 | void distribute (basic_format& self, T x); 49 | 50 | template 51 | basic_format& 52 | feed (basic_format& self, T x); 53 | 54 | template 55 | basic_format& 56 | feed_impl (basic_format& self, T x); 57 | 58 | } // namespace detail 59 | 60 | } // namespace io 61 | } // namespace boost 62 | 63 | 64 | #endif // BOOST_FORMAT_INTERNAL_FWD_HPP 65 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | The Boost Format library 9 | 10 | 11 | 12 | 13 | 14 | 16 | 17 | 19 | 20 | 22 | 23 | 25 | 26 | 28 | 29 | 31 | 32 |
15HomeLibrariesPeopleFAQMore
33 | 34 |

Boost Format library

35 | 36 |

The format library provides a class for formatting arguments according 37 | to a format-string, as does printf, but with two major differences 38 | :

39 | 40 |
    41 |
  • format sends the arguments to an internal stream, and so is entirely 42 | type-safe and naturally supports all user-defined types.
  • 43 | 44 |
  • The ellipsis (...) can not be used correctly in the strongly typed 45 | context of format, and thus the function call with arbitrary arguments is 46 | replaced by successive calls to an argument feeding 47 | operator%
  • 48 |
49 | 50 |


51 | You can find more Details in :

52 | 53 |
    54 |
  • Documentation (HTML).
  • 55 | 56 |
  • Headers 57 | 58 | 91 |
  • 92 | 93 |
  • Sample programs 94 | 95 |
      96 |
    • The program sample_formats.cpp demonstrates 98 | simple uses of format.
    • 99 | 100 |
    • sample_new_features.cpp 102 | illustrates the few formatting features that were added to printf's 103 | syntax such as simple positional directives, centered alignment, and 104 | 'tabulations'.
    • 105 | 106 |
    • sample_advanced.cpp 107 | demonstrates uses of advanced features, like reusing, and modifying, 108 | format objects, etc..
    • 109 | 110 |
    • And sample_userType.cpp shows the 112 | behaviour of the format library on user-defined types.
    • 113 |
    114 |
  • 115 |
116 |
117 | 118 |

Valid HTML 4.01 Transitional

121 | 122 |

Revised 123 | 02 December, 2006

124 | 125 |

Copyright © 2003 Samuel Krempp

126 | 127 |

Distributed under the Boost Software License, Version 1.0. (See 128 | accompanying file LICENSE_1_0.txt or 129 | copy at http://www.boost.org/LICENSE_1_0.txt)

131 | 132 | 133 | -------------------------------------------------------------------------------- /meta/libraries.json: -------------------------------------------------------------------------------- 1 | { 2 | "key": "format", 3 | "name": "Format", 4 | "authors": [ 5 | "Samuel Krempp" 6 | ], 7 | "description": "The format library provides a type-safe mechanism for formatting arguments according to a printf-like format-string.", 8 | "category": [ 9 | "IO", 10 | "String" 11 | ], 12 | "maintainers": [ 13 | "Samuel Krempp ", 14 | "James E. King III " 15 | ], 16 | "cxxstd": "11" 17 | } 18 | -------------------------------------------------------------------------------- /test/Jamfile.v2: -------------------------------------------------------------------------------- 1 | # Boost.Format Library test Jamfile 2 | # 3 | # Copyright (c) 2003 Samuel Krempp 4 | # 5 | # Distributed under the Boost Software License, Version 1.0. (See accompany- 6 | # ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | import testing ; 9 | 10 | project : requirements 11 | /boost/format//boost_format 12 | /boost/algorithm//boost_algorithm 13 | ; 14 | 15 | test-suite "format" 16 | : [ run format_test1.cpp ] 17 | [ run format_test1.cpp : : : msvc:"/FIWindows.h" : format_test1_windows_h ] 18 | [ run format_test2.cpp ] 19 | [ run format_test2.cpp : : : msvc:"/FIWindows.h" : format_test2_windows_h ] 20 | [ run format_test3.cpp ] 21 | [ run format_test3.cpp : : : msvc:"/FIWindows.h" : format_test3_windows_h ] 22 | [ run format_test_enum.cpp : : : clang:-Wno-unnamed-type-template-args ] 23 | [ run format_test_exceptions.cpp ] 24 | [ run format_test_wstring.cpp ] 25 | ; -------------------------------------------------------------------------------- /test/cmake_test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright 2021-2024 Alexander Grund 2 | # Distributed under the Boost Software License, Version 1.0. 3 | # See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt 4 | 5 | cmake_minimum_required(VERSION 3.5...3.16) 6 | 7 | project(cmake_subdir_test LANGUAGES CXX) 8 | 9 | # Those 2 should work the same 10 | # while using find_package for the installed Boost avoids the need to manually specify dependencies 11 | if(BOOST_CI_INSTALL_TEST) 12 | find_package(boost_format REQUIRED) 13 | else() 14 | set(BOOST_INCLUDE_LIBRARIES format) 15 | add_subdirectory(../../../.. deps/boost EXCLUDE_FROM_ALL) 16 | endif() 17 | 18 | add_executable(main main.cpp) 19 | target_link_libraries(main Boost::format) 20 | 21 | enable_testing() 22 | add_test(NAME main COMMAND main) 23 | -------------------------------------------------------------------------------- /test/cmake_test/main.cpp: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------ 2 | // libs/format/test/format_test1.cpp : test constructing objects and basic parsing 3 | // ------------------------------------------------------------------------------ 4 | 5 | // Copyright Samuel Krempp 2003. Use, modification, and distribution are 6 | // subject to the Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | // See http://www.boost.org/libs/format for library home page 10 | 11 | // ------------------------------------------------------------------------------ 12 | 13 | #include 14 | #include 15 | 16 | int main(int, char* []) 17 | { 18 | using boost::format; 19 | using boost::str; 20 | 21 | if(str( format(" %% ") ) != " % ") 22 | BOOST_ERROR("Basic parsing without arguments Failed"); 23 | if(str( format("nothing") ) != "nothing") 24 | BOOST_ERROR("Basic parsing without arguments Failed"); 25 | if(str( format("%% ") ) != "% ") 26 | BOOST_ERROR("Basic parsing without arguments Failed"); 27 | if(str( format(" %%") ) != " %") 28 | BOOST_ERROR("Basic parsing without arguments Failed"); 29 | if(str( format(" %n ") ) != " ") 30 | BOOST_ERROR("Basic parsing without arguments Failed"); 31 | if(str( format("%n ") ) != " ") 32 | BOOST_ERROR("Basic parsing without arguments Failed"); 33 | if(str( format(" %n") ) != " ") 34 | BOOST_ERROR("Basic parsing without arguments Failed"); 35 | 36 | if(str( format("%%##%%##%%1 %1%00") % "Escaped OK" ) != "%##%##%1 Escaped OK00") 37 | BOOST_ERROR("Basic parsing Failed"); 38 | if(str( format("%%##%#x ##%%1 %s00") % 20 % "Escaped OK" ) != "%##0x14 ##%1 Escaped OK00") 39 | BOOST_ERROR("Basic p-parsing Failed") ; 40 | 41 | return boost::report_errors(); 42 | } 43 | -------------------------------------------------------------------------------- /test/format_test1.cpp: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------ 2 | // libs/format/test/format_test1.cpp : test constructing objects and basic parsing 3 | // ------------------------------------------------------------------------------ 4 | 5 | // Copyright Samuel Krempp 2003. Use, modification, and distribution are 6 | // subject to the Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | // See http://www.boost.org/libs/format for library home page 10 | 11 | // ------------------------------------------------------------------------------ 12 | 13 | #include 14 | #include 15 | 16 | int main(int, char* []) 17 | { 18 | using boost::format; 19 | using boost::str; 20 | 21 | if(str( format(" %% ") ) != " % ") 22 | BOOST_ERROR("Basic parsing without arguments Failed"); 23 | if(str( format("nothing") ) != "nothing") 24 | BOOST_ERROR("Basic parsing without arguments Failed"); 25 | if(str( format("%% ") ) != "% ") 26 | BOOST_ERROR("Basic parsing without arguments Failed"); 27 | if(str( format(" %%") ) != " %") 28 | BOOST_ERROR("Basic parsing without arguments Failed"); 29 | if(str( format(" %n ") ) != " ") 30 | BOOST_ERROR("Basic parsing without arguments Failed"); 31 | if(str( format("%n ") ) != " ") 32 | BOOST_ERROR("Basic parsing without arguments Failed"); 33 | if(str( format(" %n") ) != " ") 34 | BOOST_ERROR("Basic parsing without arguments Failed"); 35 | 36 | if(str( format("%%##%%##%%1 %1%00") % "Escaped OK" ) != "%##%##%1 Escaped OK00") 37 | BOOST_ERROR("Basic parsing Failed"); 38 | if(str( format("%%##%#x ##%%1 %s00") % 20 % "Escaped OK" ) != "%##0x14 ##%1 Escaped OK00") 39 | BOOST_ERROR("Basic p-parsing Failed") ; 40 | 41 | return boost::report_errors(); 42 | } 43 | -------------------------------------------------------------------------------- /test/format_test2.cpp: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------ 2 | // format_test2.cpp : a few real, simple tests. 3 | // ------------------------------------------------------------------------------ 4 | 5 | // Copyright Samuel Krempp 2003. Use, modification, and distribution are 6 | // subject to the Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | // see http://www.boost.org/libs/format for library home page 10 | 11 | // ------------------------------------------------------------------------------ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | 22 | #if !defined(BOOST_NO_STD_LOCALE) 23 | #include 24 | #endif 25 | 26 | struct Rational { 27 | int n,d; 28 | Rational (int an, int ad) : n(an), d(ad) {} 29 | }; 30 | 31 | std::ostream& operator<<( std::ostream& os, const Rational& r) { 32 | os << r.n << "/" << r.d; 33 | return os; 34 | } 35 | 36 | #if !defined(BOOST_NO_STD_LOCALE) 37 | // in C++03 this has to be globally defined or gcc complains 38 | struct custom_tf : std::numpunct { 39 | std::string do_truename() const { return "POSITIVE"; } 40 | std::string do_falsename() const { return "NEGATIVE"; } 41 | }; 42 | #endif 43 | 44 | int main(int, char* []) 45 | { 46 | using namespace std; 47 | using boost::format; 48 | using boost::io::group; 49 | using boost::str; 50 | 51 | Rational r(16,9); 52 | const Rational cr(9,16); 53 | 54 | string s; 55 | s = str(format("%5%. %5$=6s . %1% format %5%, c'%3% %1% %2%.\n") 56 | % "le" % "bonheur" % "est" % "trop" % group(setfill('_'), "bref") ); 57 | 58 | if(s != "bref. _bref_ . le format bref, c'est le bonheur.\n") { 59 | cerr << s; 60 | BOOST_ERROR("centered alignement : formatting result incorrect"); 61 | } 62 | 63 | 64 | s = str(format("%+8d %-8d\n") % r % cr ); 65 | if(s != " +16/+9 9/16 \n") { 66 | cerr << s; 67 | BOOST_ERROR("(user-type) formatting result incorrect"); 68 | } 69 | 70 | s = str(format("[%0+4d %0+8d %-08d]\n") % 8 % r % r); 71 | if(s != "[+008 +0016/+9 16/9 ]\n") { 72 | cerr << s; 73 | BOOST_ERROR("(zero-padded user-type) formatting result incorrect"); 74 | } 75 | 76 | 77 | s = str( format("%1%, %20T_ (%|2$5|,%|3$5|)\n") % "98765" % 1326 % 88 ) ; 78 | if( s != "98765, _____________ ( 1326, 88)\n" ) 79 | BOOST_ERROR("(tabulation) formatting result incorrect"); 80 | s = str( format("%s, %|20t|=") % 88 ) ; 81 | if( s != "88, =" ) { 82 | cout << s << endl; 83 | BOOST_ERROR("(tabulation) formatting result incorrect"); 84 | } 85 | 86 | 87 | s = str(format("%.2s %8c.\n") % "root" % "user" ); 88 | if(s != "ro u.\n") { 89 | cerr << s; 90 | BOOST_ERROR("(truncation) formatting result incorrect"); 91 | } 92 | 93 | // width in format-string is overridden by setw manipulator : 94 | s = str( format("%|1$4| %|1$|") % group(setfill('0'), setw(6), 1) ); 95 | if( s!= "000001 000001") 96 | BOOST_ERROR("width in format VS in argument misbehaved"); 97 | 98 | s = str( format("%|=s|") % group(setfill('_'), setw(6), r) ); 99 | if( s!= "_16/9_") { 100 | cerr << s << endl; 101 | BOOST_ERROR("width in group context is not handled correctly"); 102 | } 103 | 104 | 105 | // options that uses internal alignment : + 0 # 106 | s = str( format("%+6d %0#6x %s\n") % 342 % 33 % "ok" ); 107 | if( s !=" +342 0x0021 ok\n") 108 | BOOST_ERROR("(flags +, 0, or #) formatting result incorrect"); 109 | 110 | // flags in the format string are not sticky 111 | // and hex in argument overrrides type-char d (->decimal) : 112 | s = str( format("%2$#4d %|1$4| %|2$#4| %|3$|") 113 | % 101 114 | % group(setfill('_'), hex, 2) 115 | % 103 ); 116 | if(s != "_0x2 101 _0x2 103") 117 | BOOST_ERROR("formatting error. (not-restoring state ?)"); 118 | 119 | 120 | 121 | // flag '0' is tricky . 122 | // left-align cancels '0': 123 | s = str( format("%2$0#12X %2$0#-12d %1$0#10d \n") % -20 % 10 ); 124 | if( s != "0X000000000A 10 -000000020 \n"){ 125 | cerr << s; 126 | BOOST_ERROR("formatting error. (flag 0)"); 127 | } 128 | 129 | // actually testing floating point output is implementation 130 | // specific so we're just going to do minimal checking... 131 | double dbl = 1234567.890123f; 132 | 133 | #if !defined(__MINGW32__) && ((__cplusplus >= 201103L) || (BOOST_VERSION_NUMBER_MAJOR(BOOST_COMP_MSVC) >= 12)) 134 | // mingw32 does not have support for hexfloat but does set __cplusplus to a C++11 value 135 | // msvc-12.0 and later have support for hexfloat but do not set __cplusplus to a C++11 value 136 | BOOST_TEST(boost::starts_with((boost::format("%A") % dbl).str(), "0X")); 137 | BOOST_TEST(boost::starts_with((boost::format("%a") % dbl).str(), "0x")); 138 | #endif 139 | 140 | BOOST_TEST(boost::contains((boost::format("%E") % dbl).str(), "E")); 141 | BOOST_TEST(boost::contains((boost::format("%e") % dbl).str(), "e")); 142 | BOOST_TEST(boost::contains((boost::format("%F") % dbl).str(), ".")); 143 | BOOST_TEST(boost::contains((boost::format("%f") % dbl).str(), ".")); 144 | BOOST_TEST(!(boost::format("%G") % dbl).str().empty()); 145 | BOOST_TEST(!(boost::format("%g") % dbl).str().empty()); 146 | 147 | // testing argument type parsing - remember argument types are ignored 148 | // because operator % presents the argument type. 149 | unsigned int value = 456; 150 | BOOST_TEST_EQ((boost::format("%hhu") % value).str(), "456"); 151 | BOOST_TEST_EQ((boost::format("%hu") % value).str(), "456"); 152 | BOOST_TEST_EQ((boost::format("%lu") % value).str(), "456"); 153 | BOOST_TEST_EQ((boost::format("%llu") % value).str(), "456"); 154 | BOOST_TEST_EQ((boost::format("%ju") % value).str(), "456"); 155 | BOOST_TEST_EQ((boost::format("%zu") % value).str(), "456"); 156 | BOOST_TEST(boost::starts_with((boost::format("%Lf") % value).str(), "456")); 157 | 158 | #if !defined(BOOST_NO_STD_LOCALE) 159 | // boolalpha support 160 | std::locale loc; 161 | const std::numpunct& punk(std::use_facet >(loc)); 162 | 163 | // Demonstrates how to modify the default string to something else 164 | std::locale custom(std::locale(), new custom_tf); 165 | boost::ignore_unused(locale::global(custom)); 166 | BOOST_TEST_EQ((boost::format("%b") % false).str(), "NEGATIVE"); 167 | BOOST_TEST_EQ((boost::format("%b") % true).str(), "POSITIVE"); 168 | 169 | // restore system default 170 | locale::global(loc); 171 | BOOST_TEST_EQ((boost::format("%b") % false).str(), punk.falsename()); 172 | BOOST_TEST_EQ((boost::format("%b") % true).str(), punk.truename()); 173 | #endif 174 | 175 | // Support for microsoft argument type specifiers: 'w' (same as 'l'), I, I32, I64 176 | BOOST_TEST_EQ((boost::format("%wc") % '5').str(), "5"); 177 | BOOST_TEST_EQ((boost::format("%Id") % 123).str(), "123"); 178 | BOOST_TEST_EQ((boost::format("%I32d") % 456).str(), "456"); 179 | BOOST_TEST_EQ((boost::format("%I64d") % 789).str(), "789"); 180 | 181 | // issue-36 volatile (and const) keyword 182 | volatile int vint = 1234567; 183 | BOOST_TEST_EQ((boost::format("%1%") % vint).str(), "1234567"); 184 | volatile const int vcint = 7654321; 185 | BOOST_TEST_EQ((boost::format("%1%") % vcint).str(), "7654321"); 186 | 187 | // skip width if '*' 188 | BOOST_TEST_EQ((boost::format("%*d") % vint).str(), "1234567"); 189 | 190 | // internal ios flag 191 | BOOST_TEST_EQ((boost::format("%_6d") % -77).str(), "- 77"); 192 | 193 | // combining some flags 194 | BOOST_TEST_EQ((boost::format("%+05.5d" ) % 77).str(), "+0077"); 195 | BOOST_TEST_EQ((boost::format("%+ 5.5d" ) % 77).str(), " +77"); 196 | BOOST_TEST_EQ((boost::format("%+_ 5.5d" ) % 77).str(), "+ 77"); 197 | BOOST_TEST_EQ((boost::format("%+- 5.5d" ) % 77).str(), "+77 "); 198 | BOOST_TEST_EQ((boost::format("%+05.5d" ) % -77).str(), "-0077"); 199 | BOOST_TEST_EQ((boost::format("%+ 5.5d" ) % -77).str(), " -77"); 200 | BOOST_TEST_EQ((boost::format("%+_ 5.5d" ) % -77).str(), "- 77"); 201 | BOOST_TEST_EQ((boost::format("%+- 5.5d" ) % -77).str(), "-77 "); 202 | 203 | // reuse state and reset format flags 204 | std::string mystr("abcdefghijklmnop"); 205 | BOOST_TEST_EQ((boost::format("%2.2s %-4.4s % 8.8s") 206 | % mystr % mystr % mystr).str(), "ab abcd abcdefg"); 207 | 208 | // coverage, operator =, copy constructor 209 | format fmt("%1%%2%%3%"); 210 | format fmt2; 211 | fmt2 = fmt; 212 | format fmt3(fmt); 213 | BOOST_TEST_EQ((fmt % 'a' % 'b' % 'c').str(), "abc"); 214 | BOOST_TEST_EQ((fmt2 % 'b' % 'c' % 'd').str(), "bcd"); 215 | BOOST_TEST_EQ((fmt3 % 'c' % 'd' % 'e').str(), "cde"); 216 | 217 | return boost::report_errors(); 218 | } 219 | -------------------------------------------------------------------------------- /test/format_test3.cpp: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------ 2 | // format_test3.cpp : complicated format strings and / or advanced uses 3 | // ------------------------------------------------------------------------------ 4 | 5 | // Copyright Samuel Krempp 2003. Use, modification, and distribution are 6 | // subject to the Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | // see http://www.boost.org/libs/format for library home page 10 | 11 | // ------------------------------------------------------------------------------ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | struct Rational { 19 | int n,d; 20 | Rational (int an, int ad) : n(an), d(ad) {} 21 | }; 22 | 23 | std::ostream& operator<<( std::ostream& os, const Rational& r) { 24 | os << r.n << "/" << r.d; 25 | return os; 26 | } 27 | 28 | int main(int, char* []) 29 | { 30 | using namespace std; 31 | using boost::format; 32 | using boost::io::group; 33 | using boost::str; 34 | 35 | string s, s2; 36 | // special paddings 37 | s = str( format("[%=6s] [%+6s] [%+6s] [% 6s] [%+6s]\n") 38 | % 123 39 | % group(internal, setfill('W'), 234) 40 | % group(internal, setfill('X'), -345) 41 | % group(setfill('Y'), 456) 42 | % group(setfill('Z'), -10 ) ); 43 | 44 | if(s != "[ 123 ] [+WW234] [-XX345] [YY 456] [ZZZ-10]\n" ) { 45 | cerr << s ; 46 | BOOST_ERROR("formatting error. (with special paddings)"); 47 | } 48 | 49 | s = str( format("[% 6.8s] [% 8.6s] [% 7.7s]\n") 50 | % group(internal, setfill('x'), Rational(12345,54321)) 51 | % group(internal, setfill('x'), Rational(123,45)) 52 | % group(internal, setfill('x'), Rational(123,321)) 53 | ); 54 | if(s != (s2="[ 12345/5] [ xx123/4] [ 123/32]\n" )) { 55 | cerr << s << s2; 56 | BOOST_ERROR("formatting error. (with special paddings)"); 57 | } 58 | 59 | s = str( format("[% 6.8s] [% 6.8s] [% 6.8s] [% 6.8s] [%6.8s]\n") 60 | % 1234567897 61 | % group(setfill('x'), 12) 62 | % group(internal, setfill('x'), 12) 63 | % group(internal, setfill('x'), 1234567890) 64 | % group(internal, setfill('x'), 123456) 65 | ); 66 | if(s != (s2="[ 1234567] [xxx 12] [ xxx12] [ 1234567] [123456]\n") ) { 67 | cerr << s << s2; 68 | BOOST_ERROR("formatting error. (with special paddings)"); 69 | } 70 | 71 | s = str( format("[% 8.6s] [% 6.4s] [% 6.4s] [% 8.6s] [% 8.6s]\n") 72 | % 1234567897 73 | % group(setfill('x'), 12) 74 | % group(internal, setfill('x'), 12) 75 | % group(internal, setfill('x'), 1234567890) 76 | % group(internal, setfill('x'), 12345) 77 | ); 78 | if(s != (s2="[ 12345] [xxx 12] [ xxx12] [ xx12345] [ xx12345]\n") ) { 79 | cerr << s << s2; 80 | BOOST_ERROR("formatting error. (with special paddings)"); 81 | } 82 | 83 | // nesting formats : 84 | s = str( format("%2$014x [%1%] %|2$05|\n") % (format("%05s / %s") % -18 % 7) 85 | %group(showbase, -100) 86 | ); 87 | if( s != "0x0000ffffff9c [-0018 / 7] -0100\n" ){ 88 | cerr << s ; 89 | BOOST_ERROR("nesting did not work"); 90 | } 91 | 92 | // bind args, and various arguments counts : 93 | { 94 | boost::format bf("%1% %4% %1%"); 95 | bf.bind_arg(1, "one") % 2 % "three" ; 96 | BOOST_TEST_EQ(bf.expected_args(), 4); 97 | BOOST_TEST_EQ(bf.fed_args(), 2); 98 | BOOST_TEST_EQ(bf.bound_args(), 1); 99 | BOOST_TEST_EQ(bf.remaining_args(), 1); 100 | BOOST_TEST_EQ(bf.cur_arg(), 4); 101 | bf.clear_binds(); 102 | bf % "one" % 2 % "three" ; 103 | BOOST_TEST_EQ(bf.expected_args(), 4); 104 | BOOST_TEST_EQ(bf.fed_args(), 3); 105 | BOOST_TEST_EQ(bf.bound_args(), 0); 106 | BOOST_TEST_EQ(bf.remaining_args(), 1); 107 | BOOST_TEST_EQ(bf.cur_arg(), 4); 108 | } 109 | // testcase for bug reported at 110 | // http://lists.boost.org/boost-users/2006/05/19723.php 111 | { 112 | format f("%40t%1%"); 113 | int x = 0; 114 | f.bind_arg(1, x); 115 | f.clear(); 116 | } 117 | 118 | // testcase for bug reported at 119 | // http://lists.boost.org/boost-users/2005/11/15454.php 120 | std::string l_param; 121 | std::string l_str = (boost::format("here is an empty string: %1%") % l_param).str(); 122 | BOOST_TEST_EQ(std::string("here is an empty string: "), l_str); 123 | 124 | // testcase for SourceForge bug #1506914 125 | std::string arg; // empty string 126 | s = str(format("%=8s") % arg); 127 | BOOST_TEST_EQ(std::string(" "), s); 128 | 129 | return boost::report_errors(); 130 | } 131 | -------------------------------------------------------------------------------- /test/format_test_enum.cpp: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------ 2 | // format_test_enum.cpp : test format use with enums 3 | // ------------------------------------------------------------------------------ 4 | 5 | // Copyright Steven Watanabe 2009. 6 | // 7 | // Distributed under the Boost Software License, Version 1.0. (See 8 | // accompanying file LICENSE_1_0.txt or copy at 9 | // http://www.boost.org/LICENSE_1_0.txt) 10 | 11 | // See http://www.boost.org/libs/format for library home page 12 | 13 | // ------------------------------------------------------------------------------ 14 | 15 | #include 16 | #include 17 | 18 | enum enum_plain { PLAIN }; 19 | enum { ANONYMOUS }; 20 | enum enum_overloaded { OVERLOADED }; 21 | typedef enum { OVERLOADED_TYPEDEF } enum_overloaded_typedef; 22 | 23 | std::ostream& operator<<(std::ostream& os, enum_overloaded) { 24 | os << "overloaded"; 25 | return(os); 26 | } 27 | 28 | std::ostream& operator<<(std::ostream& os, enum_overloaded_typedef) { 29 | os << "overloaded"; 30 | return(os); 31 | } 32 | 33 | int main(int, char*[]) { 34 | // in this case, we should implicitly convert to int 35 | BOOST_TEST_EQ((boost::format("%d") % PLAIN).str(), "0"); 36 | BOOST_TEST_EQ((boost::format("%d") % ANONYMOUS).str(), "0"); 37 | 38 | // but here we need to use the overloaded operator 39 | BOOST_TEST_EQ((boost::format("%s") % OVERLOADED).str(), "overloaded"); 40 | BOOST_TEST_EQ((boost::format("%s") % OVERLOADED_TYPEDEF).str(), "overloaded"); 41 | 42 | return boost::report_errors(); 43 | } 44 | -------------------------------------------------------------------------------- /test/format_test_exceptions.cpp: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------ 2 | // format_test_exceptions.cpp : exception handling 3 | // ------------------------------------------------------------------------------ 4 | 5 | // Copyright 2017 James E. King, III - Use, modification, and distribution are 6 | // subject to the Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | // see http://www.boost.org/libs/format for library home page 10 | 11 | // ------------------------------------------------------------------------------ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define CHECK_INVALID_0(FMT, EX) { BOOST_TEST_THROWS((boost::format(FMT)).str(), EX); \ 20 | boost::format safe; safe.exceptions(boost::io::no_error_bits); safe.parse(FMT); (safe).str(); } 21 | #define CHECK_INVALID_1(FMT, _1, EX) { BOOST_TEST_THROWS((boost::format(FMT) % _1).str(), EX); \ 22 | boost::format safe; safe.exceptions(boost::io::no_error_bits); safe.parse(FMT); (safe % _1).str(); } 23 | #define CHECK_INVALID_2(FMT, _1, _2, EX) { BOOST_TEST_THROWS((boost::format(FMT) % _1 % _2).str(), EX); \ 24 | boost::format safe; safe.exceptions(boost::io::no_error_bits); safe.parse(FMT); (safe % _1 % _2).str(); } 25 | 26 | int main(int, char* []) 27 | { 28 | using namespace boost::io; 29 | 30 | // https://svn.boost.org/trac10/ticket/8735 31 | 32 | CHECK_INVALID_0("%", bad_format_string); // no conversion specifier 33 | CHECK_INVALID_0("%|", bad_format_string); // truncated 34 | CHECK_INVALID_0("%|%", bad_format_string); // mismatched bars 35 | CHECK_INVALID_0("%|2%", bad_format_string); // mismatched bars 36 | CHECK_INVALID_0("%'", bad_format_string); // flag ' is ignored, no conversion specifier 37 | CHECK_INVALID_0("%2", bad_format_string); // no terminating percent 38 | CHECK_INVALID_0("%*", bad_format_string); // truncated 39 | CHECK_INVALID_1("%$2", 1, bad_format_string); // no conversion specifier 40 | CHECK_INVALID_1("%$2.*", 1, bad_format_string); // no conversion specifier 41 | CHECK_INVALID_0("%0%", bad_format_string); // positional arguments start at 1 42 | CHECK_INVALID_2("%1%", 1, 2, too_many_args); 43 | CHECK_INVALID_1("%1% %2%", 1, too_few_args); 44 | 45 | CHECK_INVALID_0("%I", bad_format_string); 46 | CHECK_INVALID_0("%I2", bad_format_string); 47 | CHECK_INVALID_0("%I2d", bad_format_string); 48 | CHECK_INVALID_0("%I3", bad_format_string); 49 | CHECK_INVALID_0("%I3d", bad_format_string); 50 | CHECK_INVALID_0("%I32", bad_format_string); 51 | CHECK_INVALID_0("%I33", bad_format_string); 52 | CHECK_INVALID_0("%I6", bad_format_string); 53 | CHECK_INVALID_0("%I62", bad_format_string); 54 | CHECK_INVALID_0("%I63", bad_format_string); 55 | CHECK_INVALID_0("%I63d", bad_format_string); 56 | CHECK_INVALID_0("%I64", bad_format_string); 57 | CHECK_INVALID_0("%I128d", bad_format_string); 58 | CHECK_INVALID_0("%3.*4d", bad_format_string); 59 | 60 | // mixing positional and non-positional 61 | CHECK_INVALID_2("%1% %2d", 1, 2, bad_format_string); 62 | CHECK_INVALID_2("%2d %2%", 1, 2, bad_format_string); 63 | 64 | // found while improving coverage - a number following the * for width 65 | // or precision was being eaten instead of being treated as an error 66 | CHECK_INVALID_0("%1$*4d", bad_format_string); 67 | CHECK_INVALID_0("%1$05.*32d", bad_format_string); 68 | CHECK_INVALID_0("%1$05.*6", bad_format_string); 69 | 70 | // found while improving coverage, this caused an unhandled exception 71 | // the "T" conversion specifier didn't handle the exception flags properly 72 | CHECK_INVALID_0("%1$T", bad_format_string); // missing fill character 73 | 74 | // test what() on exceptions 75 | format_error base_err; 76 | BOOST_TEST_GT(strlen(base_err.what()), 0u); 77 | 78 | bad_format_string bfs(2, 3); 79 | BOOST_TEST(boost::contains(bfs.what(), "bad_format_string")); 80 | 81 | too_few_args tfa(5, 4); 82 | BOOST_TEST(boost::contains(tfa.what(), "format-string")); 83 | 84 | too_many_args tma(4, 5); 85 | BOOST_TEST(boost::contains(tma.what(), "format-string")); 86 | 87 | boost::io::out_of_range oor(1, 2, 3); 88 | BOOST_TEST(boost::contains(oor.what(), "out_of_range")); 89 | 90 | // bind and unbind 91 | boost::format two("%1%, %2%"); 92 | two.bind_arg(1, 1); 93 | two.bind_arg(2, 2); 94 | BOOST_TEST_EQ(two.str(), "1, 2"); 95 | 96 | two.clear_bind(1); 97 | BOOST_TEST_THROWS(two.str(), too_few_args); 98 | BOOST_TEST_THROWS(two.clear_bind(1), boost::io::out_of_range); 99 | two.exceptions(no_error_bits); 100 | two.clear_bind(1); 101 | two.str(); 102 | 103 | return boost::report_errors(); 104 | } 105 | 106 | -------------------------------------------------------------------------------- /test/format_test_wstring.cpp: -------------------------------------------------------------------------------- 1 | // ------------------------------------------------------------------------------ 2 | // format_test_wstring.cpp : test wchar_t format use (if supported) 3 | // ------------------------------------------------------------------------------ 4 | 5 | // Copyright Samuel Krempp 2003. Use, modification, and distribution are 6 | // subject to the Boost Software License, Version 1.0. (See accompanying 7 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 8 | 9 | // See http://www.boost.org/libs/format for library home page 10 | 11 | // ------------------------------------------------------------------------------ 12 | 13 | #include 14 | #include 15 | 16 | int main(int, char* []) 17 | { 18 | using boost::format; 19 | using boost::str; 20 | 21 | #if !defined(BOOST_NO_STD_WSTRING) && !defined(BOOST_NO_STD_WSTREAMBUF) 22 | using boost::wformat; 23 | wformat wfmter(L"%%##%%##%%1 %1%00"); 24 | if(str( wfmter % L"Escaped OK" ) != L"%##%##%1 Escaped OK00") 25 | BOOST_ERROR("Basic w-parsing Failed"); 26 | if(str( wformat(L"%%##%#x ##%%1 %s00") % 20 % L"Escaped OK" ) != L"%##0x14 ##%1 Escaped OK00") 27 | BOOST_ERROR("Basic wp-parsing Failed") ; 28 | 29 | // testcase for https://svn.boost.org/trac10/ticket/7379 (for valgrind) 30 | wformat wfmt(L"%1$.1f"); 31 | std::wstring ws = str(wfmt % 123.45f); 32 | BOOST_TEST_EQ(ws.compare(L"123.4"), 0); 33 | wformat wfmt2(L"%1$.0f %%"); 34 | std::wstring ws2 = (wfmt2 % 123.45f).str(); 35 | BOOST_TEST_EQ(ws2.compare(L"123 %"), 0); 36 | 37 | #endif // wformat tests 38 | 39 | return boost::report_errors(); 40 | } 41 | -------------------------------------------------------------------------------- /tools/Jamfile.v2: -------------------------------------------------------------------------------- 1 | # Boost.Format Library tools Jamfile 2 | # 3 | # Copyright (c) 2017 James E. King, III 4 | # 5 | # Distributed under the Boost Software License, Version 1.0. (See accompany- 6 | # ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 | 8 | project 9 | : requirements 10 | /boost/format//boost_format 11 | _CRT_SECURE_NO_WARNINGS 12 | static 13 | ; 14 | 15 | exe format_matrix 16 | : format_matrix.cpp 17 | /boost/array//boost_array 18 | /boost/filesystem//boost_filesystem 19 | /boost/program_options//boost_program_options 20 | /boost/system//boost_system 21 | ; 22 | --------------------------------------------------------------------------------