Mercurial > mercurial > hgweb_golang.cgi
diff src/kaigo/superFC/fcgo.go @ 65:0369656be06c default tip
many changes.
author | pyon@macmini |
---|---|
date | Fri, 20 May 2022 06:30:34 +0900 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/kaigo/superFC/fcgo.go Fri May 20 06:30:34 2022 +0900 @@ -0,0 +1,484 @@ +/* + fcgo.go: Fucho de Go + + Last Change: 2021-06-14 月 16:14:04. +*/ +package main + +/* +#cgo LDFLAGS: -L. -lxdwapi -static +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <io.h> +#include <windows.h> +#include <xdw_api.h> +#include <xdwapian.h> + +#define MAXLINE 12000 +#define BLOCKSZ 128 + +void xdw2txt(const char* xdwfile, const char* txtfile) { + char in_path[_MAX_PATH]; + _fullpath(in_path, xdwfile, _MAX_PATH); + + XDW_DOCUMENT_HANDLE h = NULL; + XDW_OPEN_MODE_EX mode = {sizeof(XDW_OPEN_MODE_EX), XDW_OPEN_READONLY, XDW_AUTH_NODIALOGUE}; + if (XDW_OpenDocumentHandle(in_path, &h, (XDW_OPEN_MODE*)&mode)) { + printf("XDW Error: cannot open %s\n", xdwfile); + return; + } + + int api_result = XDW_GetFullText(h, txtfile, NULL); + if (api_result < 0) { + printf("Error: cannot write text\n"); + return; + } + XDW_CloseDocumentHandle(h, NULL); +} + +void xdwsplit1(const char* xdwfile) { + char in_path[_MAX_PATH]; + _fullpath(in_path, xdwfile, _MAX_PATH); + + XDW_DOCUMENT_HANDLE h = NULL; + XDW_OPEN_MODE_EX mode = {sizeof(XDW_OPEN_MODE_EX), XDW_OPEN_READONLY, XDW_AUTH_NODIALOGUE}; + if (XDW_OpenDocumentHandle(in_path, &h, (XDW_OPEN_MODE*)&mode)) { + printf("Error: cannot open %s\n", xdwfile); + return; + } + + XDW_DOCUMENT_INFO info = {sizeof(XDW_DOCUMENT_INFO), 0, 0, 0}; + XDW_GetDocumentInformation(h, &info); + int nPage = info.nPages; + + char buf[_MAX_PATH]; + for (int i = 1; i <= nPage; i++) { + sprintf(buf, "fctmp_%05d.xdw", i); + _fullpath(in_path, buf, _MAX_PATH); + + int api_result = XDW_GetPage(h, i, in_path, NULL); + if (api_result < 0) { + printf("XDW Error: cannot get page\n"); + return; + } + } + XDW_CloseDocumentHandle(h, NULL); +} + +void xdwmerge(const char* list, const char* output) { + + FILE *fp; + if ((fp = fopen(list, "r")) == NULL) { + fprintf(stderr, "can't open file [%s]\n", list); + exit(1); + } + + char *all_path = (char*)malloc(MAXLINE * sizeof(char) * _MAX_PATH); + if (all_path == NULL) { + fprintf(stderr, "can't allocate memory\n"); + exit(1); + } + + int n = 0; + char *q; + char buf[_MAX_PATH]; + + while (fgets(buf, sizeof buf, fp)) { + if ((q = strchr(buf, '\n')) != NULL) { + *q = '\0'; + } + _fullpath(buf, buf, _MAX_PATH); + strncpy(&all_path[n * _MAX_PATH], buf, _MAX_PATH); + n++; + } + fclose(fp); + + char *blk_path = (char*)malloc(BLOCKSZ * sizeof(char) * _MAX_PATH); + const char **blk_path_addr = (const char**)malloc((n / BLOCKSZ + 1) * sizeof(char*) * _MAX_PATH); + if (blk_path == NULL || blk_path_addr == NULL) { + fprintf(stderr, "can't allocate memory\n"); + exit(1); + } + + // process by block + int api_result; + int bn = 0; + for (int p = 0, m = 0; p < n; p++) { + m = p % BLOCKSZ; + if (m == 0 && p > 0) { + sprintf(buf, "fctmp_b%04d.xdw", ++bn); + _fullpath(buf, buf, _MAX_PATH); + api_result = XDW_MergeXdwFiles(blk_path_addr, BLOCKSZ, buf, NULL); + if (api_result < 0) { + fprintf(stderr, "can't merge [1] (p = %d, m = %d)\n", p, m); + exit(1); + } + } + strncpy(&blk_path[m * _MAX_PATH], &all_path[p * _MAX_PATH], _MAX_PATH); + blk_path_addr[m] = &blk_path[m * _MAX_PATH]; + } + + sprintf(buf, "fctmp_b%04d.xdw", ++bn); + _fullpath(buf, buf, _MAX_PATH); + int mod = n % BLOCKSZ; + if (mod == 0) mod = BLOCKSZ; + api_result = XDW_MergeXdwFiles(blk_path_addr, mod, buf, NULL); + if (api_result < 0) { + fprintf(stderr, "can't merge [2]\n"); + exit(1); + } + + // merge blocks + for (int b = 0; b < bn; b++) { + sprintf(buf, "fctmp_b%04d.xdw", b + 1); + _fullpath(buf, buf, _MAX_PATH); + strncpy(&blk_path[b * _MAX_PATH], buf, _MAX_PATH); + blk_path_addr[b] = &blk_path[b * _MAX_PATH]; + } + _fullpath(buf, output, _MAX_PATH ); + api_result = XDW_MergeXdwFiles(blk_path_addr, bn, buf, NULL); + if (api_result < 0) { + fprintf(stderr, "can't merge [3]\n"); + exit(1); + } + + free(all_path); + free(blk_path); + free(blk_path_addr); +} + +int xdwaddannotation(XDW_DOCUMENT_HANDLE h, int page, int x, int y, char* string, int* sz, int tr) +{ + XDW_ANNOTATION_HANDLE annoation; + int api_result = XDW_AddAnnotation(h, XDW_AID_TEXT, page, x, y, NULL, &annoation, NULL); + if (api_result < 0) { + fprintf(stderr, "can't make annotation\n"); + return -1; + } + + api_result = XDW_SetAnnotationAttribute(h, annoation, XDW_ATN_Text, XDW_ATYPE_STRING, string, 0, NULL); + api_result = XDW_SetAnnotationAttribute(h, annoation, XDW_ATN_FontSize, XDW_ATYPE_INT, (char*)(sz), 0, NULL); + if (tr) { + int color = XDW_COLOR_NONE; + api_result = XDW_SetAnnotationAttribute(h, annoation, XDW_ATN_BackColor, XDW_ATYPE_INT, (char*)(&color), 0, NULL); + } + return 0; +} + +void xdwaddpage(const char* file, int sp) { + XDW_DOCUMENT_HANDLE h = NULL; + XDW_OPEN_MODE_EX mode = {sizeof(XDW_OPEN_MODE_EX), XDW_OPEN_UPDATE, XDW_AUTH_NODIALOGUE}; + int api_result = XDW_OpenDocumentHandle(file, &h, (XDW_OPEN_MODE*)&mode); + if (api_result < 0) { + fprintf(stderr, "can't open file\n"); + exit(1); + } + + XDW_DOCUMENT_INFO info = {sizeof(XDW_DOCUMENT_INFO), 0}; + XDW_GetDocumentInformation(h, &info); + int last_page = info.nPages; + + int sz = 80; + int tr = 1; + char pagenum[12]; + + for (int p = 0; p < last_page; p++) { + sprintf(pagenum, "%05d-%05d", p + sp, last_page); + api_result = xdwaddannotation(h, p + 1, 1769, 5658, pagenum, &sz, tr); + api_result = xdwaddannotation(h, p + 1, 18297, 28326, pagenum, &sz, tr); + if (api_result < 0) break; + } + + if (api_result >= 0) api_result = XDW_SaveDocument(h, NULL); + + XDW_CloseDocumentHandle(h, NULL); +} + + +*/ +import "C" + +import ( + "encoding/csv" + "flag" + "fmt" + "io" + "log" + "os" + "regexp" + "strings" + "time" + + "golang.org/x/text/encoding/japanese" + "golang.org/x/text/transform" +) + +type Data struct { + Hno string + Page string +} + +func (d *Data) ToCsv() string { + s := []string{d.Hno, d.Page} + return strings.Join(s, ",") +} + +var ( + ver = "0.1" + + clean bool + skip bool + debug bool + xdwfile string + + txtfile = "fctmp_txt.txt" + infofile = "fctmp_info.csv" + orderfile = "sort.list" // input + pagefile = "fctmp_page.txt" + output = "output.xdw" +) + +func init() { + /* INITIALIZE FLAGS */ + flag.BoolVar(&clean, "c", false, "clean temporary files & exit") + flag.BoolVar(&skip, "e", false, "use existed files") + flag.BoolVar(&debug, "d", false, "debug mode") + flag.StringVar(&xdwfile, "i", "fc.xdw", "target xdw file") +} + +func main() { + flag.Parse() + + /* PRINT HEADER */ + fmt.Println("===================================================") + fmt.Println(" 普徴のみならず納通なら被保番でソートできるかも... ") + fmt.Printf(" - fcgo [ver %s] -\n", ver) + fmt.Println("===================================================\n") + print_time("now") + fmt.Println("[0] start ...") + + /* CLEAN TEMPORARY DIRECTORY */ + os.Remove(output) + if !skip { + clean_full() + } + if clean { + os.Exit(0) + } + print_time("check done") + + fmt.Println("[1] extract ...") + if !skip { + C.xdw2txt(C.CString(xdwfile), C.CString(txtfile)) + } + print_time("extract done.") + + c := make(chan int) + fmt.Println("[2] split ... (run background)") + go func() { + if !skip { + C.xdwsplit1(C.CString(xdwfile)) + } + print_time("split done.") + c <- 1 + }() + + fmt.Println("[3] analize ...") + data_hash, err := analize(txtfile, infofile) + if err != nil { + log.Fatal(err) + } + print_time("analize done.") + debug_print(debug, fmt.Sprintf("len = %d", len(data_hash))) + + fmt.Println("[4] read order ...") + h_order, n, err := read_order(orderfile) + if err != nil { + log.Fatal(err) + } + print_time("read order done.") + debug_print(debug, fmt.Sprintf("len = %d / %d", len(h_order), n)) + + fmt.Println("[5] make_list ...") + n, err = make_list(h_order, data_hash, pagefile) + if err != nil { + log.Fatal(err) + } + print_time("make list done.") + debug_print(debug, fmt.Sprintf("order = %d", n)) + + <-c + + fmt.Println("[6] merge ...") + clean_mini() + C.xdwmerge(C.CString(pagefile), C.CString(output)) + print_time("merge done.") + clean_mini() + + fmt.Println("[7] page ...") + C.xdwaddpage(C.CString(output), C.int(1)) + print_time("page done.") + + if !debug { + fmt.Println("[8] clean ...") + clean_full() + print_time("clean done.") + } +} + +func analize(txtfile, infofile string) (map[string]Data, error) { + hash := make(map[string]Data) + + c, err := os.ReadFile(txtfile) + if err != nil { + return hash, err + } + r := strings.NewReader(string(c)) + tr := transform.NewReader(r, japanese.ShiftJIS.NewDecoder()) + b, err := io.ReadAll(tr) + if err != nil { + return hash, err + } + + regHno := regexp.MustCompile(`0[1238]0[0-9]{7}`) + + var csv string + + buf := strings.Split(string(b), "期別保険料額") + for p, v := range buf[:len(buf)-1] { + s := zen2han(v) + hno := regHno.FindString(s) + page := fmt.Sprintf("%05d", p + 1) + + data := Data { + Hno: hno, + Page: page, + } + hash[hno] = data + + csv += data.ToCsv() + "\n" + } + + if err := os.WriteFile(infofile, []byte(csv), 0644); err != nil { + return hash, err + } + return hash, nil; +} + +func zen2han(s string) (string) { + s = strings.ReplaceAll(s, "0", "0") + s = strings.ReplaceAll(s, "1", "1") + s = strings.ReplaceAll(s, "2", "2") + s = strings.ReplaceAll(s, "3", "3") + s = strings.ReplaceAll(s, "4", "4") + s = strings.ReplaceAll(s, "5", "5") + s = strings.ReplaceAll(s, "6", "6") + s = strings.ReplaceAll(s, "7", "7") + s = strings.ReplaceAll(s, "8", "8") + return strings.ReplaceAll(s, "9", "9") +} + +func read_order(csvfile string) ([]string, int, error) { + var order []string + + c, err := os.ReadFile(csvfile) + if err != nil { + return order, -1, err + } + r := strings.NewReader(string(c)) + tr := transform.NewReader(r, japanese.ShiftJIS.NewDecoder()) + b, err := io.ReadAll(tr) + if err != nil { + return order, -1, err + } + + n := 0 + cr := csv.NewReader(strings.NewReader(string(b))) + for { + record, err := cr.Read() + if err == io.EOF { + break + } + if err != nil { + return order, n, err + } + + s := zen2han(record[0]) + if strings.HasPrefix(s, "0") { + order = append(order, s) + } + n++ + } + return order, n, nil +} + +func make_list(h_order []string, hash map[string]Data, pagefile string) (int, error) { + var n int + var list []string + done := make(map[string]bool) + + for _, h := range h_order { + if _, ok := done[h]; !ok { + if data, ok := hash[h]; ok { + list = append(list, data.Page) + done[h] = true + n++ + } + } + } + + if err := write_pagefile(pagefile, list); err != nil { + return n, err + } + return n, nil +} + +func write_pagefile(file string, list []string) error { + f, err := os.OpenFile(file, os.O_RDWR|os.O_CREATE, 0755) + if err != nil { + return err + } + for _, p := range list { + fmt.Fprintf(f, "fctmp_%s.xdw\n", p) + } + if err := f.Close(); err != nil { + return err + } + return nil +} + +func print_time(msg string) { + now := time.Now() + fmt.Printf("\t%v # %s\n", now, msg) +} + +func debug_print(debug bool, msg string) { + if debug { + fmt.Printf("\t%s\n", msg) + } +} + +func clean_full() error { + return clean_file("fctmp_") +} + +func clean_mini() error { + return clean_file("fctmp_b") +} + +func clean_file(prefix string) error { + files, err := os.ReadDir(".") + if err != nil { + return err + } + + for _, file := range files { + if strings.HasPrefix(file.Name(), prefix) { + os.Remove(file.Name()) + continue + } + } + return err +} +