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 }