go1 updates: standard errors now in syscall package, no more makefile support
This commit is contained in:
		
							parent
							
								
									8c9fe240c5
								
							
						
					
					
						commit
						d8ca80955a
					
				
							
								
								
									
										23
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								Makefile
									
									
									
									
									
								
							@ -1,23 +0,0 @@
 | 
			
		||||
# standard GO make file preamble
 | 
			
		||||
include $(GOROOT)/src/Make.inc
 | 
			
		||||
 | 
			
		||||
# target package name
 | 
			
		||||
TARG=iconv
 | 
			
		||||
 | 
			
		||||
# regular go files
 | 
			
		||||
GOFILES=\
 | 
			
		||||
	reader.go\
 | 
			
		||||
	writer.go\
 | 
			
		||||
 | 
			
		||||
# files that must be processed by cgo
 | 
			
		||||
CGOFILES=\
 | 
			
		||||
	converter.go\
 | 
			
		||||
	iconv.go\
 | 
			
		||||
 | 
			
		||||
# on non glibc systems, we usually need to load the library
 | 
			
		||||
ifneq ($(GOOS),linux)
 | 
			
		||||
CGO_LDFLAGS=-liconv
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
# standard GO make file include for packages
 | 
			
		||||
include $(GOROOT)/src/Make.pkg
 | 
			
		||||
							
								
								
									
										26
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								README.md
									
									
									
									
									
								
							@ -1,28 +1,14 @@
 | 
			
		||||
# Install
 | 
			
		||||
 | 
			
		||||
The main method of installation is through gomake (provided in $GOROOT/bin)
 | 
			
		||||
The main method of installation is through "go install" (provided in $GOROOT/bin)
 | 
			
		||||
 | 
			
		||||
	git clone git://github.com/djimenez/iconv.go.git iconv
 | 
			
		||||
	cd iconv
 | 
			
		||||
	gomake install
 | 
			
		||||
 | 
			
		||||
Alternatively, you can try using goinstall (also provided in $GOROOT/bin).
 | 
			
		||||
However, because iconv.go uses cgo to wrap iconv functions, the build may not
 | 
			
		||||
succeed on all systems. At time of writing goinstall was still experimental and
 | 
			
		||||
has known issues with cgo based packages because of how it produces its own
 | 
			
		||||
make file.
 | 
			
		||||
 | 
			
		||||
	goinstall github.com/djimenez/iconv.go
 | 
			
		||||
	go install github.com/djimenez/iconv.go
 | 
			
		||||
 | 
			
		||||
# Usage
 | 
			
		||||
 | 
			
		||||
