// parse a network resource
func (p *Parser) ParseUri(uri string, base_uri string) chan *Statement {
	p.out = make(chan *Statement)
	go func() {
		p.mutex.Lock()
		defer p.mutex.Unlock()

		curi := C.CString(uri)
		ruri := C.raptor_new_uri(p.world, (*C.uchar)(unsafe.Pointer(curi)))
		C.free(unsafe.Pointer(curi))

		var buri *C.raptor_uri
		if len(base_uri) == 0 {
			buri = C.raptor_uri_copy(ruri)
		} else {
			cbase_uri := C.CString(base_uri)
			buri = C.raptor_new_uri(p.world, (*C.uchar)(unsafe.Pointer(cbase_uri)))
			C.free(unsafe.Pointer(cbase_uri))
		}

		C.raptor_parser_parse_uri(p.parser, ruri, buri)

		C.raptor_free_uri(ruri)
		C.raptor_free_uri(buri)

		close(p.out)
	}()
	return p.out
}
// parse a local file
func (p *Parser) ParseFile(filename string, base_uri string) chan *Statement {
	p.out = make(chan *Statement)
	go func() {
		p.mutex.Lock()
		defer p.mutex.Unlock()

		cfilename := C.CString(filename)
		uri_string := C.raptor_uri_filename_to_uri_string(cfilename)
		C.free(unsafe.Pointer(cfilename))

		uri := C.raptor_new_uri(p.world, uri_string)
		C.raptor_free_memory(unsafe.Pointer(uri_string))

		var buri *C.raptor_uri
		if len(base_uri) == 0 {
			buri = C.raptor_uri_copy(uri)
		} else {
			cbase_uri := C.CString(base_uri)
			buri = C.raptor_new_uri(p.world, (*C.uchar)(unsafe.Pointer(cbase_uri)))
			C.free(unsafe.Pointer(cbase_uri))
		}

		C.raptor_parser_parse_file(p.parser, uri, buri)

		C.raptor_free_uri(uri)
		C.raptor_free_uri(buri)

		close(p.out)
	}()
	return p.out
}
func (s *Serializer) StartStream(file *os.File, base_uri string) (err error) {
	var buri *C.raptor_uri

	s.mutex.Lock()
	defer s.mutex.Unlock()

	if s.running {
		err = errors.New("serializer already running")
		return
	}
	s.running = true

	if len(base_uri) > 0 {
		cbase_uri := C.CString(base_uri)
		buri = C.raptor_new_uri(s.world, (*C.uchar)(unsafe.Pointer(cbase_uri)))
		C.free(unsafe.Pointer(cbase_uri))
		// XXX LEAK defer C.raptor_free_uri(buri)
	}

	cwb := C.CString("wb")
	fh, err := C.fdopen(C.int(file.Fd()), cwb)
	C.free(unsafe.Pointer(cwb))
	if fh == nil {
		err = errors.New("fdopen: ...")
		return
	}
	s.fh = fh

	if C.raptor_serializer_start_to_file_handle(s.serializer, buri, s.fh) != 0 {
		err = errors.New("raptor_serializer_start_to_file_handle failed")
		return
	}

	return
}
func (s *Serializer) SetFile(fp *os.File, base_uri string) (err error) {
	s.mutex.Lock()
	defer s.mutex.Unlock()

	mode := C.CString("w")
	fh, err := C.fdopen(C.int(fp.Fd()), mode) // do something better with mode?
	C.free(unsafe.Pointer(mode))
	if err != nil {
		return
	}
	s.fh = fh

	var buri *C.raptor_uri
	if len(base_uri) > 0 {
		cbase_uri := C.CString(base_uri)
		buri = C.raptor_new_uri(s.world, (*C.uchar)(unsafe.Pointer(cbase_uri)))
		C.free(unsafe.Pointer(cbase_uri))
		defer C.raptor_free_uri(buri)
	}
	if C.raptor_serializer_start_to_file_handle(s.serializer, buri, s.fh) != 0 {
		err = errors.New("C.raptor_serializer_start_to_file_handle failed")
		return
	}

	s.running = true

	return
}
// Parse RDF data from an io.Reader
func (p *Parser) Parse(reader io.Reader, base_uri string) chan *Statement {
	p.out = make(chan *Statement)
	go func() {
		var (
			err error
		)
		p.mutex.Lock()
		defer p.mutex.Unlock()

		cbase_uri := C.CString(base_uri)
		buri := C.raptor_new_uri(p.world, (*C.uchar)(unsafe.Pointer(cbase_uri)))
		C.free(unsafe.Pointer(cbase_uri))

		if C.raptor_parser_parse_start(p.parser, buri) == 0 {
			n := 0
			buf := make([]byte, 8192)
			for err == nil {
				n, err = reader.Read(buf)
				if n > 0 {
					C.raptor_parser_parse_chunk(p.parser, (*C.uchar)(unsafe.Pointer(&buf[0])), C.size_t(n), 0)
				}
			}
			C.raptor_parser_parse_chunk(p.parser, nil, 0, 1)
		}

		close(p.out)
	}()
	return p.out
}
func (l *Literal) raptor_term() (term *C.raptor_term) {
	value := (*C.uchar)(unsafe.Pointer(C.CString(l.Value)))
	llen := len(l.Value)
	var lang *C.uchar
	langlen := len(l.Lang)
	if langlen != 0 {
		lang = (*C.uchar)(unsafe.Pointer(C.CString(l.Lang)))
	}
	var datatype *C.raptor_uri
	if len(l.Datatype) != 0 {
		dtstr := (*C.uchar)(unsafe.Pointer(C.CString(l.Datatype)))
		datatype = C.raptor_new_uri(global_world, dtstr)
		C.free(unsafe.Pointer(dtstr))
	}
	term = C.raptor_new_term_from_counted_literal(global_world,
		value, C.size_t(llen), datatype, lang, C.uchar(langlen))
	if datatype != nil {
		C.raptor_free_uri(datatype)
	}
	if lang != nil {
		C.free(unsafe.Pointer(lang))
	}
	C.free(unsafe.Pointer(value))
	return
}
func (s *Serializer) SetNamespace(prefix, uri string) {
	cprefix := C.CString(prefix)
	curistr := C.CString(uri)
	curi := C.raptor_new_uri(s.world, (*C.uchar)(unsafe.Pointer(curistr)))
	C.raptor_serializer_set_namespace(s.serializer, curi, (*C.uchar)(unsafe.Pointer(cprefix)))
	C.free(unsafe.Pointer(cprefix))
	C.free(unsafe.Pointer(curistr))
}
func (s *Serializer) Serialize(ch chan *Statement, base_uri string) (str string, err error) {
	var cstrp unsafe.Pointer
	var cstrlen C.size_t
	var buri *C.raptor_uri

	s.mutex.Lock()
	defer s.mutex.Unlock()

	if s.running {
		err = errors.New("serializer already running")
		return
	}
	s.running = true

	if len(base_uri) > 0 {
		cbase_uri := C.CString(base_uri)
		buri = C.raptor_new_uri(s.world, (*C.uchar)(unsafe.Pointer(cbase_uri)))
		C.free(unsafe.Pointer(cbase_uri))
		defer C.raptor_free_uri(buri)
	}

	if C.raptor_serializer_start_to_string(s.serializer, buri, &cstrp, &cstrlen) != 0 {
		err = errors.New("raptor_serializer_start_to_string failed")
		return
	}

	for {
		statement, ok := <-ch
		if !ok {
			break
		}
		err = s.add(statement)
		if err != nil {
			log.Print(err)
			break
		}
	}

	s.end()

	if cstrp == nil {
		err = errors.New("serialising failed")
		return
	}
	str = C.GoString((*C.char)(cstrp))
	C.free(cstrp)

	return
}