Update Spirit Po sources from source repo

This incorporates changes from cbeck88/spirit-po as of 111402d716b48486b7952bfe58b49fddbdcd9969 and
covers a period of approximately 16 months since the addition of this code to the Wesnoth repo in
June 2016. This also bumps our included Spirit Po version from 1.0.1 to 1.1.2.

I've retained our own changes from:
* fd671b1132

The following changes have been discarded in favor of changes made in the source repo:
* 69b070afb4
* 65dacf6bc7
* ae60ff80e6
* b4dc11ce36
This commit is contained in:
Charles Dang 2017-10-09 12:33:17 +11:00
parent b7ac634e78
commit 6f952a0dae
6 changed files with 90 additions and 45 deletions

View file

@ -6,10 +6,19 @@
#ifndef SPIRIT_PO_CATALOG_HPP_INCLUDED
#define SPIRIT_PO_CATALOG_HPP_INCLUDED
// This isn't necessary after boost 1.57 I think but we'll leave it here for compat
#ifndef BOOST_SPIRIT_USE_PHOENIX_V3
#define BOOST_SPIRIT_USE_PHOENIX_V3
#endif
// SPIRIT_PO_NO_EXCEPTIONS used to be named SPIRIT_PO_NOEXCEPT, but we leave this
// here to avoid breakage.
#if (!defined SPIRIT_PO_NO_EXCEPTIONS) && (defined SPIRIT_PO_NOEXCEPT)
#define SPIRIT_PO_NO_EXCEPTIONS
#endif
#include <spirit_po/catalog_metadata.hpp>
#include <spirit_po/default_plural_forms_compiler.hpp>
#include <spirit_po/exceptions.hpp>
@ -39,23 +48,23 @@ class catalog {
typename pf_compiler::result_type pf_function_object_;
uint singular_index_; // cached result of pf_function_object(1)
#ifdef SPIRIT_PO_NOEXCEPT
#ifdef SPIRIT_PO_NO_EXCEPTIONS
boost::optional<std::string> error_message_;
// if loading failed, error_message_ contains an error
// (rather than throwing an exception)
#endif // SPIRIT_PO_NOEXCEPT
#endif // SPIRIT_PO_NO_EXCEPTIONS
warning_channel_type warning_channel_;
hashmap_type hashmap_;
public:
static const char EOT = '\x4';
// ASCII 4 is EOT character
// Used to separate msg context from msgid in the hashmap, in MO files
// We use the same formatting system, just for consistency.
// c.f. https://www.gnu.org/software/gettext/manual/html_node/MO-Files.html
static std::string form_context_index(const std::string & msgctxt, const std::string & id) {
const char EOT = static_cast<char>(4);
// ASCII 4 is EOT character
// Used to separate msg context from msgid in the hashmap, in MO files
// We use the same formatting system, just for consistency.
// c.f. https://www.gnu.org/software/gettext/manual/html_node/MO-Files.html
return msgctxt + EOT + id;
}
@ -76,6 +85,7 @@ private:
const std::string & get(const po_message & msg, uint plural) const {
uint idx = (plural == 1 ? singular_index_ : pf_function_object_(plural));
if (idx >= msg.strings().size()) { idx = 0; }
return msg.strings()[idx];
}
@ -114,7 +124,7 @@ private:
}
public:
#ifdef SPIRIT_PO_NOEXCEPT
#ifdef SPIRIT_PO_NO_EXCEPTIONS
/***
* Error checking (this is done so we don't have to throw exceptions from the ctor.
*/
@ -125,7 +135,7 @@ public:
std::string error() const {
return *error_message_; // UB if there there is not an error message
}
#endif // SPIRIT_PO_NOEXCEPT
#endif // SPIRIT_PO_NO_EXCEPTIONS
/***
* Ctors
@ -134,6 +144,7 @@ public:
catalog(spirit::line_pos_iterator<Iterator> & it, spirit::line_pos_iterator<Iterator> & end, warning_channel_type warn_channel = warning_channel_type(), pf_compiler compiler = pf_compiler())
: metadata_()
, pf_function_object_()
, singular_index_(0)
, warning_channel_(warn_channel)
, hashmap_()
{
@ -186,7 +197,7 @@ public:
}
msg.line_no = line_no;
insert_message(std::move(msg)); // for compatibility, need to insert the header message at msgid ""
this->insert_message(std::move(msg)); // for compatibility, need to insert the header message at msgid ""
}
// Now parse non-fuzzy messages
@ -219,7 +230,7 @@ public:
}
msg.line_no = line_no;
// only insert it if it wasn't marked fuzzy
if (!fuzzy) { insert_message(std::move(msg)); }
if (!fuzzy) { this->insert_message(std::move(msg)); }
}
}
@ -280,7 +291,7 @@ public:
const char * gettext(const char * msgid) const {
auto it = hashmap_.find(msgid);
if (it != hashmap_.end()) {
return get(it->second).c_str();
return this->get(it->second).c_str();
} else {
return msgid;
}
@ -289,7 +300,7 @@ public:
const char * ngettext(const char * msgid, const char * msgid_plural, uint plural) const {
auto it = hashmap_.find(msgid);
if (it != hashmap_.end() && it->second.is_plural()) {
return get(it->second, plural).c_str();
return this->get(it->second, plural).c_str();
} else {
return (plural == 1 ? msgid : msgid_plural);
}
@ -298,7 +309,7 @@ public:
const char * pgettext(const char * context, const char * msgid) const {
auto it = hashmap_.find(form_context_index(context, msgid));
if (it != hashmap_.end()) {
return get(it->second).c_str();
return this->get(it->second).c_str();
} else {
return msgid;
}
@ -307,7 +318,7 @@ public:
const char * npgettext(const char * context, const char * msgid, const char * msgid_plural, uint plural) const {
auto it = hashmap_.find(form_context_index(context, msgid));
if (it != hashmap_.end() && it->second.is_plural()) {
return get(it->second, plural).c_str();
return this->get(it->second, plural).c_str();
} else {
return (plural == 1 ? msgid : msgid_plural);
}
@ -317,43 +328,78 @@ public:
* Lookup strings from catalog, return std::string.
*
* When, for whatever reason, it is more comfortable to use idiomatic C++.
*
* Template arguments here should always be `std::string &&` or `const std::string &`
*/
std::string gettext_str(const std::string & msgid) const {
private:
template <typename S>
std::string gettext_str_impl(S && msgid) const {
auto it = hashmap_.find(msgid);
if (it != hashmap_.end()) {
return get(it->second);
return this->get(it->second);
} else {
return msgid;
return std::forward<S>(msgid);
}
}
std::string ngettext_str(const std::string & msgid, const std::string & msgid_plural, uint plural) const {
template <typename S1, typename S2>
std::string ngettext_str_impl(S1 && msgid, S2 && msgid_plural, uint plural) const {
auto it = hashmap_.find(msgid);
if (it != hashmap_.end() && it->second.is_plural()) {
return get(it->second, plural);
return this->get(it->second, plural);
} else {
return (plural == 1 ? msgid : msgid_plural);
if (plural == 1) {
return std::forward<S1>(msgid);
} else {
return std::forward<S2>(msgid_plural);
}
}
}
std::string pgettext_str(const std::string & context, const std::string & msgid) const {
template <typename S>
std::string pgettext_str_impl(const std::string & context, S && msgid) const {
auto it = hashmap_.find(form_context_index(context, msgid));
if (it != hashmap_.end()) {
return get(it->second);
return this->get(it->second);
} else {
return msgid;
return std::forward<S>(msgid);
}
}
std::string npgettext_str(const std::string & context, const std::string & msgid, const std::string & msgid_plural, uint plural) const {
template <typename S1, typename S2>
std::string npgettext_str_impl(const std::string & context, S1 && msgid, S2 && msgid_plural, uint plural) const {
auto it = hashmap_.find(form_context_index(context, msgid));
if (it != hashmap_.end() && it->second.is_plural()) {
return get(it->second, plural);
return this->get(it->second, plural);
} else {
return (plural == 1 ? msgid : msgid_plural);
if (plural == 1) {
return std::forward<S1>(msgid);
} else {
return std::forward<S2>(msgid_plural);
}
}
}
public:
// Interface to implementations above, enforcing that arguments are `std::string`.
std::string gettext_str(const std::string & msgid) const { return this->gettext_str_impl(msgid); }
std::string gettext_str(std::string && msgid) const { return this->gettext_str_impl(std::move(msgid)); }
std::string ngettext_str(const std::string & msgid, const std::string & msgid_plural, uint plural) const { return this->ngettext_str_impl(msgid, msgid_plural, plural); }
std::string ngettext_str(std::string && msgid, const std::string & msgid_plural, uint plural) const { return this->ngettext_str_impl(std::move(msgid), msgid_plural, plural); }
std::string ngettext_str(const std::string & msgid, std::string && msgid_plural, uint plural) const { return this->ngettext_str_impl(msgid, std::move(msgid_plural), plural); }
std::string ngettext_str(std::string && msgid, std::string && msgid_plural, uint plural) const { return this->ngettext_str_impl(std::move(msgid), std::move(msgid_plural), plural); }
std::string pgettext_str(const std::string & context, const std::string & msgid) const { return this->pgettext_str_impl(context, msgid); }
std::string pgettext_str(const std::string & context, std::string && msgid) const { return this->pgettext_str_impl(context, std::move(msgid)); }
std::string npgettext_str(const std::string & context, const std::string & msgid, const std::string & msgid_plural, uint plural) const { return this->npgettext_str_impl(context, msgid, msgid_plural, plural); }
std::string npgettext_str(const std::string & context, std::string && msgid, const std::string & msgid_plural, uint plural) const { return this->npgettext_str_impl(context, std::move(msgid), msgid_plural, plural); }
std::string npgettext_str(const std::string & context, const std::string & msgid, std::string && msgid_plural, uint plural) const { return this->npgettext_str_impl(context, msgid, std::move(msgid_plural), plural); }
std::string npgettext_str(const std::string & context, std::string && msgid, std::string && msgid_plural, uint plural) const { return this->npgettext_str_impl(context, std::move(msgid), std::move(msgid_plural), plural); }
/***
* Get line numbers of messages
*/
@ -409,7 +455,7 @@ public:
}
for (auto & p : other.hashmap_) {
if (p.first.size()) { // don't copy over the header, keep our original header
insert_message(std::move(p.second));
this->insert_message(std::move(p.second));
}
}
}

View file

@ -66,7 +66,7 @@ private:
}
};
#define DEFAULT_CHARSET "UTF-8"
#define SPIRIT_PO_DEFAULT_CHARSET "UTF-8"
template <typename Iterator>
struct content_type_grammar : qi::grammar<Iterator, std::string()> {
@ -75,15 +75,15 @@ private:
using qi::lit;
using qi::omit;
using qi::skip;
main = skip(' ')[ omit[ *(qi::char_ - ';') >> lit(';') ] >> ((lit("charset=") >> *(qi::char_)) | qi::attr(DEFAULT_CHARSET)) ];
main = skip(' ')[ omit[ *(qi::char_ - ';') >> lit(';') ] >> ((lit("charset=") >> *(qi::char_)) | qi::attr(SPIRIT_PO_DEFAULT_CHARSET)) ];
}
};
public:
// nonempty return is an error mesage
std::string parse_header(const std::string & header) {
const char * default_charset = DEFAULT_CHARSET;
#undef DEFAULT_CHARSET
const char * const default_charset = SPIRIT_PO_DEFAULT_CHARSET;
#undef SPIRIT_PO_DEFAULT_CHARSET
project_id = find_header_line(header, "Project-Id-Version:");
language = find_header_line(header, "Language:");

View file

@ -83,8 +83,8 @@ class function_object {
boost::optional<std::string> parse_error_;
public:
function_object(const expr & _e) : machine_(_e), parse_error_() {}
function_object(const std::string & s) : machine_(n_var()), parse_error_(s) {}
explicit function_object(const expr & _e) : machine_(_e), parse_error_() {}
explicit function_object(const std::string & s) : machine_(constant{0}), parse_error_(s) {}
function_object() : function_object(std::string{"uninitialized"}) {}
uint operator()(uint n) const {
@ -113,7 +113,7 @@ struct compiler {
}
};
} // end namespace default_plura_forms
} // end namespace default_plural_forms
} // end namespace spirit_po

