xcb: refactor and clean up
No clean way to write Go tests for this package. Will rely on NixOS tests for now. Signed-off-by: Ophestra Umiker <cat@ophivana.moe>
This commit is contained in:
parent
aeda40fc92
commit
c2b178e626
137
xcb/c.go
137
xcb/c.go
@ -1,33 +1,124 @@
|
|||||||
package xcb
|
package xcb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"runtime"
|
||||||
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
//#include <stdlib.h>
|
/*
|
||||||
//#include <xcb/xcb.h>
|
#cgo linux pkg-config: xcb
|
||||||
//#cgo linux LDFLAGS: -lxcb
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <xcb/xcb.h>
|
||||||
|
|
||||||
|
static int _go_xcb_change_hosts_checked(xcb_connection_t *c, uint8_t mode, uint8_t family, uint16_t address_len, const uint8_t *address) {
|
||||||
|
xcb_void_cookie_t cookie = xcb_change_hosts_checked(c, mode, family, address_len, address);
|
||||||
|
free((void *)address);
|
||||||
|
|
||||||
|
int errno = xcb_connection_has_error(c);
|
||||||
|
if (errno != 0)
|
||||||
|
return errno;
|
||||||
|
|
||||||
|
xcb_generic_error_t *e = xcb_request_check(c, cookie);
|
||||||
|
if (e != NULL) {
|
||||||
|
// don't want to deal with xcb errors
|
||||||
|
free((void *)e);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
func xcbHandleConnectionError(c *C.xcb_connection_t) error {
|
const (
|
||||||
if errno := C.xcb_connection_has_error(c); errno != 0 {
|
HostModeInsert = C.XCB_HOST_MODE_INSERT
|
||||||
switch errno {
|
HostModeDelete = C.XCB_HOST_MODE_DELETE
|
||||||
case C.XCB_CONN_ERROR:
|
|
||||||
return errors.New("connection error")
|
FamilyInternet = C.XCB_FAMILY_INTERNET
|
||||||
case C.XCB_CONN_CLOSED_EXT_NOTSUPPORTED:
|
FamilyDecnet = C.XCB_FAMILY_DECNET
|
||||||
return errors.New("extension not supported")
|
FamilyChaos = C.XCB_FAMILY_CHAOS
|
||||||
case C.XCB_CONN_CLOSED_MEM_INSUFFICIENT:
|
FamilyServerInterpreted = C.XCB_FAMILY_SERVER_INTERPRETED
|
||||||
return errors.New("memory not available")
|
FamilyInternet6 = C.XCB_FAMILY_INTERNET_6
|
||||||
case C.XCB_CONN_CLOSED_REQ_LEN_EXCEED:
|
)
|
||||||
return errors.New("request length exceeded")
|
|
||||||
case C.XCB_CONN_CLOSED_PARSE_ERR:
|
type (
|
||||||
return errors.New("invalid display string")
|
HostMode = C.xcb_host_mode_t
|
||||||
case C.XCB_CONN_CLOSED_INVALID_SCREEN:
|
Family = C.xcb_family_t
|
||||||
return errors.New("server has no screen matching display")
|
)
|
||||||
default:
|
|
||||||
return errors.New("generic X11 failure")
|
func (conn *connection) changeHostsChecked(mode HostMode, family Family, address string) error {
|
||||||
}
|
errno := C._go_xcb_change_hosts_checked(
|
||||||
} else {
|
conn.c,
|
||||||
|
C.uint8_t(mode),
|
||||||
|
C.uint8_t(family),
|
||||||
|
C.uint16_t(len(address)),
|
||||||
|
(*C.uint8_t)(unsafe.Pointer(C.CString(address))),
|
||||||
|
)
|
||||||
|
switch errno {
|
||||||
|
case 0:
|
||||||
return nil
|
return nil
|
||||||
|
case -1:
|
||||||
|
return ErrChangeHosts
|
||||||
|
default:
|
||||||
|
return &ConnectionError{errno}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type connection struct{ c *C.xcb_connection_t }
|
||||||
|
|
||||||
|
func connect() (*connection, error) {
|
||||||
|
conn := newConnection(C.xcb_connect(nil, nil))
|
||||||
|
return conn, conn.hasError()
|
||||||
|
}
|
||||||
|
|
||||||
|
func newConnection(c *C.xcb_connection_t) *connection {
|
||||||
|
conn := &connection{c}
|
||||||
|
runtime.SetFinalizer(conn, (*connection).disconnect)
|
||||||
|
return conn
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
ConnError = C.XCB_CONN_ERROR
|
||||||
|
ConnClosedExtNotSupported = C.XCB_CONN_CLOSED_EXT_NOTSUPPORTED
|
||||||
|
ConnClosedMemInsufficient = C.XCB_CONN_CLOSED_MEM_INSUFFICIENT
|
||||||
|
ConnClosedReqLenExceed = C.XCB_CONN_CLOSED_REQ_LEN_EXCEED
|
||||||
|
ConnClosedParseErr = C.XCB_CONN_CLOSED_PARSE_ERR
|
||||||
|
ConnClosedInvalidScreen = C.XCB_CONN_CLOSED_INVALID_SCREEN
|
||||||
|
)
|
||||||
|
|
||||||
|
type ConnectionError struct{ errno C.int }
|
||||||
|
|
||||||
|
func (ce *ConnectionError) Error() string {
|
||||||
|
switch ce.errno {
|
||||||
|
case ConnError:
|
||||||
|
return "connection error"
|
||||||
|
case ConnClosedExtNotSupported:
|
||||||
|
return "extension not supported"
|
||||||
|
case ConnClosedMemInsufficient:
|
||||||
|
return "memory not available"
|
||||||
|
case ConnClosedReqLenExceed:
|
||||||
|
return "request length exceeded"
|
||||||
|
case ConnClosedParseErr:
|
||||||
|
return "invalid display string"
|
||||||
|
case ConnClosedInvalidScreen:
|
||||||
|
return "server has no screen matching display"
|
||||||
|
default:
|
||||||
|
return "generic X11 failure"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (conn *connection) hasError() error {
|
||||||
|
errno := C.xcb_connection_has_error(conn.c)
|
||||||
|
if errno == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &ConnectionError{errno}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (conn *connection) disconnect() {
|
||||||
|
C.xcb_disconnect(conn.c)
|
||||||
|
|
||||||
|
// no need for a finalizer anymore
|
||||||
|
runtime.SetFinalizer(conn, nil)
|
||||||
|
}
|
||||||
|
@ -1,63 +1,22 @@
|
|||||||
// Package xcb implements X11 ChangeHosts via libxcb.
|
// Package xcb implements X11 ChangeHosts via libxcb.
|
||||||
package xcb
|
package xcb
|
||||||
|
|
||||||
//#include <stdlib.h>
|
|
||||||
//#include <xcb/xcb.h>
|
|
||||||
//#cgo linux LDFLAGS: -lxcb
|
|
||||||
import "C"
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"unsafe"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
var ErrChangeHosts = errors.New("xcb_change_hosts() failed")
|
||||||
HostModeInsert = C.XCB_HOST_MODE_INSERT
|
|
||||||
HostModeDelete = C.XCB_HOST_MODE_DELETE
|
|
||||||
|
|
||||||
FamilyInternet = C.XCB_FAMILY_INTERNET
|
func ChangeHosts(mode HostMode, family Family, address string) error {
|
||||||
FamilyDecnet = C.XCB_FAMILY_DECNET
|
var conn *connection
|
||||||
FamilyChaos = C.XCB_FAMILY_CHAOS
|
|
||||||
FamilyServerInterpreted = C.XCB_FAMILY_SERVER_INTERPRETED
|
|
||||||
FamilyInternet6 = C.XCB_FAMILY_INTERNET_6
|
|
||||||
)
|
|
||||||
|
|
||||||
type ConnectionError struct {
|
if c, err := connect(); err != nil {
|
||||||
err error
|
c.disconnect()
|
||||||
}
|
return err
|
||||||
|
} else {
|
||||||
func (e *ConnectionError) Error() string {
|
defer c.disconnect()
|
||||||
return e.err.Error()
|
conn = c
|
||||||
}
|
|
||||||
|
|
||||||
func (e *ConnectionError) Unwrap() error {
|
|
||||||
return e.err
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
ErrChangeHosts = errors.New("xcb_change_hosts() failed")
|
|
||||||
)
|
|
||||||
|
|
||||||
func ChangeHosts(mode, family C.uint8_t, address string) error {
|
|
||||||
c := C.xcb_connect(nil, nil)
|
|
||||||
defer C.xcb_disconnect(c)
|
|
||||||
|
|
||||||
if err := xcbHandleConnectionError(c); err != nil {
|
|
||||||
return &ConnectionError{err}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addr := C.CString(address)
|
return conn.changeHostsChecked(mode, family, address)
|
||||||
cookie := C.xcb_change_hosts_checked(c, mode, family, C.ushort(len(address)), (*C.uchar)(unsafe.Pointer(addr)))
|
|
||||||
C.free(unsafe.Pointer(addr))
|
|
||||||
|
|
||||||
if err := xcbHandleConnectionError(c); err != nil {
|
|
||||||
return &ConnectionError{err}
|
|
||||||
}
|
|
||||||
|
|
||||||
e := C.xcb_request_check(c, cookie)
|
|
||||||
if e != nil {
|
|
||||||
defer C.free(unsafe.Pointer(e))
|
|
||||||
return ErrChangeHosts
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user