Lingua-HE-MacHebrew
view release on metacpan or search on metacpan
MacHebrew.xs view on Meta::CPAN
/* Perl 5.6.1 ? */
#ifndef uvuni_to_utf8
#define uvuni_to_utf8 uv_to_utf8
#endif /* uvuni_to_utf8 */
/* Perl 5.6.1 ? */
#ifndef utf8n_to_uvuni
#define utf8n_to_uvuni utf8_to_uv
#endif /* utf8n_to_uvuni */
#define SBCS_LEN 1
#define FromMacTbl fm_mache_tbl
#define FromMacDir fm_mache_dir
#define ToMacTbl to_mache_table
#define ToMacTblN to_mache_N
#define ToMacTblL to_mache_L
#define ToMacTblR to_mache_R
#define ToMacTblC to_mache_C
static STDCHAR ** ToMacTbl [] = {
ToMacTblN,
ToMacTblL,
ToMacTblR
};
static void
sv_cat_cvref (SV *dst, SV *cv, SV *sv)
{
dSP;
int count;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(sv));
PUTBACK;
count = call_sv(cv, (G_EVAL|G_SCALAR));
SPAGAIN;
if (SvTRUE(ERRSV) || count != 1) {
croak("died in XS, " PkgName "\n");
}
sv_catsv(dst,POPs);
PUTBACK;
FREETMPS;
LEAVE;
}
MODULE = Lingua::HE::MacHebrew PACKAGE = Lingua::HE::MacHebrew
PROTOTYPES: DISABLE
void
decode(...)
ALIAS:
decodeMacHebrew = 1
PREINIT:
SV *src, *dst;
STRLEN srclen;
U8 *s, *e, *p;
STDCHAR *str, *utf_string;
STDCHAR curdir, predir;
PPCODE:
if (0 < items && SvROK(ST(0))) {
croak(PkgName " 1st argument is REF, but handler for decode is NG.");
}
src = (0 < items) ? ST(0) : &PL_sv_undef;
if (SvUTF8(src)) {
src = sv_mortalcopy(src);
sv_utf8_downgrade(src, 0);
}
s = (U8*)SvPV(src,srclen);
e = s + srclen;
dst = sv_2mortal(newSV(1));
(void)SvPOK_only(dst);
SvUTF8_on(dst);
predir = MACBIDI_DIR_NT;
for (p = s; p < e; p++, predir = curdir) {
curdir = FromMacDir[*p];
if (predir != curdir) {
if (predir != MACBIDI_DIR_NT) {
sv_catpv(dst, (char*)MACBIDI_STR_PDF);
}
if (curdir != MACBIDI_DIR_NT) {
str = (curdir == MACBIDI_DIR_LR) ? MACBIDI_STR_LRO :
(curdir == MACBIDI_DIR_RL) ? MACBIDI_STR_RLO :
NULL; /* Panic */;
if (!str) {
croak(PkgName "Panic: undefined direction in decode");
}
sv_catpv(dst, (char*)str);
}
}
utf_string = FromMacTbl[*p];
if (utf_string) {
if (*utf_string)
sv_catpv(dst, (char*)utf_string);
else /* \0 to \0 */
sv_catpvn(dst, (char*)utf_string, 1);
}
}
if (predir != MACBIDI_DIR_NT) {
sv_catpv(dst, (char*)MACBIDI_STR_PDF);
}
XPUSHs(dst);
void
encode(...)
ALIAS:
encodeMacHebrew = 1
PREINIT:
SV *src, *dst, *ref;
STRLEN srclen, retlen;
U8 *s, *e, *p;
STDCHAR b, *t, **table;
struct macbidi_contra *p_contra, *cel_contra, **row_contra;
UV uv;
STDCHAR dir;
bool has_cv = FALSE;
bool has_pv = FALSE;
PPCODE:
ref = NULL;
if (0 < items && SvROK(ST(0))) {
ref = SvRV(ST(0));
if (SvTYPE(ref) == SVt_PVCV)
has_cv = TRUE;
else if (SvPOK(ref))
has_pv = TRUE;
else
croak(PkgName " 1st argument is not STRING nor CODEREF");
}
src = ref
? (1 < items) ? ST(1) : &PL_sv_undef
: (0 < items) ? ST(0) : &PL_sv_undef;
if (!SvUTF8(src)) {
src = sv_mortalcopy(src);
sv_utf8_upgrade(src);
}
s = (U8*)SvPV(src,srclen);
e = s + srclen;
dst = sv_2mortal(newSV(1));
(void)SvPOK_only(dst);
SvUTF8_off(dst);
dir = MACBIDI_DIR_NT;
for (p = s; p < e;) {
uv = utf8n_to_uvuni(p, e - p, &retlen, 0);
p += retlen;
switch (uv) {
case MACBIDI_UV_PDF:
dir = MACBIDI_DIR_NT;
break;
case MACBIDI_UV_LRO:
dir = MACBIDI_DIR_LR;
break;
case MACBIDI_UV_RLO:
dir = MACBIDI_DIR_RL;
break;
default:
b = 0;
row_contra = uv < 0x10000 ? ToMacTblC[uv >> 8] : NULL;
cel_contra = row_contra ? row_contra[uv & 0xff] : NULL;
if (cel_contra) {
for (p_contra = cel_contra; cel_contra->len; cel_contra++) {
if (cel_contra->len <= (e - p) &&
memEQ(p, cel_contra->string, cel_contra->len)) {
p += cel_contra->len;
b = cel_contra->byte;
break;
}
}
}
if (!b) {
table = ToMacTbl[dir];
t = uv < 0x10000 ? table[uv >> 8] : NULL;
b = t ? t[uv & 0xff] : 0;
( run in 0.423 second using v1.01-cache-2.11-cpan-5511b514fd6 )