moved main.go to bin and updated build files accordingly
This commit is contained in:
		
							
								
								
									
										519
									
								
								hak-cb.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										519
									
								
								hak-cb.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,519 @@
 | 
			
		||||
package hak
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
#include <hak.h>
 | 
			
		||||
#include <hak-utl.h>
 | 
			
		||||
#include <string.h> // for memcpy
 | 
			
		||||
*/
 | 
			
		||||
import "C"
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"io"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
//import "fmt"
 | 
			
		||||
 | 
			
		||||
type IOHandle struct {
 | 
			
		||||
	file *os.File
 | 
			
		||||
	ioif interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type IOHandleTable struct {
 | 
			
		||||
	mtx        sync.Mutex
 | 
			
		||||
	handles    []IOHandle
 | 
			
		||||
	free_slots []int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (io *IOHandleTable) add_io_handle(f *os.File, ioif interface{}) int {
 | 
			
		||||
	io.mtx.Lock()
 | 
			
		||||
	defer io.mtx.Unlock()
 | 
			
		||||
 | 
			
		||||
	var n int = len(io.free_slots)
 | 
			
		||||
 | 
			
		||||
	if n <= 0 { // no free slots
 | 
			
		||||
		io.handles = append(io.handles, IOHandle{file: f, ioif: ioif})
 | 
			
		||||
		return len(io.handles) - 1
 | 
			
		||||
	} else {
 | 
			
		||||
		var slot int
 | 
			
		||||
		n--
 | 
			
		||||
		slot = io.free_slots[n]
 | 
			
		||||
		io.free_slots = io.free_slots[:n]
 | 
			
		||||
		io.handles[slot].file = f
 | 
			
		||||
		io.handles[slot].ioif = ioif
 | 
			
		||||
		return slot
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (io *IOHandleTable) del_io_handle(slot int) IOHandle {
 | 
			
		||||
	var (
 | 
			
		||||
		h IOHandle
 | 
			
		||||
		n int
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	io.mtx.Lock()
 | 
			
		||||
	defer io.mtx.Unlock()
 | 
			
		||||
 | 
			
		||||
	h = io.handles[slot]
 | 
			
		||||
	io.handles[slot].file = nil
 | 
			
		||||
	io.handles[slot].ioif = nil
 | 
			
		||||
 | 
			
		||||
	n = len(io.handles)
 | 
			
		||||
	if slot == n-1 {
 | 
			
		||||
		io.handles = io.handles[:n-1]
 | 
			
		||||
	} else {
 | 
			
		||||
		io.free_slots = append(io.free_slots, slot)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return h
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (io *IOHandleTable) slot_to_io_handle(slot int) IOHandle {
 | 
			
		||||
	io.mtx.Lock()
 | 
			
		||||
	defer io.mtx.Unlock()
 | 
			
		||||
	return io.handles[slot]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var io_tab IOHandleTable = IOHandleTable{}
 | 
			
		||||
 | 
			
		||||
//export hak_go_cci_handler
 | 
			
		||||
func hak_go_cci_handler(c *C.hak_t, cmd C.hak_io_cmd_t, arg unsafe.Pointer) C.int {
 | 
			
		||||
	var (
 | 
			
		||||
		g   *Hak
 | 
			
		||||
		err error
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	g = c_to_go(c)
 | 
			
		||||
 | 
			
		||||
	switch cmd {
 | 
			
		||||
	case C.HAK_IO_OPEN:
 | 
			
		||||
		var (
 | 
			
		||||
			ioarg         *C.hak_io_cciarg_t
 | 
			
		||||
			name          string
 | 
			
		||||
			fd            int
 | 
			
		||||
			tptr          unsafe.Pointer
 | 
			
		||||
			tlen          C.size_t
 | 
			
		||||
		)
 | 
			
		||||
 | 
			
		||||
		ioarg = (*C.hak_io_cciarg_t)(arg)
 | 
			
		||||
 | 
			
		||||
		if ioarg.includer == nil /* || ioarg.includer.name == nil */ {
 | 
			
		||||
			// main stream
 | 
			
		||||
			name = g.io.cci_main
 | 
			
		||||
		} else {
 | 
			
		||||
			// actual included stream
 | 
			
		||||
			var includer_name string
 | 
			
		||||
 | 
			
		||||
			name = string(ucstr_to_rune_slice(ioarg.name))
 | 
			
		||||
 | 
			
		||||
			tptr = ioarg.includer.handle
 | 
			
		||||
			tlen = *(*C.size_t)(unsafe.Pointer(uintptr(tptr) + unsafe.Sizeof(fd)))
 | 
			
		||||
 | 
			
		||||
			includer_name = C.GoStringN((*C.char)(unsafe.Pointer(uintptr(tptr)+unsafe.Sizeof(fd)+unsafe.Sizeof(tlen))), C.int(tlen))
 | 
			
		||||
			name = filepath.Join(path.Dir(includer_name), name)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		tlen = C.size_t(len(name)) // number of bytes in the string
 | 
			
		||||
		tptr = C.hak_allocmem(c, C.size_t(unsafe.Sizeof(fd)) + C.size_t(unsafe.Sizeof(tlen)) + tlen)
 | 
			
		||||
		if tptr == nil {
 | 
			
		||||
			g.set_errmsg(C.HAK_ESYSMEM, "cci name allocation failure")
 | 
			
		||||
			return -1
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if ioarg.includer == nil {
 | 
			
		||||
			fd = -1
 | 
			
		||||
		} else {
 | 
			
		||||
			fd, err = g.io.cci.Open(g, name)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				g.set_errmsg(C.HAK_EIOERR, err.Error())
 | 
			
		||||
				C.hak_freemem(c, tptr)
 | 
			
		||||
				return -1
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// | fd | length | name bytes of the length |
 | 
			
		||||
		*(*int)(tptr) = fd;
 | 
			
		||||
		*(*C.size_t)(unsafe.Pointer(uintptr(tptr)+unsafe.Sizeof(fd))) = tlen;
 | 
			
		||||
 | 
			
		||||
		// C.CString() allocates a memory block. Use a SliceHeader to avoid extra memory allocation
 | 
			
		||||
		// for the string conversion. Create a fake slice header that can be used with copy() instead.
 | 
			
		||||
		var dsthdr reflect.SliceHeader
 | 
			
		||||
		dsthdr.Data = uintptr(tptr)+unsafe.Sizeof(fd)+unsafe.Sizeof(tlen)
 | 
			
		||||
		dsthdr.Len = int(tlen)
 | 
			
		||||
		dsthdr.Cap = int(tlen)
 | 
			
		||||
		copy(*(*[]byte)(unsafe.Pointer(&dsthdr)), name);
 | 
			
		||||
 | 
			
		||||
		ioarg.handle = tptr
 | 
			
		||||
		return 0
 | 
			
		||||
 | 
			
		||||
	case C.HAK_IO_CLOSE:
 | 
			
		||||
		var (
 | 
			
		||||
			fd    int
 | 
			
		||||
			ioarg *C.hak_io_cciarg_t
 | 
			
		||||
		)
 | 
			
		||||
 | 
			
		||||
		ioarg = (*C.hak_io_cciarg_t)(arg)
 | 
			
		||||
		fd = *(*int)(ioarg.handle) // the descriptor at the beginning
 | 
			
		||||
		if fd >= 0 {
 | 
			
		||||
			g.io.cci.Close(fd)
 | 
			
		||||
		}
 | 
			
		||||
		C.hak_freemem(c, ioarg.handle)
 | 
			
		||||
		ioarg.handle = nil
 | 
			
		||||
		return 0
 | 
			
		||||
 | 
			
		||||
	case C.HAK_IO_READ:
 | 
			
		||||
		var (
 | 
			
		||||
			ioarg *C.hak_io_cciarg_t
 | 
			
		||||
			n     int
 | 
			
		||||
			i     int
 | 
			
		||||
			buf   []rune
 | 
			
		||||
			dummy C.hak_uch_t
 | 
			
		||||
			fd    int
 | 
			
		||||
		)
 | 
			
		||||
		ioarg = (*C.hak_io_cciarg_t)(arg)
 | 
			
		||||
 | 
			
		||||
		fd = *(*int)(ioarg.handle) // the descriptor at the beginning
 | 
			
		||||
 | 
			
		||||
		buf = make([]rune, 1024) // TODO:  different size...
 | 
			
		||||
		n, err = g.io.cci.Read(fd, buf)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			g.set_errmsg(C.HAK_EIOERR, err.Error())
 | 
			
		||||
			return -1
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ioarg.byte_oriented = 0
 | 
			
		||||
		if unsafe.Sizeof(buf[0]) == unsafe.Sizeof(dummy) {
 | 
			
		||||
			C.memcpy(
 | 
			
		||||
				unsafe.Pointer(&ioarg.buf[0]),
 | 
			
		||||
				unsafe.Pointer(&buf[0]),
 | 
			
		||||
				C.size_t(unsafe.Sizeof(buf[0])*uintptr(n)))
 | 
			
		||||
		} else {
 | 
			
		||||
			var dst uintptr
 | 
			
		||||
			// work around cgo's union issue. not able to access individual union
 | 
			
		||||
			// member fields. cgo treats union as byte aggregates.
 | 
			
		||||
			dst = uintptr(unsafe.Pointer(&ioarg.buf[0]))
 | 
			
		||||
			for i = 0; i < n; i++ {
 | 
			
		||||
				//ioarg.buf.c[i] = C.hak_uch_t(buf[i])
 | 
			
		||||
				*(*C.hak_uch_t)(unsafe.Pointer(dst)) = C.hak_uch_t(buf[i])
 | 
			
		||||
				dst += unsafe.Sizeof(dummy)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ioarg.xlen = C.hak_oow_t(n)
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	C.hak_seterrnum(c, C.HAK_EIOERR)
 | 
			
		||||
	return -1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//export hak_go_udi_handler
 | 
			
		||||
func hak_go_udi_handler(c *C.hak_t, cmd C.hak_io_cmd_t, arg unsafe.Pointer) C.int {
 | 
			
		||||
	var (
 | 
			
		||||
		g   *Hak
 | 
			
		||||
		err error
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	g = c_to_go(c)
 | 
			
		||||
 | 
			
		||||
	switch cmd {
 | 
			
		||||
	case C.HAK_IO_OPEN:
 | 
			
		||||
		err = g.io.udi.Open(g)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			g.set_errmsg(C.HAK_EIOERR, err.Error())
 | 
			
		||||
			return -1
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// we don't need to set ioarg.handle because the c object to go object
 | 
			
		||||
		// mapping has been established and it doesn't handle multiple streams
 | 
			
		||||
		return 0
 | 
			
		||||
 | 
			
		||||
	case C.HAK_IO_CLOSE:
 | 
			
		||||
		g.io.udi.Close()
 | 
			
		||||
		return 0
 | 
			
		||||
 | 
			
		||||
	case C.HAK_IO_READ:
 | 
			
		||||
		var (
 | 
			
		||||
			ioarg *C.hak_io_udiarg_t
 | 
			
		||||
			n     int
 | 
			
		||||
			err   error
 | 
			
		||||
			buf   []rune
 | 
			
		||||
		)
 | 
			
		||||
		ioarg = (*C.hak_io_udiarg_t)(arg)
 | 
			
		||||
 | 
			
		||||
		buf = make([]rune, 1024) // TODO:  different size...
 | 
			
		||||
		n, err = g.io.udi.Read(buf)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			g.set_errmsg(C.HAK_EIOERR, err.Error())
 | 
			
		||||
			return -1
 | 
			
		||||
		}
 | 
			
		||||
		ioarg.xlen = C.hak_oow_t(n)
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	C.hak_seterrnum(c, C.HAK_EIOERR)
 | 
			
		||||
	return -1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//export hak_go_udo_handler
 | 
			
		||||
func hak_go_udo_handler(c *C.hak_t, cmd C.hak_io_cmd_t, arg unsafe.Pointer) C.int {
 | 
			
		||||
	var (
 | 
			
		||||
		g   *Hak
 | 
			
		||||
		err error
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	g = c_to_go(c)
 | 
			
		||||
 | 
			
		||||
	switch cmd {
 | 
			
		||||
	case C.HAK_IO_OPEN:
 | 
			
		||||
		err = g.io.udo.Open(g)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			g.set_errmsg(C.HAK_EIOERR, err.Error())
 | 
			
		||||
			return -1
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// we don't need to set ioarg.handle because the c object to go object
 | 
			
		||||
		// mapping has been established and it doesn't handle multiple streams
 | 
			
		||||
		return 0
 | 
			
		||||
 | 
			
		||||
	case C.HAK_IO_CLOSE:
 | 
			
		||||
		g.io.udo.Close()
 | 
			
		||||
		return 0
 | 
			
		||||
 | 
			
		||||
	case C.HAK_IO_WRITE:
 | 
			
		||||
		var (
 | 
			
		||||
			ioarg *C.hak_io_udoarg_t
 | 
			
		||||
			data  []rune
 | 
			
		||||
			err   error
 | 
			
		||||
		)
 | 
			
		||||
		ioarg = (*C.hak_io_udoarg_t)(arg)
 | 
			
		||||
		data = uchars_to_rune_slice((*C.hak_uch_t)(ioarg.ptr), uintptr(ioarg.len))
 | 
			
		||||
		err = g.io.udo.Write(data)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			g.set_errmsg(C.HAK_EIOERR, err.Error())
 | 
			
		||||
			return -1
 | 
			
		||||
		}
 | 
			
		||||
		ioarg.xlen = C.hak_oow_t(len(data))
 | 
			
		||||
		return 0
 | 
			
		||||
 | 
			
		||||
	case C.HAK_IO_WRITE_BYTES:
 | 
			
		||||
		var (
 | 
			
		||||
			ioarg *C.hak_io_udoarg_t
 | 
			
		||||
			data  []byte
 | 
			
		||||
			err   error
 | 
			
		||||
		)
 | 
			
		||||
		ioarg = (*C.hak_io_udoarg_t)(arg)
 | 
			
		||||
		data = unsafe.Slice((*byte)(ioarg.ptr), ioarg.len)
 | 
			
		||||
		err = g.io.udo.WriteBytes(data)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			g.set_errmsg(C.HAK_EIOERR, err.Error())
 | 
			
		||||
			return -1
 | 
			
		||||
		}
 | 
			
		||||
		ioarg.xlen = C.hak_oow_t(len(data))
 | 
			
		||||
		return 0
 | 
			
		||||
 | 
			
		||||
	case C.HAK_IO_FLUSH:
 | 
			
		||||
		var err error = g.io.udo.Flush()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			g.set_errmsg(C.HAK_EIOERR, err.Error())
 | 
			
		||||
			return -1
 | 
			
		||||
		}
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	C.hak_seterrnum(c, C.HAK_EIOERR)
 | 
			
		||||
	return -1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------
 | 
			
		||||
type CciFileHandler struct {
 | 
			
		||||
	g *Hak
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *CciFileHandler) Open(g *Hak, name string) (int, error) {
 | 
			
		||||
	var (
 | 
			
		||||
		f   *os.File
 | 
			
		||||
		r   *bufio.Reader
 | 
			
		||||
		fd  int
 | 
			
		||||
		err error
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	if name == "" {
 | 
			
		||||
		f = os.Stdin
 | 
			
		||||
	} else {
 | 
			
		||||
		f, err = os.Open(name)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return -1, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r = bufio.NewReader(f)
 | 
			
		||||
	fd = io_tab.add_io_handle(f, r)
 | 
			
		||||
 | 
			
		||||
	p.g = g
 | 
			
		||||
	return fd, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *CciFileHandler) Close(fd int) {
 | 
			
		||||
	var hnd IOHandle = io_tab.slot_to_io_handle(fd)
 | 
			
		||||
	if hnd.file != nil {
 | 
			
		||||
		if hnd.file != os.Stdout && hnd.file != os.Stderr {
 | 
			
		||||
			hnd.file.Close()
 | 
			
		||||
		}
 | 
			
		||||
		hnd.file = nil
 | 
			
		||||
		hnd.ioif = nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *CciFileHandler) Read(fd int, buf []rune) (int, error) {
 | 
			
		||||
	var (
 | 
			
		||||
		hnd IOHandle
 | 
			
		||||
		i   int
 | 
			
		||||
		c   rune
 | 
			
		||||
		r   *bufio.Reader
 | 
			
		||||
		err error
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	hnd = io_tab.slot_to_io_handle(fd)
 | 
			
		||||
	r, _ = hnd.ioif.(*bufio.Reader)
 | 
			
		||||
	for i = 0; i < len(buf); i++ {
 | 
			
		||||
		c, _, err = r.ReadRune()
 | 
			
		||||
		if err == io.EOF {
 | 
			
		||||
			break
 | 
			
		||||
		} else if err != nil {
 | 
			
		||||
			return -1, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		buf[i] = c
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return i, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------
 | 
			
		||||
type UdiFileHandler struct {
 | 
			
		||||
	g *Hak
 | 
			
		||||
	f *os.File
 | 
			
		||||
	r *bufio.Reader
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *UdiFileHandler) Open(g *Hak) error {
 | 
			
		||||
	var (
 | 
			
		||||
		f *os.File
 | 
			
		||||
	//	err error
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	f = os.Stdin
 | 
			
		||||
	//f, err = os.Open("/dev/stdin")
 | 
			
		||||
	//if err != nil {
 | 
			
		||||
	//	return err
 | 
			
		||||
	//}
 | 
			
		||||
 | 
			
		||||
	p.r = bufio.NewReader(f)
 | 
			
		||||
	p.f = f
 | 
			
		||||
	p.g = g
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *UdiFileHandler) Close() {
 | 
			
		||||
	if p.f != nil {
 | 
			
		||||
		if p.f != os.Stdout && p.f != os.Stderr {
 | 
			
		||||
			p.f.Close()
 | 
			
		||||
		}
 | 
			
		||||
		p.f = nil
 | 
			
		||||
		p.r = nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *UdiFileHandler) Read(buf []rune) (int, error) {
 | 
			
		||||
	var (
 | 
			
		||||
		i   int
 | 
			
		||||
		c   rune
 | 
			
		||||
		err error
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	// flush all pending print out before reading
 | 
			
		||||
	p.g.io.udo.Flush()
 | 
			
		||||
 | 
			
		||||
	for i = 0; i < len(buf); i++ {
 | 
			
		||||
		c, _, err = p.r.ReadRune()
 | 
			
		||||
		if err == io.EOF {
 | 
			
		||||
			break
 | 
			
		||||
		} else if err != nil {
 | 
			
		||||
			return -1, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		buf[i] = c
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return i, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
type UdoFileHandler struct {
 | 
			
		||||
	f *os.File
 | 
			
		||||
	w *bufio.Writer
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *UdoFileHandler) Open(g *Hak) error {
 | 
			
		||||
	var (
 | 
			
		||||
		f *os.File
 | 
			
		||||
	//	err error
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	//		f, err = os.OpenFile("/dev/stdout", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
 | 
			
		||||
	//		if err != nil {
 | 
			
		||||
	//			return err
 | 
			
		||||
	//		}
 | 
			
		||||
 | 
			
		||||
	f = os.Stdout
 | 
			
		||||
 | 
			
		||||
	p.w = bufio.NewWriter(f)
 | 
			
		||||
	p.f = f
 | 
			
		||||
 | 
			
		||||
	//fmt.Fprintf(os.Stderr, "XXXXXXXXXX open porint\n")
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *UdoFileHandler) Close() {
 | 
			
		||||
 | 
			
		||||
	//fmt.Fprintf(os.Stderr, "XXXXXXXXXX close porint\n")
 | 
			
		||||
	if p.f != nil {
 | 
			
		||||
		if p.f != os.Stdout && p.f != os.Stderr {
 | 
			
		||||
			p.f.Close()
 | 
			
		||||
		}
 | 
			
		||||
		p.f = nil
 | 
			
		||||
		p.w = nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *UdoFileHandler) Write(data []rune) error {
 | 
			
		||||
	var err error
 | 
			
		||||
 | 
			
		||||
	//fmt.Fprintf(os.Stderr, "XXXXXXXXXX write porint\n")
 | 
			
		||||
	_, err = p.w.WriteString(string(data))
 | 
			
		||||
	p.w.Flush() // TODO: is this needed?
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *UdoFileHandler) WriteBytes(data []byte) error {
 | 
			
		||||
	var err error
 | 
			
		||||
 | 
			
		||||
	//fmt.Fprintf(os.Stderr, "XXXXXXXXXX write porint\n")
 | 
			
		||||
	_, err = p.w.Write(data)
 | 
			
		||||
	p.w.Flush() // TODO: is this needed?
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *UdoFileHandler) Flush() error {
 | 
			
		||||
	//fmt.Fprintf(os.Stderr, "XXXXXXXXXX flush porint\n")
 | 
			
		||||
	return p.w.Flush()
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user