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

     1  package util
     2  
     3  import (
     4  	"sort"
     5  )
     6  
     7  /*
     8  Abstract base class for performing write operations of Lucene's
     9  low-level data types.
    10  
    11  DataOutput may only be used from one thread, because it is not thread
    12  safe (it keeps internal state like file position).
    13  */
    14  type DataOutput interface {
    15  	DataWriter
    16  	WriteInt(i int32) error
    17  	WriteVInt(i int32) error
    18  	WriteLong(i int64) error
    19  	WriteVLong(i int64) error
    20  	WriteString(s string) error
    21  	CopyBytes(input DataInput, numBytes int64) error
    22  	WriteStringStringMap(m map[string]string) error
    23  	WriteStringSet(m map[string]bool) error
    24  }
    25  
    26  type DataWriter interface {
    27  	WriteByte(b byte) error
    28  	WriteBytes(buf []byte) error
    29  }
    30  
    31  type DataOutputImpl struct {
    32  	Writer     DataWriter
    33  	copyBuffer []byte
    34  }
    35  
    36  func NewDataOutput(part DataWriter) *DataOutputImpl {
    37  	assert(part != nil)
    38  	return &DataOutputImpl{Writer: part}
    39  }
    40  
    41  /*
    42  Writes an int as four bytes.
    43  
    44  32-bit unsigned integer written as four bytes, high-order bytes first.
    45  */
    46  func (out *DataOutputImpl) WriteInt(i int32) error {
    47  	assert(out.Writer != nil)
    48  	err := out.Writer.WriteByte(byte(i >> 24))
    49  	if err == nil {
    50  		err = out.Writer.WriteByte(byte(i >> 16))
    51  		if err == nil {
    52  			err = out.Writer.WriteByte(byte(i >> 8))
    53  			if err == nil {
    54  				err = out.Writer.WriteByte(byte(i))
    55  			}
    56  		}
    57  	}
    58  	return err
    59  }
    60  
    61  /*
    62  Writes an int in a variable-length format. Writes between one and
    63  five bytes. Smaller values take fewer bytes. Negative numbers are
    64  supported, by should be avoided.
    65  
    66  VByte is a variable-length format. For positive integers, it is
    67  defined where the high-order bit of each byte indicates whether more
    68  bytes remain to be read. The low-order seven bits are appended as
    69  increasingly more significant bits in the resulting integer value.
    70  Thus values from zero to 127 may be stored in a single byte, values
    71  from 128 to 16,383 may be stored in two bytes, and so on.
    72  
    73  VByte Encoding Examle
    74  
    75  	| Value		| Byte 1		| Byte 2		| Byte 3		|
    76  	| 0				| 00000000	|
    77  	| 1				| 00000001	|
    78  	| 2				| 00000010	|
    79  	| ...			|
    80  	| 127			| 01111111	|
    81  	| 128			| 10000000	| 00000001	|
    82  	| 129			| 10000001	| 00000001	|
    83  	| 130			| 10000010	| 00000001	|
    84  	| ...			|
    85  	| 16,383	| 11111111	| 01111111	|
    86  	| 16,384	| 10000000	| 10000000	| 00000001	|
    87  	| 16,385	| 10000001	| 10000000	| 00000001	|
    88  	| ...			|
    89  
    90  This provides compression while still being efficient to decode.
    91  */
    92  func (out *DataOutputImpl) WriteVInt(i int32) error {
    93  	for (i & ^0x7F) != 0 {
    94  		err := out.Writer.WriteByte(byte(i&0x7F) | 0x80)
    95  		if err != nil {
    96  			return err
    97  		}
    98  		i = int32(uint32(i) >> 7)
    99  	}
   100  	return out.Writer.WriteByte(byte(i))
   101  }
   102  
   103  /*
   104  Writes a long as eight bytes.
   105  
   106  64-bit unsigned integer written as eight bytes, high-order bytes first.
   107  */
   108  func (out *DataOutputImpl) WriteLong(i int64) error {
   109  	err := out.WriteInt(int32(i >> 32))
   110  	if err == nil {
   111  		err = out.WriteInt(int32(i))
   112  	}
   113  	return err
   114  }
   115  
   116  /*
   117  Writes an long in a variable-length format. Writes between one and
   118  none bytes. Smaller values take fewer bytes. Negative number are not
   119  supported.
   120  
   121  The format is described further in WriteVInt().
   122  */
   123  func (out *DataOutputImpl) WriteVLong(i int64) error {
   124  	assert(i >= 0)
   125  	return out.writeNegativeVLong(i)
   126  }
   127  
   128  /* write a potentially negative gLong */
   129  func (out *DataOutputImpl) writeNegativeVLong(i int64) error {
   130  	for (i & ^0x7F) != 0 {
   131  		err := out.Writer.WriteByte(byte((i & 0x7F) | 0x80))
   132  		if err != nil {
   133  			return err
   134  		}
   135  		i = int64(uint64(i) >> 7)
   136  	}
   137  	return out.Writer.WriteByte(byte(i))
   138  }
   139  
   140  /*
   141  Writes a string.
   142  
   143  Writes strings as UTF-8 encoded bytes. First the length, in bytes, is
   144  written as a VInt, followed by the bytes.
   145  */
   146  func (out *DataOutputImpl) WriteString(s string) error {
   147  	bytes := []byte(s)
   148  	err := out.WriteVInt(int32(len(bytes)))
   149  	if err == nil {
   150  		err = out.Writer.WriteBytes(bytes)
   151  	}
   152  	return err
   153  }
   154  
   155  const DATA_OUTPUT_COPY_BUFFER_SIZE = 16384
   156  
   157  func (out *DataOutputImpl) CopyBytes(input DataInput, numBytes int64) error {
   158  	assert(numBytes >= 0)
   159  	left := numBytes
   160  	if out.copyBuffer == nil {
   161  		out.copyBuffer = make([]byte, DATA_OUTPUT_COPY_BUFFER_SIZE)
   162  	}
   163  	for left > 0 {
   164  		var toCopy int32
   165  		if left > DATA_OUTPUT_COPY_BUFFER_SIZE {
   166  			toCopy = DATA_OUTPUT_COPY_BUFFER_SIZE
   167  		} else {
   168  			toCopy = int32(left)
   169  		}
   170  		err := input.ReadBytes(out.copyBuffer[0:toCopy])
   171  		if err != nil {
   172  			return err
   173  		}
   174  		err = out.Writer.WriteBytes(out.copyBuffer[0:toCopy])
   175  		if err != nil {
   176  			return err
   177  		}
   178  		left -= int64(toCopy)
   179  	}
   180  	return nil
   181  }
   182  
   183  /*
   184  Writes a string map.
   185  
   186  First the size is written as an int32, followed by each key-value
   187  pair written as two consecutive strings.
   188  */
   189  func (out *DataOutputImpl) WriteStringStringMap(m map[string]string) error {
   190  	if m == nil {
   191  		return out.WriteInt(0)
   192  	}
   193  	err := out.WriteInt(int32(len(m)))
   194  	if err != nil {
   195  		return err
   196  	}
   197  	// enforce key order during serialization
   198  	var keys []string
   199  	for k, _ := range m {
   200  		keys = append(keys, k)
   201  	}
   202  	sort.Strings(keys)
   203  	for _, k := range keys {
   204  		v := m[k]
   205  		// for k, v := range m {
   206  		err = out.WriteString(k)
   207  		if err == nil {
   208  			err = out.WriteString(v)
   209  		}
   210  		if err != nil {
   211  			return err
   212  		}
   213  	}
   214  	return nil
   215  }
   216  
   217  /*
   218  Writes a String set.
   219  
   220  First the size is written as an int32, followed by each value written
   221  as a string.
   222  */
   223  func (out *DataOutputImpl) WriteStringSet(m map[string]bool) error {
   224  	if m == nil {
   225  		return out.WriteInt(0)
   226  	}
   227  	err := out.WriteInt(int32(len(m)))
   228  	if err != nil {
   229  		return err
   230  	}
   231  	for value, _ := range m {
   232  		err = out.WriteString(value)
   233  		if err != nil {
   234  			return err
   235  		}
   236  	}
   237  	return nil
   238  }