diff --git a/examples/XSLT/mangle.cpp b/examples/XSLT/mangle.cpp index 1d992f53..9e99abb6 100755 --- a/examples/XSLT/mangle.cpp +++ b/examples/XSLT/mangle.cpp @@ -1,18 +1,14 @@ #ifdef _MSC_VER -#pragma warning(disable : 4250) +#pragma warning(disable : 4250 4244) #endif #include #include #include -#include -#include -#include #include -Arabica::DOM::Document buildDOM(const std::wstring& xml); -typedef Arabica::default_string_adaptor adaptor; +Arabica::DOM::Document buildDOM(const std::string & xml); int main(int argc, const char* argv[]) { @@ -24,12 +20,12 @@ int main(int argc, const char* argv[]) return 0; } // if ... - Arabica::XSLT::StylesheetCompiler compiler; - std::wostringstream errors; + Arabica::XSLT::StylesheetCompiler compiler; + std::ostringstream errors; try { - Arabica::SAX::InputSource source(adaptor::construct_from_utf8(argv[2])); - std::auto_ptr > stylesheet = compiler.compile(source); + Arabica::SAX::InputSource source(argv[2]); + std::auto_ptr > stylesheet = compiler.compile(source); if(stylesheet.get() == 0) { std::cerr << "Couldn't compile stylesheet: " << compiler.error() << std::endl; @@ -38,41 +34,28 @@ int main(int argc, const char* argv[]) stylesheet->set_error_output(errors); - Arabica::DOM::Document document = buildDOM(adaptor::construct_from_utf8(argv[1])); + Arabica::DOM::Document document = buildDOM(argv[1]); if(document == 0) { std::cerr << "Could not parse XML source" << std::endl; return 0; } // if ... - //document.normalize(); stylesheet->execute(document); - -/* - std::cout << "\n==============" << std::endl; - - Arabica::XSLT::DOMSink output; - stylesheet->set_output(output); - - stylesheet->execute(document); - - Arabica::DOM::Node node = output.node(); - std::cout << node << std::endl; -*/ } catch(const std::runtime_error& ex) { std::cerr << ex.what() << std::endl; } // catch - std::wcerr << "\n\n" << errors.str() << std::endl; + std::cerr << "\n\n" << errors.str() << std::endl; return 0; } // main -Arabica::DOM::Document buildDOM(const std::wstring& filename) +Arabica::DOM::Document buildDOM(const std::string & filename) { - Arabica::SAX::InputSource is(filename); - Arabica::SAX2DOM::Parser parser; + Arabica::SAX::InputSource is(filename); + Arabica::SAX2DOM::Parser parser; parser.parse(is); return parser.getDocument(); diff --git a/include/Arabica/StringAdaptor.hpp b/include/Arabica/StringAdaptor.hpp index 75cac5a4..41d1fc2e 100644 --- a/include/Arabica/StringAdaptor.hpp +++ b/include/Arabica/StringAdaptor.hpp @@ -1,217 +1,226 @@ -#ifndef ARABICA_UTILS_STRING_ADAPTOR_H -#define ARABICA_UTILS_STRING_ADAPTOR_H - -#include -#include -#include -#include -#include - -namespace Arabica -{ - -template class default_string_adaptor; - -template -class default_string_adaptor_base -{ -public: - typedef stringT string_type; - typedef typename string_type::const_iterator const_iterator; - typedef typename string_type::iterator mutable_iterator; - typedef typename string_type::iterator iterator; - typedef typename string_type::value_type value_type; - typedef typename string_type::size_type size_type; - - virtual ~default_string_adaptor_base() {} - - static size_type npos() - { - return static_cast(-1); - } - - //todo: is this safe? - template - static inline string_type construct(InputIterator from, InputIterator to) - { - return string_type(from, to); - } - - static inline string_type construct(const_iterator from, const_iterator to) - { - return string_type(from, to); - } - - - static string_type construct(const value_type* str) - { - return str ? string_type(str) : string_type(); - } - - static const string_type& empty_string() { static string_type es; return es; } - - //todo: fix for utf8 - static size_type length(const string_type& str) { return str.length(); } - - // all these functions should operate as std::string member functions do - static bool empty(const string_type& str) { return str.empty(); } - static size_type find(const string_type& str, value_type what) { return str.find(what); } - static size_type find(const string_type& str, const string_type& what) { return str.find(what); } - static size_type find(const string_type& str, value_type what, size_type from) { return str.find(what, from); } - static size_type find(const string_type& str, const string_type& what, size_type from) { return str.find(what, from); } - static string_type substr(const string_type& str, const size_type& offset) { return str.substr(offset); } - static string_type substr(const string_type& str, const size_type& offset, const size_type& count) { return str.substr(offset, count); } - static void append(string_type& str, const string_type& a) { str.append(a); } - static void insert(string_type& str, size_type offset, const string_type& a) { str.insert(offset, a); } - static void replace(string_type& str, size_type offset, size_type count, const string_type& a) { str.replace(offset, count, a); } - - static const_iterator begin(const string_type& str) { return str.begin(); } - static const_iterator end(const string_type& str) { return str.end(); } - - static iterator begin(string_type& str) { return str.begin(); } - static iterator end(string_type& str) { return str.end(); } - - - // only used to constuct error strings - don't have to be highly efficient! - static std::string asStdString(const string_type& str); - -#ifndef ARABICA_NO_WCHAR_T - static string_type construct_from_utf16(const wchar_t* str); - static string_type construct_from_utf16(const wchar_t* str, int length); - static std::wstring asStdWString(const string_type& str); - - typedef Arabica::io::basic_iconvertstream, - char, std::char_traits > widener_t; - typedef Arabica::io::basic_oconvertstream, - char, std::char_traits > narrower_t; - - - static const std::locale& utf8ucs2_locale() - { - static const std::locale loc = std::locale(std::locale(), new Arabica::convert::utf8ucs2codecvt); - return loc; - } -#endif //ARABICA_NO_WCHAR_T - -}; // class default_string_adaptor_base - - -// specialize for std::string and std::wstring -template<> -class default_string_adaptor : - public string_adaptor_tag, - public default_string_adaptor_base -{ -public: - - static char convert_from_utf8(char c) { return c; } - - static std::string construct_from_utf8(const char* str) - { - return str ? std::string(str) : std::string(); - } // construct_from_utf8 - - static std::string construct_from_utf8(const char* str, int length) - { - return std::string(str, length); - } // construct_from_utf8 - - static const std::string& asStdString(const std::string& str) - { - return str; - } // asStdString - -#ifndef ARABICA_NO_WCHAR_T - static std::string construct_from_utf16(const wchar_t* str) - { - narrower_t n; - n.imbue(utf8ucs2_locale()); - n.str(str ? str : L""); - //n << str; - return n.str(); - } - - static std::string construct_from_utf16(const wchar_t* str, int length) - { - narrower_t n; - n.imbue(utf8ucs2_locale()); - n.str(std::wstring(str, length)); - //for(int i = 0; i < length; ++i) - // n << str[i]; - return n.str(); - } // construct_from_utf16 - - static std::wstring asStdWString(const std::string& str) - { - widener_t w; - w.imbue(utf8ucs2_locale()); - w.str(str); - return w.str(); - } // toStdWString -#endif //ARABICA_NO_WCHAR_T - -}; // class default_string_adaptor - - -#ifndef ARABICA_NO_WCHAR_T - -template<> -class default_string_adaptor : - public string_adaptor_tag, - public default_string_adaptor_base -{ -public: - - static wchar_t makeValueT(char c) - { - return static_cast(c); - } // makeValueT - - static std::wstring construct_from_utf8(const char* str) - { - widener_t w; - w.imbue(utf8ucs2_locale()); - w.str(str ? str : ""); - return w.str(); - } - - static std::wstring construct_from_utf8(const char* str, int length) - { - widener_t w; - w.imbue(utf8ucs2_locale()); - w.str(std::string(str, length)); - return w.str(); - } - - static std::wstring construct_from_utf16(const wchar_t* str) - { - return str ? std::wstring(str) : std::wstring(); - } - - static std::wstring construct_from_utf16(const wchar_t* str, int length) - { - return std::wstring(str, length); - } - - static std::string asStdString(const std::wstring& str) - { - narrower_t n; - n.imbue(utf8ucs2_locale()); - n.str(str); - return n.str(); - } // toStdString - - static const std::wstring& asStdWString(const std::wstring& str) - { - return str; - } // toStdWString - -}; // class default_string_adaptor - - -#endif // ARABICA_NO_WCHAR_T - -} // namespace Arabica - -#endif -// end of file +#ifndef ARABICA_UTILS_STRING_ADAPTOR_H +#define ARABICA_UTILS_STRING_ADAPTOR_H + +#include +#include +#include +#include +#include + +namespace Arabica +{ + +template class default_string_adaptor; + +template +class default_string_adaptor_base +{ +public: + typedef stringT string_type; + typedef typename string_type::const_iterator const_iterator; + typedef typename string_type::iterator mutable_iterator; + typedef typename string_type::const_reverse_iterator const_reverse_iterator; + typedef typename string_type::iterator iterator; + typedef typename string_type::value_type value_type; + typedef typename string_type::size_type size_type; + + virtual ~default_string_adaptor_base() {} + + static size_type npos() + { + return static_cast(-1); + } + + //todo: is this safe? + template + static inline string_type construct(InputIterator from, InputIterator to) + { + return string_type(from, to); + } + + static inline string_type construct(const_iterator from, const_iterator to) + { + return string_type(from, to); + } + + static inline string_type construct(const std::basic_string& str) + { + return construct(str.begin(), str.end()); + } // construct + + static string_type construct(const value_type* str) + { + return str ? string_type(str) : string_type(); + } + + static const string_type& empty_string() { static string_type es; return es; } + + //todo: fix for utf8 + static size_type length(const string_type& str) { return str.length(); } + + // all these functions should operate as std::string member functions do + static bool empty(const string_type& str) { return str.empty(); } + static size_type find(const string_type& str, value_type what) { return str.find(what); } + static size_type find(const string_type& str, const string_type& what) { return str.find(what); } + static size_type find(const string_type& str, value_type what, size_type from) { return str.find(what, from); } + static size_type find(const string_type& str, const string_type& what, size_type from) { return str.find(what, from); } + static string_type substr(const string_type& str, const size_type& offset) { return str.substr(offset); } + static string_type substr(const string_type& str, const size_type& offset, const size_type& count) { return str.substr(offset, count); } + static void append(string_type& str, const string_type& a) { str.append(a); } + static void append(string_type& str, const value_type& a) { str += a; } + static string_type concat(const string_type& str, const string_type& a) { return str + a; } + static string_type concat(const string_type& str, const value_type& a) { return str + a; } + static void insert(string_type& str, size_type offset, const string_type& a) { str.insert(offset, a); } + static void replace(string_type& str, size_type offset, size_type count, const string_type& a) { str.replace(offset, count, a); } + + static const_iterator begin(const string_type& str) { return str.begin(); } + static const_iterator end(const string_type& str) { return str.end(); } + + static iterator begin(string_type& str) { return str.begin(); } + static iterator end(string_type& str) { return str.end(); } + + static const_reverse_iterator rbegin(const string_type& str) { return str.rbegin(); } + + // only used to constuct error strings - don't have to be highly efficient! + static std::string asStdString(const string_type& str); + +#ifndef ARABICA_NO_WCHAR_T + static string_type construct_from_utf16(const wchar_t* str); + static string_type construct_from_utf16(const wchar_t* str, int length); + static std::wstring asStdWString(const string_type& str); + + typedef Arabica::io::basic_iconvertstream, + char, std::char_traits > widener_t; + typedef Arabica::io::basic_oconvertstream, + char, std::char_traits > narrower_t; + + + static const std::locale& utf8ucs2_locale() + { + static const std::locale loc = std::locale(std::locale(), new Arabica::convert::utf8ucs2codecvt); + return loc; + } +#endif //ARABICA_NO_WCHAR_T + +}; // class default_string_adaptor_base + + +// specialize for std::string and std::wstring +template<> +class default_string_adaptor : + public string_adaptor_tag, + public default_string_adaptor_base +{ +public: + + static char convert_from_utf8(char c) { return c; } + + static std::string construct_from_utf8(const char* str) + { + return str ? std::string(str) : std::string(); + } // construct_from_utf8 + + static std::string construct_from_utf8(const char* str, int length) + { + return std::string(str, length); + } // construct_from_utf8 + + static const std::string& asStdString(const std::string& str) + { + return str; + } // asStdString + +#ifndef ARABICA_NO_WCHAR_T + static std::string construct_from_utf16(const wchar_t* str) + { + narrower_t n; + n.imbue(utf8ucs2_locale()); + n.str(str ? str : L""); + //n << str; + return n.str(); + } + + static std::string construct_from_utf16(const wchar_t* str, int length) + { + narrower_t n; + n.imbue(utf8ucs2_locale()); + n.str(std::wstring(str, length)); + //for(int i = 0; i < length; ++i) + // n << str[i]; + return n.str(); + } // construct_from_utf16 + + static std::wstring asStdWString(const std::string& str) + { + widener_t w; + w.imbue(utf8ucs2_locale()); + w.str(str); + return w.str(); + } // toStdWString +#endif //ARABICA_NO_WCHAR_T + +}; // class default_string_adaptor + + +#ifndef ARABICA_NO_WCHAR_T + +template<> +class default_string_adaptor : + public string_adaptor_tag, + public default_string_adaptor_base +{ +public: + + static wchar_t makeValueT(char c) + { + return static_cast(c); + } // makeValueT + + static std::wstring construct_from_utf8(const char* str) + { + widener_t w; + w.imbue(utf8ucs2_locale()); + w.str(str ? str : ""); + return w.str(); + } + + static std::wstring construct_from_utf8(const char* str, int length) + { + widener_t w; + w.imbue(utf8ucs2_locale()); + w.str(std::string(str, length)); + return w.str(); + } + + static std::wstring construct_from_utf16(const wchar_t* str) + { + return str ? std::wstring(str) : std::wstring(); + } + + static std::wstring construct_from_utf16(const wchar_t* str, int length) + { + return std::wstring(str, length); + } + + static std::string asStdString(const std::wstring& str) + { + narrower_t n; + n.imbue(utf8ucs2_locale()); + n.str(str); + return n.str(); + } // toStdString + + static const std::wstring& asStdWString(const std::wstring& str) + { + return str; + } // toStdWString + +}; // class default_string_adaptor + + +#endif // ARABICA_NO_WCHAR_T + +} // namespace Arabica + +#endif +// end of file diff --git a/include/SAX/helpers/NamespaceSupport.hpp b/include/SAX/helpers/NamespaceSupport.hpp index f2a32c23..4f9998cd 100644 --- a/include/SAX/helpers/NamespaceSupport.hpp +++ b/include/SAX/helpers/NamespaceSupport.hpp @@ -1,390 +1,390 @@ -#ifndef ARABICA_NAMESPACE_SUPPORT_H -#define ARABICA_NAMESPACE_SUPPORT_H - -#include -#include -#include -#include -#include -#include - -namespace Arabica -{ -namespace SAX -{ - -template -struct NamespaceConstants -{ - const string_type xml; - const string_type xmlns; - const string_type xml_uri; - const string_type xmlns_uri; - const string_type xmlns11_uri; - const string_type colon; - - NamespaceConstants() : - xml(string_adaptor::construct_from_utf8("xml")), - xmlns(string_adaptor::construct_from_utf8("xmlns")), - xml_uri(string_adaptor::construct_from_utf8("http://www.w3.org/XML/1998/namespace")), - xmlns_uri(), - xmlns11_uri(string_adaptor::construct_from_utf8("http://www.w3.org/2000/xmlns/")), - colon(string_adaptor::construct_from_utf8(":")) - { - } // NamespaceConstants -}; // struct NamespaceContants - -/** - * Encapsulate Namespace logic for use by SAX drivers. - * - *