View file

@ -126,7 +126,7 @@ FOREACH_SPIRIT_PO_CONJUNCTION(EVAL_OP_)
*/
BOOST_FUSION_ADAPT_STRUCT(spirit_po::default_plural_forms::constant,
(spirit_po::uint, value))
(unsigned int, value))
BOOST_FUSION_ADAPT_STRUCT(spirit_po::default_plural_forms::not_op,
(spirit_po::default_plural_forms::expr, e1))
BOOST_FUSION_ADAPT_STRUCT(spirit_po::default_plural_forms::ternary_op,

View file

@ -6,7 +6,6 @@
#ifndef SPIRIT_PO_EXCEPTIONS_HPP_INCLUDED
#define SPIRIT_PO_EXCEPTIONS_HPP_INCLUDED
#include <spirit_po/default_plural_forms_expressions.hpp>
#include <boost/spirit/include/support_line_pos_iterator.hpp>
#include <string>
@ -48,7 +47,7 @@ inline std::string string_iterator_context(const std::string & str,
} // end namespace spirit_po
#ifdef SPIRIT_PO_NOEXCEPT
#ifdef SPIRIT_PO_NO_EXCEPTIONS
#define SPIRIT_PO_CATALOG_FAIL(Message) \
do { \
@ -56,15 +55,15 @@ do { \
return ; \
} while(0)
#else // SPIRIT_PO_NOEXCEPT
#else // SPIRIT_PO_NO_EXCEPTIONS
#include <stdexcept>
namespace spirit_po {
struct catalog_exception : std::runtime_error {
catalog_exception(const char * what) : runtime_error(what) {}
catalog_exception(const std::string & what) : runtime_error(what) {}
explicit catalog_exception(const char * what) : runtime_error(what) {}
explicit catalog_exception(const std::string & what) : runtime_error(what) {}
};
} // end namespace spirit_po
@ -75,6 +74,6 @@ do { \
} while(0)
#endif // SPIRIT_PO_NOEXCEPT
#endif // SPIRIT_PO_NO_EXCEPTIONS
#endif // SPIRIT_PO_EXCEPTIONS_HPP_INCLUDED

View file

@ -7,7 +7,7 @@
#define SPIRIT_PO_VERSION_HPP_INCLUDED
#define SPIRIT_PO_VERSION_MAJOR 1
#define SPIRIT_PO_VERSION_MINOR 0
#define SPIRIT_PO_VERSION_PATCH 1
#define SPIRIT_PO_VERSION_MINOR 1
#define SPIRIT_PO_VERSION_PATCH 2
#endif // SPIRIT_PO_VERSION_HPP_INCLUDED