This source file includes following definitions.
- DecodeUtf8
- EncodeUtf8
- tables_dir
- CheckTable
- Translate
- BackTranslate
#include "liblouis_wrapper.h"
#include <cstddef>
#include "liblouis/liblouis.h"
namespace {
static bool DecodeUtf8(const std::string& in, std::vector<widechar>* out) {
int len = in.length();
std::vector<widechar> result;
result.reserve(len);
int i = 0;
while (i < len) {
int ch = static_cast<unsigned char>(in[i++]);
widechar cp;
if ((ch & 0x80) == 0x00) {
cp = ch;
} else if ((ch & 0xe0) == 0xc0 && i < len) {
cp = (ch & 0x1f) << 6;
ch = static_cast<unsigned char>(in[i++]);
cp |= (ch & 0x3f);
} else if ((ch & 0xf0) == 0xe0 && i+1 < len) {
cp = (ch & 0x0f) << 12;
ch = static_cast<unsigned char>(in[i++]);
cp |= (ch & 0x3f) << 6;
ch = static_cast<unsigned char>(in[i++]);
cp |= (ch & 0x3f);
} else if ((ch & 0xf8) == 0xf0 && i+2 < len) {
i += 3;
continue;
} else if ((ch & 0xfc) == 0xf8 && i+3 < len) {
i += 4;
continue;
} else if ((ch & 0xfe) == 0xfc && i+4 < len) {
i += 5;
continue;
} else {
return false;
}
result.push_back(cp);
}
out->swap(result);
return true;
}
static bool EncodeUtf8(const std::vector<widechar>& in, std::string* out) {
std::string result;
result.reserve(in.size() * 2);
for (std::vector<widechar>::const_iterator it = in.begin(); it != in.end();
++it) {
unsigned int cp = *it;
if (cp <= 0x007f) {
result.push_back(static_cast<char>(cp));
} else if (cp <= 0x07ff) {
result.push_back(static_cast<char>(0xc0 | ((cp >> 6) & 0x1f)));
result.push_back(static_cast<char>(0x80 | (cp & 0x3f)));
} else if (cp <= 0xffff) {
result.push_back(static_cast<char>(0xe0 | ((cp >> 12) & 0x0f)));
result.push_back(static_cast<char>(0x80 | ((cp >> 6) & 0x3f)));
result.push_back(static_cast<char>(0x80 | (cp & 0x3f)));
} else {
}
}
out->swap(result);
return true;
}
}
namespace liblouis_nacl {
LibLouisWrapper::LibLouisWrapper() {
char data_path[] = "/";
lou_setDataPath(data_path);
}
LibLouisWrapper::~LibLouisWrapper() {
lou_free();
}
const char* LibLouisWrapper::tables_dir() const {
return "/liblouis/tables";
}
bool LibLouisWrapper::CheckTable(const std::string& table_name) {
return lou_getTable(table_name.c_str()) != NULL;
}
bool LibLouisWrapper::Translate(const TranslationParams& params,
TranslationResult* out) {
std::vector<widechar> inbuf;
if (!DecodeUtf8(params.text, &inbuf)) {
return false;
}
int inbufsize = inbuf.size();
std::vector<widechar> outbuf;
std::vector<int> text_to_braille(inbuf.size());
std::vector<int> braille_to_text;
int outlen;
int out_cursor_position;
int* out_cursor_position_ptr;
if (params.cursor_position < 0) {
out_cursor_position = -1;
out_cursor_position_ptr = NULL;
} else {
out_cursor_position = params.cursor_position;
out_cursor_position_ptr = &out_cursor_position;
}
for (int outalloc = (inbufsize + 1) * 2, maxoutalloc = (inbufsize + 1) * 8;
outalloc <= maxoutalloc; outalloc *= 2) {
int inlen = inbufsize;
outlen = outalloc;
outbuf.resize(outalloc);
braille_to_text.resize(outalloc);
int result = lou_translate(params.table_name.c_str(),
&inbuf[0], &inlen, &outbuf[0], &outlen,
NULL , NULL ,
&text_to_braille[0], &braille_to_text[0],
out_cursor_position_ptr, dotsIO );
if (result == 0) {
return false;
}
if (inlen == inbufsize && outlen < outalloc)
break;
outbuf.clear();
braille_to_text.clear();
}
std::vector<unsigned char> cells;
cells.reserve(outlen);
for (int i = 0; i < outlen; i++) {
cells.push_back(outbuf[i]);
}
braille_to_text.resize(outlen);
out->cells.swap(cells);
out->text_to_braille.swap(text_to_braille);
out->braille_to_text.swap(braille_to_text);
out->cursor_position = out_cursor_position;
return true;
}
bool LibLouisWrapper::BackTranslate(const std::string& table_name,
const std::vector<unsigned char>& cells, std::string* out) {
std::vector<widechar> inbuf;
inbuf.reserve(cells.size());
for (std::vector<unsigned char>::const_iterator it = cells.begin();
it != cells.end(); ++it) {
inbuf.push_back(*it | 0x8000);
}
int inbufsize = inbuf.size();
std::vector<widechar> outbuf;
int outlen;
for (int outalloc = (inbufsize + 1) * 2, maxoutalloc = (inbufsize + 1) * 8;
outalloc <= maxoutalloc; outalloc *= 2) {
int inlen = inbufsize;
outlen = outalloc;
outbuf.resize(outalloc);
int result = lou_backTranslateString(
table_name.c_str(), &inbuf[0], &inlen, &outbuf[0], &outlen,
NULL , NULL , dotsIO );
if (result == 0) {
return false;
}
if (inlen == inbufsize && outlen < outalloc)
break;
outbuf.clear();
}
outbuf.resize(outlen);
std::string text;
if (!EncodeUtf8(outbuf, &text)) {
return false;
}
out->swap(text);
return true;
}
}