summaryrefslogtreecommitdiffstats
path: root/unicode/unicodecpp.C
diff options
context:
space:
mode:
Diffstat (limited to 'unicode/unicodecpp.C')
-rw-r--r--unicode/unicodecpp.C306
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=&paragraph_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);
+}