@@ -88,23 +88,23 @@ var (
88
88
_ indexBtree = & indexInterior {}
89
89
)
90
90
91
- func newBtree (b []byte , isFileHeader bool ) (interface {}, error ) {
91
+ func newBtree (b []byte , isFileHeader bool , pageSize int ) (interface {}, error ) {
92
92
hb := b
93
93
if isFileHeader {
94
94
hb = b [headerSize :]
95
95
}
96
96
cells := int (binary .BigEndian .Uint16 (hb [3 :5 ]))
97
97
switch typ := int (hb [0 ]); typ {
98
98
case 0x0d :
99
- return newLeafTableBtree (cells , hb [8 :], b )
99
+ return newLeafTableBtree (cells , hb [8 :], b , pageSize )
100
100
case 0x05 :
101
101
rightmostPointer := int (binary .BigEndian .Uint32 (hb [8 :12 ]))
102
102
return newInteriorTableBtree (cells , hb [12 :], b , rightmostPointer )
103
103
case 0x0a :
104
- return newLeafIndex (cells , b [8 :], b )
104
+ return newLeafIndex (cells , b [8 :], b , pageSize )
105
105
case 0x02 :
106
106
rightmostPointer := int (binary .BigEndian .Uint32 (b [8 :12 ]))
107
- return newInteriorIndex (cells , b [12 :], b , rightmostPointer )
107
+ return newInteriorIndex (cells , b [12 :], b , rightmostPointer , pageSize )
108
108
default :
109
109
return nil , errors .New ("unsupported page type" )
110
110
}
@@ -114,14 +114,15 @@ func newLeafTableBtree(
114
114
count int ,
115
115
pointers []byte ,
116
116
content []byte ,
117
+ pageSize int ,
117
118
) (* tableLeaf , error ) {
118
119
cells , err := parseCellpointers (count , pointers , len (content ))
119
120
if err != nil {
120
121
return nil , err
121
122
}
122
123
leafs := make ([]tableLeafCell , len (cells ))
123
124
for i , start := range cells {
124
- leafs [i ], err = parseTableLeaf (content [start :])
125
+ leafs [i ], err = parseTableLeaf (content [start :], pageSize )
125
126
if err != nil {
126
127
return nil , err
127
128
}
@@ -250,14 +251,15 @@ func newLeafIndex(
250
251
count int ,
251
252
pointers []byte ,
252
253
content []byte ,
254
+ pageSize int ,
253
255
) (* indexLeaf , error ) {
254
256
cells , err := parseCellpointers (count , pointers , len (content ))
255
257
if err != nil {
256
258
return nil , err
257
259
}
258
260
cs := make ([]cellPayload , len (cells ))
259
261
for i , start := range cells {
260
- cs [i ], err = parseIndexLeaf (content [start :])
262
+ cs [i ], err = parseIndexLeaf (content [start :], pageSize )
261
263
if err != nil {
262
264
return nil , err
263
265
}
@@ -323,14 +325,15 @@ func newInteriorIndex(
323
325
pointers []byte ,
324
326
content []byte ,
325
327
rightmost int ,
328
+ pageSize int ,
326
329
) (* indexInterior , error ) {
327
330
cells , err := parseCellpointers (count , pointers , len (content ))
328
331
if err != nil {
329
332
return nil , err
330
333
}
331
334
cs := make ([]indexInteriorCell , len (cells ))
332
335
for i , start := range cells {
333
- cs [i ], err = parseIndexInterior (content [start :])
336
+ cs [i ], err = parseIndexInterior (content [start :], pageSize )
334
337
if err != nil {
335
338
return nil , err
336
339
}
@@ -458,28 +461,48 @@ func (l *indexInterior) Count(db *Database) (int, error) {
458
461
return total + n , err
459
462
}
460
463
464
+ func calculateCellInPageBytes (l int64 , pageSize int , maxInPagePayload int ) int {
465
+ // Overflow calculation described in the file format spec. The
466
+ // variable names and magic constants are from the spec exactly.
467
+ u := int64 (pageSize )
468
+ p := l
469
+ x := int64 (maxInPagePayload )
470
+ m := ((u - 12 ) * 32 / 255 ) - 23
471
+ k := m + ((p - m ) % (u - 4 ))
472
+
473
+ if p <= x {
474
+ return int (l )
475
+ } else if k <= x {
476
+ return int (k )
477
+ } else {
478
+ return int (m )
479
+ }
480
+ }
481
+
461
482
// shared code for parsing payload from cells
462
- func parsePayload (l int64 , c []byte ) (cellPayload , error ) {
483
+ func parsePayload (l int64 , c []byte , pageSize int , maxInPagePayload int ) (cellPayload , error ) {
463
484
overflow := 0
485
+ inPageBytes := calculateCellInPageBytes (l , pageSize , maxInPagePayload )
464
486
if l < 0 {
465
487
return cellPayload {}, ErrCorrupted
466
488
}
467
- if int64 (len (c )) > l {
468
- c = c [:l ]
489
+
490
+ if int64 (inPageBytes ) == l {
491
+ return cellPayload {l , c , 0 }, nil
469
492
}
470
- if int64 ( len ( c )) != l {
471
- if len (c ) < 4 {
472
- return cellPayload {}, ErrCorrupted
473
- }
474
- c , overflow = c [: len ( c ) - 4 ], int ( binary . BigEndian . Uint32 ( c [ len ( c ) - 4 :]))
475
- if overflow == 0 {
476
- return cellPayload {}, ErrCorrupted
477
- }
493
+
494
+ if len (c ) < inPageBytes + 4 {
495
+ return cellPayload {}, ErrCorrupted
496
+ }
497
+
498
+ c , overflow = c [: inPageBytes ], int ( binary . BigEndian . Uint32 ( c [ inPageBytes : inPageBytes + 4 ]))
499
+ if overflow == 0 {
500
+ return cellPayload {}, ErrCorrupted
478
501
}
479
502
return cellPayload {l , c , overflow }, nil
480
503
}
481
504
482
- func parseTableLeaf (c []byte ) (tableLeafCell , error ) {
505
+ func parseTableLeaf (c []byte , pageSize int ) (tableLeafCell , error ) {
483
506
l , n := readVarint (c )
484
507
if n < 0 {
485
508
return tableLeafCell {}, ErrCorrupted
@@ -489,7 +512,8 @@ func parseTableLeaf(c []byte) (tableLeafCell, error) {
489
512
if n < 0 {
490
513
return tableLeafCell {}, ErrCorrupted
491
514
}
492
- pl , err := parsePayload (l , c [n :])
515
+
516
+ pl , err := parsePayload (l , c [n :], pageSize , pageSize - 35 )
493
517
return tableLeafCell {
494
518
left : rowid ,
495
519
payload : pl ,
@@ -511,15 +535,15 @@ func parseTableInterior(c []byte) (tableInteriorCell, error) {
511
535
}, nil
512
536
}
513
537
514
- func parseIndexLeaf (c []byte ) (cellPayload , error ) {
538
+ func parseIndexLeaf (c []byte , pageSize int ) (cellPayload , error ) {
515
539
l , n := readVarint (c )
516
540
if n < 0 {
517
541
return cellPayload {}, ErrCorrupted
518
542
}
519
- return parsePayload (l , c [n :])
543
+ return parsePayload (l , c [n :], pageSize , (( pageSize - 12 ) * 64 / 255 ) - 23 )
520
544
}
521
545
522
- func parseIndexInterior (c []byte ) (indexInteriorCell , error ) {
546
+ func parseIndexInterior (c []byte , pageSize int ) (indexInteriorCell , error ) {
523
547
if len (c ) < 4 {
524
548
return indexInteriorCell {}, ErrCorrupted
525
549
}
@@ -529,7 +553,7 @@ func parseIndexInterior(c []byte) (indexInteriorCell, error) {
529
553
if n < 0 {
530
554
return indexInteriorCell {}, ErrCorrupted
531
555
}
532
- pl , err := parsePayload (l , c [n :])
556
+ pl , err := parsePayload (l , c [n :], pageSize , (( pageSize - 12 ) * 64 / 255 ) - 23 )
533
557
return indexInteriorCell {
534
558
left : int (left ),
535
559
payload : pl ,
0 commit comments