To use the package, you'll need the appropriate import statement:
 | 
			
		||||
 | 
			
		||||
	import (
 | 
			
		||||
		// if you used gomake install directly, you'll want this import
 | 
			
		||||
		iconv
 | 
			
		||||
		
 | 
			
		||||
		// if you used goinstall, you'll want this import
 | 
			
		||||
		iconv "github.com/djimenez/iconv.go"
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
@ -96,18 +82,18 @@ automatically do this since it can be used to process a full stream in chunks.
 | 
			
		||||
So you'll need to remember to pass a nil input buffer at the end yourself, just
 | 
			
		||||
like you would with direct iconv usage.
 | 
			
		||||
 | 
			
		||||
## Converting an *io.Reader
 | 
			
		||||
## Converting an \*io.Reader
 | 
			
		||||
 | 
			
		||||
The iconv.Reader allows any other *io.Reader to be wrapped and have its bytes
 | 
			
		||||
The iconv.Reader allows any other \*io.Reader to be wrapped and have its bytes
 | 
			
		||||
transcoded as they are read. 
 | 
			
		||||
 | 
			
		||||
	// We're wrapping stdin for simplicity, but a File or network reader could
 | 
			
		||||
	// be wrapped as well
 | 
			
		||||
	reader,_ := iconv.NewReader(os.Stdin, "utf-8", "windows-1252")
 | 
			
		||||
 | 
			
		||||
## Converting an *io.Writer
 | 
			
		||||
## Converting an \*io.Writer
 | 
			
		||||
 | 
			
		||||
The iconv.Writer allows any other *io.Writer to be wrapped and have its bytes
 | 
			
		||||
The iconv.Writer allows any other \*io.Writer to be wrapped and have its bytes
 | 
			
		||||
transcoded as they are written. 
 | 
			
		||||
 | 
			
		||||
	// We're wrapping stdout for simplicity, but a File or network reader could
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										37
									
								
								converter.go
									
									
									
									
									
								
							
							
						
						
									
										37
									
								
								converter.go
									
									
									
									
									
								
							@ -1,22 +1,23 @@
 | 
			
		||||
package iconv
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
#cgo darwin LDFLAGS: -liconv 
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <iconv.h>
 | 
			
		||||
*/
 | 
			
		||||
import "C"
 | 
			
		||||
import "os"
 | 
			
		||||
import "syscall"
 | 
			
		||||
import "unsafe"
 | 
			
		||||
 | 
			
		||||
type Converter struct {
 | 
			
		||||
	context C.iconv_t
 | 
			
		||||
	open bool
 | 
			
		||||
	open    bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Initialize a new Converter. If fromEncoding or toEncoding are not supported by
 | 
			
		||||
// iconv then an EINVAL error will be returned. An ENOMEM error maybe returned if
 | 
			
		||||
// there is not enough memory to initialize an iconv descriptor
 | 
			
		||||
func NewConverter(fromEncoding string, toEncoding string) (converter *Converter, err Error) {
 | 
			
		||||
func NewConverter(fromEncoding string, toEncoding string) (converter *Converter, err error) {
 | 
			
		||||
	converter = new(Converter)
 | 
			
		||||
 | 
			
		||||
	// convert to C strings
 | 
			
		||||
@ -45,7 +46,7 @@ func (this *Converter) destroy() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Close a Converter's iconv description explicitly
 | 
			
		||||
func (this *Converter) Close() (err os.Error) {
 | 
			
		||||
func (this *Converter) Close() (err error) {
 | 
			
		||||
	if this.open {
 | 
			
		||||
		_, err = C.iconv_close(this.context)
 | 
			
		||||
	}
 | 
			
		||||
@ -64,7 +65,7 @@ func (this *Converter) Close() (err os.Error) {
 | 
			
		||||
// For shift based output encodings, any end shift byte sequences can be generated by
 | 
			
		||||
// passing a 0 length byte slice as input. Also passing a 0 length byte slice for output
 | 
			
		||||
// will simply reset the iconv descriptor shift state without writing any bytes.
 | 
			
		||||
func (this *Converter) Convert(input []byte, output []byte) (bytesRead int, bytesWritten int, err Error) {
 | 
			
		||||
func (this *Converter) Convert(input []byte, output []byte) (bytesRead int, bytesWritten int, err error) {
 | 
			
		||||
	// make sure we are still open
 | 
			
		||||
	if this.open {
 | 
			
		||||
		inputLeft := C.size_t(len(input))
 | 
			
		||||
@ -77,7 +78,7 @@ func (this *Converter) Convert(input []byte, output []byte) (bytesRead int, byte
 | 
			
		||||
			inputPointer := (*C.char)(unsafe.Pointer(&input[0]))
 | 
			
		||||
			outputPointer := (*C.char)(unsafe.Pointer(&output[0]))
 | 
			
		||||
 | 
			
		||||
			_,err = C.iconv(this.context, &inputPointer, &inputLeft, &outputPointer, &outputLeft)
 | 
			
		||||
			_, err = C.iconv(this.context, &inputPointer, &inputLeft, &outputPointer, &outputLeft)
 | 
			
		||||
 | 
			
		||||
			// update byte counters
 | 
			
		||||
			bytesRead = len(input) - int(inputLeft)
 | 
			
		||||
@ -86,16 +87,16 @@ func (this *Converter) Convert(input []byte, output []byte) (bytesRead int, byte
 | 
			
		||||
			// inputPointer will be nil, outputPointer is generated as above
 | 
			
		||||
			outputPointer := (*C.char)(unsafe.Pointer(&output[0]))
 | 
			
		||||
 | 
			
		||||
			_,err = C.iconv(this.context, nil, &inputLeft, &outputPointer, &outputLeft)
 | 
			
		||||
			_, err = C.iconv(this.context, nil, &inputLeft, &outputPointer, &outputLeft)
 | 
			
		||||
 | 
			
		||||
			// update write byte counter
 | 
			
		||||
			bytesWritten = len(output) - int(outputLeft)
 | 
			
		||||
		} else {
 | 
			
		||||
			// both input and output are zero length, do a shift state reset
 | 
			
		||||
			_,err = C.iconv(this.context, nil, &inputLeft, nil, &outputLeft)
 | 
			
		||||
			_, err = C.iconv(this.context, nil, &inputLeft, nil, &outputLeft)
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		err = EBADF
 | 
			
		||||
		err = syscall.EBADF
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return bytesRead, bytesWritten, err
 | 
			
		||||
@ -105,12 +106,12 @@ func (this *Converter) Convert(input []byte, output []byte) (bytesRead int, byte
 | 
			
		||||
//
 | 
			
		||||
// EILSEQ error may be returned if input contains invalid bytes for the
 | 
			
		||||
// Converter's fromEncoding.
 | 
			
		||||
func (this *Converter) ConvertString(input string) (output string, err Error) {
 | 
			
		||||
func (this *Converter) ConvertString(input string) (output string, err error) {
 | 
			
		||||
	// make sure we are still open
 | 
			
		||||
	if this.open {
 | 
			
		||||
		// construct the buffers
 | 
			
		||||
		inputBuffer := []byte(input)
 | 
			
		||||
		outputBuffer := make([]byte, len(inputBuffer) * 2) // we use a larger buffer to help avoid resizing later
 | 
			
		||||
		outputBuffer := make([]byte, len(inputBuffer)*2) // we use a larger buffer to help avoid resizing later
 | 
			
		||||
 | 
			
		||||
		// call Convert until all input bytes are read or an error occurs
 | 
			
		||||
		var bytesRead, totalBytesRead, bytesWritten, totalBytesWritten int
 | 
			
		||||
@ -124,11 +125,11 @@ func (this *Converter) ConvertString(input string) (output string, err Error) {
 | 
			
		||||
 | 
			
		||||
			// check for the E2BIG error specifically, we can add to the output
 | 
			
		||||
			// buffer to correct for it and then continue
 | 
			
		||||
			if err == E2BIG {
 | 
			
		||||
			if err == syscall.E2BIG {
 | 
			
		||||
				// increase the size of the output buffer by another input length
 | 
			
		||||
				// first, create a new buffer
 | 
			
		||||
				tempBuffer := make([]byte, len(outputBuffer) + len(inputBuffer))
 | 
			
		||||
			
 | 
			
		||||
				tempBuffer := make([]byte, len(outputBuffer)+len(inputBuffer))
 | 
			
		||||
 | 
			
		||||
				// copy the existing data
 | 
			
		||||
				copy(tempBuffer, outputBuffer)
 | 
			
		||||
 | 
			
		||||
@ -139,19 +140,19 @@ func (this *Converter) ConvertString(input string) (output string, err Error) {
 | 
			
		||||
				err = nil
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			// perform a final shift state reset
 | 
			
		||||
			_, bytesWritten, err = this.Convert([]byte{}, outputBuffer[totalBytesWritten:])
 | 
			
		||||
			
 | 
			
		||||
 | 
			
		||||
			// update total count
 | 
			
		||||
			totalBytesWritten += bytesWritten
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
		// construct the final output string
 | 
			
		||||
		output = string(outputBuffer[:totalBytesWritten])
 | 
			
		||||
	} else {
 | 
			
		||||
		err = EBADF
 | 
			
		||||
		err = syscall.EBADF
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return output, err
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										26
									
								
								iconv.go
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								iconv.go
									
									
									
									
									
								
							@ -5,26 +5,8 @@ some convenient interface implementations like a Reader and Writer.
 | 
			
		||||
*/
 | 
			
		||||
package iconv
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
*/
 | 
			
		||||
import "C"
 | 
			
		||||
import "os"
 | 
			
		||||
 | 
			
		||||
// Alias os.Error for convenience
 | 
			
		||||
type Error os.Error
 | 
			
		||||
 | 
			
		||||
// Error codes returned from iconv functions
 | 
			
		||||
var (
 | 
			
		||||
	E2BIG Error = os.Errno(int(C.E2BIG))
 | 
			
		||||
	EBADF Error = os.Errno(int(C.EBADF))
 | 
			
		||||
	EINVAL Error = os.Errno(int(C.EINVAL))
 | 
			
		||||
	EILSEQ Error = os.Errno(int(C.EILSEQ))
 | 
			
		||||
	ENOMEM Error = os.Errno(int(C.ENOMEM))
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// All in one Convert method, rather than requiring the construction of an iconv.Converter
 | 
			
		||||
func Convert(input []byte, output []byte, fromEncoding string, toEncoding string) (bytesRead int, bytesWritten int, err Error) {
 | 
			
		||||
func Convert(input []byte, output []byte, fromEncoding string, toEncoding string) (bytesRead int, bytesWritten int, err error) {
 | 
			
		||||
	// create a temporary converter
 | 
			
		||||
	converter, err := NewConverter(fromEncoding, toEncoding)
 | 
			
		||||
 | 
			
		||||
@ -34,10 +16,10 @@ func Convert(input []byte, output []byte, fromEncoding string, toEncoding string
 | 
			
		||||
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			var shiftBytesWritten int
 | 
			
		||||
			
 | 
			
		||||
 | 
			
		||||
			// call Convert with a nil input to generate any end shift sequences
 | 
			
		||||
			_, shiftBytesWritten, err = converter.Convert(nil, output[bytesWritten:])
 | 
			
		||||
			
 | 
			
		||||
 | 
			
		||||
			// add shift bytes to total bytes
 | 
			
		||||
			bytesWritten += shiftBytesWritten
 | 
			
		||||
		}
 | 
			
		||||
@ -50,7 +32,7 @@ func Convert(input []byte, output []byte, fromEncoding string, toEncoding string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// All in one ConvertString method, rather than requiring the construction of an iconv.Converter
 | 
			
		||||
func ConvertString(input string, fromEncoding string, toEncoding string) (output string, err Error) {
 | 
			
		||||
func ConvertString(input string, fromEncoding string, toEncoding string) (output string, err error) {
 | 
			
		||||
	// create a temporary converter
 | 
			
		||||
	converter, err := NewConverter(fromEncoding, toEncoding)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,21 +1,22 @@
 | 
			
		||||
package iconv
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type iconvTest struct {
 | 
			
		||||
	description string
 | 
			
		||||
	input string
 | 
			
		||||
	inputEncoding string
 | 
			
		||||
	output string
 | 
			
		||||
	description    string
 | 
			
		||||
	input          string
 | 
			
		||||
	inputEncoding  string
 | 
			
		||||
	output         string
 | 
			
		||||
	outputEncoding string
 | 
			
		||||
	bytesRead int
 | 
			
		||||
	bytesWritten int
 | 
			
		||||
	err Error
 | 
			
		||||
	bytesRead      int
 | 
			
		||||
	bytesWritten   int
 | 
			
		||||
	err            error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var iconvTests = []iconvTest {
 | 
			
		||||
var iconvTests = []iconvTest{
 | 
			
		||||
	iconvTest{
 | 
			
		||||
		"simple utf-8 to latin1 conversion success",
 | 
			
		||||
		"Hello World!", "utf-8",
 | 
			
		||||
@ -26,25 +27,25 @@ var iconvTests = []iconvTest {
 | 
			
		||||
		"invalid source encoding causes EINVAL",
 | 
			
		||||
		"", "doesnotexist",
 | 
			
		||||
		"", "utf-8",
 | 
			
		||||
		0, 0, EINVAL,
 | 
			
		||||
		0, 0, syscall.EINVAL,
 | 
			
		||||
	},
 | 
			
		||||
	iconvTest{
 | 
			
		||||
		"invalid destination encoding causes EINVAL",
 | 
			
		||||
		"", "utf-8",
 | 
			
		||||
		"", "doesnotexist",
 | 
			
		||||
		0, 0, EINVAL,
 | 
			
		||||
		0, 0, syscall.EINVAL,
 | 
			
		||||
	},
 | 
			
		||||
	iconvTest{
 | 
			
		||||
		"invalid input sequence causes EILSEQ",
 | 
			
		||||
		"\xFF", "utf-8",
 | 
			
		||||
		"", "latin1",
 | 
			
		||||
		0, 0, EILSEQ,
 | 
			
		||||
		0, 0, syscall.EILSEQ,
 | 
			
		||||
	},
 | 
			
		||||
	iconvTest{
 | 
			
		||||
		"invalid input causes partial output and EILSEQ",
 | 
			
		||||
		"Hello\xFF", "utf-8",
 | 
			
		||||
		"Hello", "latin1",
 | 
			
		||||
		5, 5, EILSEQ,
 | 
			
		||||
		5, 5, syscall.EILSEQ,
 | 
			
		||||
	},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -52,12 +53,12 @@ func TestConvertString(t *testing.T) {
 | 
			
		||||
	for _, test := range iconvTests {
 | 
			
		||||
		// perform the conversion
 | 
			
		||||
		output, err := ConvertString(test.input, test.inputEncoding, test.outputEncoding)
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
		// check that output and err match
 | 
			
		||||
		if output != test.output {
 | 
			
		||||
			t.Errorf("test \"%s\" failed, output did not match expected", test.description)
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
		// check that err is same as expected
 | 
			
		||||
		if err != test.err {
 | 
			
		||||
			if test.err != nil {
 | 
			
		||||
@ -77,29 +78,29 @@ func TestConvert(t *testing.T) {
 | 
			
		||||
	for _, test := range iconvTests {
 | 
			
		||||
		// setup input buffer
 | 
			
		||||
		input := []byte(test.input)
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
		// setup a buffer as large as the expected bytesWritten
 | 
			
		||||
		output := make([]byte, 50)
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
		// peform the conversion
 | 
			
		||||
		bytesRead, bytesWritten, err := Convert(input, output, test.inputEncoding, test.outputEncoding)
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
		// check that bytesRead is same as expected
 | 
			
		||||
		if bytesRead != test.bytesRead {
 | 
			
		||||
			t.Errorf("test \"%s\" failed, bytesRead did not match expected", test.description)
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
		// check that bytesWritten is same as expected
 | 
			
		||||
		if bytesWritten != test.bytesWritten {
 | 
			
		||||
			t.Errorf("test \"%s\" failed, bytesWritten did not match expected", test.description)
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
		// check output bytes against expected - simplest to convert output to
 | 
			
		||||
		// string and then do an equality check which is actually a byte wise operation
 | 
			
		||||
		if string(output[:bytesWritten]) != test.output {
 | 
			
		||||
			t.Errorf("test \"%s\" failed, output did not match expected", test.description)
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
		// check that err is same as expected
 | 
			
		||||
		if err != test.err {
 | 
			
		||||
			if test.err != nil {
 | 
			
		||||
@ -113,4 +114,4 @@ func TestConvert(t *testing.T) {
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										22
									
								
								reader.go
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								reader.go
									
									
									
									
									
								
							@ -1,19 +1,19 @@
 | 
			
		||||
package iconv
 | 
			
		||||
 | 
			
		||||
import ( 
 | 
			
		||||
import (
 | 
			
		||||
	"io"
 | 
			
		||||
	"os"
 | 
			
		||||
	"syscall"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Reader struct {
 | 
			
		||||
	source io.Reader
 | 
			
		||||
	converter *Converter
 | 
			
		||||
	buffer []byte
 | 
			
		||||
	source            io.Reader
 | 
			
		||||
	converter         *Converter
 | 
			
		||||
	buffer            []byte
 | 
			
		||||
	readPos, writePos int
 | 
			
		||||
	err os.Error
 | 
			
		||||
	err               error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewReader(source io.Reader, fromEncoding string, toEncoding string) (*Reader, os.Error) {
 | 
			
		||||
func NewReader(source io.Reader, fromEncoding string, toEncoding string) (*Reader, error) {
 | 
			
		||||
	// create a converter
 | 
			
		||||
	converter, err := NewConverter(fromEncoding, toEncoding)
 | 
			
		||||
 | 
			
		||||
@ -33,7 +33,7 @@ func NewReaderFromConverter(source io.Reader, converter *Converter) (reader *Rea
 | 
			
		||||
	reader.converter = converter
 | 
			
		||||
 | 
			
		||||
	// create 8K buffers
 | 
			
		||||
	reader.buffer = make([]byte, 8 * 1024)
 | 
			
		||||
	reader.buffer = make([]byte, 8*1024)
 | 
			
		||||
 | 
			
		||||
	return reader
 | 
			
		||||
}
 | 
			
		||||
@ -62,7 +62,7 @@ func (this *Reader) fillBuffer() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// implement the io.Reader interface
 | 
			
		||||
func (this *Reader) Read(p []byte) (n int, err os.Error) {
 | 
			
		||||
func (this *Reader) Read(p []byte) (n int, err error) {
 | 
			
		||||
	// checks for when we have no data
 | 
			
		||||
	for this.writePos == 0 || this.readPos == this.writePos {
 | 
			
		||||
		// if we have an error / EOF, just return it
 | 
			
		||||
@ -72,7 +72,7 @@ func (this *Reader) Read(p []byte) (n int, err os.Error) {
 | 
			
		||||
 | 
			
		||||
		// else, fill our buffer
 | 
			
		||||
		this.fillBuffer()
 | 
			
		||||
	}	
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// TODO: checks for when we have less data than len(p)
 | 
			
		||||
 | 
			
		||||
@ -89,7 +89,7 @@ func (this *Reader) Read(p []byte) (n int, err os.Error) {
 | 
			
		||||
		// as at least 1 byte was written. If we experienced an E2BIG
 | 
			
		||||
		// and no bytes were written then the buffer is too small for
 | 
			
		||||
		// even the next character
 | 
			
		||||
		if err != E2BIG || bytesWritten == 0 {
 | 
			
		||||
		if err != syscall.E2BIG || bytesWritten == 0 {
 | 
			
		||||
			// track anything else
 | 
			
		||||
			this.err = err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										33
									
								
								writer.go
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								writer.go
									
									
									
									
									
								
							@ -1,19 +1,16 @@
 | 
			
		||||
package iconv
 | 
			
		||||
 | 
			
		||||
import ( 
 | 
			
		||||
	"io"
 | 
			
		||||
	"os"
 | 
			
		||||
)
 | 
			
		||||
import "io"
 | 
			
		||||
 | 
			
		||||
type Writer struct {
 | 
			
		||||
	destination io.Writer
 | 
			
		||||
	converter *Converter
 | 
			
		||||
	buffer []byte
 | 
			
		||||
	destination       io.Writer
 | 
			
		||||
	converter         *Converter
 | 
			
		||||
	buffer            []byte
 | 
			
		||||
	readPos, writePos int
 | 
			
		||||
	err os.Error
 | 
			
		||||
	err               error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewWriter(destination io.Writer, fromEncoding string, toEncoding string) (*Writer, os.Error) {
 | 
			
		||||
func NewWriter(destination io.Writer, fromEncoding string, toEncoding string) (*Writer, error) {
 | 
			
		||||
	// create a converter
 | 
			
		||||
	converter, err := NewConverter(fromEncoding, toEncoding)
 | 
			
		||||
 | 
			
		||||
@ -33,7 +30,7 @@ func NewWriterFromConverter(destination io.Writer, converter *Converter) (writer
 | 
			
		||||
	writer.converter = converter
 | 
			
		||||
 | 
			
		||||
	// create 8K buffers
 | 
			
		||||
	writer.buffer = make([]byte, 8 * 1024)
 | 
			
		||||
	writer.buffer = make([]byte, 8*1024)
 | 
			
		||||
 | 
			
		||||
	return writer
 | 
			
		||||
}
 | 
			
		||||
@ -41,10 +38,10 @@ func NewWriterFromConverter(destination io.Writer, converter *Converter) (writer
 | 
			
		||||
func (this *Writer) emptyBuffer() {
 | 
			
		||||
	// write new data out of buffer 
 | 
			
		||||
	bytesWritten, err := this.destination.Write(this.buffer[this.readPos:this.writePos])
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
	// update read position
 | 
			
		||||
	this.readPos += bytesWritten
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
	// slide existing data to beginning
 | 
			
		||||
	if this.readPos > 0 {
 | 
			
		||||
		// copy current bytes - is this guaranteed safe?
 | 
			
		||||
@ -62,24 +59,24 @@ func (this *Writer) emptyBuffer() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// implement the io.Writer interface
 | 
			
		||||
func (this *Writer) Write(p []byte) (n int, err os.Error) {
 | 
			
		||||
func (this *Writer) Write(p []byte) (n int, err error) {
 | 
			
		||||
	// write data into our internal buffer
 | 
			
		||||
	bytesRead, bytesWritten, err := this.converter.Convert(p, this.buffer[this.writePos:])
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
	// update bytes written for return
 | 
			
		||||
	n += bytesRead
 | 
			
		||||
	this.writePos += bytesWritten
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
	// checks for when we have a full buffer
 | 
			
		||||
	for this.writePos > 0 {
 | 
			
		||||
		// if we have an error, just return it
 | 
			
		||||
		if this.err != nil {
 | 
			
		||||
			return 
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
		// else empty the buffer
 | 
			
		||||
		this.emptyBuffer()
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
	return n, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user