Importing NetBSD "Kyua" test framework
To do so, a few dependencies have been imported: * external/bsd/lutok * external/mit/lua * external/public-domain/sqlite * external/public-domain/xz The Kyua framework is the new generation of ATF (Automated Test Framework), it is composed of: * external/bsd/atf * external/bsd/kyua-atf-compat * external/bsd/kyua-cli * external/bsd/kyua-tester * tests Kyua/ATF being written in C++, it depends on libstdc++ which is provided by GCC. As this is not part of the sources, Kyua is only compiled when the native GCC utils are installed. To install Kyua do the following: * In a cross-build enviromnent, add the following to the build.sh commandline: -V MKBINUTILS=yes -V MKGCCCMDS=yes WARNING: At this point the import is still experimental, and not supported on native builds (a.k.a make build). Change-Id: I26aee23c5bbd2d64adcb7c1beb98fe0d479d7ada
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
syntax(2)
|
||||
|
||||
test_suite("kyua")
|
||||
|
||||
atf_test_program{name="exceptions_test"}
|
||||
atf_test_program{name="formatter_test"}
|
||||
@@ -0,0 +1,110 @@
|
||||
// Copyright 2010 Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "utils/format/exceptions.hpp"
|
||||
|
||||
using utils::format::bad_format_error;
|
||||
using utils::format::error;
|
||||
using utils::format::extra_args_error;
|
||||
|
||||
|
||||
/// Constructs a new error with a plain-text message.
|
||||
///
|
||||
/// \param message The plain-text error message.
|
||||
error::error(const std::string& message) :
|
||||
std::runtime_error(message)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// Destructor for the error.
|
||||
error::~error(void) throw()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// Constructs a new bad_format_error.
|
||||
///
|
||||
/// \param format_ The invalid format string.
|
||||
/// \param message Description of the error in the format string.
|
||||
bad_format_error::bad_format_error(const std::string& format_,
|
||||
const std::string& message) :
|
||||
error("Invalid formatting string '" + format_ + "': " + message),
|
||||
_format(format_)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// Destructor for the error.
|
||||
bad_format_error::~bad_format_error(void) throw()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// Gets the invalid format string.
|
||||
const std::string&
|
||||
bad_format_error::format(void) const
|
||||
{
|
||||
return _format;
|
||||
}
|
||||
|
||||
|
||||
/// Constructs a new extra_args_error.
|
||||
///
|
||||
/// \param format_ The format string.
|
||||
/// \param arg_ The first extra argument passed to the format string.
|
||||
extra_args_error::extra_args_error(const std::string& format_,
|
||||
const std::string& arg_) :
|
||||
error("Not enough fields in formatting string '" + format_ + "' to place "
|
||||
"argument '" + arg_ + "'"),
|
||||
_format(format_),
|
||||
_arg(arg_)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// Destructor for the error.
|
||||
extra_args_error::~extra_args_error(void) throw()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// Gets the format string.
|
||||
const std::string&
|
||||
extra_args_error::format(void) const
|
||||
{
|
||||
return _format;
|
||||
}
|
||||
|
||||
|
||||
/// Gets the value of the first extra argument.
|
||||
const std::string&
|
||||
extra_args_error::arg(void) const
|
||||
{
|
||||
return _arg;
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
// Copyright 2010 Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/// \file utils/format/exceptions.hpp
|
||||
/// Exception types raised by the format module.
|
||||
|
||||
#if !defined(UTILS_FORMAT_EXCEPTIONS_HPP)
|
||||
#define UTILS_FORMAT_EXCEPTIONS_HPP
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
namespace utils {
|
||||
namespace format {
|
||||
|
||||
|
||||
/// Base exception for format errors.
|
||||
class error : public std::runtime_error {
|
||||
public:
|
||||
explicit error(const std::string&);
|
||||
virtual ~error(void) throw();
|
||||
};
|
||||
|
||||
|
||||
/// Error denoting a bad format string.
|
||||
class bad_format_error : public error {
|
||||
/// The format string that caused the error.
|
||||
std::string _format;
|
||||
|
||||
public:
|
||||
explicit bad_format_error(const std::string&, const std::string&);
|
||||
virtual ~bad_format_error(void) throw();
|
||||
|
||||
const std::string& format(void) const;
|
||||
};
|
||||
|
||||
|
||||
/// Error denoting too many arguments for the format string.
|
||||
class extra_args_error : public error {
|
||||
/// The format string that was passed too many arguments.
|
||||
std::string _format;
|
||||
|
||||
/// The first argument that caused the error.
|
||||
std::string _arg;
|
||||
|
||||
public:
|
||||
explicit extra_args_error(const std::string&, const std::string&);
|
||||
virtual ~extra_args_error(void) throw();
|
||||
|
||||
const std::string& format(void) const;
|
||||
const std::string& arg(void) const;
|
||||
};
|
||||
|
||||
|
||||
} // namespace format
|
||||
} // namespace utils
|
||||
|
||||
|
||||
#endif // !defined(UTILS_FORMAT_EXCEPTIONS_HPP)
|
||||
@@ -0,0 +1,74 @@
|
||||
// Copyright 2010 Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "utils/format/exceptions.hpp"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <atf-c++.hpp>
|
||||
|
||||
using utils::format::bad_format_error;
|
||||
using utils::format::error;
|
||||
using utils::format::extra_args_error;
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(error);
|
||||
ATF_TEST_CASE_BODY(error)
|
||||
{
|
||||
const error e("Some text");
|
||||
ATF_REQUIRE(std::strcmp("Some text", e.what()) == 0);
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(bad_format_error);
|
||||
ATF_TEST_CASE_BODY(bad_format_error)
|
||||
{
|
||||
const bad_format_error e("format-string", "the-error");
|
||||
ATF_REQUIRE(std::strcmp("Invalid formatting string 'format-string': "
|
||||
"the-error", e.what()) == 0);
|
||||
ATF_REQUIRE_EQ("format-string", e.format());
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(extra_args_error);
|
||||
ATF_TEST_CASE_BODY(extra_args_error)
|
||||
{
|
||||
const extra_args_error e("fmt", "extra");
|
||||
ATF_REQUIRE(std::strcmp("Not enough fields in formatting string 'fmt' to "
|
||||
"place argument 'extra'", e.what()) == 0);
|
||||
ATF_REQUIRE_EQ("fmt", e.format());
|
||||
ATF_REQUIRE_EQ("extra", e.arg());
|
||||
}
|
||||
|
||||
|
||||
ATF_INIT_TEST_CASES(tcs)
|
||||
{
|
||||
ATF_ADD_TEST_CASE(tcs, error);
|
||||
ATF_ADD_TEST_CASE(tcs, bad_format_error);
|
||||
ATF_ADD_TEST_CASE(tcs, extra_args_error);
|
||||
}
|
||||
@@ -0,0 +1,291 @@
|
||||
// Copyright 2010 Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "utils/format/formatter.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "utils/format/exceptions.hpp"
|
||||
#include "utils/sanity.hpp"
|
||||
#include "utils/text/exceptions.hpp"
|
||||
#include "utils/text/operations.ipp"
|
||||
|
||||
namespace format = utils::format;
|
||||
namespace text = utils::text;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
/// Finds the next placeholder in a string.
|
||||
///
|
||||
/// \param format The original format string provided by the user; needed for
|
||||
/// error reporting purposes only.
|
||||
/// \param expansion The string containing the placeholder to look for. Any
|
||||
/// '%%' in the string will be skipped, and they must be stripped later by
|
||||
/// strip_double_percent().
|
||||
/// \param begin The position from which to start looking for the next
|
||||
/// placeholder.
|
||||
///
|
||||
/// \return The position in the string in which the placeholder is located and
|
||||
/// the placeholder itself. If there are no placeholders left, this returns
|
||||
/// the length of the string and an empty string.
|
||||
///
|
||||
/// \throw bad_format_error If the input string contains a trailing formatting
|
||||
/// character. We cannot detect any other kind of invalid formatter because
|
||||
/// we do not implement a full parser for them.
|
||||
static std::pair< std::string::size_type, std::string >
|
||||
find_next_placeholder(const std::string& format,
|
||||
const std::string& expansion,
|
||||
std::string::size_type begin)
|
||||
{
|
||||
begin = expansion.find('%', begin);
|
||||
while (begin != std::string::npos && expansion[begin + 1] == '%')
|
||||
begin = expansion.find('%', begin + 2);
|
||||
if (begin == std::string::npos)
|
||||
return std::make_pair(expansion.length(), "");
|
||||
if (begin == expansion.length() - 1)
|
||||
throw format::bad_format_error(format, "Trailing %");
|
||||
|
||||
std::string::size_type end = begin + 1;
|
||||
while (end < expansion.length() && expansion[end] != 's')
|
||||
end++;
|
||||
const std::string placeholder = expansion.substr(begin, end - begin + 1);
|
||||
if (end == expansion.length() ||
|
||||
placeholder.find('%', 1) != std::string::npos)
|
||||
throw format::bad_format_error(format, "Unterminated placeholder '" +
|
||||
placeholder + "'");
|
||||
return std::make_pair(begin, placeholder);
|
||||
}
|
||||
|
||||
|
||||
/// Converts a string to an integer.
|
||||
///
|
||||
/// \param format The format string; for error reporting purposes only.
|
||||
/// \param str The string to conver.
|
||||
/// \param what The name of the field this integer belongs to; for error
|
||||
/// reporting purposes only.
|
||||
///
|
||||
/// \return An integer representing the input string.
|
||||
inline int
|
||||
to_int(const std::string& format, const std::string& str, const char* what)
|
||||
{
|
||||
try {
|
||||
return text::to_type< int >(str);
|
||||
} catch (const text::value_error& e) {
|
||||
throw format::bad_format_error(format, "Invalid " + std::string(what) +
|
||||
"specifier");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Constructs an std::ostringstream based on a formatting placeholder.
|
||||
///
|
||||
/// \param format The format placeholder; may be empty.
|
||||
///
|
||||
/// \return A new std::ostringstream that is prepared to format a single
|
||||
/// object in the manner specified by the format placeholder.
|
||||
///
|
||||
/// \throw bad_format_error If the format string is bad. We do minimal
|
||||
/// validation on this string though.
|
||||
static std::ostringstream*
|
||||
new_ostringstream(const std::string& format)
|
||||
{
|
||||
std::auto_ptr< std::ostringstream > output(new std::ostringstream());
|
||||
|
||||
if (format.length() <= 2) {
|
||||
// If the format is empty, we create a new stream so that we don't have
|
||||
// to check for NULLs later on. We rarely should hit this condition
|
||||
// (and when we do it's a bug in the caller), so this is not a big deal.
|
||||
//
|
||||
// Otherwise, if the format is a regular '%s', then we don't have to do
|
||||
// any processing for additional formatters. So this is just a "fast
|
||||
// path".
|
||||
} else {
|
||||
std::string partial = format.substr(1, format.length() - 2);
|
||||
if (partial[0] == '0') {
|
||||
output->fill('0');
|
||||
partial.erase(0, 1);
|
||||
}
|
||||
if (!partial.empty()) {
|
||||
const std::string::size_type dot = partial.find('.');
|
||||
if (dot != 0)
|
||||
output->width(to_int(format, partial.substr(0, dot), "width"));
|
||||
if (dot != std::string::npos) {
|
||||
output->setf(std::ios::fixed, std::ios::floatfield);
|
||||
output->precision(to_int(format, partial.substr(dot + 1),
|
||||
"precision"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return output.release();
|
||||
}
|
||||
|
||||
|
||||
/// Replaces '%%' by '%' in a given string range.
|
||||
///
|
||||
/// \param in The input string to be rewritten.
|
||||
/// \param begin The position at which to start the replacement.
|
||||
/// \param end The position at which to end the replacement.
|
||||
///
|
||||
/// \return The modified string and the amount of characters removed.
|
||||
static std::pair< std::string, int >
|
||||
strip_double_percent(const std::string& in, const std::string::size_type begin,
|
||||
std::string::size_type end)
|
||||
{
|
||||
std::string part = in.substr(begin, end - begin);
|
||||
|
||||
int removed = 0;
|
||||
std::string::size_type pos = part.find("%%");
|
||||
while (pos != std::string::npos) {
|
||||
part.erase(pos, 1);
|
||||
++removed;
|
||||
pos = part.find("%%", pos + 1);
|
||||
}
|
||||
|
||||
return std::make_pair(in.substr(0, begin) + part + in.substr(end), removed);
|
||||
}
|
||||
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
/// Performs internal initialization of the formatter.
|
||||
///
|
||||
/// This is separate from the constructor just because it is shared by different
|
||||
/// overloaded constructors.
|
||||
void
|
||||
format::formatter::init(void)
|
||||
{
|
||||
const std::pair< std::string::size_type, std::string > placeholder =
|
||||
find_next_placeholder(_format, _expansion, _last_pos);
|
||||
const std::pair< std::string, int > no_percents =
|
||||
strip_double_percent(_expansion, _last_pos, placeholder.first);
|
||||
|
||||
_oss = new_ostringstream(placeholder.second);
|
||||
|
||||
_expansion = no_percents.first;
|
||||
_placeholder_pos = placeholder.first - no_percents.second;
|
||||
_placeholder = placeholder.second;
|
||||
}
|
||||
|
||||
|
||||
/// Constructs a new formatter object (internal).
|
||||
///
|
||||
/// \param format The format string.
|
||||
/// \param expansion The format string with any replacements performed so far.
|
||||
/// \param last_pos The position from which to start looking for formatting
|
||||
/// placeholders. This must be maintained in case one of the replacements
|
||||
/// introduced a new placeholder, which must be ignored. Think, for
|
||||
/// example, replacing a "%s" string with "foo %s".
|
||||
format::formatter::formatter(const std::string& format,
|
||||
const std::string& expansion,
|
||||
const std::string::size_type last_pos) :
|
||||
_format(format),
|
||||
_expansion(expansion),
|
||||
_last_pos(last_pos),
|
||||
_oss(NULL)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
/// Constructs a new formatter object.
|
||||
///
|
||||
/// \param format The format string. The formatters in the string are not
|
||||
/// validated during construction, but will cause errors when used later if
|
||||
/// they are invalid.
|
||||
format::formatter::formatter(const std::string& format) :
|
||||
_format(format),
|
||||
_expansion(format),
|
||||
_last_pos(0),
|
||||
_oss(NULL)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
format::formatter::~formatter(void)
|
||||
{
|
||||
delete _oss;
|
||||
}
|
||||
|
||||
|
||||
/// Returns the formatted string.
|
||||
const std::string&
|
||||
format::formatter::str(void) const
|
||||
{
|
||||
return _expansion;
|
||||
}
|
||||
|
||||
|
||||
/// Automatic conversion of formatter objects to strings.
|
||||
///
|
||||
/// This is provided to allow painless injection of formatter objects into
|
||||
/// streams, without having to manually call the str() method.
|
||||
format::formatter::operator const std::string&(void) const
|
||||
{
|
||||
return _expansion;
|
||||
}
|
||||
|
||||
|
||||
/// Specialization of operator% for booleans.
|
||||
///
|
||||
/// \param value The boolean to inject into the format string.
|
||||
///
|
||||
/// \return A new formatter that has one less format placeholder.
|
||||
format::formatter
|
||||
format::formatter::operator%(const bool& value) const
|
||||
{
|
||||
(*_oss) << (value ? "true" : "false");
|
||||
return replace(_oss->str());
|
||||
}
|
||||
|
||||
|
||||
/// Replaces the first formatting placeholder with a value.
|
||||
///
|
||||
/// \param arg The replacement string.
|
||||
///
|
||||
/// \return A new formatter in which the first formatting placeholder has been
|
||||
/// replaced by arg and is ready to replace the next item.
|
||||
///
|
||||
/// \throw utils::format::extra_args_error If there are no more formatting
|
||||
/// placeholders in the input string, or if the placeholder is invalid.
|
||||
format::formatter
|
||||
format::formatter::replace(const std::string& arg) const
|
||||
{
|
||||
if (_placeholder_pos == _expansion.length())
|
||||
throw format::extra_args_error(_format, arg);
|
||||
|
||||
const std::string expansion = _expansion.substr(0, _placeholder_pos)
|
||||
+ arg + _expansion.substr(_placeholder_pos + _placeholder.length());
|
||||
return formatter(_format, expansion, _placeholder_pos + arg.length());
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
// Copyright 2010 Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/// \file utils/format/formatter.hpp
|
||||
/// Provides the definition of the utils::format::formatter class.
|
||||
///
|
||||
/// The utils::format::formatter class is a poor man's replacement for the
|
||||
/// Boost.Format library, as it is much simpler and has less dependencies.
|
||||
///
|
||||
/// Be aware that the formatting supported by this module is NOT compatible
|
||||
/// with printf(3) nor with Boost.Format. The general syntax for a
|
||||
/// placeholder in a formatting string is:
|
||||
///
|
||||
/// %[0][width][.precision]s
|
||||
///
|
||||
/// In particular, note that the only valid formatting specifier is %s: the
|
||||
/// library deduces what to print based on the type of the variable passed
|
||||
/// in, not based on what the format string says. Also, note that the only
|
||||
/// valid padding character is 0.
|
||||
|
||||
#if !defined(UTILS_FORMAT_FORMATTER_HPP)
|
||||
#define UTILS_FORMAT_FORMATTER_HPP
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
namespace utils {
|
||||
namespace format {
|
||||
|
||||
|
||||
/// Mechanism to format strings similar to printf.
|
||||
///
|
||||
/// A formatter always maintains the original format string but also holds a
|
||||
/// partial expansion. The partial expansion is immutable in the context of a
|
||||
/// formatter instance, but calls to operator% return new formatter objects with
|
||||
/// one less formatting placeholder.
|
||||
///
|
||||
/// In general, one can format a string in the following manner:
|
||||
///
|
||||
/// \code
|
||||
/// const std::string s = (formatter("%s %s") % "foo" % 5).str();
|
||||
/// \endcode
|
||||
///
|
||||
/// which, following the explanation above, would correspond to:
|
||||
///
|
||||
/// \code
|
||||
/// const formatter f1("%s %s");
|
||||
/// const formatter f2 = f1 % "foo";
|
||||
/// const formatter f3 = f2 % 5;
|
||||
/// const std::string s = f3.str();
|
||||
/// \endcode
|
||||
class formatter {
|
||||
/// The original format string provided by the user.
|
||||
std::string _format;
|
||||
|
||||
/// The current "expansion" of the format string.
|
||||
///
|
||||
/// This field gets updated on every call to operator%() to have one less
|
||||
/// formatting placeholder.
|
||||
std::string _expansion;
|
||||
|
||||
/// The position of _expansion from which to scan for placeholders.
|
||||
std::string::size_type _last_pos;
|
||||
|
||||
/// The position of the first placeholder in the current expansion.
|
||||
std::string::size_type _placeholder_pos;
|
||||
|
||||
/// The first placeholder in the current expansion.
|
||||
std::string _placeholder;
|
||||
|
||||
/// Stream used to format any possible argument supplied by operator%().
|
||||
std::ostringstream* _oss;
|
||||
|
||||
formatter replace(const std::string&) const;
|
||||
|
||||
void init(void);
|
||||
formatter(const std::string&, const std::string&,
|
||||
const std::string::size_type);
|
||||
|
||||
public:
|
||||
explicit formatter(const std::string&);
|
||||
~formatter(void);
|
||||
|
||||
const std::string& str(void) const;
|
||||
operator const std::string&(void) const;
|
||||
|
||||
template< typename Type > formatter operator%(const Type&) const;
|
||||
formatter operator%(const bool&) const;
|
||||
};
|
||||
|
||||
|
||||
} // namespace format
|
||||
} // namespace utils
|
||||
|
||||
|
||||
#endif // !defined(UTILS_FORMAT_FORMATTER_HPP)
|
||||
@@ -0,0 +1,76 @@
|
||||
// Copyright 2010 Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#if !defined(UTILS_FORMAT_FORMATTER_IPP)
|
||||
#define UTILS_FORMAT_FORMATTER_IPP
|
||||
|
||||
#include <ostream>
|
||||
|
||||
#include "utils/format/formatter.hpp"
|
||||
|
||||
namespace utils {
|
||||
namespace format {
|
||||
|
||||
|
||||
/// Replaces the first format placeholder in a formatter.
|
||||
///
|
||||
/// Constructs a new formatter object that has one less formatting placeholder,
|
||||
/// as this has been replaced by the provided argument. Calling this operator
|
||||
/// N times, where N is the number of formatting placeholders, effectively
|
||||
/// formats the string.
|
||||
///
|
||||
/// \param arg The argument to use as replacement for the format placeholder.
|
||||
///
|
||||
/// \return A new formatter that has one less format placeholder.
|
||||
template< typename Type >
|
||||
inline formatter
|
||||
formatter::operator%(const Type& arg) const
|
||||
{
|
||||
(*_oss) << arg;
|
||||
return replace(_oss->str());
|
||||
}
|
||||
|
||||
|
||||
/// Inserts a formatter string into a stream.
|
||||
///
|
||||
/// \param os The output stream.
|
||||
/// \param f The formatter to process and inject into the stream.
|
||||
///
|
||||
/// \return The output stream os.
|
||||
inline std::ostream&
|
||||
operator<<(std::ostream& os, const formatter& f)
|
||||
{
|
||||
return (os << f.str());
|
||||
}
|
||||
|
||||
|
||||
} // namespace format
|
||||
} // namespace utils
|
||||
|
||||
|
||||
#endif // !defined(UTILS_FORMAT_FORMATTER_IPP)
|
||||
@@ -0,0 +1,265 @@
|
||||
// Copyright 2010 Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "utils/format/formatter.hpp"
|
||||
|
||||
#include <ostream>
|
||||
|
||||
#include <atf-c++.hpp>
|
||||
|
||||
#include "utils/format/exceptions.hpp"
|
||||
#include "utils/format/macros.hpp"
|
||||
|
||||
namespace format = utils::format;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
/// Wraps an integer in a C++ class.
|
||||
///
|
||||
/// This custom type exists to ensure that we can feed arbitrary objects that
|
||||
/// support operator<< to the formatter;
|
||||
class int_wrapper {
|
||||
/// The wrapped integer.
|
||||
int _value;
|
||||
|
||||
public:
|
||||
/// Constructs a new wrapper.
|
||||
///
|
||||
/// \param value_ The value to wrap.
|
||||
int_wrapper(const int value_) : _value(value_)
|
||||
{
|
||||
}
|
||||
|
||||
/// Returns the wrapped value.
|
||||
///
|
||||
/// \return An integer.
|
||||
int
|
||||
value(void) const
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// Writes a wrapped integer into an output stream.
|
||||
///
|
||||
/// \param output The output stream into which to place the integer.
|
||||
/// \param wrapper The wrapped integer.
|
||||
///
|
||||
/// \return The output stream.
|
||||
std::ostream&
|
||||
operator<<(std::ostream& output, const int_wrapper& wrapper)
|
||||
{
|
||||
return (output << wrapper.value());
|
||||
}
|
||||
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
/// Calls ATF_REQUIRE_EQ on an expected string and a formatter.
|
||||
///
|
||||
/// This is pure syntactic sugar to avoid calling the str() method on all the
|
||||
/// individual tests below, which results in very long lines that require
|
||||
/// wrapping and clutter readability.
|
||||
///
|
||||
/// \param expected The expected string generated by the formatter.
|
||||
/// \param formatter The formatter to test.
|
||||
#define EQ(expected, formatter) ATF_REQUIRE_EQ(expected, (formatter).str())
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(no_fields);
|
||||
ATF_TEST_CASE_BODY(no_fields)
|
||||
{
|
||||
EQ("Plain string", F("Plain string"));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(one_field);
|
||||
ATF_TEST_CASE_BODY(one_field)
|
||||
{
|
||||
EQ("foo", F("%sfoo") % "");
|
||||
EQ(" foo", F("%sfoo") % " ");
|
||||
EQ("foo ", F("foo %s") % "");
|
||||
EQ("foo bar", F("foo %s") % "bar");
|
||||
EQ("foo bar baz", F("foo %s baz") % "bar");
|
||||
EQ("foo %s %s", F("foo %s %s") % "%s" % "%s");
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(many_fields);
|
||||
ATF_TEST_CASE_BODY(many_fields)
|
||||
{
|
||||
EQ("", F("%s%s") % "" % "");
|
||||
EQ("foo", F("%s%s%s") % "" % "foo" % "");
|
||||
EQ("some 5 text", F("%s %s %s") % "some" % 5 % "text");
|
||||
EQ("f%s 5 text", F("%s %s %s") % "f%s" % 5 % "text");
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(escape);
|
||||
ATF_TEST_CASE_BODY(escape)
|
||||
{
|
||||
EQ("%", F("%%"));
|
||||
EQ("% %", F("%% %%"));
|
||||
EQ("%% %%", F("%%%% %%%%"));
|
||||
|
||||
EQ("foo %", F("foo %%"));
|
||||
EQ("foo bar %", F("foo %s %%") % "bar");
|
||||
EQ("foo % bar", F("foo %% %s") % "bar");
|
||||
|
||||
EQ("foo %%", F("foo %s") % "%%");
|
||||
EQ("foo a%%b", F("foo a%sb") % "%%");
|
||||
EQ("foo a%%b", F("foo %s") % "a%%b");
|
||||
|
||||
EQ("foo % bar %%", F("foo %% %s %%%%") % "bar");
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(extra_args_error);
|
||||
ATF_TEST_CASE_BODY(extra_args_error)
|
||||
{
|
||||
using format::extra_args_error;
|
||||
|
||||
ATF_REQUIRE_THROW(extra_args_error, F("foo") % "bar");
|
||||
ATF_REQUIRE_THROW(extra_args_error, F("foo %%") % "bar");
|
||||
ATF_REQUIRE_THROW(extra_args_error, F("foo %s") % "bar" % "baz");
|
||||
ATF_REQUIRE_THROW(extra_args_error, F("foo %s") % "%s" % "bar");
|
||||
ATF_REQUIRE_THROW(extra_args_error, F("%s foo %s") % "bar" % "baz" % "foo");
|
||||
|
||||
try {
|
||||
F("foo %s %s") % "bar" % "baz" % "something extra";
|
||||
fail("extra_args_error not raised");
|
||||
} catch (const extra_args_error& e) {
|
||||
ATF_REQUIRE_EQ("foo %s %s", e.format());
|
||||
ATF_REQUIRE_EQ("something extra", e.arg());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(format__class);
|
||||
ATF_TEST_CASE_BODY(format__class)
|
||||
{
|
||||
EQ("foo bar", F("%s") % std::string("foo bar"));
|
||||
EQ("3", F("%s") % int_wrapper(3));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(format__pointer);
|
||||
ATF_TEST_CASE_BODY(format__pointer)
|
||||
{
|
||||
EQ("0xcafebabe", F("%s") % reinterpret_cast< void* >(0xcafebabe));
|
||||
EQ("foo bar", F("%s") % "foo bar");
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(format__bool);
|
||||
ATF_TEST_CASE_BODY(format__bool)
|
||||
{
|
||||
EQ("true", F("%s") % true);
|
||||
EQ("false", F("%s") % false);
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(format__char);
|
||||
ATF_TEST_CASE_BODY(format__char)
|
||||
{
|
||||
EQ("Z", F("%s") % 'Z');
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(format__float);
|
||||
ATF_TEST_CASE_BODY(format__float)
|
||||
{
|
||||
EQ("3", F("%s") % 3.0);
|
||||
EQ("3.0", F("%.1s") % 3.0);
|
||||
EQ("3.0", F("%0.1s") % 3.0);
|
||||
EQ(" 15.600", F("%8.3s") % 15.6);
|
||||
EQ("01.52", F("%05.2s") % 1.52);
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(format__int);
|
||||
ATF_TEST_CASE_BODY(format__int)
|
||||
{
|
||||
EQ("3", F("%s") % 3);
|
||||
EQ("3", F("%0s") % 3);
|
||||
EQ(" -123", F("%5s") % -123);
|
||||
EQ("00078", F("%05s") % 78);
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(format__error);
|
||||
ATF_TEST_CASE_BODY(format__error)
|
||||
{
|
||||
using format::bad_format_error;
|
||||
|
||||
ATF_REQUIRE_THROW_RE(bad_format_error, "Trailing %", F("%"));
|
||||
ATF_REQUIRE_THROW_RE(bad_format_error, "Trailing %", F("f%"));
|
||||
ATF_REQUIRE_THROW_RE(bad_format_error, "Trailing %", F("f%%%"));
|
||||
ATF_REQUIRE_THROW_RE(bad_format_error, "Trailing %", F("ab %s cd%") % "cd");
|
||||
|
||||
ATF_REQUIRE_THROW_RE(bad_format_error, "Invalid width", F("%1bs"));
|
||||
|
||||
ATF_REQUIRE_THROW_RE(bad_format_error, "Invalid precision", F("%.s"));
|
||||
ATF_REQUIRE_THROW_RE(bad_format_error, "Invalid precision", F("%0.s"));
|
||||
ATF_REQUIRE_THROW_RE(bad_format_error, "Invalid precision", F("%123.s"));
|
||||
ATF_REQUIRE_THROW_RE(bad_format_error, "Invalid precision", F("%.12bs"));
|
||||
|
||||
ATF_REQUIRE_THROW_RE(bad_format_error, "Unterminated", F("%c") % 'Z');
|
||||
ATF_REQUIRE_THROW_RE(bad_format_error, "Unterminated", F("%d") % 5);
|
||||
ATF_REQUIRE_THROW_RE(bad_format_error, "Unterminated", F("%.1f") % 3);
|
||||
ATF_REQUIRE_THROW_RE(bad_format_error, "Unterminated", F("%d%s") % 3 % "a");
|
||||
|
||||
try {
|
||||
F("foo %s%") % "bar";
|
||||
fail("bad_format_error not raised");
|
||||
} catch (const bad_format_error& e) {
|
||||
ATF_REQUIRE_EQ("foo %s%", e.format());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ATF_INIT_TEST_CASES(tcs)
|
||||
{
|
||||
ATF_ADD_TEST_CASE(tcs, no_fields);
|
||||
ATF_ADD_TEST_CASE(tcs, one_field);
|
||||
ATF_ADD_TEST_CASE(tcs, many_fields);
|
||||
ATF_ADD_TEST_CASE(tcs, escape);
|
||||
ATF_ADD_TEST_CASE(tcs, extra_args_error);
|
||||
|
||||
ATF_ADD_TEST_CASE(tcs, format__class);
|
||||
ATF_ADD_TEST_CASE(tcs, format__pointer);
|
||||
ATF_ADD_TEST_CASE(tcs, format__bool);
|
||||
ATF_ADD_TEST_CASE(tcs, format__char);
|
||||
ATF_ADD_TEST_CASE(tcs, format__float);
|
||||
ATF_ADD_TEST_CASE(tcs, format__int);
|
||||
ATF_ADD_TEST_CASE(tcs, format__error);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// Copyright 2010 Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/// \file utils/format/macros.hpp
|
||||
/// Convenience macros to simplify usage of the format library.
|
||||
///
|
||||
/// This file <em>must not be included from other header files</em>.
|
||||
|
||||
#if !defined(UTILS_FORMAT_MACROS_HPP)
|
||||
#define UTILS_FORMAT_MACROS_HPP
|
||||
|
||||
// We include the .ipp file instead of .hpp because, after all, macros.hpp
|
||||
// is provided purely for convenience and must not be included from other
|
||||
// header files. Henceforth, we make things easier to the callers.
|
||||
#include "utils/format/formatter.ipp"
|
||||
|
||||
|
||||
/// Constructs a utils::format::formatter object with the given format string.
|
||||
///
|
||||
/// This macro is just a wrapper to make the construction of
|
||||
/// utils::format::formatter objects shorter, and thus to allow inlining these
|
||||
/// calls right in where formatted strings are required. A typical usage would
|
||||
/// look like:
|
||||
///
|
||||
/// \code
|
||||
/// std::cout << F("%s %d\n") % my_str % my_int;
|
||||
/// \endcode
|
||||
///
|
||||
/// \param fmt The format string.
|
||||
#define F(fmt) utils::format::formatter(fmt)
|
||||
|
||||
|
||||
#endif // !defined(UTILS_FORMAT_MACROS_HPP)
|
||||
Reference in New Issue
Block a user