mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2024-12-29 07:07:16 +00:00
222bb666e9
``` ➜ erigon-lib git:(fieldalign) ✗ fieldalignment -fix ./... /Users/estensen/Developer/erigon-lib/commitment/bin_patricia_hashed.go:81:16: struct of size 1065120 could be 1065112 /Users/estensen/Developer/erigon-lib/commitment/bin_patricia_hashed.go:1063:14: struct of size 1032 could be 1024 /Users/estensen/Developer/erigon-lib/commitment/hex_patricia_hashed.go:62:24: struct of size 952776 could be 952768 /Users/estensen/Developer/erigon-lib/commitment/hex_patricia_hashed.go:98:12: struct of size 1832 could be 1824 /Users/estensen/Developer/erigon-lib/commitment/hex_patricia_hashed.go:113:12: struct with 208 pointer bytes could be 152 /Users/estensen/Developer/erigon-lib/commitment/hex_patricia_hashed.go:143:11: struct of size 464 could be 456 /Users/estensen/Developer/erigon-lib/gointerfaces/types/types.pb.go:24:11: struct with 24 pointer bytes could be 16 /Users/estensen/Developer/erigon-lib/gointerfaces/types/types.pb.go:79:11: struct of size 56 could be 48 /Users/estensen/Developer/erigon-lib/gointerfaces/types/types.pb.go:134:11: struct with 56 pointer bytes could be 32 /Users/estensen/Developer/erigon-lib/gointerfaces/types/types.pb.go:189:11: struct with 56 pointer bytes could be 32 /Users/estensen/Developer/erigon-lib/gointerfaces/types/types.pb.go:244:12: struct with 56 pointer bytes could be 32 /Users/estensen/Developer/erigon-lib/gointerfaces/types/types.pb.go:299:12: struct with 56 pointer bytes could be 32 /Users/estensen/Developer/erigon-lib/gointerfaces/types/types.pb.go:355:19: struct of size 56 could be 48 /Users/estensen/Developer/erigon-lib/gointerfaces/types/types.pb.go:418:23: struct with 168 pointer bytes could be 128 /Users/estensen/Developer/erigon-lib/gointerfaces/types/types.pb.go:571:20: struct with 24 pointer bytes could be 16 /Users/estensen/Developer/erigon-lib/gointerfaces/types/types.pb.go:626:20: struct with 136 pointer bytes could be 128 /Users/estensen/Developer/erigon-lib/gointerfaces/types/types.pb.go:721:15: struct of size 168 could be 160 /Users/estensen/Developer/erigon-lib/etl/buffers.go:75:21: struct with 88 pointer bytes could be 64 /Users/estensen/Developer/erigon-lib/etl/buffers.go:182:27: struct with 56 pointer bytes could be 24 /Users/estensen/Developer/erigon-lib/etl/buffers.go:274:32: struct with 56 pointer bytes could be 24 /Users/estensen/Developer/erigon-lib/etl/collector.go:41:16: struct with 72 pointer bytes could be 40 /Users/estensen/Developer/erigon-lib/etl/etl.go:66:20: struct with 96 pointer bytes could be 64 /Users/estensen/Developer/erigon-lib/etl/heap.go:25:15: struct with 40 pointer bytes could be 32 /Users/estensen/Developer/erigon-lib/patricia/patricia.go:29:11: struct with 40 pointer bytes could be 32 /Users/estensen/Developer/erigon-lib/patricia/patricia.go:347:12: struct with 32 pointer bytes could be 16 /Users/estensen/Developer/erigon-lib/patricia/patricia.go:367:18: struct with 48 pointer bytes could be 32 /Users/estensen/Developer/erigon-lib/patricia/patricia.go:377:19: struct with 168 pointer bytes could be 144 /Users/estensen/Developer/erigon-lib/compress/compress.go:52:17: struct with 176 pointer bytes could be 136 /Users/estensen/Developer/erigon-lib/compress/compress.go:241:24: struct with 48 pointer bytes could be 32 /Users/estensen/Developer/erigon-lib/compress/compress.go:327:14: struct with 40 pointer bytes could be 8 /Users/estensen/Developer/erigon-lib/compress/compress.go:353:18: struct with 48 pointer bytes could be 32 /Users/estensen/Developer/erigon-lib/compress/compress.go:450:19: struct with 48 pointer bytes could be 32 /Users/estensen/Developer/erigon-lib/compress/compress.go:670:21: struct with 48 pointer bytes could be 24 /Users/estensen/Developer/erigon-lib/compress/compress.go:734:23: struct with 48 pointer bytes could be 40 /Users/estensen/Developer/erigon-lib/compress/decompress.go:31:15: struct with 32 pointer bytes could be 24 /Users/estensen/Developer/erigon-lib/compress/decompress.go:39:19: struct with 40 pointer bytes could be 16 /Users/estensen/Developer/erigon-lib/compress/decompress.go:117:15: struct with 64 pointer bytes could be 56 /Users/estensen/Developer/erigon-lib/compress/decompress.go:125:19: struct with 96 pointer bytes could be 80 /Users/estensen/Developer/erigon-lib/compress/decompress.go:386:13: struct with 64 pointer bytes could be 40 /Users/estensen/Developer/erigon-lib/compress/parallel_compress.go:208:22: struct with 16 pointer bytes could be 8 /Users/estensen/Developer/erigon-lib/recsplit/golomb_rice.go:32:17: struct with 16 pointer bytes could be 8 /Users/estensen/Developer/erigon-lib/recsplit/index.go:35:12: struct of size 432 could be 424 /Users/estensen/Developer/erigon-lib/recsplit/index_reader.go:26:18: struct with 48 pointer bytes could be 24 /Users/estensen/Developer/erigon-lib/recsplit/recsplit.go:64:15: struct of size 704 could be 680 /Users/estensen/Developer/erigon-lib/recsplit/recsplit.go:111:19: struct of size 104 could be 96 /Users/estensen/Developer/erigon-lib/aggregator/aggregator.go:171:17: struct of size 640 could be 632 /Users/estensen/Developer/erigon-lib/aggregator/aggregator.go:198:17: struct with 168 pointer bytes could be 144 /Users/estensen/Developer/erigon-lib/aggregator/aggregator.go:389:14: struct with 584 pointer bytes could be 568 /Users/estensen/Developer/erigon-lib/aggregator/aggregator.go:921:21: struct with 72 pointer bytes could be 56 /Users/estensen/Developer/erigon-lib/aggregator/aggregator.go:1195:22: struct with 2432 pointer bytes could be 2416 /Users/estensen/Developer/erigon-lib/aggregator/aggregator.go:2123:13: struct with 2448 pointer bytes could be 2416 /Users/estensen/Developer/erigon-lib/aggregator/aggregator.go:2634:17: struct with 96 pointer bytes could be 64 /Users/estensen/Developer/erigon-lib/aggregator/history.go:39:14: struct with 96 pointer bytes could be 88 /Users/estensen/Developer/erigon-lib/bptree/binary_file.go:33:17: struct with 40 pointer bytes could be 16 /Users/estensen/Developer/erigon-lib/bptree/node.go:79:13: struct of size 88 could be 80 /Users/estensen/Developer/erigon-lib/chain/chain_config.go:28:13: struct with 136 pointer bytes could be 120 /Users/estensen/Developer/erigon-lib/common/background/progress.go:26:18: struct with 40 pointer bytes could be 8 /Users/estensen/Developer/erigon-lib/gointerfaces/downloader/downloader.pb.go:25:19: struct with 64 pointer bytes could be 40 /Users/estensen/Developer/erigon-lib/gointerfaces/downloader/downloader.pb.go:80:22: struct with 48 pointer bytes could be 40 /Users/estensen/Developer/erigon-lib/gointerfaces/downloader/downloader.pb.go:127:20: struct with 24 pointer bytes could be 16 /Users/estensen/Developer/erigon-lib/gointerfaces/downloader/downloader.pb.go:165:19: struct with 24 pointer bytes could be 16 /Users/estensen/Developer/erigon-lib/gointerfaces/downloader/downloader.pb.go:203:17: struct of size 104 could be 96 /Users/estensen/Developer/erigon-lib/gointerfaces/remote/ethbackend.pb.go:135:23: struct with 24 pointer bytes could be 16 /Users/estensen/Developer/erigon-lib/gointerfaces/remote/ethbackend.pb.go:173:21: struct with 48 pointer bytes could be 24 /Users/estensen/Developer/erigon-lib/gointerfaces/remote/ethbackend.pb.go:220:24: struct with 24 pointer bytes could be 16 /Users/estensen/Developer/erigon-lib/gointerfaces/remote/ethbackend.pb.go:258:22: struct with 24 pointer bytes could be 16 /Users/estensen/Developer/erigon-lib/gointerfaces/remote/ethbackend.pb.go:305:26: struct with 24 pointer bytes could be 16 /Users/estensen/Developer/erigon-lib/gointerfaces/remote/ethbackend.pb.go:343:24: struct with 24 pointer bytes could be 16 /Users/estensen/Developer/erigon-lib/gointerfaces/remote/ethbackend.pb.go:390:30: struct with 24 pointer bytes could be 16 /Users/estensen/Developer/erigon-lib/gointerfaces/remote/ethbackend.pb.go:437:26: struct of size 72 could be 64 /Users/estensen/Developer/erigon-lib/gointerfaces/remote/ethbackend.pb.go:500:30: struct with 64 pointer bytes could be 32 /Users/estensen/Developer/erigon-lib/gointerfaces/remote/ethbackend.pb.go:563:28: struct with 64 pointer bytes could be 40 /Users/estensen/Developer/erigon-lib/gointerfaces/remote/ethbackend.pb.go:626:37: struct with 56 pointer bytes could be 32 /Users/estensen/Developer/erigon-lib/gointerfaces/remote/ethbackend.pb.go:681:35: struct with 48 pointer bytes could be 24 /Users/estensen/Developer/erigon-lib/gointerfaces/remote/ethbackend.pb.go:736:29: struct with 24 pointer bytes could be 16 /Users/estensen/Developer/erigon-lib/gointerfaces/remote/ethbackend.pb.go:774:27: struct with 24 pointer bytes could be 16 /Users/estensen/Developer/erigon-lib/gointerfaces/remote/ethbackend.pb.go:821:27: struct with 24 pointer bytes could be 16 /Users/estensen/Developer/erigon-lib/gointerfaces/remote/ethbackend.pb.go:859:25: struct with 48 pointer bytes could be 32 /Users/estensen/Developer/erigon-lib/gointerfaces/remote/ethbackend.pb.go:906:23: struct of size 48 could be 40 /Users/estensen/Developer/erigon-lib/gointerfaces/remote/ethbackend.pb.go:953:21: struct of size 72 could be 64 /Users/estensen/Developer/erigon-lib/gointerfaces/remote/ethbackend.pb.go:1008:24: struct of size 104 could be 88 /Users/estensen/Developer/erigon-lib/gointerfaces/remote/ethbackend.pb.go:1079:25: struct of size 144 could be 136 /Users/estensen/Developer/erigon-lib/gointerfaces/remote/ethbackend.pb.go:1190:19: struct with 56 pointer bytes could be 24 /Users/estensen/Developer/erigon-lib/gointerfaces/remote/ethbackend.pb.go:1245:17: struct with 72 pointer bytes could be 64 /Users/estensen/Developer/erigon-lib/gointerfaces/remote/ethbackend.pb.go:1300:23: struct with 48 pointer bytes could be 24 /Users/estensen/Developer/erigon-lib/gointerfaces/remote/ethbackend.pb.go:1347:21: struct with 24 pointer bytes could be 16 /Users/estensen/Developer/erigon-lib/gointerfaces/remote/ethbackend.pb.go:1394:23: struct of size 48 could be 40 /Users/estensen/Developer/erigon-lib/gointerfaces/remote/ethbackend.pb.go:1441:21: struct with 48 pointer bytes could be 40 /Users/estensen/Developer/erigon-lib/gointerfaces/remote/ethbackend.pb.go:1488:17: struct with 48 pointer bytes could be 40 /Users/estensen/Developer/erigon-lib/gointerfaces/remote/ethbackend.pb.go:1535:24: struct with 48 pointer bytes could be 40 /Users/estensen/Developer/erigon-lib/gointerfaces/remote/kv.pb.go:220:13: struct of size 120 could be 112 /Users/estensen/Developer/erigon-lib/gointerfaces/remote/kv.pb.go:299:11: struct of size 104 could be 96 /Users/estensen/Developer/erigon-lib/gointerfaces/remote/kv.pb.go:370:20: struct with 56 pointer bytes could be 48 /Users/estensen/Developer/erigon-lib/gointerfaces/remote/kv.pb.go:425:20: struct of size 136 could be 128 /Users/estensen/Developer/erigon-lib/gointerfaces/remote/kv.pb.go:513:23: struct with 56 pointer bytes could be 40 /Users/estensen/Developer/erigon-lib/gointerfaces/remote/kv.pb.go:585:18: struct of size 112 could be 104 /Users/estensen/Developer/erigon-lib/gointerfaces/remote/kv.pb.go:664:25: struct of size 48 could be 40 /Users/estensen/Developer/erigon-lib/gointerfaces/remote/kv.pb.go:719:23: struct with 24 pointer bytes could be 16 /Users/estensen/Developer/erigon-lib/gointerfaces/remote/kv.pb.go:757:21: struct with 72 pointer bytes could be 64 /Users/estensen/Developer/erigon-lib/gointerfaces/sentry/sentry.pb.go:300:26: struct of size 72 could be 64 /Users/estensen/Developer/erigon-lib/gointerfaces/sentry/sentry.pb.go:355:35: struct with 48 pointer bytes could be 24 /Users/estensen/Developer/erigon-lib/gointerfaces/sentry/sentry.pb.go:410:29: struct with 56 pointer bytes could be 32 /Users/estensen/Developer/erigon-lib/gointerfaces/sentry/sentry.pb.go:465:38: struct with 48 pointer bytes could be 24 /Users/estensen/Developer/erigon-lib/gointerfaces/sentry/sentry.pb.go:520:16: struct with 48 pointer bytes could be 40 /Users/estensen/Developer/erigon-lib/gointerfaces/sentry/sentry.pb.go:567:26: struct of size 56 could be 48 /Users/estensen/Developer/erigon-lib/gointerfaces/sentry/sentry.pb.go:622:26: struct with 48 pointer bytes could be 24 /Users/estensen/Developer/erigon-lib/gointerfaces/sentry/sentry.pb.go:677:21: struct of size 80 could be 72 /Users/estensen/Developer/erigon-lib/gointerfaces/sentry/sentry.pb.go:740:12: struct with 56 pointer bytes could be 48 /Users/estensen/Developer/erigon-lib/gointerfaces/sentry/sentry.pb.go:795:17: struct with 72 pointer bytes could be 40 /Users/estensen/Developer/erigon-lib/gointerfaces/sentry/sentry.pb.go:874:21: struct with 24 pointer bytes could be 16 /Users/estensen/Developer/erigon-lib/gointerfaces/sentry/sentry.pb.go:912:21: struct of size 48 could be 40 /Users/estensen/Developer/erigon-lib/gointerfaces/sentry/sentry.pb.go:959:22: struct with 48 pointer bytes could be 40 /Users/estensen/Developer/erigon-lib/gointerfaces/sentry/sentry.pb.go:1006:17: struct with 48 pointer bytes could be 40 /Users/estensen/Developer/erigon-lib/gointerfaces/sentry/sentry.pb.go:1053:23: struct with 24 pointer bytes could be 16 /Users/estensen/Developer/erigon-lib/gointerfaces/sentry/sentry.pb.go:1091:21: struct with 24 pointer bytes could be 16 /Users/estensen/Developer/erigon-lib/gointerfaces/sentry/sentry.pb.go:1138:22: struct with 48 pointer bytes could be 24 /Users/estensen/Developer/erigon-lib/gointerfaces/sentry/sentry.pb.go:1185:20: struct with 48 pointer bytes could be 24 /Users/estensen/Developer/erigon-lib/gointerfaces/sentry/sentry.pb.go:1232:24: struct with 24 pointer bytes could be 16 /Users/estensen/Developer/erigon-lib/gointerfaces/sentry/sentry.pb.go:1270:16: struct of size 56 could be 48 /Users/estensen/Developer/erigon-lib/gointerfaces/txpool/mining.pb.go:25:28: struct with 24 pointer bytes could be 16 /Users/estensen/Developer/erigon-lib/gointerfaces/txpool/mining.pb.go:63:26: struct with 48 pointer bytes could be 40 /Users/estensen/Developer/erigon-lib/gointerfaces/txpool/mining.pb.go:110:26: struct with 24 pointer bytes could be 16 /Users/estensen/Developer/erigon-lib/gointerfaces/txpool/mining.pb.go:148:24: struct with 48 pointer bytes could be 40 /Users/estensen/Developer/erigon-lib/gointerfaces/txpool/mining.pb.go:195:27: struct with 24 pointer bytes could be 16 /Users/estensen/Developer/erigon-lib/gointerfaces/txpool/mining.pb.go:233:25: struct with 48 pointer bytes could be 40 /Users/estensen/Developer/erigon-lib/gointerfaces/txpool/mining.pb.go:280:21: struct with 24 pointer bytes could be 16 /Users/estensen/Developer/erigon-lib/gointerfaces/txpool/mining.pb.go:318:19: struct with 96 pointer bytes could be 80 /Users/estensen/Developer/erigon-lib/gointerfaces/txpool/mining.pb.go:389:24: struct with 96 pointer bytes could be 88 /Users/estensen/Developer/erigon-lib/gointerfaces/txpool/mining.pb.go:452:22: struct of size 48 could be 40 /Users/estensen/Developer/erigon-lib/gointerfaces/txpool/mining.pb.go:499:28: struct with 56 pointer bytes could be 40 /Users/estensen/Developer/erigon-lib/gointerfaces/txpool/mining.pb.go:554:26: struct of size 48 could be 40 /Users/estensen/Developer/erigon-lib/gointerfaces/txpool/mining.pb.go:601:22: struct with 24 pointer bytes could be 16 /Users/estensen/Developer/erigon-lib/gointerfaces/txpool/mining.pb.go:639:20: struct with 24 pointer bytes could be 16 /Users/estensen/Developer/erigon-lib/gointerfaces/txpool/mining.pb.go:686:20: struct with 24 pointer bytes could be 16 /Users/estensen/Developer/erigon-lib/gointerfaces/txpool/mining.pb.go:724:18: struct of size 48 could be 40 /Users/estensen/Developer/erigon-lib/gointerfaces/txpool/txpool.pb.go:132:15: struct with 48 pointer bytes could be 40 /Users/estensen/Developer/erigon-lib/gointerfaces/txpool/txpool.pb.go:179:17: struct with 48 pointer bytes could be 40 /Users/estensen/Developer/erigon-lib/gointerfaces/txpool/txpool.pb.go:226:15: struct with 72 pointer bytes could be 64 /Users/estensen/Developer/erigon-lib/gointerfaces/txpool/txpool.pb.go:281:26: struct with 48 pointer bytes could be 40 /Users/estensen/Developer/erigon-lib/gointerfaces/txpool/txpool.pb.go:328:24: struct with 48 pointer bytes could be 40 /Users/estensen/Developer/erigon-lib/gointerfaces/txpool/txpool.pb.go:375:19: struct with 24 pointer bytes could be 16 /Users/estensen/Developer/erigon-lib/gointerfaces/txpool/txpool.pb.go:413:17: struct with 48 pointer bytes could be 40 /Users/estensen/Developer/erigon-lib/gointerfaces/txpool/txpool.pb.go:460:17: struct with 24 pointer bytes could be 16 /Users/estensen/Developer/erigon-lib/gointerfaces/txpool/txpool.pb.go:498:15: struct with 48 pointer bytes could be 40 /Users/estensen/Developer/erigon-lib/gointerfaces/txpool/txpool.pb.go:545:19: struct with 48 pointer bytes could be 40 /Users/estensen/Developer/erigon-lib/gointerfaces/txpool/txpool.pb.go:592:20: struct with 24 pointer bytes could be 16 /Users/estensen/Developer/erigon-lib/gointerfaces/txpool/txpool.pb.go:630:18: struct of size 56 could be 48 /Users/estensen/Developer/erigon-lib/gointerfaces/txpool/txpool.pb.go:693:19: struct with 48 pointer bytes could be 24 /Users/estensen/Developer/erigon-lib/gointerfaces/txpool/txpool.pb.go:740:17: struct of size 56 could be 48 /Users/estensen/Developer/erigon-lib/gointerfaces/txpool/txpool.pb.go:795:18: struct of size 80 could be 72 /Users/estensen/Developer/erigon-lib/gointerfaces/txpool/txpool.pb.go:858:22: struct of size 80 could be 72 /Users/estensen/Developer/erigon-lib/direct/sentry_client.go:171:25: struct with 24 pointer bytes could be 16 /Users/estensen/Developer/erigon-lib/kv/mdbx/kv_mdbx.go:50:15: struct with 104 pointer bytes could be 40 /Users/estensen/Developer/erigon-lib/kv/mdbx/kv_mdbx.go:355:13: struct with 160 pointer bytes could be 152 /Users/estensen/Developer/erigon-lib/kv/memdb/memory_mutation_cursor.go:39:27: struct with 200 pointer bytes could be 184 /Users/estensen/Developer/erigon-lib/kv/remotedb/kv_remote.go:22:17: struct with 72 pointer bytes could be 48 /Users/estensen/Developer/erigon-lib/kv/remotedb/kv_remote.go:38:15: struct with 80 pointer bytes could be 64 /Users/estensen/Developer/erigon-lib/kv/remotedbserver/server.go:314:24: struct with 40 pointer bytes could be 8 /Users/estensen/Developer/erigon-lib/state/aggregator.go:44:17: struct with 192 pointer bytes could be 128 /Users/estensen/Developer/erigon-lib/state/aggregator.go:422:13: struct of size 384 could be 360 /Users/estensen/Developer/erigon-lib/state/aggregator.go:455:26: struct with 424 pointer bytes could be 368 /Users/estensen/Developer/erigon-lib/state/aggregator.go:853:22: struct with 24 pointer bytes could be 8 /Users/estensen/Developer/erigon-lib/state/aggregator22.go:37:19: struct with 176 pointer bytes could be 136 /Users/estensen/Developer/erigon-lib/state/aggregator22.go:643:15: struct of size 240 could be 216 /Users/estensen/Developer/erigon-lib/state/aggregator22.go:674:28: struct with 272 pointer bytes could be 224 /Users/estensen/Developer/erigon-lib/state/aggregator22.go:1126:26: struct with 104 pointer bytes could be 88 /Users/estensen/Developer/erigon-lib/state/aggregator22.go:1156:23: struct with 24 pointer bytes could be 16 /Users/estensen/Developer/erigon-lib/state/domain.go:52:16: struct with 32 pointer bytes could be 16 /Users/estensen/Developer/erigon-lib/state/domain.go:89:13: struct with 120 pointer bytes could be 48 /Users/estensen/Developer/erigon-lib/state/domain.go:399:17: struct with 96 pointer bytes could be 64 /Users/estensen/Developer/erigon-lib/state/domain.go:443:14: struct with 32 pointer bytes could be 16 /Users/estensen/Developer/erigon-lib/state/domain.go:594:16: struct with 72 pointer bytes could be 48 /Users/estensen/Developer/erigon-lib/state/history.go:48:14: struct with 72 pointer bytes could be 48 /Users/estensen/Developer/erigon-lib/state/history.go:435:20: struct with 48 pointer bytes could be 32 /Users/estensen/Developer/erigon-lib/state/history.go:529:23: struct with 40 pointer bytes could be 24 /Users/estensen/Developer/erigon-lib/state/history.go:1150:23: struct of size 344 could be 336 /Users/estensen/Developer/erigon-lib/state/inverted_index.go:46:20: struct with 128 pointer bytes could be 88 /Users/estensen/Developer/erigon-lib/state/inverted_index.go:389:23: struct with 136 pointer bytes could be 88 /Users/estensen/Developer/erigon-lib/state/inverted_index.go:541:24: struct with 184 pointer bytes could be 152 /Users/estensen/Developer/erigon-lib/state/merge.go:69:19: struct of size 72 could be 56 /Users/estensen/Developer/erigon-lib/state/merge.go:143:20: struct of size 48 could be 40 /Users/estensen/Developer/erigon-lib/state/read_indices.go:29:18: struct with 64 pointer bytes could be 48 /Users/estensen/Developer/erigon-lib/state/read_indices.go:211:14: struct of size 72 could be 56 /Users/estensen/Developer/erigon-lib/state/read_indices.go:233:27: struct with 72 pointer bytes could be 56 /Users/estensen/Developer/erigon-lib/state/state_recon.go:61:16: struct with 56 pointer bytes could be 16 /Users/estensen/Developer/erigon-lib/state/state_recon.go:112:19: struct with 136 pointer bytes could be 112 /Users/estensen/Developer/erigon-lib/state/state_recon.go:190:22: struct with 128 pointer bytes could be 112 /Users/estensen/Developer/erigon-lib/types/testdata.go:81:26: struct with 40 pointer bytes could be 8 /Users/estensen/Developer/erigon-lib/types/txn.go:46:21: struct with 400 pointer bytes could be 40 /Users/estensen/Developer/erigon-lib/types/txn.go:82:13: struct with 200 pointer bytes could be 8 /Users/estensen/Developer/erigon-lib/types/txn.go:691:18: struct with 32 pointer bytes could be 8 /Users/estensen/Developer/erigon-lib/txpool/fetch.go:43:12: struct with 136 pointer bytes could be 112 /Users/estensen/Developer/erigon-lib/txpool/pool.go:69:13: struct with 104 pointer bytes could be 24 /Users/estensen/Developer/erigon-lib/txpool/pool.go:221:13: struct of size 104 could be 96 /Users/estensen/Developer/erigon-lib/txpool/pool.go:291:13: struct with 336 pointer bytes could be 288 /Users/estensen/Developer/erigon-lib/txpool/pool.go:1789:29: struct with 32 pointer bytes could be 8 /Users/estensen/Developer/erigon-lib/txpool/pool.go:1819:19: struct with 32 pointer bytes could be 24 /Users/estensen/Developer/erigon-lib/txpool/pool.go:1994:18: struct of size 64 could be 56 /Users/estensen/Developer/erigon-lib/txpool/pool.go:2102:14: struct of size 64 could be 56 /Users/estensen/Developer/erigon-lib/txpool/send.go:37:11: struct with 64 pointer bytes could be 48 /Users/estensen/Developer/erigon-lib/txpool/test_util.go:31:17: struct with 72 pointer bytes could be 40 ```
806 lines
22 KiB
Go
806 lines
22 KiB
Go
/*
|
|
Copyright 2022 Erigon contributors
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package compress
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/ledgerwatch/erigon-lib/common/dbg"
|
|
"github.com/ledgerwatch/erigon-lib/mmap"
|
|
)
|
|
|
|
type word []byte // plain text word associated with code from dictionary
|
|
|
|
type codeword struct {
|
|
pattern *word // Pattern corresponding to entries
|
|
ptr *patternTable // pointer to deeper level tables
|
|
next *codeword // points to next word in condensed table
|
|
code uint16 // code associated with that word
|
|
len byte // Number of bits in the codes
|
|
}
|
|
|
|
type patternTable struct {
|
|
head *codeword
|
|
patterns []*codeword
|
|
bitLen int // Number of bits to lookup in the table
|
|
}
|
|
|
|
func newPatternTable(bitLen int) *patternTable {
|
|
pt := &patternTable{
|
|
bitLen: bitLen,
|
|
}
|
|
if bitLen <= condensePatternTableBitThreshold {
|
|
pt.patterns = make([]*codeword, 1<<pt.bitLen)
|
|
}
|
|
return pt
|
|
}
|
|
|
|
func (pt *patternTable) insertWord(cw *codeword) {
|
|
if pt.bitLen <= condensePatternTableBitThreshold {
|
|
codeStep := uint16(1) << uint16(cw.len)
|
|
codeFrom, codeTo := cw.code, cw.code+codeStep
|
|
if pt.bitLen != int(cw.len) && cw.len > 0 {
|
|
codeTo = codeFrom | (uint16(1) << pt.bitLen)
|
|
}
|
|
|
|
// cw := &codeword{code: codeFrom, pattern: &pattern, len: byte(bits), ptr: nil}
|
|
for c := codeFrom; c < codeTo; c += codeStep {
|
|
if p := pt.patterns[c]; p == nil {
|
|
pt.patterns[c] = cw
|
|
} else {
|
|
p.pattern, p.len, p.ptr, p.code = cw.pattern, cw.len, nil, c
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
if pt.head == nil {
|
|
cw.next = nil
|
|
pt.head = cw
|
|
return
|
|
}
|
|
|
|
var prev *codeword
|
|
for cur := pt.head; cur != nil; prev, cur = cur, cur.next {
|
|
}
|
|
cw.next = nil
|
|
prev.next = cw
|
|
}
|
|
|
|
func (pt *patternTable) condensedTableSearch(code uint16) *codeword {
|
|
if pt.bitLen <= condensePatternTableBitThreshold {
|
|
return pt.patterns[code]
|
|
}
|
|
var prev *codeword
|
|
for cur := pt.head; cur != nil; prev, cur = cur, cur.next {
|
|
if cur.code == code {
|
|
if prev != nil {
|
|
prev.next = cur.next
|
|
cur.next = pt.head
|
|
pt.head = cur
|
|
}
|
|
return cur
|
|
}
|
|
d := code - cur.code
|
|
if d&1 != 0 {
|
|
continue
|
|
}
|
|
if checkDistance(int(cur.len), int(d)) {
|
|
if prev != nil {
|
|
prev.next = cur.next
|
|
cur.next = pt.head
|
|
pt.head = cur
|
|
}
|
|
return cur
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type posTable struct {
|
|
pos []uint64
|
|
lens []byte
|
|
ptrs []*posTable
|
|
bitLen int
|
|
}
|
|
|
|
// Decompressor provides access to the superstrings in a file produced by a compressor
|
|
type Decompressor struct {
|
|
f *os.File
|
|
mmapHandle2 *[mmap.MaxMapSize]byte // mmap handle for windows (this is used to close mmap)
|
|
dict *patternTable
|
|
posDict *posTable
|
|
compressedFile string
|
|
mmapHandle1 []byte // mmap handle for unix (this is used to close mmap)
|
|
data []byte // slice of correct size for the decompressor to work with
|
|
wordsStart uint64 // Offset of whether the superstrings actually start
|
|
size int64
|
|
wordsCount uint64
|
|
emptyWordsCount uint64
|
|
}
|
|
|
|
// Tables with bitlen greater than threshold will be condensed.
|
|
// Condensing reduces size of decompression table but leads to slower reads.
|
|
// To disable condesning at all set to 9 (we dont use tables larger than 2^9)
|
|
// To enable condensing for tables of size larger 64 = 6
|
|
// for all tables = 0
|
|
// There is no sense to condense tables of size [1 - 64] in terms of performance
|
|
//
|
|
// Should be set before calling NewDecompression.
|
|
var condensePatternTableBitThreshold = 9
|
|
|
|
func SetDecompressionTableCondensity(fromBitSize int) {
|
|
condensePatternTableBitThreshold = fromBitSize
|
|
}
|
|
|
|
func NewDecompressor(compressedFile string) (*Decompressor, error) {
|
|
d := &Decompressor{
|
|
compressedFile: compressedFile,
|
|
}
|
|
|
|
var err error
|
|
defer func() {
|
|
if rec := recover(); rec != nil {
|
|
err = fmt.Errorf("decompressing file: %s, %+v, trace: %s", compressedFile, rec, dbg.Stack())
|
|
}
|
|
}()
|
|
|
|
d.f, err = os.Open(compressedFile)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var stat os.FileInfo
|
|
if stat, err = d.f.Stat(); err != nil {
|
|
return nil, err
|
|
}
|
|
d.size = stat.Size()
|
|
if d.size < 32 {
|
|
return nil, fmt.Errorf("compressed file is too short: %d", d.size)
|
|
}
|
|
if d.mmapHandle1, d.mmapHandle2, err = mmap.Mmap(d.f, int(d.size)); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// read patterns from file
|
|
d.data = d.mmapHandle1[:d.size]
|
|
d.wordsCount = binary.BigEndian.Uint64(d.data[:8])
|
|
d.emptyWordsCount = binary.BigEndian.Uint64(d.data[8:16])
|
|
dictSize := binary.BigEndian.Uint64(d.data[16:24])
|
|
data := d.data[24 : 24+dictSize]
|
|
|
|
var depths []uint64
|
|
var patterns [][]byte
|
|
var i uint64
|
|
var patternMaxDepth uint64
|
|
|
|
for i < dictSize {
|
|
d, ns := binary.Uvarint(data[i:])
|
|
if d > 2048 {
|
|
return nil, fmt.Errorf("dictionary is invalid: patternMaxDepth=%d", d)
|
|
}
|
|
depths = append(depths, d)
|
|
if d > patternMaxDepth {
|
|
patternMaxDepth = d
|
|
}
|
|
i += uint64(ns)
|
|
l, n := binary.Uvarint(data[i:])
|
|
i += uint64(n)
|
|
patterns = append(patterns, data[i:i+l])
|
|
//fmt.Printf("depth = %d, pattern = [%x]\n", d, data[i:i+l])
|
|
i += l
|
|
}
|
|
|
|
if dictSize > 0 {
|
|
var bitLen int
|
|
if patternMaxDepth > 9 {
|
|
bitLen = 9
|
|
} else {
|
|
bitLen = int(patternMaxDepth)
|
|
}
|
|
// fmt.Printf("pattern maxDepth=%d\n", tree.maxDepth)
|
|
d.dict = newPatternTable(bitLen)
|
|
buildCondensedPatternTable(d.dict, depths, patterns, 0, 0, 0, patternMaxDepth)
|
|
}
|
|
|
|
// read positions
|
|
pos := 24 + dictSize
|
|
dictSize = binary.BigEndian.Uint64(d.data[pos : pos+8])
|
|
data = d.data[pos+8 : pos+8+dictSize]
|
|
|
|
var posDepths []uint64
|
|
var poss []uint64
|
|
var posMaxDepth uint64
|
|
|
|
i = 0
|
|
for i < dictSize {
|
|
d, ns := binary.Uvarint(data[i:])
|
|
if d > 2048 {
|
|
return nil, fmt.Errorf("dictionary is invalid: posMaxDepth=%d", d)
|
|
}
|
|
posDepths = append(posDepths, d)
|
|
if d > posMaxDepth {
|
|
posMaxDepth = d
|
|
}
|
|
i += uint64(ns)
|
|
pos, n := binary.Uvarint(data[i:])
|
|
i += uint64(n)
|
|
poss = append(poss, pos)
|
|
}
|
|
|
|
if dictSize > 0 {
|
|
var bitLen int
|
|
if posMaxDepth > 9 {
|
|
bitLen = 9
|
|
} else {
|
|
bitLen = int(posMaxDepth)
|
|
}
|
|
//fmt.Printf("pos maxDepth=%d\n", tree.maxDepth)
|
|
tableSize := 1 << bitLen
|
|
d.posDict = &posTable{
|
|
bitLen: bitLen,
|
|
pos: make([]uint64, tableSize),
|
|
lens: make([]byte, tableSize),
|
|
ptrs: make([]*posTable, tableSize),
|
|
}
|
|
buildPosTable(posDepths, poss, d.posDict, 0, 0, 0, posMaxDepth)
|
|
}
|
|
d.wordsStart = pos + 8 + dictSize
|
|
return d, nil
|
|
}
|
|
|
|
func buildCondensedPatternTable(table *patternTable, depths []uint64, patterns [][]byte, code uint16, bits int, depth uint64, maxDepth uint64) int {
|
|
if len(depths) == 0 {
|
|
return 0
|
|
}
|
|
if depth == depths[0] {
|
|
pattern := word(patterns[0])
|
|
//fmt.Printf("depth=%d, maxDepth=%d, code=[%b], codeLen=%d, pattern=[%x]\n", depth, maxDepth, code, bits, pattern)
|
|
cw := &codeword{code: code, pattern: &pattern, len: byte(bits), ptr: nil}
|
|
|
|
// table.patterns = append(table.patterns, cw)
|
|
table.insertWord(cw)
|
|
return 1
|
|
}
|
|
if bits == 9 {
|
|
var bitLen int
|
|
if maxDepth > 9 {
|
|
bitLen = 9
|
|
} else {
|
|
bitLen = int(maxDepth)
|
|
}
|
|
newTable := newPatternTable(bitLen)
|
|
cw := &codeword{code: code, pattern: nil, len: byte(0), ptr: newTable}
|
|
|
|
// table.patterns = append(table.patterns, &codeword{code: code, pattern: nil, len: byte(0), ptr: newTable})
|
|
table.insertWord(cw)
|
|
return buildCondensedPatternTable(newTable, depths, patterns, 0, 0, depth, maxDepth)
|
|
}
|
|
b0 := buildCondensedPatternTable(table, depths, patterns, code, bits+1, depth+1, maxDepth-1)
|
|
return b0 + buildCondensedPatternTable(table, depths[b0:], patterns[b0:], (uint16(1)<<bits)|code, bits+1, depth+1, maxDepth-1)
|
|
}
|
|
|
|
func buildPosTable(depths []uint64, poss []uint64, table *posTable, code uint16, bits int, depth uint64, maxDepth uint64) int {
|
|
if len(depths) == 0 {
|
|
return 0
|
|
}
|
|
if depth == depths[0] {
|
|
p := poss[0]
|
|
//fmt.Printf("depth=%d, maxDepth=%d, code=[%b], codeLen=%d, pos=%d\n", depth, maxDepth, code, bits, p)
|
|
if table.bitLen == bits {
|
|
table.pos[code] = p
|
|
table.lens[code] = byte(bits)
|
|
table.ptrs[code] = nil
|
|
} else {
|
|
codeStep := uint16(1) << bits
|
|
codeFrom := code
|
|
codeTo := code | (uint16(1) << table.bitLen)
|
|
for c := codeFrom; c < codeTo; c += codeStep {
|
|
table.pos[c] = p
|
|
table.lens[c] = byte(bits)
|
|
table.ptrs[c] = nil
|
|
}
|
|
}
|
|
return 1
|
|
}
|
|
if bits == 9 {
|
|
var bitLen int
|
|
if maxDepth > 9 {
|
|
bitLen = 9
|
|
} else {
|
|
bitLen = int(maxDepth)
|
|
}
|
|
tableSize := 1 << bitLen
|
|
newTable := &posTable{
|
|
bitLen: bitLen,
|
|
pos: make([]uint64, tableSize),
|
|
lens: make([]byte, tableSize),
|
|
ptrs: make([]*posTable, tableSize),
|
|
}
|
|
table.pos[code] = 0
|
|
table.lens[code] = byte(0)
|
|
table.ptrs[code] = newTable
|
|
return buildPosTable(depths, poss, newTable, 0, 0, depth, maxDepth)
|
|
}
|
|
b0 := buildPosTable(depths, poss, table, code, bits+1, depth+1, maxDepth-1)
|
|
return b0 + buildPosTable(depths[b0:], poss[b0:], table, (uint16(1)<<bits)|code, bits+1, depth+1, maxDepth-1)
|
|
}
|
|
|
|
func (d *Decompressor) Size() int64 {
|
|
return d.size
|
|
}
|
|
|
|
func (d *Decompressor) Close() error {
|
|
if err := mmap.Munmap(d.mmapHandle1, d.mmapHandle2); err != nil {
|
|
return err
|
|
}
|
|
if err := d.f.Close(); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (d *Decompressor) FilePath() string { return d.compressedFile }
|
|
|
|
// WithReadAhead - Expect read in sequential order. (Hence, pages in the given range can be aggressively read ahead, and may be freed soon after they are accessed.)
|
|
func (d *Decompressor) WithReadAhead(f func() error) error {
|
|
_ = mmap.MadviseSequential(d.mmapHandle1)
|
|
//_ = mmap.MadviseWillNeed(d.mmapHandle1)
|
|
defer mmap.MadviseRandom(d.mmapHandle1)
|
|
return f()
|
|
}
|
|
|
|
// DisableReadAhead - usage: `defer d.EnableReadAhead().DisableReadAhead()`. Please don't use this funcs without `defer` to avoid leak.
|
|
func (d *Decompressor) DisableReadAhead() { _ = mmap.MadviseRandom(d.mmapHandle1) }
|
|
func (d *Decompressor) EnableReadAhead() *Decompressor {
|
|
_ = mmap.MadviseSequential(d.mmapHandle1)
|
|
return d
|
|
}
|
|
func (d *Decompressor) EnableMadvNormal() *Decompressor {
|
|
_ = mmap.MadviseNormal(d.mmapHandle1)
|
|
return d
|
|
}
|
|
func (d *Decompressor) EnableWillNeed() *Decompressor {
|
|
_ = mmap.MadviseWillNeed(d.mmapHandle1)
|
|
return d
|
|
}
|
|
|
|
// Getter represent "reader" or "interator" that can move accross the data of the decompressor
|
|
// The full state of the getter can be captured by saving dataP, and dataBit
|
|
type Getter struct {
|
|
patternDict *patternTable
|
|
posDict *posTable
|
|
fName string
|
|
data []byte
|
|
dataP uint64
|
|
dataBit int // Value 0..7 - position of the bit
|
|
trace bool
|
|
}
|
|
|
|
func (g *Getter) Trace(t bool) { g.trace = t }
|
|
|
|
func (g *Getter) nextPos(clean bool) uint64 {
|
|
if clean {
|
|
if g.dataBit > 0 {
|
|
g.dataP++
|
|
g.dataBit = 0
|
|
}
|
|
}
|
|
table := g.posDict
|
|
if table.bitLen == 0 {
|
|
return table.pos[0]
|
|
}
|
|
var l byte
|
|
var pos uint64
|
|
for l == 0 {
|
|
code := uint16(g.data[g.dataP]) >> g.dataBit
|
|
if 8-g.dataBit < table.bitLen && int(g.dataP)+1 < len(g.data) {
|
|
code |= uint16(g.data[g.dataP+1]) << (8 - g.dataBit)
|
|
}
|
|
code &= (uint16(1) << table.bitLen) - 1
|
|
l = table.lens[code]
|
|
if l == 0 {
|
|
table = table.ptrs[code]
|
|
g.dataBit += 9
|
|
} else {
|
|
g.dataBit += int(l)
|
|
pos = table.pos[code]
|
|
}
|
|
g.dataP += uint64(g.dataBit / 8)
|
|
g.dataBit = g.dataBit % 8
|
|
}
|
|
return pos
|
|
}
|
|
|
|
func (g *Getter) nextPattern() []byte {
|
|
table := g.patternDict
|
|
|
|
if table.bitLen == 0 {
|
|
return *table.patterns[0].pattern
|
|
}
|
|
|
|
var l byte
|
|
var pattern []byte
|
|
for l == 0 {
|
|
code := uint16(g.data[g.dataP]) >> g.dataBit
|
|
if 8-g.dataBit < table.bitLen && int(g.dataP)+1 < len(g.data) {
|
|
code |= uint16(g.data[g.dataP+1]) << (8 - g.dataBit)
|
|
}
|
|
code &= (uint16(1) << table.bitLen) - 1
|
|
|
|
cw := table.condensedTableSearch(code)
|
|
l = cw.len
|
|
if l == 0 {
|
|
table = cw.ptr
|
|
g.dataBit += 9
|
|
} else {
|
|
g.dataBit += int(l)
|
|
pattern = *cw.pattern
|
|
}
|
|
g.dataP += uint64(g.dataBit / 8)
|
|
g.dataBit = g.dataBit % 8
|
|
}
|
|
return pattern
|
|
}
|
|
|
|
var condensedWordDistances = buildCondensedWordDistances()
|
|
|
|
func checkDistance(power int, d int) bool {
|
|
for _, dist := range condensedWordDistances[power] {
|
|
if dist == d {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func buildCondensedWordDistances() [][]int {
|
|
dist2 := make([][]int, 10)
|
|
for i := 1; i <= 9; i++ {
|
|
dl := make([]int, 0)
|
|
for j := 1 << i; j < 512; j += 1 << i {
|
|
dl = append(dl, j)
|
|
}
|
|
dist2[i] = dl
|
|
}
|
|
return dist2
|
|
}
|
|
|
|
func (g *Getter) Size() int {
|
|
return len(g.data)
|
|
}
|
|
|
|
func (d *Decompressor) Count() int { return int(d.wordsCount) }
|
|
func (d *Decompressor) EmptyWordsCount() int { return int(d.emptyWordsCount) }
|
|
|
|
// MakeGetter creates an object that can be used to access superstrings in the decompressor's file
|
|
// Getter is not thread-safe, but there can be multiple getters used simultaneously and concurrently
|
|
// for the same decompressor
|
|
func (d *Decompressor) MakeGetter() *Getter {
|
|
return &Getter{
|
|
posDict: d.posDict,
|
|
data: d.data[d.wordsStart:],
|
|
patternDict: d.dict,
|
|
fName: d.compressedFile,
|
|
}
|
|
}
|
|
|
|
func (g *Getter) Reset(offset uint64) {
|
|
g.dataP = offset
|
|
g.dataBit = 0
|
|
}
|
|
|
|
func (g *Getter) HasNext() bool {
|
|
return g.dataP < uint64(len(g.data))
|
|
}
|
|
|
|
// Next extracts a compressed word from current offset in the file
|
|
// and appends it to the given buf, returning the result of appending
|
|
// After extracting next word, it moves to the beginning of the next one
|
|
func (g *Getter) Next(buf []byte) ([]byte, uint64) {
|
|
defer func() {
|
|
if rec := recover(); rec != nil {
|
|
panic(fmt.Sprintf("file: %s, %s, %s", g.fName, rec, dbg.Stack()))
|
|
}
|
|
}()
|
|
savePos := g.dataP
|
|
wordLen := g.nextPos(true)
|
|
wordLen-- // because when create huffman tree we do ++ , because 0 is terminator
|
|
if wordLen == 0 {
|
|
if g.dataBit > 0 {
|
|
g.dataP++
|
|
g.dataBit = 0
|
|
}
|
|
return buf, g.dataP
|
|
}
|
|
bufPos := len(buf) // Tracking position in buf where to insert part of the word
|
|
lastUncovered := len(buf)
|
|
if len(buf)+int(wordLen) > cap(buf) {
|
|
newBuf := make([]byte, len(buf)+int(wordLen))
|
|
copy(newBuf, buf)
|
|
buf = newBuf
|
|
} else {
|
|
// Expand buffer
|
|
buf = buf[:len(buf)+int(wordLen)]
|
|
}
|
|
// Loop below fills in the patterns
|
|
for pos := g.nextPos(false /* clean */); pos != 0; pos = g.nextPos(false) {
|
|
bufPos += int(pos) - 1 // Positions where to insert patterns are encoded relative to one another
|
|
pt := g.nextPattern()
|
|
copy(buf[bufPos:], pt)
|
|
}
|
|
if g.dataBit > 0 {
|
|
g.dataP++
|
|
g.dataBit = 0
|
|
}
|
|
postLoopPos := g.dataP
|
|
g.dataP = savePos
|
|
g.dataBit = 0
|
|
g.nextPos(true /* clean */) // Reset the state of huffman reader
|
|
bufPos = lastUncovered // Restore to the beginning of buf
|
|
// Loop below fills the data which is not in the patterns
|
|
for pos := g.nextPos(false); pos != 0; pos = g.nextPos(false) {
|
|
bufPos += int(pos) - 1 // Positions where to insert patterns are encoded relative to one another
|
|
if bufPos > lastUncovered {
|
|
dif := uint64(bufPos - lastUncovered)
|
|
copy(buf[lastUncovered:bufPos], g.data[postLoopPos:postLoopPos+dif])
|
|
postLoopPos += dif
|
|
}
|
|
lastUncovered = bufPos + len(g.nextPattern())
|
|
}
|
|
if int(wordLen) > lastUncovered {
|
|
dif := wordLen - uint64(lastUncovered)
|
|
copy(buf[lastUncovered:wordLen], g.data[postLoopPos:postLoopPos+dif])
|
|
postLoopPos += dif
|
|
}
|
|
g.dataP = postLoopPos
|
|
g.dataBit = 0
|
|
return buf, postLoopPos
|
|
}
|
|
|
|
func (g *Getter) NextUncompressed() ([]byte, uint64) {
|
|
defer func() {
|
|
if rec := recover(); rec != nil {
|
|
panic(fmt.Sprintf("file: %s, %s, %s", g.fName, rec, dbg.Stack()))
|
|
}
|
|
}()
|
|
wordLen := g.nextPos(true)
|
|
wordLen-- // because when create huffman tree we do ++ , because 0 is terminator
|
|
if wordLen == 0 {
|
|
if g.dataBit > 0 {
|
|
g.dataP++
|
|
g.dataBit = 0
|
|
}
|
|
return g.data[g.dataP:g.dataP], g.dataP
|
|
}
|
|
g.nextPos(false)
|
|
if g.dataBit > 0 {
|
|
g.dataP++
|
|
g.dataBit = 0
|
|
}
|
|
pos := g.dataP
|
|
g.dataP += wordLen
|
|
return g.data[pos:g.dataP], g.dataP
|
|
}
|
|
|
|
// Skip moves offset to the next word and returns the new offset.
|
|
func (g *Getter) Skip() uint64 {
|
|
l := g.nextPos(true)
|
|
l-- // because when create huffman tree we do ++ , because 0 is terminator
|
|
if l == 0 {
|
|
if g.dataBit > 0 {
|
|
g.dataP++
|
|
g.dataBit = 0
|
|
}
|
|
return g.dataP
|
|
}
|
|
wordLen := int(l)
|
|
|
|
var add uint64
|
|
var bufPos int
|
|
var lastUncovered int
|
|
for pos := g.nextPos(false /* clean */); pos != 0; pos = g.nextPos(false) {
|
|
bufPos += int(pos) - 1
|
|
if wordLen < bufPos {
|
|
panic(fmt.Sprintf("likely .idx is invalid: %s", g.fName))
|
|
}
|
|
if bufPos > lastUncovered {
|
|
add += uint64(bufPos - lastUncovered)
|
|
}
|
|
lastUncovered = bufPos + len(g.nextPattern())
|
|
}
|
|
if g.dataBit > 0 {
|
|
g.dataP++
|
|
g.dataBit = 0
|
|
}
|
|
if int(l) > lastUncovered {
|
|
add += l - uint64(lastUncovered)
|
|
}
|
|
// Uncovered characters
|
|
g.dataP += add
|
|
return g.dataP
|
|
}
|
|
|
|
func (g *Getter) SkipUncompressed() uint64 {
|
|
wordLen := g.nextPos(true)
|
|
wordLen-- // because when create huffman tree we do ++ , because 0 is terminator
|
|
if wordLen == 0 {
|
|
if g.dataBit > 0 {
|
|
g.dataP++
|
|
g.dataBit = 0
|
|
}
|
|
return g.dataP
|
|
}
|
|
g.nextPos(false)
|
|
if g.dataBit > 0 {
|
|
g.dataP++
|
|
g.dataBit = 0
|
|
}
|
|
g.dataP += wordLen
|
|
return g.dataP
|
|
}
|
|
|
|
// Match returns true and next offset if the word at current offset fully matches the buf
|
|
// returns false and current offset otherwise.
|
|
func (g *Getter) Match(buf []byte) (bool, uint64) {
|
|
savePos := g.dataP
|
|
wordLen := g.nextPos(true)
|
|
wordLen-- // because when create huffman tree we do ++ , because 0 is terminator
|
|
lenBuf := len(buf)
|
|
if wordLen == 0 || int(wordLen) != lenBuf {
|
|
if g.dataBit > 0 {
|
|
g.dataP++
|
|
g.dataBit = 0
|
|
}
|
|
if lenBuf != 0 {
|
|
g.dataP, g.dataBit = savePos, 0
|
|
}
|
|
return lenBuf == int(wordLen), g.dataP
|
|
}
|
|
|
|
var bufPos int
|
|
// In the first pass, we only check patterns
|
|
for pos := g.nextPos(false /* clean */); pos != 0; pos = g.nextPos(false) {
|
|
bufPos += int(pos) - 1
|
|
pattern := g.nextPattern()
|
|
if lenBuf < bufPos+len(pattern) || !bytes.Equal(buf[bufPos:bufPos+len(pattern)], pattern) {
|
|
g.dataP, g.dataBit = savePos, 0
|
|
return false, savePos
|
|
}
|
|
}
|
|
if g.dataBit > 0 {
|
|
g.dataP++
|
|
g.dataBit = 0
|
|
}
|
|
postLoopPos := g.dataP
|
|
g.dataP, g.dataBit = savePos, 0
|
|
g.nextPos(true /* clean */) // Reset the state of huffman decoder
|
|
// Second pass - we check spaces not covered by the patterns
|
|
var lastUncovered int
|
|
bufPos = 0
|
|
for pos := g.nextPos(false /* clean */); pos != 0; pos = g.nextPos(false) {
|
|
bufPos += int(pos) - 1
|
|
if bufPos > lastUncovered {
|
|
dif := uint64(bufPos - lastUncovered)
|
|
if lenBuf < bufPos || !bytes.Equal(buf[lastUncovered:bufPos], g.data[postLoopPos:postLoopPos+dif]) {
|
|
g.dataP, g.dataBit = savePos, 0
|
|
return false, savePos
|
|
}
|
|
postLoopPos += dif
|
|
}
|
|
lastUncovered = bufPos + len(g.nextPattern())
|
|
}
|
|
if int(wordLen) > lastUncovered {
|
|
dif := wordLen - uint64(lastUncovered)
|
|
if lenBuf < int(wordLen) || !bytes.Equal(buf[lastUncovered:wordLen], g.data[postLoopPos:postLoopPos+dif]) {
|
|
g.dataP, g.dataBit = savePos, 0
|
|
return false, savePos
|
|
}
|
|
postLoopPos += dif
|
|
}
|
|
if lenBuf != int(wordLen) {
|
|
g.dataP, g.dataBit = savePos, 0
|
|
return false, savePos
|
|
}
|
|
g.dataP, g.dataBit = postLoopPos, 0
|
|
return true, postLoopPos
|
|
}
|
|
|
|
// MatchPrefix only checks if the word at the current offset has a buf prefix. Does not move offset to the next word.
|
|
func (g *Getter) MatchPrefix(prefix []byte) bool {
|
|
savePos := g.dataP
|
|
defer func() {
|
|
g.dataP, g.dataBit = savePos, 0
|
|
}()
|
|
|
|
wordLen := g.nextPos(true /* clean */)
|
|
wordLen-- // because when create huffman tree we do ++ , because 0 is terminator
|
|
prefixLen := len(prefix)
|
|
if wordLen == 0 || int(wordLen) < prefixLen {
|
|
if g.dataBit > 0 {
|
|
g.dataP++
|
|
g.dataBit = 0
|
|
}
|
|
if prefixLen != 0 {
|
|
g.dataP, g.dataBit = savePos, 0
|
|
}
|
|
return prefixLen == int(wordLen)
|
|
}
|
|
|
|
var bufPos int
|
|
// In the first pass, we only check patterns
|
|
// Only run this loop as far as the prefix goes, there is no need to check further
|
|
for pos := g.nextPos(false /* clean */); pos != 0; pos = g.nextPos(false) {
|
|
bufPos += int(pos) - 1
|
|
pattern := g.nextPattern()
|
|
var comparisonLen int
|
|
if prefixLen < bufPos+len(pattern) {
|
|
comparisonLen = prefixLen - bufPos
|
|
} else {
|
|
comparisonLen = len(pattern)
|
|
}
|
|
if bufPos < prefixLen {
|
|
if !bytes.Equal(prefix[bufPos:bufPos+comparisonLen], pattern[:comparisonLen]) {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
|
|
if g.dataBit > 0 {
|
|
g.dataP++
|
|
g.dataBit = 0
|
|
}
|
|
postLoopPos := g.dataP
|
|
g.dataP, g.dataBit = savePos, 0
|
|
g.nextPos(true /* clean */) // Reset the state of huffman decoder
|
|
// Second pass - we check spaces not covered by the patterns
|
|
var lastUncovered int
|
|
bufPos = 0
|
|
for pos := g.nextPos(false /* clean */); pos != 0 && lastUncovered < prefixLen; pos = g.nextPos(false) {
|
|
bufPos += int(pos) - 1
|
|
if bufPos > lastUncovered {
|
|
dif := uint64(bufPos - lastUncovered)
|
|
var comparisonLen int
|
|
if prefixLen < lastUncovered+int(dif) {
|
|
comparisonLen = prefixLen - lastUncovered
|
|
} else {
|
|
comparisonLen = int(dif)
|
|
}
|
|
if !bytes.Equal(prefix[lastUncovered:lastUncovered+comparisonLen], g.data[postLoopPos:postLoopPos+uint64(comparisonLen)]) {
|
|
return false
|
|
}
|
|
postLoopPos += dif
|
|
}
|
|
lastUncovered = bufPos + len(g.nextPattern())
|
|
}
|
|
if prefixLen > lastUncovered && int(wordLen) > lastUncovered {
|
|
dif := wordLen - uint64(lastUncovered)
|
|
var comparisonLen int
|
|
if prefixLen < int(wordLen) {
|
|
comparisonLen = prefixLen - lastUncovered
|
|
} else {
|
|
comparisonLen = int(dif)
|
|
}
|
|
if !bytes.Equal(prefix[lastUncovered:lastUncovered+comparisonLen], g.data[postLoopPos:postLoopPos+uint64(comparisonLen)]) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|