optimiseDataModes optimises the list of segments to reduce the overall output encoded data length. The algorithm coalesces adjacent segments. segments are only coalesced when the Data Modes are compatible, and when the coalesced segment has a shorter encoded length than separate segments. Multiple
()
| 263 | // Multiple segments may be coalesced. For example a string of alternating |
| 264 | // alphanumeric/numeric segments ANANANANA can be optimised to just A. |
| 265 | func (d *dataEncoder) optimiseDataModes() error { |
| 266 | for i := 0; i < len(d.actual); { |
| 267 | mode := d.actual[i].dataMode |
| 268 | numChars := len(d.actual[i].data) |
| 269 | |
| 270 | j := i + 1 |
| 271 | for j < len(d.actual) { |
| 272 | nextNumChars := len(d.actual[j].data) |
| 273 | nextMode := d.actual[j].dataMode |
| 274 | |
| 275 | if nextMode > mode { |
| 276 | break |
| 277 | } |
| 278 | |
| 279 | coalescedLength, err := d.encodedLength(mode, numChars+nextNumChars) |
| 280 | |
| 281 | if err != nil { |
| 282 | return err |
| 283 | } |
| 284 | |
| 285 | seperateLength1, err := d.encodedLength(mode, numChars) |
| 286 | |
| 287 | if err != nil { |
| 288 | return err |
| 289 | } |
| 290 | |
| 291 | seperateLength2, err := d.encodedLength(nextMode, nextNumChars) |
| 292 | |
| 293 | if err != nil { |
| 294 | return err |
| 295 | } |
| 296 | |
| 297 | if coalescedLength < seperateLength1+seperateLength2 { |
| 298 | j++ |
| 299 | numChars += nextNumChars |
| 300 | } else { |
| 301 | break |
| 302 | } |
| 303 | } |
| 304 | |
| 305 | optimised := segment{dataMode: mode, |
| 306 | data: make([]byte, 0, numChars)} |
| 307 | |
| 308 | for k := i; k < j; k++ { |
| 309 | optimised.data = append(optimised.data, d.actual[k].data...) |
| 310 | } |
| 311 | |
| 312 | d.optimised = append(d.optimised, optimised) |
| 313 | |
| 314 | i = j |
| 315 | } |
| 316 | |
| 317 | return nil |
| 318 | } |
| 319 | |
| 320 | // encodeDataRaw encodes data in dataMode. The encoded data is appended to |
| 321 | // encoded. |