Merge 0efdb40d57 into 8960e66bd3
				
					
				
			This commit is contained in:
		
						commit
						ee044a164c
					
				
							
								
								
									
										26
									
								
								reader.go
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								reader.go
									
									
									
									
									
								
							@ -5,6 +5,8 @@ import (
 | 
			
		||||
	"syscall"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const bufferSize = 8 * 1024
 | 
			
		||||
 | 
			
		||||
type Reader struct {
 | 
			
		||||
	source            io.Reader
 | 
			
		||||
	converter         *Converter
 | 
			
		||||
@ -33,12 +35,12 @@ 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, bufferSize)
 | 
			
		||||
 | 
			
		||||
	return reader
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *Reader) fillBuffer() {
 | 
			
		||||
func (this *Reader) fillBuffer() int {
 | 
			
		||||
	// slide existing data to beginning
 | 
			
		||||
	if this.readPos > 0 {
 | 
			
		||||
		// copy current bytes - is this guaranteed safe?
 | 
			
		||||
@ -59,6 +61,7 @@ func (this *Reader) fillBuffer() {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.err = err
 | 
			
		||||
	}
 | 
			
		||||
	return bytesRead
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// implement the io.Reader interface
 | 
			
		||||
@ -85,6 +88,18 @@ func (this *Reader) Read(p []byte) (n int, err error) {
 | 
			
		||||
 | 
			
		||||
	// if we experienced an iconv error, check it
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		// EINVAL:
 | 
			
		||||
		// An incomplete multibyte sequence is encountered in the input,
 | 
			
		||||
		// and the input byte sequence terminates after it.
 | 
			
		||||
		if err == syscall.EINVAL {
 | 
			
		||||
			// If we can read new data, then this should NOT be
 | 
			
		||||
			// considered as an error.
 | 
			
		||||
			newData := this.fillBuffer()
 | 
			
		||||
			if newData > 0 {
 | 
			
		||||
				return n, nil
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// E2BIG errors can be ignored (we'll get them often) as long
 | 
			
		||||
		// as at least 1 byte was written. If we experienced an E2BIG
 | 
			
		||||
		// and no bytes were written then the buffer is too small for
 | 
			
		||||
@ -92,6 +107,13 @@ func (this *Reader) Read(p []byte) (n int, err error) {
 | 
			
		||||
		if err != syscall.E2BIG || bytesWritten == 0 {
 | 
			
		||||
			// track anything else
 | 
			
		||||
			this.err = err
 | 
			
		||||
		} else {
 | 
			
		||||
			// Should not return this.err
 | 
			
		||||
			// If we got EOF from source in last fillBuffer() call, and
 | 
			
		||||
			// there is still more data to process in buffer, in this
 | 
			
		||||
			// case, if we return this.err(=EOF), then data in buffer
 | 
			
		||||
			// will be lost.
 | 
			
		||||
			return n, nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										38
									
								
								reader_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								reader_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,38 @@
 | 
			
		||||
package iconv
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func GbkToUtf8(src []byte) ([]byte, error) {
 | 
			
		||||
	reader, err := NewReader(bytes.NewReader(src), "gbk", "utf-8")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return ioutil.ReadAll(reader)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Utf8ToGbk(src []byte) ([]byte, error) {
 | 
			
		||||
	reader, err := NewReader(bytes.NewReader(src), "utf-8", "gbk")
 | 
			
		||||
	reader.buffer = make([]byte, 16)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return ioutil.ReadAll(reader)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestReaderWithDataLargerThanBuffer(t *testing.T) {
 | 
			
		||||
	chars := []byte("梅")
 | 
			
		||||
	for len(chars) < bufferSize*2 {
 | 
			
		||||
		t.Logf("input size: %d", len(chars))
 | 
			
		||||
		chars = append(chars, chars...)
 | 
			
		||||
		_, err := Utf8ToGbk(chars)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Fail()
 | 
			
		||||
			t.Logf("failed with %d bytes data", len(chars))
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user