@@ -88,23 +88,23 @@ var (
8888 _ indexBtree = & indexInterior {}
8989)
9090
91- func newBtree (b []byte , isFileHeader bool ) (interface {}, error ) {
91+ func newBtree (b []byte , isFileHeader bool , pageSize int ) (interface {}, error ) {
9292 hb := b
9393 if isFileHeader {
9494 hb = b [headerSize :]
9595 }
9696 cells := int (binary .BigEndian .Uint16 (hb [3 :5 ]))
9797 switch typ := int (hb [0 ]); typ {
9898 case 0x0d :
99- return newLeafTableBtree (cells , hb [8 :], b )
99+ return newLeafTableBtree (cells , hb [8 :], b , pageSize )
100100 case 0x05 :
101101 rightmostPointer := int (binary .BigEndian .Uint32 (hb [8 :12 ]))
102102 return newInteriorTableBtree (cells , hb [12 :], b , rightmostPointer )
103103 case 0x0a :
104- return newLeafIndex (cells , b [8 :], b )
104+ return newLeafIndex (cells , b [8 :], b , pageSize )
105105 case 0x02 :
106106 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 )
108108 default :
109109 return nil , errors .New ("unsupported page type" )
110110 }
@@ -114,14 +114,15 @@ func newLeafTableBtree(
114114 count int ,
115115 pointers []byte ,
116116 content []byte ,
117+ pageSize int ,
117118) (* tableLeaf , error ) {
118119 cells , err := parseCellpointers (count , pointers , len (content ))
119120 if err != nil {
120121 return nil , err
121122 }
122123 leafs := make ([]tableLeafCell , len (cells ))
123124 for i , start := range cells {
124- leafs [i ], err = parseTableLeaf (content [start :])
125+ leafs [i ], err = parseTableLeaf (content [start :], pageSize )
125126 if err != nil {
126127 return nil , err
127128 }
@@ -250,14 +251,15 @@ func newLeafIndex(
250251 count int ,
251252 pointers []byte ,
252253 content []byte ,
254+ pageSize int ,
253255) (* indexLeaf , error ) {
254256 cells , err := parseCellpointers (count , pointers , len (content ))
255257 if err != nil {
256258 return nil , err
257259 }
258260 cs := make ([]cellPayload , len (cells ))
259261 for i , start := range cells {
260- cs [i ], err = parseIndexLeaf (content [start :])
262+ cs [i ], err = parseIndexLeaf (content [start :], pageSize )
261263 if err != nil {
262264 return nil , err
263265 }
@@ -323,14 +325,15 @@ func newInteriorIndex(
323325 pointers []byte ,
324326 content []byte ,
325327 rightmost int ,
328+ pageSize int ,
326329) (* indexInterior , error ) {
327330 cells , err := parseCellpointers (count , pointers , len (content ))
328331 if err != nil {
329332 return nil , err
330333 }
331334 cs := make ([]indexInteriorCell , len (cells ))
332335 for i , start := range cells {
333- cs [i ], err = parseIndexInterior (content [start :])
336+ cs [i ], err = parseIndexInterior (content [start :], pageSize )
334337 if err != nil {
335338 return nil , err
336339 }
@@ -458,28 +461,48 @@ func (l *indexInterior) Count(db *Database) (int, error) {
458461 return total + n , err
459462}
460463
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+
461482// 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 ) {
463484 overflow := 0
485+ inPageBytes := calculateCellInPageBytes (l , pageSize , maxInPagePayload )
464486 if l < 0 {
465487 return cellPayload {}, ErrCorrupted
466488 }
467- if int64 (len (c )) > l {
468- c = c [:l ]
489+
490+ if int64 (inPageBytes ) == l {
491+ return cellPayload {l , c , 0 }, nil
469492 }
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
478501 }
479502 return cellPayload {l , c , overflow }, nil
480503}
481504
482- func parseTableLeaf (c []byte ) (tableLeafCell , error ) {
505+ func parseTableLeaf (c []byte , pageSize int ) (tableLeafCell , error ) {
483506 l , n := readVarint (c )
484507 if n < 0 {
485508 return tableLeafCell {}, ErrCorrupted
@@ -489,7 +512,8 @@ func parseTableLeaf(c []byte) (tableLeafCell, error) {
489512 if n < 0 {
490513 return tableLeafCell {}, ErrCorrupted
491514 }
492- pl , err := parsePayload (l , c [n :])
515+
516+ pl , err := parsePayload (l , c [n :], pageSize , pageSize - 35 )
493517 return tableLeafCell {
494518 left : rowid ,
495519 payload : pl ,
@@ -511,15 +535,15 @@ func parseTableInterior(c []byte) (tableInteriorCell, error) {
511535 }, nil
512536}
513537
514- func parseIndexLeaf (c []byte ) (cellPayload , error ) {
538+ func parseIndexLeaf (c []byte , pageSize int ) (cellPayload , error ) {
515539 l , n := readVarint (c )
516540 if n < 0 {
517541 return cellPayload {}, ErrCorrupted
518542 }
519- return parsePayload (l , c [n :])
543+ return parsePayload (l , c [n :], pageSize , (( pageSize - 12 ) * 64 / 255 ) - 23 )
520544}
521545
522- func parseIndexInterior (c []byte ) (indexInteriorCell , error ) {
546+ func parseIndexInterior (c []byte , pageSize int ) (indexInteriorCell , error ) {
523547 if len (c ) < 4 {
524548 return indexInteriorCell {}, ErrCorrupted
525549 }
@@ -529,7 +553,7 @@ func parseIndexInterior(c []byte) (indexInteriorCell, error) {
529553 if n < 0 {
530554 return indexInteriorCell {}, ErrCorrupted
531555 }
532- pl , err := parsePayload (l , c [n :])
556+ pl , err := parsePayload (l , c [n :], pageSize , (( pageSize - 12 ) * 64 / 255 ) - 23 )
533557 return indexInteriorCell {
534558 left : int (left ),
535559 payload : pl ,
0 commit comments