github.com/balzaczyy/golucene@v0.0.0-20151210033525-d0be9ee89713/core/store/buffer.go (about)

     1  package store
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  )
     7  
     8  type SeekReader interface {
     9  	seekInternal(pos int64) error
    10  	readInternal(buf []byte) error
    11  	Length() int64
    12  }
    13  
    14  /* Minimum buffer size allowed */
    15  const MIN_BUFFER_SIZE = 8
    16  
    17  /* Base implementation class for buffered IndexInput. */
    18  type BufferedIndexInput struct {
    19  	*IndexInputImpl
    20  	spi            SeekReader
    21  	bufferSize     int
    22  	buffer         []byte
    23  	bufferStart    int64
    24  	bufferLength   int
    25  	bufferPosition int
    26  }
    27  
    28  func newBufferedIndexInput(spi SeekReader, desc string, context IOContext) *BufferedIndexInput {
    29  	return newBufferedIndexInputBySize(spi, desc, bufferSize(context))
    30  }
    31  
    32  func newBufferedIndexInputBySize(spi SeekReader, desc string, bufferSize int) *BufferedIndexInput {
    33  	checkBufferSize(bufferSize)
    34  	ans := &BufferedIndexInput{spi: spi, bufferSize: bufferSize}
    35  	ans.IndexInputImpl = NewIndexInputImpl(desc, ans)
    36  	return ans
    37  }
    38  
    39  func (in *BufferedIndexInput) newBuffer(newBuffer []byte) {
    40  	// Subclasses can do something here
    41  	in.buffer = newBuffer
    42  }
    43  
    44  func (in *BufferedIndexInput) ReadByte() (b byte, err error) {
    45  	if in.bufferPosition >= in.bufferLength {
    46  		err = in.refill()
    47  		if err != nil {
    48  			return 0, err
    49  		}
    50  	}
    51  	b = in.buffer[in.bufferPosition]
    52  	in.bufferPosition++
    53  	return
    54  }
    55  
    56  func checkBufferSize(bufferSize int) {
    57  	assert2(bufferSize >= MIN_BUFFER_SIZE,
    58  		"bufferSize must be at least MIN_BUFFER_SIZE (got %v)",
    59  		bufferSize)
    60  }
    61  
    62  func (in *BufferedIndexInput) ReadBytes(buf []byte) error {
    63  	return in.ReadBytesBuffered(buf, true)
    64  }
    65  
    66  func (in *BufferedIndexInput) ReadBytesBuffered(buf []byte, useBuffer bool) error {
    67  	available := in.bufferLength - in.bufferPosition
    68  	if length := len(buf); length <= available {
    69  		// the buffer contains enough data to satisfy this request
    70  		if length > 0 { // to allow b to be null if len is 0...
    71  			copy(buf, in.buffer[in.bufferPosition:in.bufferPosition+length])
    72  		}
    73  		in.bufferPosition += length
    74  	} else {
    75  		// the buffer does not have enough data. First serve all we've got.
    76  		if available > 0 {
    77  			copy(buf, in.buffer[in.bufferPosition:in.bufferPosition+available])
    78  			buf = buf[available:]
    79  			in.bufferPosition += available
    80  		}
    81  		// and now, read the remaining 'len' bytes:
    82  		if length := len(buf); useBuffer && length < in.bufferSize {
    83  			// If the amount left to read is small enough, and
    84  			// we are allowed to use our buffer, do it in the usual
    85  			// buffered way: fill the buffer and copy from it:
    86  			if err := in.refill(); err != nil {
    87  				return err
    88  			}
    89  			if in.bufferLength < length {
    90  				// Throw an exception when refill() could not read len bytes:
    91  				copy(buf, in.buffer[0:in.bufferLength])
    92  				return errors.New(fmt.Sprintf("read past EOF: %v", in))
    93  			} else {
    94  				copy(buf, in.buffer[0:length])
    95  				in.bufferPosition += length
    96  			}
    97  		} else {
    98  			// The amount left to read is larger than the buffer
    99  			// or we've been asked to not use our buffer -
   100  			// there's no performance reason not to read it all
   101  			// at once. Note that unlike the previous code of
   102  			// this function, there is no need to do a seek
   103  			// here, because there's no need to reread what we
   104  			// had in the buffer.
   105  			length := len(buf)
   106  			after := in.bufferStart + int64(in.bufferPosition) + int64(length)
   107  			if after > in.spi.Length() {
   108  				return errors.New(fmt.Sprintf("read past EOF: %v", in))
   109  			}
   110  			if err := in.spi.readInternal(buf); err != nil {
   111  				return err
   112  			}
   113  			in.bufferStart = after
   114  			in.bufferPosition = 0
   115  			in.bufferLength = 0 // trigger refill() on read
   116  		}
   117  	}
   118  	return nil
   119  }
   120  
   121  func (in *BufferedIndexInput) ReadShort() (n int16, err error) {
   122  	if 2 <= in.bufferLength-in.bufferPosition {
   123  		in.bufferPosition += 2
   124  		return (int16(in.buffer[in.bufferPosition-2]) << 8) | int16(in.buffer[in.bufferPosition-1]), nil
   125  	}
   126  	return in.DataInputImpl.ReadShort()
   127  }
   128  
   129  func (in *BufferedIndexInput) ReadInt() (n int32, err error) {
   130  	if 4 <= in.bufferLength-in.bufferPosition {
   131  		// log.Print("Reading int from buffer...")
   132  		in.bufferPosition += 4
   133  		return (int32(in.buffer[in.bufferPosition-4]) << 24) | (int32(in.buffer[in.bufferPosition-3]) << 16) |
   134  			(int32(in.buffer[in.bufferPosition-2]) << 8) | int32(in.buffer[in.bufferPosition-1]), nil
   135  	}
   136  	return in.DataInputImpl.ReadInt()
   137  }
   138  
   139  func (in *BufferedIndexInput) ReadLong() (n int64, err error) {
   140  	if 8 <= in.bufferLength-in.bufferPosition {
   141  		in.bufferPosition += 4
   142  		i1 := (int64(in.buffer[in.bufferPosition-4]) << 24) | (int64(in.buffer[in.bufferPosition-3]) << 16) |
   143  			(int64(in.buffer[in.bufferPosition-2]) << 8) | int64(in.buffer[in.bufferPosition-1])
   144  		in.bufferPosition += 4
   145  		i2 := (int64(in.buffer[in.bufferPosition-4]) << 24) | (int64(in.buffer[in.bufferPosition-3]) << 16) |
   146  			(int64(in.buffer[in.bufferPosition-2]) << 8) | int64(in.buffer[in.bufferPosition-1])
   147  		return (i1 << 32) | i2, nil
   148  	}
   149  	return in.DataInputImpl.ReadLong()
   150  }
   151  
   152  func (in *BufferedIndexInput) ReadVInt() (n int32, err error) {
   153  	if 5 <= in.bufferLength-in.bufferPosition {
   154  		b := in.buffer[in.bufferPosition]
   155  		in.bufferPosition++
   156  		if b < 128 {
   157  			return int32(b), nil
   158  		}
   159  		n := int32(b) & 0x7F
   160  		b = in.buffer[in.bufferPosition]
   161  		in.bufferPosition++
   162  		n |= (int32(b) & 0x7F) << 7
   163  		if b < 128 {
   164  			return n, nil
   165  		}
   166  		b = in.buffer[in.bufferPosition]
   167  		in.bufferPosition++
   168  		n |= (int32(b) & 0x7F) << 14
   169  		if b < 128 {
   170  			return n, nil
   171  		}
   172  		b = in.buffer[in.bufferPosition]
   173  		in.bufferPosition++
   174  		n |= (int32(b) & 0x7F) << 21
   175  		if b < 128 {
   176  			return n, nil
   177  		}
   178  		b = in.buffer[in.bufferPosition]
   179  		in.bufferPosition++
   180  		// Warning: the next ands use 0x0F / 0xF0 - beware copy/paste errors:
   181  		n |= (int32(b) & 0x0F) << 28
   182  		if (b & 0xF0) == 0 {
   183  			return n, nil
   184  		}
   185  		return 0, errors.New("Invalid vInt detected (too many bits)")
   186  	}
   187  	return in.DataInputImpl.ReadVInt()
   188  }
   189  
   190  func (in *BufferedIndexInput) ReadVLong() (n int64, err error) {
   191  	if 9 <= in.bufferLength-in.bufferPosition {
   192  		b := in.buffer[in.bufferPosition]
   193  		in.bufferPosition++
   194  		if b < 128 {
   195  			return int64(b), nil
   196  		}
   197  		n := int64(b & 0x7F)
   198  		b = in.buffer[in.bufferPosition]
   199  		in.bufferPosition++
   200  		n |= (int64(b&0x7F) << 7)
   201  		if b < 128 {
   202  			return n, nil
   203  		}
   204  		b = in.buffer[in.bufferPosition]
   205  		in.bufferPosition++
   206  		n |= (int64(b&0x7F) << 14)
   207  		if b < 128 {
   208  			return n, nil
   209  		}
   210  		b = in.buffer[in.bufferPosition]
   211  		in.bufferPosition++
   212  		n |= (int64(b&0x7F) << 21)
   213  		if b < 128 {
   214  			return n, nil
   215  		}
   216  		b = in.buffer[in.bufferPosition]
   217  		in.bufferPosition++
   218  		n |= (int64(b&0x7F) << 28)
   219  		if b < 128 {
   220  			return n, nil
   221  		}
   222  		b = in.buffer[in.bufferPosition]
   223  		in.bufferPosition++
   224  		n |= (int64(b&0x7F) << 35)
   225  		if b < 128 {
   226  			return n, nil
   227  		}
   228  		b = in.buffer[in.bufferPosition]
   229  		in.bufferPosition++
   230  		n |= (int64(b&0x7F) << 42)
   231  		if b < 128 {
   232  			return n, nil
   233  		}
   234  		b = in.buffer[in.bufferPosition]
   235  		in.bufferPosition++
   236  		n |= (int64(b&0x7F) << 49)
   237  		if b < 128 {
   238  			return n, nil
   239  		}
   240  		b = in.buffer[in.bufferPosition]
   241  		in.bufferPosition++
   242  		n |= (int64(b&0x7F) << 56)
   243  		if b < 128 {
   244  			return n, nil
   245  		}
   246  		return 0, errors.New("Invalid vLong detected (negative values disallowed)")
   247  	}
   248  	return in.DataInputImpl.ReadVLong()
   249  }
   250  
   251  // use panic/recover to handle error
   252  func (in *BufferedIndexInput) refill() error {
   253  	start := in.bufferStart + int64(in.bufferPosition)
   254  	end := start + int64(in.bufferSize)
   255  	if n := in.spi.Length(); end > n { // don't read past EOF
   256  		end = n
   257  	}
   258  	newLength := int(end - start)
   259  	if newLength <= 0 {
   260  		return errors.New(fmt.Sprintf("read past EOF: %v", in))
   261  	}
   262  
   263  	if in.buffer == nil {
   264  		in.newBuffer(make([]byte, in.bufferSize)) // allocate buffer lazily
   265  		in.spi.seekInternal(int64(in.bufferStart))
   266  	}
   267  	in.spi.readInternal(in.buffer[0:newLength])
   268  	in.bufferLength = newLength
   269  	in.bufferStart = start
   270  	in.bufferPosition = 0
   271  	return nil
   272  }
   273  
   274  func (in *BufferedIndexInput) FilePointer() int64 {
   275  	return in.bufferStart + int64(in.bufferPosition)
   276  }
   277  
   278  func (in *BufferedIndexInput) Seek(pos int64) error {
   279  	if pos >= in.bufferStart && pos < in.bufferStart+int64(in.bufferLength) {
   280  		in.bufferPosition = int(pos - in.bufferStart) // seek within buffer
   281  		return nil
   282  	} else {
   283  		in.bufferStart = pos
   284  		in.bufferPosition = 0
   285  		in.bufferLength = 0 // trigger refill() on read()
   286  		return in.spi.seekInternal(pos)
   287  	}
   288  }
   289  
   290  func (in *BufferedIndexInput) Clone() *BufferedIndexInput {
   291  	ans := &BufferedIndexInput{
   292  		bufferSize:     in.bufferSize,
   293  		buffer:         nil,
   294  		bufferStart:    in.FilePointer(),
   295  		bufferLength:   0,
   296  		bufferPosition: 0,
   297  	}
   298  	ans.IndexInputImpl = NewIndexInputImpl(in.desc, ans)
   299  	return ans
   300  }
   301  
   302  func (in *BufferedIndexInput) Slice(desc string, offset, length int64) (IndexInput, error) {
   303  	panic("not implemented yet")
   304  }
   305  
   306  /* The default buffer size in bytes. */
   307  const DEFAULT_BUFFER_SIZE = 16384