Use a "format accumulator" for error strings
This makes it possible to internationalize strings while still using
I/O streams. For example:
std::cout << ACCUM(_("Hello to %1 and %2!") << "me" << "you")
<< std::endl;
This commit is contained in:
parent
a577e8c48e
commit
66c5cd4427
5 changed files with 187 additions and 4 deletions
|
|
@ -18,6 +18,7 @@ libledger_util_la_SOURCES = \
|
|||
src/times.cc \
|
||||
src/error.cc \
|
||||
src/utils.cc \
|
||||
src/accum.cc \
|
||||
lib/sha1.cpp
|
||||
|
||||
libledger_util_la_CPPFLAGS = $(lib_cppflags)
|
||||
|
|
@ -86,6 +87,7 @@ pkginclude_HEADERS = \
|
|||
src/stream.h \
|
||||
src/pstream.h \
|
||||
src/unistring.h \
|
||||
src/accum.h \
|
||||
\
|
||||
src/amount.h \
|
||||
src/commodity.h \
|
||||
|
|
|
|||
70
src/accum.cc
Normal file
70
src/accum.cc
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC 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.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
std::streamsize straccbuf::xsputn(const char * s, std::streamsize num)
|
||||
{
|
||||
if (index == 0) {
|
||||
// The first item received is the format string
|
||||
str = std::string(s, num);
|
||||
index++;
|
||||
return num;
|
||||
}
|
||||
else {
|
||||
std::ostringstream buf;
|
||||
|
||||
// Every item thereafter is an argument that substitutes for %# in the
|
||||
// format string
|
||||
for (const char * p = str.c_str(); *p; p++) {
|
||||
if (*p == '%') {
|
||||
const char * q = p + 1;
|
||||
if (*q && *q != '%' && std::isdigit(*q) &&
|
||||
std::size_t(*q - '0') == index) {
|
||||
p++;
|
||||
buf << std::string(s, num);
|
||||
} else {
|
||||
buf << *p;
|
||||
}
|
||||
} else {
|
||||
buf << *p;
|
||||
}
|
||||
}
|
||||
str = buf.str();
|
||||
index++;
|
||||
|
||||
return num;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ledger
|
||||
100
src/accum.h
Normal file
100
src/accum.h
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2009, John Wiegley. 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 New Artisans LLC 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup util
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file accum.h
|
||||
* @author John Wiegley
|
||||
*
|
||||
* @ingroup util
|
||||
*
|
||||
* @brief Brief
|
||||
*
|
||||
* Full.
|
||||
*/
|
||||
#ifndef _ACCUM_H
|
||||
#define _ACCUM_H
|
||||
|
||||
namespace ledger {
|
||||
|
||||
/**
|
||||
* @brief Brief
|
||||
*
|
||||
* Full.
|
||||
*/
|
||||
class straccbuf : public std::streambuf
|
||||
{
|
||||
protected:
|
||||
std::string str; // accumulator
|
||||
std::size_t index;
|
||||
|
||||
public:
|
||||
straccbuf() : index(0) {}
|
||||
|
||||
protected:
|
||||
virtual std::streamsize xsputn(const char * s, std::streamsize num);
|
||||
|
||||
friend class straccstream;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Brief
|
||||
*
|
||||
* Full.
|
||||
*/
|
||||
class straccstream : public std::ostream
|
||||
{
|
||||
protected:
|
||||
straccbuf buf;
|
||||
|
||||
public:
|
||||
straccstream() : std::ostream(0) {
|
||||
rdbuf(&buf);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
buf.str.clear();
|
||||
buf.index = 0;
|
||||
}
|
||||
|
||||
std::string str() const {
|
||||
return buf.str;
|
||||
}
|
||||
};
|
||||
|
||||
#define ACCUM(obj) (static_cast<straccstream&>(obj).str())
|
||||
|
||||
} // namespace ledger
|
||||
|
||||
#endif // _ACCUM_H
|
||||
|
|
@ -33,8 +33,10 @@
|
|||
|
||||
namespace ledger {
|
||||
|
||||
std::ostringstream _desc_buffer;
|
||||
straccstream _ctxt_accum;
|
||||
std::ostringstream _ctxt_buffer;
|
||||
straccstream _desc_accum;
|
||||
std::ostringstream _desc_buffer;
|
||||
|
||||
string error_context()
|
||||
{
|
||||
|
|
|
|||
15
src/error.h
15
src/error.h
|
|
@ -46,8 +46,11 @@
|
|||
#ifndef _ERROR_H
|
||||
#define _ERROR_H
|
||||
|
||||
#include "accum.h"
|
||||
|
||||
namespace ledger {
|
||||
|
||||
extern straccstream _desc_accum;
|
||||
extern std::ostringstream _desc_buffer;
|
||||
|
||||
template <typename T>
|
||||
|
|
@ -56,14 +59,20 @@ inline void throw_func(const string& message) {
|
|||
throw T(message);
|
||||
}
|
||||
|
||||
#define throw_(cls, msg) \
|
||||
((_desc_buffer << msg), throw_func<cls>(_desc_buffer.str()))
|
||||
#define throw_(cls, msg) \
|
||||
((_desc_buffer << ACCUM(_desc_accum << msg)), \
|
||||
_desc_accum.clear(), \
|
||||
throw_func<cls>(_desc_buffer.str()))
|
||||
|
||||
extern straccstream _ctxt_accum;
|
||||
extern std::ostringstream _ctxt_buffer;
|
||||
|
||||
#define add_error_context(msg) \
|
||||
((long(_ctxt_buffer.tellp()) == 0) ? \
|
||||
(_ctxt_buffer << msg) : (_ctxt_buffer << std::endl << msg))
|
||||
((_ctxt_buffer << ACCUM(_ctxt_accum << msg)), \
|
||||
_ctxt_accum.clear()) : \
|
||||
((_ctxt_buffer << std::endl << ACCUM(_ctxt_accum << msg)), \
|
||||
_ctxt_accum.clear()))
|
||||
|
||||
string error_context();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue