-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpage.js
169 lines (135 loc) · 4.22 KB
/
page.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
// Martin Pravda
// page.js
// A page parser
// A page is is a block of data of a fixed size
// There are 4 types of pages
// 1. Table b-tree leaf page
// 2. Table b-tree interior page
// 3. Index b-tree leaf page
// 4. Index b-tree interion page
// A page consists of:
// 1. Page header
// 2. An array of cell pointers
// 3. An unallocated space
// 4. Cell content area
// 5. A reserved region
// A complete documentation for the B-Tree pages structure can be found here
// https://www.sqlite.org/fileformat.html#b_tree_pages
/* jslint browser, node */
import cell from "./cell.js";
import record from "./record.js";
function is_leaf(type) {
const types = [10, 13];
return types.includes(type);
}
function parse_header(view, offset, page_start) {
const page_type = view.getUint8(offset);
const freeblock_start = view.getUint16(offset + 1);
const number_of_cells = view.getUint16(offset + 3);
// cell content area is start of the cells
// since start of the cell is an offset of the cell within the page
// we need to sum start (offset) of the page with the offset of the cell
const cell_content_area = page_start + view.getUint16(offset + 5);
const fragmented_free_bytes_nr = view.getUint8(offset + 7);
const right_most_pointer = view.getUint32(offset + 8);
return Object.freeze({
// the start of the content area
// is defined in the spec file https://www.sqlite.org/fileformat2.html
cell_content_area: (
cell_content_area === 0
? 65536
: cell_content_area
),
fragmented_free_bytes_nr,
freeblock_start,
number_of_cells,
page_type,
right_most_pointer
});
}
function parse_table_leaf_page(view, cell_pointers, encoding) {
const cells = cell_pointers.map(function (offset) {
return cell.parse_table_leaf(view, offset);
});
const records = cells.map(function (cell) {
return record.parse(view, cell.payload_start, encoding);
});
return Object.freeze({
cells,
records
});
}
function parse_table_interior_page(view, cell_pointers) {
const cells = cell_pointers.map(function (offset) {
return cell.parse_table_interior(view, offset);
});
return Object.freeze({
cells
});
}
function parse_index_leaf_page(view, cell_pointers, encoding) {
const cells = cell_pointers.map(function (offset) {
return cell.parse_index_leaf(view, offset);
});
const records = cells.map(function (cell) {
return record.parse(view, cell.payload_start, encoding);
});
return Object.freeze({
cells,
records
});
}
function parse_index_interior_page(view, cell_pointers, encoding) {
const cells = cell_pointers.map(function (offset) {
return cell.parse_index_interior(view, offset);
});
const records = cells.map(function (cell) {
return record.parse(view, cell.payload_start, encoding);
});
return Object.freeze({
cells,
records
});
}
function parse(view, offset, encoding) {
const page_start = (
offset === 100
? 0
: offset
);
const header = parse_header(view, offset, page_start);
const cell_pointers = cell.parse_pointers(
view,
page_start,
(
is_leaf(header.page_type)
? offset + 8
: offset + 12
),
header.number_of_cells
);
let page = {};
// page type 2 indicates the page is an index btree interior page
if (header.page_type === 2) {
page = parse_index_interior_page(view, cell_pointers, encoding);
}
// page type 5 indicates the page is a table btree interior page
if (header.page_type === 5) {
page = parse_table_interior_page(view, cell_pointers);
}
// page type 10 indicates the page is an index btree leaf page
if (header.page_type === 10) {
page = parse_index_leaf_page(view, cell_pointers, encoding);
}
// page type 13 indicates the page is a table btree leaf page
if (header.page_type === 13) {
page = parse_table_leaf_page(view, cell_pointers, encoding);
}
return Object.freeze(
Object.assign({header}, page)
);
}
export default Object.freeze({
is_leaf,
parse
});