diff options
Diffstat (limited to 'appl/lib/convcs/gb2312_btos.b')
| -rw-r--r-- | appl/lib/convcs/gb2312_btos.b | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/appl/lib/convcs/gb2312_btos.b b/appl/lib/convcs/gb2312_btos.b new file mode 100644 index 00000000..8a06a75f --- /dev/null +++ b/appl/lib/convcs/gb2312_btos.b @@ -0,0 +1,70 @@ +implement Btos; + +include "sys.m"; +include "convcs.m"; + +GBMAX : con 8795; + +GBDATA : con "/lib/convcs/gb2312"; + +MAXINT : con 16r7fffffff; +BADCHAR : con 16rFFFD; + +gbmap := ""; + +init(nil : string): string +{ + sys := load Sys Sys->PATH; + fd := sys->open(GBDATA, Sys->OREAD); + if (fd == nil) + return sys->sprint("%s: %r", GBDATA); + + buf := array[GBMAX * Sys->UTFmax] of byte; + nread := 0; + for (;nread < len buf;) { + n := sys->read(fd, buf[nread:], Sys->ATOMICIO); + if (n <= 0) + break; + nread += n; + } + gbmap = string buf[:nread]; + if (len gbmap != GBMAX) { + gbmap = nil; + return sys->sprint("%s: corrupt data", GBDATA); + } + return nil; +} + +btos(nil : Convcs->State, b : array of byte, n : int) : (Convcs->State, string, int) +{ + nbytes := 0; + str := ""; + + if (n == -1) + n = MAXINT; + + font := -1; + for (i := 0; i < len b && len str < n; i++) { + c := int b[i]; + ch := Sys->UTFerror; + if (font == -1) { + # idle state + if (c >= 16rA1) { + font = c; + continue; + } + ch = c; + } else { + # seen a font spec + if (c >= 16rA1) { + ix := (font - 16rA0)*100 + (c-16rA0); + ch = gbmap[ix]; + } + font = -1; + } + str[len str] = ch; + nbytes = i + 1; + } + return (nil, str, nbytes); +} + |