This class encapsulates the logic of Namespace processing: - * it tracks the declarations currently in force for each context - * and automatically processes qualified XML 1.0 names into their - * Namespace parts; it can also be used in reverse for generating - * XML 1.0 from Namespaces.

- * - *

Namespace support objects are reusable, but the reset method - * must be invoked between each session.

- * - *

Here is a simple session:

- * - *
- * NamespaceSupport support;
- *
- * support.pushContext();
- * support.declarePrefix("", "http://www.w3.org/1999/xhtml");
- * support.declarePrefix("dc", "http://www.purl.org/dc#");
- *
- * NamespaceSupport parts = support.processName("p", parts, false);
- * std::cout << "Namespace URI: " << parts.URI << std::endl;
- * std::cout << "Local name: " << parts.localName << std::endl;
- * std::cout << "Raw name: " << parts.rawName << std::endl;
-
- * parts = support.processName("dc:title", parts, false);
- * std::cout << "Namespace URI: " << parts.URI << std::endl;
- * std::cout << "Local name: " << parts.localName << std::endl;
- * std::cout << "Raw name: " << parts.rawName << std::endl;
-
- * support.popContext();
- * 
- * - *

Note that this class is optimized for the use case where most - * elements do not contain Namespace declarations: if the same - * prefix/URI mapping is repeated for each context (for example), this - * class will be somewhat less efficient.

