Qi + UTF-32 (Unicode) question regarding performance (small example attached)

"Mathias Born" <[email protected]>
Newsgroups gmane.comp.parsers.spirit.general
Message-ID <[email protected]>
Hi,

I'd appreciate advice on how to achieve best performance. I need to parse
text encoded as UTF-32.
A minimal example is attached and looks like this:

--start--

#define BOOST_SPIRIT_UNICODE

#include <string>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>

using namespace std::string_literals; 
using namespace boost;
using namespace boost::spirit;


// This is needed to make qi::parse work with
std::u32string::const_iterator.
namespace boost {
	template<> struct is_scalar<std::u32string::const_iterator> : public
true_type {};
}

// Enable auto conversion from std::u32string (UTF-32) to std::string
(UTF-8).
namespace boost {
	namespace spirit {
		namespace traits {
			template <> // <typename Attrib, typename T,
typename Enable>
			struct assign_to_container_from_value<std::string,
std::u32string, void>
			{
				typedef
u32_to_u8_iterator<std::u32string::const_iterator> Conv;

				static void call(std::u32string const& val,
std::string& attr) {
					attr.assign(Conv(val.begin()),
Conv(val.end()));
				}
			};
		}
	}
}

int main()
{
	qi::rule<std::u32string::const_iterator, std::u32string()> test1 =
"ASCII" > +unicode::char_;
	qi::symbols<char32_t> syms;
	syms.add(U"sym");
	qi::rule<std::u32string::const_iterator, std::u32string()> test2 =
L"WIDE" > syms > +unicode::char_;

	// The following line doesn't compile. Error msg:
	//
c:\cpp\boost_1_63_0\boost\spirit\home\qi\nonterminal\rule.hpp(177) : error
C2338 : error_invalid_expression
	// qi::rule<std::u32string::const_iterator, std::u32string()> test3
= U"U32" > +unicode::char_;

	auto input1 = U"ASCIIfoo"s;
	auto input2 = U"WIDEsymbar"s;

	std::string attr1, attr2;

	auto result1 = qi::parse(input1.cbegin(), input1.cend(), test1,
attr1);
	std::cout << result1 << " " << attr1 << std::endl;

	auto result2 = qi::parse(input2.cbegin(), input2.cend(), test2,
attr2);
	std::cout << result2 << " " << attr2 << std::endl;

	return 0;
}

--end--

Output is:
---
1 foo
1 bar
---

As you can see, I already figured out how to make qi accept u32string as
input, and all parsers work as expected.
However, I wonder what happens behind the scenes. Parsers "test1" and
"test2" use literals which are not UTF-32.
(At least on Windows, where wchar_t is 16 bit.)
But the input is, so isn't there a conversion to UTF-32 necessary at
runtime? If so, I'd like to use UTF-32 literals
in order to avoid any conversion, but that doesn't compile (see "test3").

But somehow spirit is already capable of processing UTF-32 literals, as
"syms" demonstrates.
Looks to me like I may just be missing some magic template to enable it.

Best Regards,
Mathias

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot

_______________________________________________
Spirit-general mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/spirit-general
simple.cpp (text/plain, 1.7 KB)
#define BOOST_SPIRIT_UNICODE

#include <string>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>

using namespace std::string_literals; 
using namespace boost;
using namespace boost::spirit;


// This is needed to make qi::parse work with std::u32string::const_iterator.
namespace boost {
	template<> struct is_scalar<std::u32string::const_iterator> : public true_type {};
}

// Enable auto conversion from std::u32string (UTF-32) to std::string (UTF-8).
namespace boost {
	namespace spirit {
		namespace traits {
			template <> // <typename Attrib, typename T, typename Enable>
			struct assign_to_container_from_value<std::string, std::u32string, void>
			{
				typedef u32_to_u8_iterator<std::u32string::const_iterator> Conv;

				static void call(std::u32string const& val, std::string& attr) {
					attr.assign(Conv(val.begin()), Conv(val.end()));
				}
			};
		}
	}
}

int main()
{
	qi::rule<std::u32string::const_iterator, std::u32string()> test1 = "ASCII" > +unicode::char_;
	qi::symbols<char32_t> syms;
	syms.add(U"sym");
	qi::rule<std::u32string::const_iterator, std::u32string()> test2 = L"WIDE" > syms > +unicode::char_;

	// The following line doesn't compile. Error msg:
	// c:\cpp\boost_1_63_0\boost\spirit\home\qi\nonterminal\rule.hpp(177) : error C2338 : error_invalid_expression
	// qi::rule<std::u32string::const_iterator, std::u32string()> test3 = U"U32" > +unicode::char_;

	auto input1 = U"ASCIIfoo"s;
	auto input2 = U"WIDEsymbar"s;

	std::string attr1, attr2;

	auto result1 = qi::parse(input1.cbegin(), input1.cend(), test1, attr1);
	std::cout << result1 << " " << attr1 << std::endl;

	auto result2 = qi::parse(input2.cbegin(), input2.cend(), test2, attr2);
	std::cout << result2 << " " << attr2 << std::endl;

	return 0;
}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.