diff options
Diffstat (limited to 'unicode/unicodecpp.C')
| -rw-r--r-- | unicode/unicodecpp.C | 306 | 
1 files changed, 305 insertions, 1 deletions
| diff --git a/unicode/unicodecpp.C b/unicode/unicodecpp.C index 51bed3c..4217630 100644 --- a/unicode/unicodecpp.C +++ b/unicode/unicodecpp.C @@ -1,5 +1,5 @@  /* -** Copyright 2011-2014 Double Precision, Inc. +** Copyright 2011-2020 Double Precision, Inc.  ** See COPYING for distribution information.  **  */ @@ -8,6 +8,7 @@  #include	"courier-unicode.h"  #include <algorithm> +#include <exception>  extern "C" { @@ -180,7 +181,10 @@ std::string unicode::iconvert::convert(const std::u32string &uc,  	int err;  	if (uc.empty()) +	{ +		errflag=false;  		return buf; +	}  	if (unicode_convert_fromu_tobuf(&uc[0], uc.size(),  					  dstcharset.c_str(), &c, &csize, @@ -557,3 +561,303 @@ std::u32string unicode::toupper(const std::u32string &u)  	return copy;  } + +std::tuple<std::vector<unicode_bidi_level_t>, unicode_bidi_level_t> +unicode::bidi_calc(const std::u32string &s) +{ +	return unicode::bidi_calc(s, UNICODE_BIDI_SKIP); +} + +std::tuple<std::vector<unicode_bidi_level_t>, unicode_bidi_level_t> +unicode::bidi_calc(const std::u32string &s, +		   unicode_bidi_level_t paragraph_embedding_level) +{ +	const unicode_bidi_level_t *initial_embedding_level=0; + +	if (paragraph_embedding_level == UNICODE_BIDI_LR || +	    paragraph_embedding_level == UNICODE_BIDI_RL) +	{ +		initial_embedding_level=¶graph_embedding_level; +	} + +	std::tuple<std::vector<unicode_bidi_level_t>, unicode_bidi_level_t> +		ret; + +	std::get<0>(ret).resize(s.size()); +	std::get<1>(ret)=UNICODE_BIDI_LR; + +	if (s.size()) +	{ +		std::get<1>(ret)=unicode_bidi_calc(s.c_str(), s.size(), +						   &std::get<0>(ret)[0], +						   initial_embedding_level); +	} +	return ret; +} + +namespace { +#if 0 +} +#endif +template<typename callable> +struct cb_wrapper { + +	const std::function<callable> &cb; +	std::exception_ptr caught; + +	cb_wrapper(const std::function<callable> &cb) : cb{cb} +	{ +	} + +	template<typename ...Args> void operator()(Args && ...args) +	{ +		try { +			cb(std::forward<Args>(args)...); +		} catch (...) +		{ +			caught=std::current_exception(); +		} +	} + +	void rethrow() +	{ +		if (caught) +			std::rethrow_exception(caught); +	} +}; +#if 0 +{ +#endif +} + + +extern "C" { +	static void reorder_callback(size_t i, size_t cnt, +				     void *arg) +	{ +		auto p=reinterpret_cast<cb_wrapper<void (size_t, +							 size_t)> *>(arg); + +		(*p)(i, cnt); +	} +} + +int unicode::bidi_reorder(std::u32string &string, +			  std::vector<unicode_bidi_level_t> &levels, +			  const std::function<void (size_t, size_t)> &lambda) +{ +	size_t s=string.size(); + +	if (s != levels.size()) +		return -1; + +	if (!s) +		return 0; + +	cb_wrapper<void (size_t, size_t)> cb{lambda}; + +	unicode_bidi_reorder(&string[0], &levels[0], s, +			     reorder_callback, +			     reinterpret_cast<void *>(&cb)); + +	cb.rethrow(); +	return 0; +} + +void unicode::bidi_reorder(std::vector<unicode_bidi_level_t> &levels, +			   const std::function<void (size_t, size_t)> &lambda) +{ +	size_t s=levels.size(); + +	if (!s) +		return; + +	cb_wrapper<void (size_t, size_t)> cb{lambda}; + +	unicode_bidi_reorder(0, &levels[0], s, reorder_callback, +			     reinterpret_cast<void *>(&cb)); +	cb.rethrow(); + +} + +extern "C" { +	static void removed_callback(size_t i, +				     void *arg) +	{ +		auto p=reinterpret_cast<cb_wrapper<void (size_t)> *>(arg); + +		(*p)(i); +	} +} + +void unicode::bidi_cleanup(std::u32string &string, +			   const std::function<void (size_t)> &lambda) +{ +	if (string.empty()) +		return; + +	cb_wrapper<void (size_t)> cb{lambda}; + +	size_t n=unicode_bidi_cleanup(&string[0], +				      0, +				      string.size(), +				      removed_callback, +				      reinterpret_cast<void *>(&cb)); +	cb.rethrow(); +	string.resize(n); +} + +int unicode::bidi_cleanup(std::u32string &string, +			  std::vector<unicode_bidi_level_t> &levels, +			  const std::function<void (size_t)> &lambda) +{ +	if (levels.size() != string.size()) +		return -1; + +	cb_wrapper<void (size_t)> cb{lambda}; +	size_t n=unicode_bidi_cleanup(&string[0], +				      &levels[0], +				      string.size(), +				      removed_callback, +				      reinterpret_cast<void *>(&cb)); +	cb.rethrow(); + +	string.resize(n); +	levels.resize(n); +	return 0; +} + + +void unicode::bidi_extra_cleanup(std::u32string &string, +				 const std::function<void (size_t)> &lambda) +{ +	if (string.empty()) +		return; + +	cb_wrapper<void (size_t)> cb{lambda}; +	size_t n=unicode_bidi_extra_cleanup(&string[0], +					    0, +					    string.size(), +					    removed_callback, +					    reinterpret_cast<void *>(&cb)); +	cb.rethrow(); +	string.resize(n); +} + +int unicode::bidi_extra_cleanup(std::u32string &string, +				std::vector<unicode_bidi_level_t> &levels, +				const std::function<void (size_t)> &lambda) +{ +	if (levels.size() != string.size()) +		return -1; + +	cb_wrapper<void (size_t)> cb{lambda}; +	size_t n=unicode_bidi_extra_cleanup(&string[0], +					    &levels[0], +					    string.size(), +					    removed_callback, +					    reinterpret_cast<void *>(&cb)); +	cb.rethrow(); +	string.resize(n); +	levels.resize(n); +	return 0; +} + +int unicode::bidi_logical_order(std::u32string &string, +				std::vector<unicode_bidi_level_t> &levels, +				unicode_bidi_level_t paragraph_embedding, +				const std::function<void (size_t, size_t)> +				&lambda) +{ +	if (string.size() != levels.size()) +		return -1; + +	if (string.empty()) +		return 0; + +	cb_wrapper<void (size_t, size_t)> cb{lambda}; +	unicode_bidi_logical_order(&string[0], &levels[0], string.size(), +				   paragraph_embedding, +				   &reorder_callback, +				   reinterpret_cast<void *>(&cb)); +	cb.rethrow(); +	return 0; +} + +void unicode::bidi_logical_order(std::vector<unicode_bidi_level_t> &levels, +				 unicode_bidi_level_t paragraph_embedding, +				 const std::function<void (size_t, size_t)> +				 &lambda) +{ +	if (levels.size() == 0) +		return; + +	cb_wrapper<void (size_t, size_t)> cb{lambda}; +	unicode_bidi_logical_order(NULL, &levels[0], levels.size(), +				   paragraph_embedding, +				   &reorder_callback, +				   reinterpret_cast<void *>(&cb)); +	cb.rethrow(); +} + +extern "C" { +	static void embed_callback(const char32_t *string, +				   size_t n, +				   void *arg) +	{ +		auto p=reinterpret_cast<cb_wrapper<void +						   (const char32_t *, +						    size_t n)> *>(arg); +		(*p)(string, n); +	} +} + +int unicode::bidi_embed(const std::u32string &string, +			const std::vector<unicode_bidi_level_t> &levels, +			unicode_bidi_level_t paragraph_embedding, +			const std::function<void (const char32_t *string, +						  size_t n)> +			&lambda) +{ +	if (string.size() != levels.size()) +		return -1; + +	if (string.empty()) +		return 0; + +	cb_wrapper<void (const char32_t *, size_t)> cb{lambda}; +	unicode_bidi_embed(&string[0], &levels[0], string.size(), +			   paragraph_embedding, +			   embed_callback, +			   reinterpret_cast<void *>(&cb)); + +	cb.rethrow(); +	return 0; +} + +std::u32string unicode::bidi_embed(const std::u32string &string, +				   const std::vector<unicode_bidi_level_t +				   > &levels, +				   unicode_bidi_level_t paragraph_embedding) +{ +	std::u32string new_string; + +	(void)bidi_embed(string, levels, paragraph_embedding, +			 [&] +			 (const char32_t *string, +			  size_t n) +			 { +				 new_string.insert(new_string.end(), +						   string, string+n); +			 }); + +	return new_string; +} + +char32_t unicode::bidi_embed_paragraph_level(const std::u32string &string, +					     unicode_bidi_level_t level) +{ +	return unicode_bidi_embed_paragraph_level(string.c_str(), +						  string.size(), +						  level); +} | 