- * - * @since SAX 2.0 - * @author Jez Higgins, - * jez@jezuk.co.uk - * @version 2.0 - */ -template -class NamespaceSupport -{ - public: - typedef std::vector stringListT; - - // functions - NamespaceSupport() - { - reset(); - } // NamespaceSupport - - /** - * Reset this Namespace support object for reuse. - * - *

It is necessary to invoke this method before reusing the - * Namespace support object for a new session.

- */ - void reset() - { - contexts_.clear(); - contexts_.push_back(Context()); - contexts_.back().insert(std::make_pair(nsc_.xml, nsc_.xml_uri)); - } // reset - - //////////////////////////////////////////////////////////////////// - // Context management. - //////////////////////////////////////////////////////////////////// - /** - * Start a new Namespace context. - * - *

Normally, you should push a new context at the beginning - * of each XML element: the new context will automatically inherit - * the declarations of its parent context, but it will also keep - * track of which declarations were made within this context.

- * - *

The Namespace support object always starts with a base context - * already in force: in this context, only the "xml" prefix is - * declared.

- * - * @see #popContext - */ - void pushContext() - { - contexts_.push_back(Context()); - } // pushContext - - /** - * Revert to the previous Namespace context. - * - *

Normally, you should pop the context at the end of each - * XML element. After popping the context, all Namespace prefix - * mappings that were previously in force are restored.

- * - *

You must not attempt to declare additional Namespace - * prefixes after popping a context, unless you push another - * context first.

- * - * @see #pushContext - */ - void popContext() - { - contexts_.pop_back(); - } // popContext - - //////////////////////////////////////////////////////////////////// - // Operations within a context. - //////////////////////////////////////////////////////////////////// - /** - * Declare a Namespace prefix. - * - *

This method declares a prefix in the current Namespace - * context; the prefix will remain in force until this context - * is popped, unless it is shadowed in a descendant context.

- * - *

To declare a default Namespace, use the empty string. The - * prefix must not be "xml" or "xmlns".

- * - *

Note that you must not declare a prefix after - * you've pushed and popped another Namespace.

- * - *

Note that there is an asymmetry in this library: while {@link - * #getPrefix getPrefix} will not return the default "" prefix, - * even if you have declared one; to check for a default prefix, - * you have to look it up explicitly using {@link #getURI getURI}. - * This asymmetry exists to make it easier to look up prefixes - * for attribute names, where the default prefix is not allowed.

- * - * @param prefix The prefix to declare, or the empty string. - * @param uri The Namespace URI to associate with the prefix. - * @return true if the prefix was legal, false otherwise - * @see #processName - * @see #getURI - * @see #getPrefix - */ - bool declarePrefix(const string_type& prefix, const string_type& uri) - { - if((prefix == nsc_.xml) || (prefix == nsc_.xmlns)) - return false; - - contexts_.back().insert(std::make_pair(prefix, uri)); - return true; - } // declarePrefix - - /** - * Process a raw XML 1.0 name. - * - *

This method processes a raw XML 1.0 name in the current - * context by removing the prefix and looking it up among the - * prefixes currently declared. - * - *

If - * the raw name has a prefix that has not been declared, then - * the return value will be empty.

- * - *

Note that attribute names are processed differently than - * element names: an unprefixed element name will received the - * default Namespace (if any), while an unprefixed attribute name - * will not.

- * - * @param qName The raw XML 1.0 name to be processed. - * @param isAttribute A flag indicating whether this is an - * attribute name (true) or an element name (false). - * @return A Parts holding three strings representing the - * Namespace URI (or empty string), the local name, and the raw XML - * 1.0 name. - * @see #declarePrefix - */ - private: - class URIMapper - { - public: - URIMapper(const NamespaceSupport* ns) : ns_(ns) { } - string_type operator()(const string_type& prefix) const { return ns_->getURI(prefix); } - private: - const NamespaceSupport* const ns_; - }; // class URIMapper - - public: - XML::QualifiedName processName(const string_type& rawName, bool isAttribute) const - { - try - { - return XML::QualifiedName::parseQName(rawName, isAttribute, URIMapper(this)); - } // try - catch(const std::runtime_error& ex) - { - throw SAX::SAXException(ex.what()); - } // catch - } // processName - - /** - * Look up a prefix and get the currently-mapped Namespace URI. - * - *

This method looks up the prefix in the current context. - * Use the empty string ("") for the default Namespace.

- * - * @param prefix The prefix to look up. - * @return The associated Namespace URI, or empty string if the prefix - * is undeclared in this context. - * @see #getPrefix - * @see #getPrefixes - */ - string_type getURI(const string_type& prefix) const - { - for(typename contextListT::const_reverse_iterator i = contexts_.rbegin(); i != contexts_.rend(); ++i) - { - typename stringMapT::const_iterator u = i->find(prefix); - if(u != i->end()) - return u->second; - } // for ... - - return string_type(); - } // getURI - - /** - * Return one of the prefixes mapped to a Namespace URI. - * - *

If more than one prefix is currently mapped to the same - * URI, this method will make an arbitrary selection; if you - * want all of the prefixes, use the {@link #getPrefixes} - * method instead.

- * - *

Note: this will never return the empty (default) prefix; - * to check for a default prefix, use the {@link #getURI getURI} - * method with an argument of "".

- * - * @param uri The Namespace URI. - * @return One of the prefixes currently mapped to the URI supplied, - * or an empty string if none is mapped or if the URI is assigned to - * the default Namespace. - * @see #getPrefixes(const string_type&) - * @see #getURI - */ - string_type getPrefix(const string_type& uri) const - { - for(typename contextListT::const_reverse_iterator i = contexts_.rbegin(); i != contexts_.rend(); ++i) - { - for(typename stringMapT::const_iterator u = i->begin(); u != i->end(); ++u) - if(u->second == uri) - return u->first; - } // for ... - - return string_type(); - } // getPrefix - - /** - * Returns all prefixes currently declared. - * - *

Note: if there is a default prefix, it will not be - * returned in this enumeration; check for the default prefix - * using the {@link #getURI getURI} with an argument of "".

- * - * @return A list of all prefixes declared in the - * current context except for the empty (default) - * prefix. - * @see #getDeclaredPrefixes - * @see #getURI - */ - stringListT getPrefixes() const - { - stringListT prefixes; - - for(typename contextListT::const_reverse_iterator i = contexts_.rbegin(); i != contexts_.rend(); ++i) - { - for(typename stringMapT::const_iterator u = i->begin(); u != i->end(); ++u) - if(!u->first.empty()) - prefixes.push_back(u->first); - } // for ... - - return prefixes; - } // getPrefixes - - /** - * Returns a list of all prefixes currently declared for a URI. - * - *

This method returns prefixes mapped to a specific Namespace - * URI. The xml: prefix will be included. If you want only one - * prefix that's mapped to the Namespace URI, and you don't care - * which one you get, use the {@link #getPrefix getPrefix} - * method instead.

- * - *

Note: the empty (default) prefix is never included - * in this enumeration; to check for the presence of a default - * Namespace, use the {@link #getURI getURI} method with an - * argument of "".

- * - * @param uri The Namespace URI. - * @return A list of all prefixes declared in the - * current context. - * @see #getPrefix - * @see #getDeclaredPrefixes - * @see #getURI - */ - stringListT getPrefixes(const string_type& uri) const - { - stringListT prefixes; - - for(typename contextListT::const_reverse_iterator i = contexts_.rbegin(); i != contexts_.rend(); ++i) - { - for(typename stringMapT::const_iterator u = i->begin(); u != i->end(); ++u) - if(u->second == uri) - prefixes.push_back(u->first); - } // for ... - - return prefixes; - } // getPrefixes - - /** - * Return an enumeration of all prefixes declared in this context. - * - *

The empty (default) prefix will be included in this - * enumeration; note that this behaviour differs from that of - * {@link #getPrefix} and {@link #getPrefixes}.

- * - * @return An enumeration of all prefixes declared in this - * context. - * @see #getPrefixes - * @see #getURI - */ - stringListT getDeclaredPrefixes() const - { - stringListT prefixes; - - for(typename stringMapT::const_iterator u = contexts_.back().begin(); u != contexts_.back().end(); ++u) - prefixes.push_back(u->first); - - return prefixes; - } // getDeclaredPrefixes - - private: - typedef typename std::multimap stringMapT; - typedef stringMapT Context; - typedef typename std::vector contextListT; - - // member variables - contextListT contexts_; - - const NamespaceConstants nsc_; - - // no impl - NamespaceSupport(const NamespaceSupport&); - NamespaceSupport& operator=(const NamespaceSupport&); - bool operator==(const NamespaceSupport&) const; -}; // class NamespaceSupport - -} // namespace SAX -} // namespace Arabica - -#endif // NamespaceSupportH +#ifndef ARABICA_NAMESPACE_SUPPORT_H +#define ARABICA_NAMESPACE_SUPPORT_H + +#include +#include +#include +#include +#include +#include + +namespace Arabica +{ +namespace SAX +{ + +template +struct NamespaceConstants +{ + const string_type xml; + const string_type xmlns; + const string_type xml_uri; + const string_type xmlns_uri; + const string_type xmlns11_uri; + const string_type colon; + + NamespaceConstants() : + xml(string_adaptor::construct_from_utf8("xml")), + xmlns(string_adaptor::construct_from_utf8("xmlns")), + xml_uri(string_adaptor::construct_from_utf8("http://www.w3.org/XML/1998/namespace")), + xmlns_uri(), + xmlns11_uri(string_adaptor::construct_from_utf8("http://www.w3.org/2000/xmlns/")), + colon(string_adaptor::construct_from_utf8(":")) + { + } // NamespaceConstants +}; // struct NamespaceContants + +/** + * Encapsulate Namespace logic for use by SAX drivers. + * + *

This class encapsulates the logic of Namespace processing: + * it tracks the declarations currently in force for each context + * and automatically processes qualified XML 1.0 names into their + * Namespace parts; it can also be used in reverse for generating + * XML 1.0 from Namespaces.

+ * + *

Namespace support objects are reusable, but the reset method + * must be invoked between each session.

+ * + *

Here is a simple session:

+ * + *
+ * NamespaceSupport support;
+ *
+ * support.pushContext();
+ * support.declarePrefix("", "http://www.w3.org/1999/xhtml");
+ * support.declarePrefix("dc", "http://www.purl.org/dc#");
+ *
+ * NamespaceSupport parts = support.processName("p", parts, false);
+ * std::cout << "Namespace URI: " << parts.URI << std::endl;
+ * std::cout << "Local name: " << parts.localName << std::endl;
+ * std::cout << "Raw name: " << parts.rawName << std::endl;
+
+ * parts = support.processName("dc:title", parts, false);
+ * std::cout << "Namespace URI: " << parts.URI << std::endl;
+ * std::cout << "Local name: " << parts.localName << std::endl;
+ * std::cout << "Raw name: " << parts.rawName << std::endl;
+
+ * support.popContext();
+ * 
+ * + *

Note that this class is optimized for the use case where most + * elements do not contain Namespace declarations: if the same + * prefix/URI mapping is repeated for each context (for example), this + * class will be somewhat less efficient.

+ * + * @since SAX 2.0 + * @author Jez Higgins, + * jez@jezuk.co.uk + * @version 2.0 + */ +template +class NamespaceSupport +{ + public: + typedef std::vector stringListT; + + // functions + NamespaceSupport() + { + reset(); + } // NamespaceSupport + + /** + * Reset this Namespace support object for reuse. + * + *

It is necessary to invoke this method before reusing the + * Namespace support object for a new session.

+ */ + void reset() + { + contexts_.clear(); + contexts_.push_back(Context()); + contexts_.back().insert(std::make_pair(nsc_.xml, nsc_.xml_uri)); + } // reset + + //////////////////////////////////////////////////////////////////// + // Context management. + //////////////////////////////////////////////////////////////////// + /** + * Start a new Namespace context. + * + *

Normally, you should push a new context at the beginning + * of each XML element: the new context will automatically inherit + * the declarations of its parent context, but it will also keep + * track of which declarations were made within this context.

+ * + *

The Namespace support object always starts with a base context + * already in force: in this context, only the "xml" prefix is + * declared.

+ * + * @see #popContext + */ + void pushContext() + { + contexts_.push_back(Context()); + } // pushContext + + /** + * Revert to the previous Namespace context. + * + *

Normally, you should pop the context at the end of each + * XML element. After popping the context, all Namespace prefix + * mappings that were previously in force are restored.

+ * + *

You must not attempt to declare additional Namespace + * prefixes after popping a context, unless you push another + * context first.

+ * + * @see #pushContext + */ + void popContext() + { + contexts_.pop_back(); + } // popContext + + //////////////////////////////////////////////////////////////////// + // Operations within a context. + //////////////////////////////////////////////////////////////////// + /** + * Declare a Namespace prefix. + * + *

This method declares a prefix in the current Namespace + * context; the prefix will remain in force until this context + * is popped, unless it is shadowed in a descendant context.

+ * + *

To declare a default Namespace, use the empty string. The + * prefix must not be "xml" or "xmlns".

+ * + *

Note that you must not declare a prefix after + * you've pushed and popped another Namespace.

+ * + *

Note that there is an asymmetry in this library: while {@link + * #getPrefix getPrefix} will not return the default "" prefix, + * even if you have declared one; to check for a default prefix, + * you have to look it up explicitly using {@link #getURI getURI}. + * This asymmetry exists to make it easier to look up prefixes + * for attribute names, where the default prefix is not allowed.

+ * + * @param prefix The prefix to declare, or the empty string. + * @param uri The Namespace URI to associate with the prefix. + * @return true if the prefix was legal, false otherwise + * @see #processName + * @see #getURI + * @see #getPrefix + */ + bool declarePrefix(const string_type& prefix, const string_type& uri) + { + if((prefix == nsc_.xml) || (prefix == nsc_.xmlns)) + return false; + + contexts_.back().insert(std::make_pair(prefix, uri)); + return true; + } // declarePrefix + + /** + * Process a raw XML 1.0 name. + * + *

This method processes a raw XML 1.0 name in the current + * context by removing the prefix and looking it up among the + * prefixes currently declared. + * + *

If + * the raw name has a prefix that has not been declared, then + * the return value will be empty.

+ * + *

Note that attribute names are processed differently than + * element names: an unprefixed element name will received the + * default Namespace (if any), while an unprefixed attribute name + * will not.

+ * + * @param qName The raw XML 1.0 name to be processed. + * @param isAttribute A flag indicating whether this is an + * attribute name (true) or an element name (false). + * @return A Parts holding three strings representing the + * Namespace URI (or empty string), the local name, and the raw XML + * 1.0 name. + * @see #declarePrefix + */ + private: + class URIMapper + { + public: + URIMapper(const NamespaceSupport* ns) : ns_(ns) { } + string_type operator()(const string_type& prefix) const { return ns_->getURI(prefix); } + private: + const NamespaceSupport* const ns_; + }; // class URIMapper + + public: + XML::QualifiedName processName(const string_type& rawName, bool isAttribute) const + { + try + { + return XML::QualifiedName::parseQName(rawName, isAttribute, URIMapper(this)); + } // try + catch(const std::runtime_error& ex) + { + throw SAX::SAXException(ex.what()); + } // catch + } // processName + + /** + * Look up a prefix and get the currently-mapped Namespace URI. + * + *

This method looks up the prefix in the current context. + * Use the empty string ("") for the default Namespace.

+ * + * @param prefix The prefix to look up. + * @return The associated Namespace URI, or empty string if the prefix + * is undeclared in this context. + * @see #getPrefix + * @see #getPrefixes + */ + string_type getURI(const string_type& prefix) const + { + for(typename contextListT::const_reverse_iterator i = contexts_.rbegin(); i != contexts_.rend(); ++i) + { + typename stringMapT::const_iterator u = i->find(prefix); + if(u != i->end()) + return u->second; + } // for ... + + return string_type(); + } // getURI + + /** + * Return one of the prefixes mapped to a Namespace URI. + * + *

If more than one prefix is currently mapped to the same + * URI, this method will make an arbitrary selection; if you + * want all of the prefixes, use the {@link #getPrefixes} + * method instead.

+ * + *

Note: this will never return the empty (default) prefix; + * to check for a default prefix, use the {@link #getURI getURI} + * method with an argument of "".

+ * + * @param uri The Namespace URI. + * @return One of the prefixes currently mapped to the URI supplied, + * or an empty string if none is mapped or if the URI is assigned to + * the default Namespace. + * @see #getPrefixes(const string_type&) + * @see #getURI + */ + string_type getPrefix(const string_type& uri) const + { + for(typename contextListT::const_reverse_iterator i = contexts_.rbegin(); i != contexts_.rend(); ++i) + { + for(typename stringMapT::const_iterator u = i->begin(); u != i->end(); ++u) + if(u->second == uri) + return u->first; + } // for ... + + return string_type(); + } // getPrefix + + /** + * Returns all prefixes currently declared. + * + *

Note: if there is a default prefix, it will not be + * returned in this enumeration; check for the default prefix + * using the {@link #getURI getURI} with an argument of "".

+ * + * @return A list of all prefixes declared in the + * current context except for the empty (default) + * prefix. + * @see #getDeclaredPrefixes + * @see #getURI + */ + stringListT getPrefixes() const + { + stringListT prefixes; + + for(typename contextListT::const_reverse_iterator i = contexts_.rbegin(); i != contexts_.rend(); ++i) + { + for(typename stringMapT::const_iterator u = i->begin(); u != i->end(); ++u) + if(!string_adaptor::empty(u->first)) + prefixes.push_back(u->first); + } // for ... + + return prefixes; + } // getPrefixes + + /** + * Returns a list of all prefixes currently declared for a URI. + * + *

This method returns prefixes mapped to a specific Namespace + * URI. The xml: prefix will be included. If you want only one + * prefix that's mapped to the Namespace URI, and you don't care + * which one you get, use the {@link #getPrefix getPrefix} + * method instead.

+ * + *

Note: the empty (default) prefix is never included + * in this enumeration; to check for the presence of a default + * Namespace, use the {@link #getURI getURI} method with an + * argument of "".

+ * + * @param uri The Namespace URI. + * @return A list of all prefixes declared in the + * current context. + * @see #getPrefix + * @see #getDeclaredPrefixes + * @see #getURI + */ + stringListT getPrefixes(const string_type& uri) const + { + stringListT prefixes; + + for(typename contextListT::const_reverse_iterator i = contexts_.rbegin(); i != contexts_.rend(); ++i) + { + for(typename stringMapT::const_iterator u = i->begin(); u != i->end(); ++u) + if(u->second == uri) + prefixes.push_back(u->first); + } // for ... + + return prefixes; + } // getPrefixes + + /** + * Return an enumeration of all prefixes declared in this context. + * + *

The empty (default) prefix will be included in this + * enumeration; note that this behaviour differs from that of + * {@link #getPrefix} and {@link #getPrefixes}.

+ * + * @return An enumeration of all prefixes declared in this + * context. + * @see #getPrefixes + * @see #getURI + */ + stringListT getDeclaredPrefixes() const + { + stringListT prefixes; + + for(typename stringMapT::const_iterator u = contexts_.back().begin(); u != contexts_.back().end(); ++u) + prefixes.push_back(u->first); + + return prefixes; + } // getDeclaredPrefixes + + private: + typedef typename std::multimap stringMapT; + typedef stringMapT Context; + typedef typename std::vector contextListT; + + // member variables + contextListT contexts_; + + const NamespaceConstants nsc_; + + // no impl + NamespaceSupport(const NamespaceSupport&); + NamespaceSupport& operator=(const NamespaceSupport&); + bool operator==(const NamespaceSupport&) const; +}; // class NamespaceSupport + +} // namespace SAX +} // namespace Arabica + +#endif // NamespaceSupportH diff --git a/include/SAX/helpers/XMLBaseSupport.hpp b/include/SAX/helpers/XMLBaseSupport.hpp index bcaa0b19..ce48dbfc 100644 --- a/include/SAX/helpers/XMLBaseSupport.hpp +++ b/include/SAX/helpers/XMLBaseSupport.hpp @@ -1,126 +1,126 @@ -#ifndef ARABICA_XMLBASE_SUPPORT_H -#define ARABICA_XMLBASE_SUPPORT_H - -/* - * $Id$ - * - * XMLBaseSupport is a helper class for tracking xml:base attributes. - * Usage: - * set location of the containing document by calling setDocumentLocation - * this is usually done when during the setDocumentLocator SAX event - * forward each startElement and endElement event - * to resolve a relative URL against the current base, call makeAbsolute - * - * Derived from org.apache.cocoon.xml.XMLBaseSupport. - * - * XML Base is described at http://www.w3.org/TR/xmlbase/ - */ - -#include -#include -#include -#include -#include - -namespace Arabica -{ -namespace SAX -{ - -template -struct XMLBaseConstants -{ - const string_type xml; - const string_type xml_uri; - const string_type colon; - const string_type base; - - XMLBaseConstants() : - xml(string_adaptor::construct_from_utf8("xml")), - xml_uri(string_adaptor::construct_from_utf8("http://www.w3.org/XML/1998/namespace")), - colon(string_adaptor::construct_from_utf8(":")), - base(string_adaptor::construct_from_utf8("base")) - { - } // XMLBaseConstants -}; // struct XMLBaseConstants - -template > -class XMLBaseSupport -{ -public: - typedef typename string_adaptor::value_type valueT; - typedef Attributes AttributesT; - - XMLBaseSupport() : - depth_(0) { } - - void setDocumentLocation(const string_type& loc) - { - bases_.push(std::make_pair(-1, loc)); - } // setDocumentLocation - - void startElement(const AttributesT& atts) - { - ++depth_; - string_type base = atts.getValue(xbc_.xml_uri, xbc_.base); - if(base.empty()) - return; - - string_type baseURI = absolutise(currentBase(), base); - bases_.push(std::make_pair(depth_, baseURI)); - } // startElement - - void endElement() - { - if(currentDepth() == depth_) - bases_.pop(); - --depth_; - } // endElement - - string_type currentBase() const - { - if(!bases_.size()) - return string_type(); - return bases_.top().second; - } // currentBase() - - string_type makeAbsolute(const string_type& spec) const - { - return absolutise(currentBase(), spec); - } // makeAbsolute - -private: - string_type absolutise(const string_type& baseURI, const string_type& location) const - { - Arabica::io::URI base(string_adaptor::asStdString(baseURI)); - Arabica::io::URI absolute(base, string_adaptor::asStdString(location)); - return string_adaptor::construct_from_utf8(absolute.as_string().c_str()); - } // absolutise - - int currentDepth() const - { - if(!bases_.size()) - return -1; - return bases_.top().first; - } // currentDepths - -private: - typedef std::pair baseInfoT; - typedef std::stack baseStackT; - - baseStackT bases_; - int depth_; - - const XMLBaseConstants xbc_; - - // no impl - XMLBaseSupport(const XMLBaseSupport&); - XMLBaseSupport& operator=(const XMLBaseSupport&); - bool operator==(const XMLBaseSupport&); -}; // class XMLBaseSupport - -} // namespace SAX -} // namespace Arabica - -#endif - +#ifndef ARABICA_XMLBASE_SUPPORT_H +#define ARABICA_XMLBASE_SUPPORT_H + +/* + * $Id$ + * + * XMLBaseSupport is a helper class for tracking xml:base attributes. + * Usage: + * set location of the containing document by calling setDocumentLocation + * this is usually done when during the setDocumentLocator SAX event + * forward each startElement and endElement event + * to resolve a relative URL against the current base, call makeAbsolute + * + * Derived from org.apache.cocoon.xml.XMLBaseSupport. + * + * XML Base is described at http://www.w3.org/TR/xmlbase/ + */ + +#include +#include +#include +#include +#include + +namespace Arabica +{ +namespace SAX +{ + +template +struct XMLBaseConstants +{ + const string_type xml; + const string_type xml_uri; + const string_type colon; + const string_type base; + + XMLBaseConstants() : + xml(string_adaptor::construct_from_utf8("xml")), + xml_uri(string_adaptor::construct_from_utf8("http://www.w3.org/XML/1998/namespace")), + colon(string_adaptor::construct_from_utf8(":")), + base(string_adaptor::construct_from_utf8("base")) + { + } // XMLBaseConstants +}; // struct XMLBaseConstants + +template > +class XMLBaseSupport +{ +public: + typedef typename string_adaptor::value_type valueT; + typedef Attributes AttributesT; + + XMLBaseSupport() : + depth_(0) { } + + void setDocumentLocation(const string_type& loc) + { + bases_.push(std::make_pair(-1, loc)); + } // setDocumentLocation + + void startElement(const AttributesT& atts) + { + ++depth_; + string_type base = atts.getValue(xbc_.xml_uri, xbc_.base); + if(string_adaptor::empty(base)) + return; + + string_type baseURI = absolutise(currentBase(), base); + bases_.push(std::make_pair(depth_, baseURI)); + } // startElement + + void endElement() + { + if(currentDepth() == depth_) + bases_.pop(); + --depth_; + } // endElement + + string_type currentBase() const + { + if(!bases_.size()) + return string_type(); + return bases_.top().second; + } // currentBase() + + string_type makeAbsolute(const string_type& spec) const + { + return absolutise(currentBase(), spec); + } // makeAbsolute + +private: + string_type absolutise(const string_type& baseURI, const string_type& location) const + { + Arabica::io::URI base(string_adaptor::asStdString(baseURI)); + Arabica::io::URI absolute(base, string_adaptor::asStdString(location)); + return string_adaptor::construct_from_utf8(absolute.as_string().c_str()); + } // absolutise + + int currentDepth() const + { + if(!bases_.size()) + return -1; + return bases_.top().first; + } // currentDepths + +private: + typedef std::pair baseInfoT; + typedef std::stack baseStackT; + + baseStackT bases_; + int depth_; + + const XMLBaseConstants xbc_; + + // no impl + XMLBaseSupport(const XMLBaseSupport&); + XMLBaseSupport& operator=(const XMLBaseSupport&); + bool operator==(const XMLBaseSupport&); +}; // class XMLBaseSupport + +} // namespace SAX +} // namespace Arabica + +#endif + diff --git a/include/XSLT/impl/handler/xslt_include_handler.hpp b/include/XSLT/impl/handler/xslt_include_handler.hpp index 1407eca5..02f5a046 100644 --- a/include/XSLT/impl/handler/xslt_include_handler.hpp +++ b/include/XSLT/impl/handler/xslt_include_handler.hpp @@ -107,7 +107,7 @@ public: virtual void characters(const string_type& ch) { if(no_content_) - verifyNoCharacterData(ch, SC::include + SC::import); + verifyNoCharacterData(ch, SC::include); // + SC::import context_->parentHandler().characters(ch); } // characters diff --git a/include/XSLT/impl/handler/xslt_inline_element_handler.hpp b/include/XSLT/impl/handler/xslt_inline_element_handler.hpp index c8bbdbb6..960795e8 100644 --- a/include/XSLT/impl/handler/xslt_inline_element_handler.hpp +++ b/include/XSLT/impl/handler/xslt_inline_element_handler.hpp @@ -31,7 +31,7 @@ protected: std::vector > inlineAtts; for(int i = 0; i != atts.getLength(); ++i) { - if(atts.getQName(i).find(SC::xmlns_colon) == 0) + if(string_adaptor::find(atts.getQName(i), SC::xmlns_colon) == 0) continue; if(atts.getURI(i) == StylesheetConstant::NamespaceURI) continue; @@ -42,9 +42,9 @@ protected: else { std::pair remap = baseT::context().remappedNamespace(atts.getURI(i)); - if(remap.first.empty() && !remap.second.empty()) + if(string_adaptor::empty(remap.first) && !string_adaptor::empty(remap.second)) remap.first = baseT::context().autoNamespacePrefix(); - string_type name = remap.first + SC::COLON + atts.getLocalName(i); + string_type name = makeName(remap.first, atts.getLocalName(i)); inlineAtts.push_back(InlineAttribute(name, remap.second, baseT::context().xpath_attribute_value_template(atts.getValue(i)))); @@ -55,9 +55,18 @@ protected: return new InlineElement(qName, namespaceURI, inlineAtts); const std::pair& remap = baseT::context().remappedNamespace(namespaceURI); - string_type name = remap.first + SC::COLON + localName; + string_type name = makeName(remap.first, localName); return new InlineElement(name, remap.second, inlineAtts); } // createContainer + +private: + string_type makeName(const string_type prefix, const string_type localName) const + { + string_type n = prefix; + string_adaptor::append(n, SC::COLON); + string_adaptor::append(n, localName); + return n; + } // makeName }; // class InlineElementHandler diff --git a/include/XSLT/impl/handler/xslt_item_container_handler.hpp b/include/XSLT/impl/handler/xslt_item_container_handler.hpp index 3b8c1549..daccc184 100644 --- a/include/XSLT/impl/handler/xslt_item_container_handler.hpp +++ b/include/XSLT/impl/handler/xslt_item_container_handler.hpp @@ -71,7 +71,7 @@ public: virtual void characters(const string_type& ch) { - for(typename string_type::const_iterator i = ch.begin(), e = ch.end(); i != e; ++i) + for(typename string_adaptor::const_iterator i = string_adaptor::begin(ch), e = string_adaptor::end(ch); i != e; ++i) if(!Arabica::XML::is_space(*i)) { container_->add_item(new Text(ch)); diff --git a/include/XSLT/impl/handler/xslt_namespace_alias_handler.hpp b/include/XSLT/impl/handler/xslt_namespace_alias_handler.hpp index cd4ed4a2..a6d03b49 100644 --- a/include/XSLT/impl/handler/xslt_namespace_alias_handler.hpp +++ b/include/XSLT/impl/handler/xslt_namespace_alias_handler.hpp @@ -44,10 +44,10 @@ public: std::map namespaces = context_.inScopeNamespaces(); if((namespaces.find(stylesheet_prefix) == namespaces.end()) && - (!stylesheet_prefix.empty())) + (!string_adaptor::empty(stylesheet_prefix))) throw SAX::SAXException(string_adaptor::asStdString(SC::namespace_alias) + " " + string_adaptor::asStdString(stylesheet_prefix) + " is not a declared namespace prefix"); if((namespaces.find(result_prefix) == namespaces.end()) && - (!result_prefix.empty())) + (!string_adaptor::empty(result_prefix))) throw SAX::SAXException(string_adaptor::asStdString(SC::namespace_alias) + " " + string_adaptor::asStdString(result_prefix) + " is not a declared namespace prefix"); context_.addNamespaceAlias(namespaces[stylesheet_prefix], result_prefix, namespaces[result_prefix]); diff --git a/include/XSLT/impl/handler/xslt_output_handler.hpp b/include/XSLT/impl/handler/xslt_output_handler.hpp index 05a9c681..af4a66cb 100644 --- a/include/XSLT/impl/handler/xslt_output_handler.hpp +++ b/include/XSLT/impl/handler/xslt_output_handler.hpp @@ -66,17 +66,17 @@ private: { CDATAElements elements; - if(cdata_section_elements.empty()) + if(string_adaptor::empty(cdata_section_elements)) return elements; - std::basic_istringstream - is(text::normalize_whitespace(cdata_section_elements)); + string_type norm_cdata_sec_elements = text::normalize_whitespace(cdata_section_elements); + std::basic_istringstream is(string_adaptor::asStdString(norm_cdata_sec_elements)); while(!is.eof()) { - string_type e; + std::basic_string e; is >> e; - XML::QualifiedName qualifiedName = context_.processElementQName(e); + XML::QualifiedName qualifiedName = context_.processElementQName(string_adaptor::construct(e)); elements.insert(QName::create(qualifiedName)); } // while diff --git a/include/XSLT/impl/handler/xslt_sort_handler.hpp b/include/XSLT/impl/handler/xslt_sort_handler.hpp index e9fa82c6..035ed901 100644 --- a/include/XSLT/impl/handler/xslt_sort_handler.hpp +++ b/include/XSLT/impl/handler/xslt_sort_handler.hpp @@ -43,7 +43,7 @@ public: order = context_.xpath_attribute_value_template(attr[SC::order]); caseorder = context_.xpath_attribute_value_template(attr[SC::case_order]); - if(attr[SC::lang].length() != 0) + if(string_adaptor::length(attr[SC::lang]) != 0) std::cerr << "Sorry! Don't support xsl:sort lang attribute yet" << std::endl; sort_ = new Sort(select, diff --git a/include/XSLT/impl/handler/xslt_template_handler.hpp b/include/XSLT/impl/handler/xslt_template_handler.hpp index 4b997d9a..c66852c6 100644 --- a/include/XSLT/impl/handler/xslt_template_handler.hpp +++ b/include/XSLT/impl/handler/xslt_template_handler.hpp @@ -26,7 +26,7 @@ public: { if(!done_params_) { - for(typename string_type::const_iterator i = ch.begin(), e = ch.end(); i != e; ++i) + for(typename string_adaptor::const_iterator i = string_adaptor::begin(ch), e = string_adaptor::end(ch); i != e; ++i) if(!Arabica::XML::is_space(*i)) { done_params_ = true; diff --git a/include/XSLT/impl/handler/xslt_text_handler.hpp b/include/XSLT/impl/handler/xslt_text_handler.hpp index 3d69d270..ff98bcd0 100644 --- a/include/XSLT/impl/handler/xslt_text_handler.hpp +++ b/include/XSLT/impl/handler/xslt_text_handler.hpp @@ -46,7 +46,7 @@ public: virtual void characters(const string_type& ch) { - buffer_ += ch; + string_adaptor::append(buffer_, ch); } // characters private: diff --git a/include/XSLT/impl/handler/xslt_value_validation.hpp b/include/XSLT/impl/handler/xslt_value_validation.hpp index c059e012..d2947668 100644 --- a/include/XSLT/impl/handler/xslt_value_validation.hpp +++ b/include/XSLT/impl/handler/xslt_value_validation.hpp @@ -144,7 +144,7 @@ public: { const string_type& name = r->first; const AttributeValidator& av = r->second; - if((av.mandatory()) && (atts.getValue(name).empty())) + if((av.mandatory()) && (string_adaptor::empty(atts.getValue(name)))) throw SAX::SAXException(string_adaptor::asStdString(parentElement) + ": Attribute " + string_adaptor::asStdString(name) + " must be specified"); if(av.has_default()) results[name] = av.default_value(); @@ -300,7 +300,7 @@ template void verifyNoCharacterData(const string_type& ch, const string_type& name) { - for(typename string_type::const_iterator i = ch.begin(), e = ch.end(); i != e; ++i) + for(typename string_adaptor::const_iterator i = string_adaptor::begin(ch), e = string_adaptor::end(ch); i != e; ++i) if(!Arabica::XML::is_space(*i)) throw SAX::SAXException(string_adaptor::asStdString(name) + " element can not contain character data."); } // verifyNoCharacterContent diff --git a/include/XSLT/impl/handler/xslt_variable_handler.hpp b/include/XSLT/impl/handler/xslt_variable_handler.hpp index f4800a37..5c3f7bec 100644 --- a/include/XSLT/impl/handler/xslt_variable_handler.hpp +++ b/include/XSLT/impl/handler/xslt_variable_handler.hpp @@ -63,9 +63,9 @@ protected: { if(has_select_) { - for(typename string_type::const_iterator i = ch.begin(), e = ch.end(); i != e; ++i) - if(!Arabica::XML::is_space(*i)) - throw SAX::SAXException("A variable or param can not have both a select attribute and text context"); + for(typename string_adaptor::const_iterator i = string_adaptor::begin(ch), e = string_adaptor::end(ch); i != e; ++i) + if(!Arabica::XML::is_space(*i)) + throw SAX::SAXException("A variable or param can not have both a select attribute and text context"); } ItemContainerHandler::characters(ch); } // characters diff --git a/include/XSLT/impl/xslt_attribute.hpp b/include/XSLT/impl/xslt_attribute.hpp index 4586c60b..7d890db7 100644 --- a/include/XSLT/impl/xslt_attribute.hpp +++ b/include/XSLT/impl/xslt_attribute.hpp @@ -35,7 +35,7 @@ public: ExecutionContext& context) const { string_type name = name_->evaluateAsString(node, context.xpathContext()); - if(name.empty()) + if(string_adaptor::empty(name)) throw SAX::SAXException("xsl:attribute name attribute must evaluate to a valid element name"); string_type namesp; @@ -45,7 +45,7 @@ public: else { QName qn = QName::create(name); - if(!qn.prefix.empty()) + if(!string_adaptor::empty(qn.prefix)) { typename std::map::const_iterator ns = namespaces_.find(qn.prefix); if(ns == namespaces_.end()) diff --git a/include/XSLT/impl/xslt_compilation_context.hpp b/include/XSLT/impl/xslt_compilation_context.hpp index 3fde246d..481300bd 100644 --- a/include/XSLT/impl/xslt_compilation_context.hpp +++ b/include/XSLT/impl/xslt_compilation_context.hpp @@ -171,7 +171,7 @@ public: { std::basic_ostringstream ss; ss << SC::auto_ns << autoNs_++; - return ss.str(); + return string_adaptor::construct(ss.str()); } // autoNamespacePrefix void set_precedence(const Precedence& prec) @@ -204,7 +204,7 @@ private: const string_type& name, const std::vector >& argExprs) const { - if(!namespace_uri.empty()) + if(!string_adaptor::empty(namespace_uri)) return new UndefinedFunction(namespace_uri, name, argExprs); // document diff --git a/include/XSLT/impl/xslt_functions.hpp b/include/XSLT/impl/xslt_functions.hpp index 07041e70..a6d26e09 100644 --- a/include/XSLT/impl/xslt_functions.hpp +++ b/include/XSLT/impl/xslt_functions.hpp @@ -236,7 +236,7 @@ protected: std::basic_ostringstream os; os << node.underlying_impl(); - return os.str(); + return string_adaptor::construct(os.str()); } // doEvaluate }; // class GenerateIdFunction @@ -315,7 +315,7 @@ protected: const QualifiedName expandedName = QualifiedName::parseQName(functionName, true, namespaces_); if((expandedName.namespaceUri() != StylesheetConstant::NamespaceURI) && - (!expandedName.namespaceUri().empty())) + (!string_adaptor::empty(expandedName.namespaceUri()))) return false; static string_type XSLTNames[] = { SC::apply_imports, @@ -414,14 +414,14 @@ public: { typedef Arabica::text::Unicode UnicodeT; - if(!namespace_uri.empty()) + if(!string_adaptor::empty(namespace_uri)) { - error_ += UnicodeT::LEFT_SQUARE_BRACKET; - error_ += namespace_uri; - error_ += UnicodeT::RIGHT_SQUARE_BRACKET; + string_adaptor::append(error_, UnicodeT::LEFT_SQUARE_BRACKET); + string_adaptor::append(error_, namespace_uri); + string_adaptor::append(error_, UnicodeT::RIGHT_SQUARE_BRACKET); } // if .. - error_ += name; + string_adaptor::append(error_, name); } // UndefinedFunction protected: diff --git a/include/XSLT/impl/xslt_namespace_stack.hpp b/include/XSLT/impl/xslt_namespace_stack.hpp index 311d4cee..79516b14 100644 --- a/include/XSLT/impl/xslt_namespace_stack.hpp +++ b/include/XSLT/impl/xslt_namespace_stack.hpp @@ -42,7 +42,7 @@ public: if(findPrefix(namespaceURI) != EMPTY_STRING) return; - bool remap = (attr && given_prefix.empty()) || (given_prefix == SC::xmlns); + bool remap = (attr && string_adaptor::empty(given_prefix)) || (given_prefix == SC::xmlns); string_type prefix = !remap ? given_prefix : autoNamespacePrefix(); @@ -81,7 +81,7 @@ private: { std::basic_ostringstream ss; ss << SC::auto_ns << autoNs_++; - return ss.str(); + return string_adaptor::construct(ss.str()); } // autoNamespacePrefix ScopeStack prefixStack_; diff --git a/include/XSLT/impl/xslt_output.hpp b/include/XSLT/impl/xslt_output.hpp index 8b58ded5..0c9fa348 100644 --- a/include/XSLT/impl/xslt_output.hpp +++ b/include/XSLT/impl/xslt_output.hpp @@ -65,7 +65,7 @@ public: flush_current(); namespaceStack_.pushScope(); - if(!namespaceURI.empty()) + if(!string_adaptor::empty(namespaceURI)) namespaceStack_.declareNamespace(prefix, namespaceURI); string_type mapped_prefix = namespaceStack_.findPrefix(namespaceURI); @@ -95,13 +95,21 @@ public: if(!text_mode_) { string_type mapped_prefix = namespaceStack_.findPrefix(namespaceURI); - do_end_element((!mapped_prefix.empty()) ? mapped_prefix + SC::COLON + localName : localName, namespaceURI); + do_end_element((!string_adaptor::empty(mapped_prefix)) ? makeName(mapped_prefix, localName) : localName, namespaceURI); element_stack_.pop(); } // end_element namespaceStack_.popScope(); } // end_element + string_type makeName(const string_type& prefix, const string_type& localName) const + { + string_type n = prefix; + string_adaptor::append(n, SC::COLON); + string_adaptor::append(n, localName); + return n; + } // makeName + void start_attribute(const string_type& qName, const string_type& namespaceURI) { QName qn = QName::create(qName, namespaceURI); @@ -119,11 +127,11 @@ public: return; } // if ... - if(!namespaceURI.empty()) + if(!string_adaptor::empty(namespaceURI)) namespaceStack_.declareNamespace(prefix, namespaceURI, true); string_type mapped_prefix = namespaceStack_.findPrefix(namespaceURI); - string_type qName = (!mapped_prefix.empty()) ? mapped_prefix + SC::COLON + localName : localName; + string_type qName = (!string_adaptor::empty(mapped_prefix)) ? makeName(mapped_prefix, localName) : localName; atts_.addOrReplaceAttribute(namespaceURI, localName, @@ -141,7 +149,6 @@ public: if(pending_attribute_ == -1) return; - atts_.setValue(pending_attribute_, buffer_.str()); pending_attribute_ = -1; } // end_attribute @@ -173,7 +180,7 @@ public: if(pending_attribute_ != -1) { - atts_.setValue(pending_attribute_, atts_.getValue(pending_attribute_) + ch); + atts_.setValue(pending_attribute_, string_adaptor::concat(atts_.getValue(pending_attribute_), ch)); return; } // if ... @@ -204,9 +211,9 @@ public: if(!text_mode_) { - string_type comment = escape(buffer_.str(), SC::double_hyphen, SC::escaped_double_hyphen); - if(comment.length() && *(comment.rbegin()) == SC::HYPHEN_MINUS) - comment += SC::SPACE; + string_type comment = escape(string_adaptor::construct(buffer_.str()), SC::double_hyphen, SC::escaped_double_hyphen); + if(string_adaptor::length(comment) && *(string_adaptor::rbegin(comment)) == SC::HYPHEN_MINUS) + string_adaptor::append(comment, SC::SPACE); do_comment(comment); } // if ... } // end_comment @@ -228,7 +235,7 @@ public: if(!text_mode_) { - string_type data = escape(buffer_.str(), SC::PIEnd, SC::escaped_pi_end); + string_type data = escape(string_adaptor::construct(buffer_.str()), SC::PIEnd, SC::escaped_pi_end); do_processing_instruction(target_, data); } // if ... } // end_processing_instruction @@ -260,11 +267,14 @@ protected: private: string_type escape(string_type str, const string_type& t, const string_type& r) const { - typename string_type::size_type naughty = str.find(t); - while(naughty != string_type::npos) + typename string_adaptor::size_type naughty = string_adaptor::find(str, t); + while(naughty != string_adaptor::npos()) { - str.replace(naughty, t.length(), r, 0, r.length()); - naughty = str.find(t, naughty); + string_type newstr = string_adaptor::substr(str, 0, naughty); + string_adaptor::append(newstr, r); + string_adaptor::append(newstr, string_adaptor::substr(str, naughty + string_adaptor::length(t))); + str = newstr; + naughty = string_adaptor::find(str, t, naughty); } // while return str; } // escape @@ -277,7 +287,7 @@ private: if(is_buf) return true; - buffer_.str(string_adaptor::empty_string()); + buffer_.str(std::basic_string()); return false; } // push_buffering @@ -349,7 +359,7 @@ private: if(n->first == SC::xml) continue; - string_type qName = (n->first.empty()) ? SC::xmlns : SC::xmlns_colon + n->first; + string_type qName = (string_adaptor::empty(n->first)) ? SC::xmlns : string_adaptor::concat(SC::xmlns_colon, n->first); atts_.addAttribute(SC::xmlns_uri, n->first, qName, diff --git a/include/XSLT/impl/xslt_processing_instruction.hpp b/include/XSLT/impl/xslt_processing_instruction.hpp index d3866f09..cbc78122 100644 --- a/include/XSLT/impl/xslt_processing_instruction.hpp +++ b/include/XSLT/impl/xslt_processing_instruction.hpp @@ -37,25 +37,29 @@ public: private: void validate_name(const string_type& name) const { - if(name.empty()) + if(string_adaptor::empty(name)) throw SAX::SAXException("xsl:processing-instruction : name attribute must evaluate to a valid name"); if(!Arabica::XML::is_ncname(name)) throw SAX::SAXException("xsl:processing-instruction : '" + string_adaptor::asStdString(name) + "' is not valid as the name"); - if(name.length() != 3) + if(string_adaptor::length(name) != 3) return; typedef Arabica::text::Unicode UnicodeT; - if((name[0] != UnicodeT::CAPITAL_X) && - (name[0] != UnicodeT::LOWERCASE_X)) + typename string_adaptor::const_iterator i = string_adaptor::begin(name); + + if((*i != UnicodeT::CAPITAL_X) && + (*i != UnicodeT::LOWERCASE_X)) return; - if((name[1] != UnicodeT::CAPITAL_M) && - (name[1] != UnicodeT::LOWERCASE_M)) + ++i; + if((*i != UnicodeT::CAPITAL_M) && + (*i != UnicodeT::LOWERCASE_M)) return; - if((name[2] != UnicodeT::CAPITAL_L) && - (name[2] != UnicodeT::LOWERCASE_L)) + ++i; + if((*i != UnicodeT::CAPITAL_L) && + (*i != UnicodeT::LOWERCASE_L)) return; throw SAX::SAXException("xsl:processing-instruction name can not be 'xml'"); diff --git a/include/XSLT/impl/xslt_qname.hpp b/include/XSLT/impl/xslt_qname.hpp index 9ae6201b..c0185907 100644 --- a/include/XSLT/impl/xslt_qname.hpp +++ b/include/XSLT/impl/xslt_qname.hpp @@ -20,18 +20,24 @@ struct QName string_type qname; QName(const string_type& p, - const string_type& lN, - const string_type& uri) : + const string_type& lN, + const string_type& uri) : prefix(p), localName(lN), namespaceURI(uri), - qname(p.empty() ? lN : (p + SC::COLON + lN)) + qname() { + if(!string_adaptor::empty(p)) + { + string_adaptor::append(qname, p); + string_adaptor::append(qname, SC::COLON); + } // if ... + string_adaptor::append(qname, lN); } // QName static QName create(const XML::QualifiedName& qName) { - if(qName.prefix().length() && qName.namespaceUri().empty()) + if(string_adaptor::length(qName.prefix()) && string_adaptor::empty(qName.namespaceUri())) throw SAX::SAXException("Prefix " + string_adaptor::asStdString(qName.prefix()) + " is not declared."); return QName(qName.prefix(), qName.localName(), qName.namespaceUri()); } // create @@ -49,14 +55,14 @@ struct QName string_type prefix; string_type localName; - size_t colon = qName.find(SC::COLON); + size_t colon = string_adaptor::find(qName, SC::COLON); - if(colon == string_type::npos) + if(colon == string_adaptor::npos()) localName = qName; else { - prefix = qName.substr(0, colon); - localName = qName.substr(colon+1); + prefix = string_adaptor::substr(qName, 0, colon); + localName = string_adaptor::substr(qName, colon+1); } return QName(prefix, localName, namespaceURI); } // create diff --git a/include/XSLT/impl/xslt_sink.hpp b/include/XSLT/impl/xslt_sink.hpp index 5937c069..1b8add64 100644 --- a/include/XSLT/impl/xslt_sink.hpp +++ b/include/XSLT/impl/xslt_sink.hpp @@ -146,7 +146,7 @@ protected: { stream_ << ' ' << atts.getQName(a) << '=' << '\"'; string_type ch = atts.getValue(a); - std::for_each(ch.begin(), ch.end(), Arabica::XML::attribute_escaper(stream_)); + std::for_each(string_adaptor::begin(ch), string_adaptor::end(ch), Arabica::XML::attribute_escaper(stream_)); stream_ << '\"'; } empty_ = true; @@ -175,11 +175,11 @@ protected: close_element_if_empty(); if(!disable_output_escaping_ && !in_cdata_) - std::for_each(ch.begin(), ch.end(), Arabica::XML::text_escaper(stream_)); + std::for_each(string_adaptor::begin(ch), string_adaptor::end(ch), Arabica::XML::text_escaper(stream_)); else if(in_cdata_) { - size_t breakAt = ch.find(SC::CDATAEnd); - if(breakAt == string_type::npos) + size_t breakAt = string_adaptor::find(ch, SC::CDATAEnd); + if(breakAt == string_adaptor::npos()) { stream_ << ch; return; @@ -188,14 +188,14 @@ protected: do { breakAt += 2; - stream_ << ch.substr(start, breakAt); + stream_ << string_adaptor::substr(ch, start, breakAt); do_end_CDATA(); start = breakAt; do_start_CDATA(); - breakAt = ch.find(SC::CDATAEnd, breakAt); + breakAt = string_adaptor::find(ch, SC::CDATAEnd, breakAt); } - while(breakAt != string_type::npos); - stream_ << ch.substr(start); + while(breakAt != string_adaptor::npos()); + stream_ << string_adaptor::substr(ch, start); } else stream_ << ch; @@ -294,26 +294,26 @@ private: { string_type version = setting(SC::version); - if(version.empty()) + if(string_adaptor::empty(version)) version = SC::Version; stream_ << "\n"; - if(!qName.empty()) + if(!string_adaptor::empty(qName)) { string_type pub = setting(SC::doctype_public); string_type sys = setting(SC::doctype_system); - if(!sys.empty()) + if(!string_adaptor::empty(sys)) { stream_ << "\n"; else stream_ << " SYSTEM \"" << sys << "\">\n"; @@ -382,7 +382,7 @@ protected: if(lc == 0 || lc.getNodeType() != DOM::Node_base::TEXT_NODE) current().appendChild(document().createTextNode(ch)); else - lc.setNodeValue(lc.getNodeValue() + ch); + lc.setNodeValue(string_adaptor::concat(lc.getNodeValue(), ch)); } // do_characters void do_start_CDATA() @@ -462,9 +462,10 @@ private: string_type sps; if(indent_ != 0) { - sps += '\n'; - std::fill_n(std::back_inserter(sps), indent_, ' '); - do_characters(sps); + std::basic_string sps; + sps += SC::CARRIAGE_RETURN; + std::fill_n(std::back_inserter >(sps), indent_, SC::SPACE); + do_characters(string_adaptor::construct(sps)); } // if ... indent_ += 2; diff --git a/include/XSLT/impl/xslt_stylesheet_compiler.hpp b/include/XSLT/impl/xslt_stylesheet_compiler.hpp index 1b65753e..d94064b6 100644 --- a/include/XSLT/impl/xslt_stylesheet_compiler.hpp +++ b/include/XSLT/impl/xslt_stylesheet_compiler.hpp @@ -63,7 +63,7 @@ public: if(namespaceURI == SC::NamespaceURI) startXSLTElement(namespaceURI, localName, qName, atts); - else if(!namespaceURI.empty()) + else if(!string_adaptor::empty(namespaceURI)) startForeignElement(namespaceURI, localName, qName, atts); else oops(qName); @@ -103,7 +103,7 @@ private: std::map attributes = rules.gather(qName, atts); if(attributes[SC::version] != SC::Version) throw SAX::SAXException("I'm only a poor version 1.0 XSLT Transformer."); - if(!attributes[SC::extension_element_prefixes].empty()) + if(!string_adaptor::empty(attributes[SC::extension_element_prefixes])) throw SAX::SAXException("Haven't implemented extension-element-prefixes yet"); } // startStylesheet @@ -121,7 +121,7 @@ private: break; } - if(version.empty()) + if(string_adaptor::empty(version)) throw SAX::SAXException("The source file does not look like a stylesheet."); if(version != SC::Version) throw SAX::SAXException("I'm only a poor version 1.0 XSLT Transformer."); diff --git a/include/XSLT/impl/xslt_template.hpp b/include/XSLT/impl/xslt_template.hpp index 81611d95..03045f30 100644 --- a/include/XSLT/impl/xslt_template.hpp +++ b/include/XSLT/impl/xslt_template.hpp @@ -40,7 +40,7 @@ public: mode_(mode), precedence_(precedence) { - if(!priority.empty()) + if(!string_adaptor::empty(priority)) { double p = boost::lexical_cast(Arabica::text::normalize_whitespace(priority)); for(typename MatchExprList::iterator m = matches_.begin(), me = matches_.end(); m != me; ++m) @@ -58,7 +58,7 @@ public: } // execute const MatchExprList& compiled_matches() const { return matches_; } - bool has_name() const { return !name_.empty(); } + bool has_name() const { return !string_adaptor::empty(name_); } const string_type& name() const { return name_; } const string_type& mode() const { return mode_; } const Precedence& precedence() const { return precedence_; } diff --git a/include/XSLT/impl/xslt_variable_stack.hpp b/include/XSLT/impl/xslt_variable_stack.hpp index dd375ad5..c896a3aa 100644 --- a/include/XSLT/impl/xslt_variable_stack.hpp +++ b/include/XSLT/impl/xslt_variable_stack.hpp @@ -159,7 +159,7 @@ public: { typedef Arabica::text::Unicode UnicodeT; - string_type clarkName = namespace_uri.empty() ? name : make_clark_name(namespace_uri, name); + string_type clarkName = string_adaptor::empty(namespace_uri) ? name : make_clark_name(namespace_uri, name); if(std::find(resolutionStack_.begin(), resolutionStack_.end(), clarkName) != resolutionStack_.end()) throw std::runtime_error("Circular dependency: " + string_adaptor::asStdString(clarkName) + " refers to itself directly or indirectly."); diff --git a/tests/silly_string/silly_string.cpp b/tests/silly_string/silly_string.cpp index 90a8ae8c..fe77038e 100644 --- a/tests/silly_string/silly_string.cpp +++ b/tests/silly_string/silly_string.cpp @@ -1,156 +1,177 @@ -#include "silly_string.hpp" - -#include -#include -#include - -silly_string::silly_string() -{ -} // silly_string - -silly_string::silly_string(const silly_string& rhs) -{ - s_ = rhs.s_; -} // silly_string - -silly_string::~silly_string() -{ -} // ~silly_string - -bool silly_string::operator==(const silly_string& rhs) const -{ - return s_ == rhs.s_; -} // operator== - -silly_string& silly_string::operator=(const silly_string& rhs) -{ - s_ = rhs.s_; - return *this; -} // operator= - -bool operator<(const silly_string& lhs, const silly_string& rhs) -{ - return lhs.s_ < rhs.s_; -} // operator< - -//////////////////////////////////////// -//////////////////////////////////////// -char silly_string_adaptor::convert_from_utf8(char c) -{ - return c; -} // convert_from_utf8 - -silly_string silly_string_adaptor::construct_from_utf8(const char* str) -{ - silly_string s; - if(str) - s.s_ = str; - return s; -} // construct_from_utf8 - -silly_string silly_string_adaptor::construct_from_utf8(const char* str, int length) -{ - silly_string s; - if(str) - s.s_ = std::string(str, length); - return s; -} // construct_from_utf8 - -#ifndef ARABICA_NO_WCHAR_T -silly_string silly_string_adaptor::construct_from_utf16(const wchar_t* str) -{ - Arabica::io::basic_oconvertstream, - char, std::char_traits > narrower; - narrower.imbue(std::locale(narrower.getloc(), new Arabica::convert::utf8ucs2codecvt())); - narrower.str(str ? str : L""); - silly_string s; - s.s_ = narrower.str(); - return s; -} // construct_from_utf16 - -silly_string silly_string_adaptor::construct_from_utf16(const wchar_t* str, int length) -{ - Arabica::io::basic_oconvertstream, - char, std::char_traits > narrower; - narrower.imbue(std::locale(narrower.getloc(), new Arabica::convert::utf8ucs2codecvt())); - narrower.str(std::wstring(str, length)); - silly_string s; - s.s_ = narrower.str(); - return s; -} // construct_from_utf16 -#endif - -bool silly_string_adaptor::empty(const silly_string& s) -{ - return s.s_.empty(); -} // empty - -silly_string_adaptor::size_type silly_string_adaptor::find(const silly_string& str, const silly_string& what) -{ - return str.s_.find(what.s_); -} // find - -silly_string_adaptor::size_type silly_string_adaptor::find(const silly_string& str, value_type c) -{ - return str.s_.find(c); -} // find - -silly_string_adaptor::size_type silly_string_adaptor::find(const silly_string& str, const silly_string& what, silly_string_adaptor::size_type from) -{ - return str.s_.find(what.s_, from); -} // find - -silly_string_adaptor::size_type silly_string_adaptor::find(const silly_string& str, value_type c, silly_string_adaptor::size_type from) -{ - return str.s_.find(c, from); -} // find - -silly_string silly_string_adaptor::substr(const silly_string& str, const size_type& offset) -{ - return silly_string_adaptor::construct_from_utf8(str.s_.substr(offset).c_str()); -} // substr - -silly_string silly_string_adaptor::substr(const silly_string& str, const size_type& offset, const size_type& count) -{ - return silly_string_adaptor::construct_from_utf8(str.s_.substr(offset, count).c_str()); -} // substr - -silly_string_adaptor::size_type silly_string_adaptor::length(const silly_string& str) -{ - return str.s_.length(); -} // length - -void silly_string_adaptor::append(silly_string& str, const silly_string& a) -{ - str.s_.append(a.s_); -} // append - -void silly_string_adaptor::insert(silly_string& str, size_type offset, const silly_string& a) -{ - str.s_.insert(offset, a.s_); -} // insert - -void silly_string_adaptor::replace(silly_string& str, size_type offset, size_type count, const silly_string& a) -{ - str.s_.replace(offset, count, a.s_); -} // replace - - -// only used to constuct error strings - don't have to be highly efficient! -std::string silly_string_adaptor::asStdString(const silly_string& str) -{ - return str.s_; -} // asStdString - -#ifndef ARABICA_NO_WCHAR_T -std::wstring silly_string_adaptor::asStdWString(const silly_string& str) -{ - Arabica::io::basic_oconvertstream, - wchar_t, std::char_traits > widener; - std::codecvt* cc = new Arabica::convert::ucs2utf8codecvt(); - widener.imbue(std::locale(widener.getloc(), cc)); - widener.str(str.s_); - return widener.str(); -} // asStdWString -#endif - +#include "silly_string.hpp" + +#include +#include +#include + +silly_string::silly_string() +{ +} // silly_string + +silly_string::silly_string(const silly_string& rhs) +{ + s_ = rhs.s_; +} // silly_string + +silly_string::~silly_string() +{ +} // ~silly_string + +bool silly_string::operator==(const silly_string& rhs) const +{ + return s_ == rhs.s_; +} // operator== + +silly_string& silly_string::operator=(const silly_string& rhs) +{ + s_ = rhs.s_; + return *this; +} // operator= + +bool operator<(const silly_string& lhs, const silly_string& rhs) +{ + return lhs.s_ < rhs.s_; +} // operator< + +bool operator>(const silly_string& lhs, const silly_string& rhs) +{ + return lhs.s_ > rhs.s_; +} // operator< + +//////////////////////////////////////// +//////////////////////////////////////// +char silly_string_adaptor::convert_from_utf8(char c) +{ + return c; +} // convert_from_utf8 + +silly_string silly_string_adaptor::construct_from_utf8(const char* str) +{ + silly_string s; + if(str) + s.s_ = str; + return s; +} // construct_from_utf8 + +silly_string silly_string_adaptor::construct_from_utf8(const char* str, int length) +{ + silly_string s; + if(str) + s.s_ = std::string(str, length); + return s; +} // construct_from_utf8 + +#ifndef ARABICA_NO_WCHAR_T +silly_string silly_string_adaptor::construct_from_utf16(const wchar_t* str) +{ + Arabica::io::basic_oconvertstream, + char, std::char_traits > narrower; + narrower.imbue(std::locale(narrower.getloc(), new Arabica::convert::utf8ucs2codecvt())); + narrower.str(str ? str : L""); + silly_string s; + s.s_ = narrower.str(); + return s; +} // construct_from_utf16 + +silly_string silly_string_adaptor::construct_from_utf16(const wchar_t* str, int length) +{ + Arabica::io::basic_oconvertstream, + char, std::char_traits > narrower; + narrower.imbue(std::locale(narrower.getloc(), new Arabica::convert::utf8ucs2codecvt())); + narrower.str(std::wstring(str, length)); + silly_string s; + s.s_ = narrower.str(); + return s; +} // construct_from_utf16 +#endif + +bool silly_string_adaptor::empty(const silly_string& s) +{ + return s.s_.empty(); +} // empty + +silly_string_adaptor::size_type silly_string_adaptor::find(const silly_string& str, const silly_string& what) +{ + return str.s_.find(what.s_); +} // find + +silly_string_adaptor::size_type silly_string_adaptor::find(const silly_string& str, value_type c) +{ + return str.s_.find(c); +} // find + +silly_string_adaptor::size_type silly_string_adaptor::find(const silly_string& str, const silly_string& what, silly_string_adaptor::size_type from) +{ + return str.s_.find(what.s_, from); +} // find + +silly_string_adaptor::size_type silly_string_adaptor::find(const silly_string& str, value_type c, silly_string_adaptor::size_type from) +{ + return str.s_.find(c, from); +} // find + +silly_string silly_string_adaptor::substr(const silly_string& str, const size_type& offset) +{ + return silly_string_adaptor::construct_from_utf8(str.s_.substr(offset).c_str()); +} // substr + +silly_string silly_string_adaptor::substr(const silly_string& str, const size_type& offset, const size_type& count) +{ + return silly_string_adaptor::construct_from_utf8(str.s_.substr(offset, count).c_str()); +} // substr + +silly_string_adaptor::size_type silly_string_adaptor::length(const silly_string& str) +{ + return str.s_.length(); +} // length + +void silly_string_adaptor::append(silly_string& str, const silly_string& a) +{ + str.s_.append(a.s_); +} // append + +void silly_string_adaptor::append(silly_string& str, const char& a) +{ + str.s_ += a; +} // append + +silly_string silly_string_adaptor::concat(const silly_string& str, const silly_string& a) +{ + return construct(str.s_ + a.s_); +} + +silly_string silly_string_adaptor::concat(const silly_string& str, const char& a) +{ + return construct(str.s_ + a); +} + + +void silly_string_adaptor::insert(silly_string& str, size_type offset, const silly_string& a) +{ + str.s_.insert(offset, a.s_); +} // insert + +void silly_string_adaptor::replace(silly_string& str, size_type offset, size_type count, const silly_string& a) +{ + str.s_.replace(offset, count, a.s_); +} // replace + + +// only used to constuct error strings - don't have to be highly efficient! +std::string silly_string_adaptor::asStdString(const silly_string& str) +{ + return str.s_; +} // asStdString + +#ifndef ARABICA_NO_WCHAR_T +std::wstring silly_string_adaptor::asStdWString(const silly_string& str) +{ + Arabica::io::basic_oconvertstream, + wchar_t, std::char_traits > widener; + std::codecvt* cc = new Arabica::convert::ucs2utf8codecvt(); + widener.imbue(std::locale(widener.getloc(), cc)); + widener.str(str.s_); + return widener.str(); +} // asStdWString +#endif + diff --git a/tests/silly_string/silly_string.hpp b/tests/silly_string/silly_string.hpp index 3f0eacf8..4dec2930 100644 --- a/tests/silly_string/silly_string.hpp +++ b/tests/silly_string/silly_string.hpp @@ -1,117 +1,130 @@ -#ifndef ARABICA_TEST_SILLY_STRING_HPP -#define ARABICA_TEST_SILLY_STRING_HPP - -#include -#include -#include -#include -// testing purposes only -// a string with as minimal interface as possible - -class silly_string -{ -public: - silly_string(); - silly_string(const silly_string& rhs); - ~silly_string(); - - bool operator==(const silly_string& rhs) const; - bool operator!=(const silly_string& rhs) const { return !(this->operator==(rhs)); } - silly_string& operator=(const silly_string& rhs); - -private: - // use a std::string to the actual work - std::string s_; - - friend class silly_string_adaptor; - friend bool operator<(const silly_string& lhs, - const silly_string& rhs); -}; // class silly_string - -bool operator<(const silly_string& lhs, const silly_string& rhs); - -class silly_string_adaptor : public Arabica::string_adaptor_tag -{ -public: - typedef silly_string string_type; - typedef std::string::const_iterator const_iterator; - typedef std::string::iterator mutable_iterator; - typedef char value_type; - typedef std::string::size_type size_type; - static size_type npos() - { - return std::string::npos; - } - - static const silly_string& empty_string() { static silly_string es; return es; } - - template - static silly_string construct(InputIterator from, InputIterator to) - { - silly_string ss; - ss.s_ = std::string(from, to); - return ss; - } // construct - - static string_type construct(const value_type* s) - { - silly_string ss; - ss.s_ = std::string(s); - return ss; - } // construct - - static char convert_from_utf8(char c); - static silly_string construct_from_utf8(const char* str); - static silly_string construct_from_utf8(const char* str, int length); -#ifndef ARABICA_NO_WCHAR_T - static silly_string construct_from_utf16(const wchar_t* str); - static silly_string construct_from_utf16(const wchar_t* str, int length); -#endif - - // here we go - static bool empty(const silly_string& s); - static size_type find(const silly_string& str, const silly_string& what); - static size_type find(const silly_string& str, value_type c); - static size_type find(const silly_string& str, const silly_string& what, size_type from); - static size_type find(const silly_string& str, value_type c, size_type from); - static silly_string substr(const silly_string& str, const size_type& offset); - static silly_string substr(const silly_string& str, const size_type& offset, const size_type& count); - static size_type length(const silly_string& str); - static void append(silly_string& str, const silly_string& a); - static void insert(silly_string& str, size_type offset, const silly_string& a); - static void replace(silly_string& str, size_type offset, size_type count, const silly_string& a); - static const_iterator begin(const silly_string& str) { return str.s_.begin(); } - static mutable_iterator begin(silly_string& str) { return str.s_.begin(); } - static const_iterator end(const silly_string& str) { return str.s_.end(); } - static mutable_iterator end(silly_string& str) { return str.s_.end(); } - - // mainly used to constuct error strings - don't have to be highly efficient! - static std::string asStdString(const silly_string& str); -#ifndef ARABICA_NO_WCHAR_T - static std::wstring asStdWString(const silly_string& str); -#endif -}; // class silly_string_adaptor - -template -std::basic_ostream& operator<<(std::basic_ostream& os, const silly_string& s) -{ - os << silly_string_adaptor::asStdString(s); - return os; -} // operator<< - -namespace std { - -template<> -struct less : public binary_function -{ - // functor for operator< - bool operator()(const silly_string& lhs, const silly_string& rhs) const - { - // apply operator< to operands - return (silly_string_adaptor::asStdString(lhs) < silly_string_adaptor::asStdString(rhs)); - } // operator() -}; - -} // namespace std - -#endif +#ifndef ARABICA_TEST_SILLY_STRING_HPP +#define ARABICA_TEST_SILLY_STRING_HPP + +#include +#include +#include +#include +// testing purposes only +// a string with as minimal interface as possible + +class silly_string +{ +public: + silly_string(); + silly_string(const silly_string& rhs); + ~silly_string(); + + bool operator==(const silly_string& rhs) const; + bool operator!=(const silly_string& rhs) const { return !(this->operator==(rhs)); } + silly_string& operator=(const silly_string& rhs); + +private: + // use a std::string to the actual work + std::string s_; + + friend class silly_string_adaptor; + friend bool operator<(const silly_string& lhs, + const silly_string& rhs); + friend bool operator>(const silly_string& lhs, + const silly_string& rhs); +}; // class silly_string + +bool operator<(const silly_string& lhs, const silly_string& rhs); +bool operator>(const silly_string& lhs, const silly_string& rhs); + +class silly_string_adaptor : public Arabica::string_adaptor_tag +{ +public: + typedef silly_string string_type; + typedef std::string::const_iterator const_iterator; + typedef std::string::iterator mutable_iterator; + typedef std::string::const_reverse_iterator const_reverse_iterator; + typedef char value_type; + typedef std::string::size_type size_type; + static size_type npos() + { + return std::string::npos; + } + + static const silly_string& empty_string() { static silly_string es; return es; } + + template + static silly_string construct(InputIterator from, InputIterator to) + { + silly_string ss; + ss.s_ = std::string(from, to); + return ss; + } // construct + + static string_type construct(const value_type* s) + { + silly_string ss; + ss.s_ = std::string(s); + return ss; + } // construct + + static silly_string construct(const std::basic_string& str) + { + return construct(str.c_str()); + } // construct + + static char convert_from_utf8(char c); + static silly_string construct_from_utf8(const char* str); + static silly_string construct_from_utf8(const char* str, int length); +#ifndef ARABICA_NO_WCHAR_T + static silly_string construct_from_utf16(const wchar_t* str); + static silly_string construct_from_utf16(const wchar_t* str, int length); +#endif + + // here we go + static bool empty(const silly_string& s); + static size_type find(const silly_string& str, const silly_string& what); + static size_type find(const silly_string& str, value_type c); + static size_type find(const silly_string& str, const silly_string& what, size_type from); + static size_type find(const silly_string& str, value_type c, size_type from); + static silly_string substr(const silly_string& str, const size_type& offset); + static silly_string substr(const silly_string& str, const size_type& offset, const size_type& count); + static size_type length(const silly_string& str); + static void append(silly_string& str, const silly_string& a); + static void append(silly_string& str, const char& a); + static silly_string concat(const silly_string& str, const silly_string& a); + static silly_string concat(const silly_string& str, const char& a); + static void insert(silly_string& str, size_type offset, const silly_string& a); + static void replace(silly_string& str, size_type offset, size_type count, const silly_string& a); + static const_iterator begin(const silly_string& str) { return str.s_.begin(); } + static mutable_iterator begin(silly_string& str) { return str.s_.begin(); } + static const_iterator end(const silly_string& str) { return str.s_.end(); } + static mutable_iterator end(silly_string& str) { return str.s_.end(); } + static const_reverse_iterator rbegin(const silly_string& str) { return str.s_.rbegin(); } + + // mainly used to constuct error strings - don't have to be highly efficient! + static std::string asStdString(const silly_string& str); +#ifndef ARABICA_NO_WCHAR_T + static std::wstring asStdWString(const silly_string& str); +#endif +}; // class silly_string_adaptor + +template +std::basic_ostream& operator<<(std::basic_ostream& os, const silly_string& s) +{ + os << silly_string_adaptor::asStdString(s); + return os; +} // operator<< + +namespace std { + +template<> +struct less : public binary_function +{ + // functor for operator< + bool operator()(const silly_string& lhs, const silly_string& rhs) const + { + // apply operator< to operands + return (silly_string_adaptor::asStdString(lhs) < silly_string_adaptor::asStdString(rhs)); + } // operator() +}; + +} // namespace std + +#endif diff --git a/vs2012/test_xslt_wide.vcxproj b/vs2012/test_xslt_wide.vcxproj index 0934ec43..508b4f9e 100644 --- a/vs2012/test_xslt_wide.vcxproj +++ b/vs2012/test_xslt_wide.vcxproj @@ -1,4 +1,4 @@ - + @@ -40,10 +40,10 @@ <_ProjectFileVersion>10.0.30319.1 .\..\bin\ - .\Debug_test_xslt\ + .\Debug_test_xslt_wide\ true .\..\bin\ - .\Release_test_xslt\ + .\Release_test_xslt_wide\ false xslt_test_wide xslt_test_wide