summaryrefslogtreecommitdiff
path: root/appl/lib/convcs/big5_stob.b
diff options
context:
space:
mode:
Diffstat (limited to 'appl/lib/convcs/big5_stob.b')
-rw-r--r--appl/lib/convcs/big5_stob.b93
1 files changed, 93 insertions, 0 deletions
diff --git a/appl/lib/convcs/big5_stob.b b/appl/lib/convcs/big5_stob.b
new file mode 100644
index 00000000..e2936971
--- /dev/null
+++ b/appl/lib/convcs/big5_stob.b
@@ -0,0 +1,93 @@
+implement Stob;
+
+include "sys.m";
+include "convcs.m";
+
+
+# Big5 consists of 89 fonts of 157 chars each
+BIG5MAX : con 13973;
+BIG5FONT : con 157;
+NFONTS : con 89;
+
+BIG5DATA : con "/lib/convcs/big5";
+
+big5map := "";
+r2fontchar : array of byte;
+
+# NOTE: could be more memory friendly during init()
+# by building the r2fontchar mapping table on the fly
+# instead of building it from the complete big5map string
+
+init(nil : string) : string
+{
+ sys := load Sys Sys->PATH;
+ fd := sys->open(BIG5DATA, Sys->OREAD);
+ if (fd == nil)
+ return sys->sprint("%s: %r", BIG5DATA);
+
+ buf := array[BIG5MAX * Sys->UTFmax] of byte;
+ nread := 0;
+ for (;nread < len buf;) {
+ n := sys->read(fd, buf[nread:], Sys->ATOMICIO);
+ if (n <= 0)
+ break;
+ nread += n;
+ }
+ big5map = string buf[:nread];
+ buf = nil;
+ if (len big5map != BIG5MAX) {
+ big5map = nil;
+ return sys->sprint("%s: corrupt data", BIG5DATA);
+ }
+ r2fontchar = array [2 * 16r10000] of { * => byte 16rff};
+ for (i := 0; i < len big5map; i++) {
+ f := i / BIG5FONT;
+ c := i % BIG5FONT;
+ ix := 2*big5map[i];
+ r2fontchar[ix] = byte f;
+ r2fontchar[ix+1] = byte c;
+ }
+ return nil;
+}
+
+stob(nil : Convcs->State, str : string) : (Convcs->State, array of byte)
+{
+ buf := array [1024] of byte;
+ nb := 0;
+ cbuf := array [2] of byte;
+ nc := 0;
+ for (i := 0; i < len str; i++) {
+ c := str[i];
+ nc = 0;
+ if (c < 128) {
+# if (c == '\n') # not sure abou this
+# c = 26;
+ cbuf[nc++] = byte c;
+ } else {
+ ix := 2*c;
+ f := int r2fontchar[ix];
+ c = int r2fontchar[ix+1];
+ if (f >= NFONTS) {
+ # no mapping of unicode character to big5
+ cbuf[nc++] = byte '?';
+ } else {
+ f += 16rA1;
+ cbuf[nc++] = byte f;
+ if (c <= 62)
+ c += 64;
+ else
+ c += 16rA1 - 63;
+ cbuf[nc++] = byte c;
+ }
+ }
+ if (nc + nb > len buf)
+ buf = ((array [len buf * 2] of byte)[:] = buf);
+ buf[nb:] = cbuf[:nc];
+ nb += nc;
+ }
+ if (nb == 0)
+ return (nil, nil);
+ r := array [nb] of byte;
+ r[:] = buf[:nb];
+ return (nil, r);
+}