decode.go builds without C or unsafe.
diff --git a/api_c.go b/api_c.go index 5d7a0f0..3212d0b 100644 --- a/api_c.go +++ b/api_c.go
@@ -98,6 +98,11 @@ return true } +// Destroy a parser object. +func yaml_parser_delete(parser *yaml_parser_t) { + *parser = yaml_parser_t{} +} + // String read handler. func yaml_string_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) { if parser.input_pos == len(parser.input) { @@ -794,6 +799,11 @@ // return 1; //} +// Destroy an event object. +func yaml_event_delete(event *yaml_event_t) { + *event = yaml_event_t{} +} + ///* // * Create a document object. // */
diff --git a/decode.go b/decode.go index b03f36e..6179e66 100644 --- a/decode.go +++ b/decode.go
@@ -1,16 +1,8 @@ package goyaml -// #cgo LDFLAGS: -lm -lpthread -// #cgo windows CFLAGS: -DYAML_DECLARE_STATIC=1 -Dstrdup=_strdup -// #cgo CFLAGS: -I. -DHAVE_CONFIG_H=1 -// -// #include "helpers.h" -import "C" - import ( "reflect" "strconv" - "unsafe" ) const ( @@ -31,22 +23,18 @@ anchors map[string]*node } -func stry(s *C.yaml_char_t) string { - return C.GoString((*C.char)(unsafe.Pointer(s))) -} - // ---------------------------------------------------------------------------- // Parser, produces a node tree out of a libyaml event stream. type parser struct { - parser C.yaml_parser_t - event C.yaml_event_t + parser yaml_parser_t + event yaml_event_t doc *node } func newParser(b []byte) *parser { p := parser{} - if C.yaml_parser_initialize(&p.parser) == 0 { + if !yaml_parser_initialize(&p.parser) { panic("Failed to initialize YAML emitter") } @@ -54,35 +42,31 @@ b = []byte{'\n'} } - // How unsafe is this really? Will this break if the GC becomes compacting? - // Probably not, otherwise that would likely break &parse below as well. - input := (*C.uchar)(unsafe.Pointer(&b[0])) - C.yaml_parser_set_input_string(&p.parser, input, (C.size_t)(len(b))) + yaml_parser_set_input_string(&p.parser, b) p.skip() - if p.event._type != C.YAML_STREAM_START_EVENT { - panic("Expected stream start event, got " + - strconv.Itoa(int(p.event._type))) + if p.event.typ != yaml_STREAM_START_EVENT { + panic("Expected stream start event, got " + strconv.Itoa(int(p.event.typ))) } p.skip() return &p } func (p *parser) destroy() { - if p.event._type != C.YAML_NO_EVENT { - C.yaml_event_delete(&p.event) + if p.event.typ != yaml_NO_EVENT { + yaml_event_delete(&p.event) } - C.yaml_parser_delete(&p.parser) + yaml_parser_delete(&p.parser) } func (p *parser) skip() { - if p.event._type != C.YAML_NO_EVENT { - if p.event._type == C.YAML_STREAM_END_EVENT { + if p.event.typ != yaml_NO_EVENT { + if p.event.typ == yaml_STREAM_END_EVENT { panic("Attempted to go past the end of stream. Corrupted value?") } - C.yaml_event_delete(&p.event) + yaml_event_delete(&p.event) } - if C.yaml_parser_parse(&p.parser, &p.event) == 0 { + if !yaml_parser_parse(&p.parser, &p.event) { p.fail() } } @@ -91,54 +75,56 @@ var where string var line int if p.parser.problem_mark.line != 0 { - line = int(C.int(p.parser.problem_mark.line)) + line = p.parser.problem_mark.line } else if p.parser.context_mark.line != 0 { - line = int(C.int(p.parser.context_mark.line)) + line = p.parser.context_mark.line } if line != 0 { where = "line " + strconv.Itoa(line) + ": " } var msg string - if p.parser.problem != nil { - msg = C.GoString(p.parser.problem) + if len(p.parser.problem) > 0 { + msg = p.parser.problem } else { msg = "Unknown problem parsing YAML content" } panic(where + msg) } -func (p *parser) anchor(n *node, anchor *C.yaml_char_t) { +func (p *parser) anchor(n *node, anchor []byte) { if anchor != nil { - p.doc.anchors[stry(anchor)] = n + p.doc.anchors[string(anchor)] = n } } func (p *parser) parse() *node { - switch p.event._type { - case C.YAML_SCALAR_EVENT: + switch p.event.typ { + case yaml_SCALAR_EVENT: return p.scalar() - case C.YAML_ALIAS_EVENT: + case yaml_ALIAS_EVENT: return p.alias() - case C.YAML_MAPPING_START_EVENT: + case yaml_MAPPING_START_EVENT: return p.mapping() - case C.YAML_SEQUENCE_START_EVENT: + case yaml_SEQUENCE_START_EVENT: return p.sequence() - case C.YAML_DOCUMENT_START_EVENT: + case yaml_DOCUMENT_START_EVENT: return p.document() - case C.YAML_STREAM_END_EVENT: + case yaml_STREAM_END_EVENT: // Happens when attempting to decode an empty buffer. return nil default: panic("Attempted to parse unknown event: " + - strconv.Itoa(int(p.event._type))) + strconv.Itoa(int(p.event.typ))) } panic("Unreachable") } func (p *parser) node(kind int) *node { - return &node{kind: kind, - line: int(C.int(p.event.start_mark.line)), - column: int(C.int(p.event.start_mark.column))} + return &node{ + kind: kind, + line: p.event.start_mark.line, + column: p.event.start_mark.column, + } } func (p *parser) document() *node { @@ -147,28 +133,27 @@ p.doc = n p.skip() n.children = append(n.children, p.parse()) - if p.event._type != C.YAML_DOCUMENT_END_EVENT { + if p.event.typ != yaml_DOCUMENT_END_EVENT { panic("Expected end of document event but got " + - strconv.Itoa(int(p.event._type))) + strconv.Itoa(int(p.event.typ))) } p.skip() return n } func (p *parser) alias() *node { - alias := C.event_alias(&p.event) n := p.node(aliasNode) - n.value = stry(alias.anchor) + n.value = string(p.event.alias.anchor) p.skip() return n } func (p *parser) scalar() *node { - scalar := C.event_scalar(&p.event) + scalar := p.event.scalar n := p.node(scalarNode) - n.value = stry(scalar.value) - n.tag = stry(scalar.tag) - n.implicit = (scalar.plain_implicit != 0) + n.value = string(scalar.value) + n.tag = string(scalar.tag) + n.implicit = scalar.plain_implicit p.anchor(n, scalar.anchor) p.skip() return n @@ -176,9 +161,9 @@ func (p *parser) sequence() *node { n := p.node(sequenceNode) - p.anchor(n, C.event_sequence_start(&p.event).anchor) + p.anchor(n, p.event.sequence_start.anchor) p.skip() - for p.event._type != C.YAML_SEQUENCE_END_EVENT { + for p.event.typ != yaml_SEQUENCE_END_EVENT { n.children = append(n.children, p.parse()) } p.skip() @@ -187,9 +172,9 @@ func (p *parser) mapping() *node { n := p.node(mappingNode) - p.anchor(n, C.event_mapping_start(&p.event).anchor) + p.anchor(n, p.event.mapping_start.anchor) p.skip() - for p.event._type != C.YAML_MAPPING_END_EVENT { + for p.event.typ != yaml_MAPPING_END_EVENT { n.children = append(n.children, p.parse(), p.parse()) } p.skip()
diff --git a/encode.go b/encode.go index c7fcdb2..e6375e2 100644 --- a/encode.go +++ b/encode.go
@@ -1,5 +1,9 @@ package goyaml +// #cgo LDFLAGS: -lm -lpthread +// #cgo windows CFLAGS: -DYAML_DECLARE_STATIC=1 -Dstrdup=_strdup +// #cgo CFLAGS: -I. -DHAVE_CONFIG_H=1 +// // #include "helpers.h" import "C"