17uint16_t be16(
const uint8_t *p)
19 return (uint16_t)(((uint16_t)p[0] << 8) | p[1]);
21uint32_t be32(
const uint8_t *p)
23 return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) | ((uint32_t)p[2] << 8) | (uint32_t)p[3];
26const char SQLITE_MAGIC[16] = {
'S',
'Q',
'L',
'i',
't',
'e',
' ',
'f',
'o',
'r',
'm',
'a',
't',
' ',
'3',
'\0'};
28bool is_pow2(uint32_t v)
30 return v && (v & (v - 1)) == 0;
34size_t pc_sqlite_varint_decode(
const uint8_t *buf,
size_t len, uint64_t *out)
37 for (
size_t i = 0; i < 8; i++)
43 v = (v << 7) | (uint8_t)(buf[i] & 0x7f);
44 if ((buf[i] & 0x80) == 0)
54 v = (v << 8) | buf[8];
59uint64_t pc_sqlite_serial_type_size(uint64_t t)
88 return t >= 12 ? (t - 12) / 2 : 0;
93bool pc_sqlite_parse_db_header(
const uint8_t *buf,
size_t len, SqliteDbHeader *out)
95 if (len < 100 || memcmp(buf, SQLITE_MAGIC, 16) != 0)
100 uint16_t raw_ps = be16(buf + 16);
101 uint32_t page_size = (raw_ps == 1) ? 65536u : raw_ps;
105 if (page_size < 512 || page_size > 65536 || !is_pow2(page_size))
110 out->page_size = page_size;
111 out->write_version = buf[18];
112 out->read_version = buf[19];
113 out->reserved_per_page = buf[20];
114 out->file_change_counter = be32(buf + 24);
115 out->page_count = be32(buf + 28);
116 out->freelist_first = be32(buf + 32);
117 out->freelist_count = be32(buf + 36);
118 out->schema_cookie = be32(buf + 40);
119 out->schema_format = be32(buf + 44);
120 out->text_encoding = be32(buf + 56);
121 out->user_version = be32(buf + 60);
122 out->application_id = be32(buf + 68);
123 out->pc_sqlite_version = be32(buf + 96);
127bool pc_sqlite_parse_btree_header(
const uint8_t *page,
size_t page_len,
size_t offset, SqliteBtreeHeader *out)
129 if (offset + 8 > page_len)
133 const uint8_t *p = page + offset;
136 (type == SqliteBtree::SQLITE_BTREE_INTERIOR_INDEX || type == SqliteBtree::SQLITE_BTREE_INTERIOR_TABLE);
137 bool leaf = (type == SqliteBtree::SQLITE_BTREE_LEAF_INDEX || type == SqliteBtree::SQLITE_BTREE_LEAF_TABLE);
138 if (!interior && !leaf)
142 uint8_t hdr = interior ? 12 : 8;
143 if (offset + hdr > page_len)
149 out->first_freeblock = be16(p + 1);
150 out->cell_count = be16(p + 3);
151 uint16_t ccs = be16(p + 5);
152 out->cell_content_start = (ccs == 0) ? 65536u : ccs;
153 out->frag_free_bytes = p[7];
154 out->right_most_page = interior ? be32(p + 8) : 0;
155 out->header_size = hdr;
159uint32_t pc_sqlite_cell_pointer(
const uint8_t *page,
size_t page_len,
const SqliteBtreeHeader *bh,
size_t page_offset,
162 if (i >= bh->cell_count)
166 size_t at = page_offset + bh->header_size + (size_t)i * 2;
167 if (at + 2 > page_len)
171 return be16(page + at);
174bool pc_sqlite_parse_table_leaf_cell(
const uint8_t *page,
size_t page_len, uint32_t page_size, uint8_t reserved,
175 uint32_t cell_off, SqliteTableLeafCell *out)
177 if (cell_off >= page_len)
181 uint64_t payload_len = 0;
183 size_t n1 = pc_sqlite_varint_decode(page + cell_off, page_len - cell_off, &payload_len);
188 size_t n2 = pc_sqlite_varint_decode(page + cell_off + n1, page_len - cell_off - n1, &rowid);
195 uint32_t usable = page_size - reserved;
196 uint32_t max_local = usable - 35;
197 uint32_t min_local = ((usable - 12) * 32) / 255 - 23;
199 if (payload_len <= max_local)
201 local = (uint32_t)payload_len;
205 uint32_t k = min_local + (uint32_t)((payload_len - min_local) % (usable - 4));
206 local = (k <= max_local) ? k : min_local;
210 out->payload_len = (uint32_t)payload_len;
211 out->local_off = cell_off + (uint32_t)(n1 + n2);
212 out->local_len = local;
213 out->has_overflow = local < payload_len;
214 if (out->local_off + local > page_len)
221bool pc_sqlite_read_payload(SqlitePageReader read,
void *ctx, uint32_t page_size, uint8_t reserved,
222 const uint8_t *leaf_page,
const SqliteTableLeafCell *cell, uint8_t *out, uint32_t out_cap,
225 if (cell->payload_len > out_cap)
229 if ((
size_t)cell->local_off + cell->local_len > page_size)
234 memcpy(out, leaf_page + cell->local_off, cell->local_len);
235 uint32_t got = cell->local_len;
236 if (!cell->has_overflow)
238 return got == cell->payload_len;
242 size_t ptr_off = (size_t)cell->local_off + cell->local_len;
243 if (ptr_off + 4 > page_size)
247 uint32_t next = be32(leaf_page + ptr_off);
249 uint32_t usable = page_size - reserved;
250 uint32_t content = usable - 4;
257 uint32_t max_pages = cell->payload_len / content + 2;
259 for (uint32_t pages = 0; next != 0 && got < cell->payload_len; pages++)
263 if (pages >= max_pages)
267 if (!read(ctx, next, work_page, page_size))
271 uint32_t nnext = be32(work_page);
272 uint32_t chunk = cell->payload_len - got;
279 if (got + chunk > out_cap)
283 memcpy(out + got, work_page + 4, chunk);
287 return got == cell->payload_len;
290bool pc_sqlite_record_begin(SqliteRecordCursor *c,
const uint8_t *rec, uint32_t rec_len)
292 uint64_t hdr_len = 0;
293 size_t n = pc_sqlite_varint_decode(rec, rec_len, &hdr_len);
294 if (n == 0 || hdr_len > rec_len || hdr_len < n)
299 c->rec_len = rec_len;
300 c->hdr_pos = (uint32_t)n;
301 c->hdr_end = (uint32_t)hdr_len;
302 c->val_pos = (uint32_t)hdr_len;
306bool pc_sqlite_record_next(SqliteRecordCursor *c, uint64_t *serial_type,
const uint8_t **val, uint32_t *val_len)
308 if (c->hdr_pos >= c->hdr_end)
313 size_t n = pc_sqlite_varint_decode(c->rec + c->hdr_pos, c->hdr_end - c->hdr_pos, &st);
318 uint32_t sz = (uint32_t)pc_sqlite_serial_type_size(st);
319 if (c->val_pos + sz > c->rec_len)
324 *val = c->rec + c->val_pos;
326 c->hdr_pos += (uint32_t)n;
331int64_t pc_sqlite_column_int(uint64_t serial_type,
const uint8_t *val, uint32_t val_len)
333 if (serial_type == 8)
337 if (serial_type == 9)
341 if (serial_type < 1 || serial_type > 6)
345 size_t nbytes = (size_t)pc_sqlite_serial_type_size(serial_type);
346 if (val_len < nbytes)
351 for (
size_t i = 0; i < nbytes; i++)
353 u = (u << 8) | val[i];
355 size_t bits = nbytes * 8;
356 if (bits < 64 && (u & (1ULL << (bits - 1))))
358 u |= ~((1ULL << bits) - 1);
363double pc_sqlite_column_float(
const uint8_t *val, uint32_t val_len)
370 for (
int i = 0; i < 8; i++)
372 u = (u << 8) | val[i];
382size_t page_hdr_off(uint32_t pgno)
384 return pgno == 1 ? 100 : 0;
389uint32_t interior_child(
const uint8_t *page,
size_t page_len,
const SqliteBtreeHeader *h,
size_t off, uint16_t i)
391 if (i >= h->cell_count)
393 return h->right_most_page;
395 uint32_t cp = pc_sqlite_cell_pointer(page, page_len, h, off, i);
396 if (cp == 0 || (
size_t)cp + 4 > page_len)
400 return be32(page + cp);
404bool cursor_descend(SqliteTableCursor *c, uint32_t pgno)
408 if (!c->read(c->ctx, pgno, c->work, c->page_size))
412 size_t off = page_hdr_off(pgno);
414 if (!pc_sqlite_parse_btree_header(c->work, c->page_size, off, &h))
418 if (h.type == SqliteBtree::SQLITE_BTREE_LEAF_TABLE)
420 memcpy(c->leaf, c->work, c->page_size);
422 c->leaf_off = (uint32_t)off;
424 c->leaf_count = h.cell_count;
428 if (h.type != SqliteBtree::SQLITE_BTREE_INTERIOR_TABLE)
432 if (c->depth >= SQLITE_BTREE_MAX_DEPTH)
436 uint32_t child = interior_child(c->work, c->page_size, &h, off, 0);
441 c->stack_pg[c->depth] = pgno;
442 c->stack_idx[c->depth] = 1;
449bool pc_sqlite_table_cursor_begin(SqliteTableCursor *c, SqlitePageReader read,
void *ctx, uint32_t page_size,
450 uint8_t reserved, uint32_t rootpage, uint8_t *leaf_buf, uint8_t *work_buf)
454 c->page_size = page_size;
455 c->reserved = reserved;
458 c->ovf_buf =
nullptr;
463 return cursor_descend(c, rootpage);
466void pc_sqlite_table_cursor_set_overflow_buf(SqliteTableCursor *c, uint8_t *buf, uint32_t cap)
474static bool pc_sqlite_cursor_begin_row(SqliteTableCursor *c,
const SqliteTableLeafCell *cell, SqliteRecordCursor *row)
476 if (!cell->has_overflow || !c->ovf_buf)
478 return pc_sqlite_record_begin(row, c->leaf + cell->local_off, cell->local_len);
481 if (!pc_sqlite_read_payload(c->read, c->ctx, c->page_size, c->reserved, c->leaf, cell, c->ovf_buf, c->ovf_cap,
486 return pc_sqlite_record_begin(row, c->ovf_buf, cell->payload_len);
489bool pc_sqlite_table_cursor_next(SqliteTableCursor *c, uint64_t *rowid, SqliteRecordCursor *row)
493 if (c->leaf_cell < c->leaf_count)
495 uint32_t cp = pc_sqlite_cell_pointer(c->leaf, c->page_size, &c->leaf_hdr, c->leaf_off, c->leaf_cell);
501 SqliteTableLeafCell cell;
502 if (!pc_sqlite_parse_table_leaf_cell(c->leaf, c->page_size, c->page_size, c->reserved, cp, &cell))
506 if (!pc_sqlite_cursor_begin_row(c, &cell, row))
518 int top = c->depth - 1;
519 if (!c->read(c->ctx, c->stack_pg[top], c->work, c->page_size))
523 size_t off = page_hdr_off(c->stack_pg[top]);
525 if (!pc_sqlite_parse_btree_header(c->work, c->page_size, off, &h))
529 if (c->stack_idx[top] <= h.cell_count)
531 uint32_t child = interior_child(c->work, c->page_size, &h, off, c->stack_idx[top]);
533 if (child == 0 || !cursor_descend(c, child))
551void wr_be16(uint8_t *p, uint16_t v)
553 p[0] = (uint8_t)(v >> 8);
556void wr_be32(uint8_t *p, uint32_t v)
558 p[0] = (uint8_t)(v >> 24);
559 p[1] = (uint8_t)(v >> 16);
560 p[2] = (uint8_t)(v >> 8);
565size_t varint_len(uint64_t v)
575 if (v <= 0x1fffffULL)
579 if (v <= 0xfffffffULL)
583 if (v <= 0x7ffffffffULL)
587 if (v <= 0x3ffffffffffULL)
591 if (v <= 0x1ffffffffffffULL)
595 if (v <= 0xffffffffffffffULL)
603void value_serial(
const SqliteValue *v, uint64_t *st, uint32_t *vlen)
607 case SqliteColType::SQLITE_COL_NULL:
611 case SqliteColType::SQLITE_COL_FLOAT:
615 case SqliteColType::SQLITE_COL_TEXT:
616 *st = 13 + (uint64_t)2 * v->len;
619 case SqliteColType::SQLITE_COL_BLOB:
620 *st = 12 + (uint64_t)2 * v->len;
623 case SqliteColType::SQLITE_COL_INT:
638 else if (x >= -128 && x <= 127)
643 else if (x >= -32768 && x <= 32767)
648 else if (x >= -8388608 && x <= 8388607)
653 else if (x >= -2147483648LL && x <= 2147483647LL)
658 else if (x >= -140737488355328LL && x <= 140737488355327LL)
671uint32_t write_value(
const SqliteValue *v, uint64_t st, uint32_t vlen, uint8_t *out)
673 if (v->type == SqliteColType::SQLITE_COL_TEXT || v->type == SqliteColType::SQLITE_COL_BLOB)
677 memcpy(out, v->data, vlen);
681 if (v->type == SqliteColType::SQLITE_COL_FLOAT)
684 memcpy(&u, &v->f, 8);
685 for (
int i = 7; i >= 0; i--)
687 *out++ = (uint8_t)(u >> (i * 8));
691 if (st >= 1 && st <= 6)
693 uint64_t u = (uint64_t)v->i;
694 for (
int i = (
int)vlen - 1; i >= 0; i--)
696 out[(int)vlen - 1 - i] = (uint8_t)(u >> (i * 8));
704uint32_t record_len(
const SqliteValue *cols, uint32_t n)
707 uint32_t val_len = 0;
708 for (uint32_t c = 0; c < n; c++)
712 value_serial(&cols[c], &st, &vl);
713 st_len += (uint32_t)varint_len(st);
717 size_t hs_varlen = 1;
720 uint64_t hs = hs_varlen + st_len;
721 if (varint_len(hs) == hs_varlen)
725 hs_varlen = varint_len(hs);
727 return (uint32_t)hs_varlen + st_len + val_len;
732bool write_leaf_page(uint8_t *page, uint32_t page_size, uint32_t hdr_off,
const SqliteRow *rows, uint32_t nrows)
734 const uint32_t usable = page_size;
735 const uint32_t max_local = usable - 35;
739 for (uint32_t r = 0; r < nrows; r++)
741 uint32_t rl = record_len(rows[r].cols, rows[r].ncols);
744 if (rl == 0 && rows[r].ncols != 0)
752 total += (uint32_t)varint_len(rl) + (uint32_t)varint_len(rows[r].rowid) + rl;
754 uint32_t header_end = hdr_off + 8 + 2 * nrows;
755 if ((uint64_t)header_end + total > page_size)
760 uint32_t content_start = page_size - total;
763 uint8_t *h = page + hdr_off;
764 h[0] = (uint8_t)SqliteBtree::SQLITE_BTREE_LEAF_TABLE;
766 wr_be16(h + 3, (uint16_t)nrows);
767 wr_be16(h + 5, (uint16_t)(content_start == 65536 ? 0 : content_start));
771 uint32_t off = page_size;
772 for (uint32_t r = 0; r < nrows; r++)
774 uint32_t rl = record_len(rows[r].cols, rows[r].ncols);
775 uint32_t cell_len = (uint32_t)varint_len(rl) + (uint32_t)varint_len(rows[r].rowid) + rl;
777 uint8_t *cp = page + off;
778 size_t k = pc_sqlite_varint_encode(rl, cp, cell_len);
779 k += pc_sqlite_varint_encode(rows[r].rowid, cp + k, cell_len - k);
780 uint32_t w = pc_sqlite_encode_record(rows[r].cols, rows[r].ncols, cp + k, cell_len - (uint32_t)k);
792 wr_be16(page + hdr_off + 8 + 2 * r, (uint16_t)off);
798size_t pc_sqlite_varint_encode(uint64_t v, uint8_t *out,
size_t cap)
800 size_t n = varint_len(v);
808 for (
int i = 0; i < 8; i++)
810 out[i] = (uint8_t)(0x80 | (uint8_t)((v >> (57 - 7 * i)) & 0x7f));
816 for (
size_t i = 0; i < n; i++)
818 uint8_t bits = (uint8_t)((v >> (7 * (n - 1 - i))) & 0x7f);
819 out[i] = (i + 1 < n) ? (uint8_t)(bits | 0x80) : bits;
824uint32_t pc_sqlite_encode_record(
const SqliteValue *cols, uint32_t n, uint8_t *out, uint32_t out_cap)
826 uint32_t total = record_len(cols, n);
828 if (total == 0 && n != 0)
839 for (uint32_t c = 0; c < n; c++)
843 value_serial(&cols[c], &st, &vl);
844 st_len += (uint32_t)varint_len(st);
846 size_t hs_varlen = 1;
849 uint64_t hs = hs_varlen + st_len;
850 if (varint_len(hs) == hs_varlen)
854 hs_varlen = varint_len(hs);
856 uint32_t header_size = (uint32_t)hs_varlen + st_len;
858 uint32_t pos = (uint32_t)pc_sqlite_varint_encode(header_size, out, out_cap);
860 for (uint32_t c = 0; c < n; c++)
864 value_serial(&cols[c], &st, &vl);
865 pos += (uint32_t)pc_sqlite_varint_encode(st, out + pos, out_cap - pos);
868 for (uint32_t c = 0; c < n; c++)
872 value_serial(&cols[c], &st, &vl);
873 pos += write_value(&cols[c], st, vl, out + pos);
878uint32_t pc_sqlite_build_table_db(uint32_t page_size,
const char *table_name,
const char *create_sql,
879 const SqliteRow *rows, uint32_t nrows, uint8_t *out, uint32_t out_cap)
881 if (page_size < 512 || page_size > 65536 || !is_pow2(page_size))
885 if ((uint64_t)page_size * 2 > out_cap || !table_name || !create_sql)
890 memset(out, 0, (
size_t)page_size * 2);
893 memcpy(out, SQLITE_MAGIC, 16);
894 wr_be16(out + 16, (uint16_t)(page_size == 65536 ? 1 : page_size));
901 wr_be32(out + 24, 1);
902 wr_be32(out + 28, 2);
903 wr_be32(out + 40, 1);
904 wr_be32(out + 44, 4);
905 wr_be32(out + 56, 1);
906 wr_be32(out + 92, 1);
907 wr_be32(out + 96, 3046001);
910 uint32_t name_len = (uint32_t)strnlen(table_name, out_cap);
911 uint32_t sql_len = (uint32_t)strnlen(create_sql, out_cap);
912 SqliteValue master[5];
913 master[0] = {SqliteColType::SQLITE_COL_TEXT, 0, 0, (
const uint8_t *)
"table", 5};
914 master[1] = {SqliteColType::SQLITE_COL_TEXT, 0, 0, (
const uint8_t *)table_name, name_len};
915 master[2] = {SqliteColType::SQLITE_COL_TEXT, 0, 0, (
const uint8_t *)table_name, name_len};
916 master[3] = {SqliteColType::SQLITE_COL_INT, 2, 0,
nullptr, 0};
917 master[4] = {SqliteColType::SQLITE_COL_TEXT, 0, 0, (
const uint8_t *)create_sql, sql_len};
918 SqliteRow master_row = {1, master, 5};
919 if (!write_leaf_page(out, page_size, 100, &master_row, 1))
925 if (!write_leaf_page(out + page_size, page_size, 0, rows, nrows))
930 return page_size * 2;