chore: migrate project into clean repository

This commit is contained in:
yuuux
2026-08-13 16:50:52 +08:00
commit d1d25a09e7
27405 changed files with 9422808 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
.DS_Store
.vscode

View File

@@ -0,0 +1,46 @@
if(CONFIG_CSK_SQLITE)
if(CONFIG_CSK_SQLITE_SDK_CSK6)
zephyr_library_named(csk_sqlite3)
zephyr_include_directories(
include
private_include
)
zephyr_library_sources(
sqlite3.c
shox96_0_2.c
csk6_sqlite3.c
)
elseif(CONFIG_CSK_SQLITE_SDK_ARCS)
set(LIBRARY_NAME csk_sqlite3)
add_library(${LIBRARY_NAME} STATIC "")
target_include_directories(${LIBRARY_NAME} PUBLIC
include
)
target_include_directories(${LIBRARY_NAME} PRIVATE
private_include
)
set(SOURCES
sqlite3.c
shox96_0_2.c
arcs_sqlite3.c
)
target_sources(${LIBRARY_NAME} PRIVATE
${SOURCES}
)
target_compile_options(${LIBRARY_NAME} PRIVATE -w -fno-fast-math)
target_compile_definitions(${LIBRARY_NAME} PUBLIC -DSQLITE_HAS_CODEC=1)
target_link_libraries(${LIBRARY_NAME} PUBLIC lsfs)
if(DEFINED LISTENAI_CMAKE_PATH)
listenai_link_libraries(${LIBRARY_NAME})
endif()
endif()
endif()

View File

@@ -0,0 +1,33 @@
# SPDX-License-Identifier: BSD-3-Clause
menuconfig CSK_SQLITE
bool "CSK SQLite"
if CSK_SQLITE
choice CSK_SQLITE_SDK
prompt "Select SDK Type"
default CSK_SQLITE_SDK_CSK6
config CSK_SQLITE_SDK_CSK6
bool "CSK6 SDK"
help
Use CSK6 SDK for SQLite implementation
config CSK_SQLITE_SDK_ARCS
bool "ARCS SDK"
help
Use ARCS SDK for SQLite implementation
endchoice
config CSK_SQLITE_CSK_MEM
bool "CSK SQLite CSK Memory"
default y if CSK_SQLITE_SDK_CSK6
if CSK_SQLITE_SDK_ARCS
config CSK_SQLITE_ARCS_MEM_RAM
bool "CSK SQLite ARCS RAM Memory"
default n
endif
endif

View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

View File

@@ -0,0 +1,757 @@
/* From: https://chromium.googlesource.com/chromium/src.git/+/4.1.249.1050/third_party/sqlite/src/os_symbian.cc
* https://github.com/spsoft/spmemvfs/tree/master/spmemvfs
* http://www.sqlite.org/src/doc/trunk/src/test_demovfs.c
* http://www.sqlite.org/src/doc/trunk/src/test_vfstrace.c
* http://www.sqlite.org/src/doc/trunk/src/test_onefile.c
* http://www.sqlite.org/src/doc/trunk/src/test_vfs.c
* https://github.com/nodemcu/nodemcu-firmware/blob/master/app/sqlite3/esp8266.c
**/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <time.h>
// #include <unistd.h>
#include <sqlite3.h>
#include <sys/stat.h>
#include "shox96_0_2.h"
#include <lsfs.h>
#include "sqlite3_malloc.c"
#define UNUSED(x) (void)(x)
#undef dbg_printf
// #define dbg_printf(...) printf(__VA_ARGS__)
#define dbg_printf(...)
#define CACHEBLOCKSZ 64
#define csk_DEFAULT_MAXNAMESIZE 100
// From https://stackoverflow.com/questions/19758270/read-varint-from-linux-sockets#19760246
// Encode an unsigned 64-bit varint. Returns number of encoded bytes.
// 'buffer' must have room for up to 10 bytes.
int encode_unsigned_varint(uint8_t *buffer, uint64_t value)
{
int encoded = 0;
do {
uint8_t next_byte = value & 0x7F;
value >>= 7;
if (value)
next_byte |= 0x80;
buffer[encoded++] = next_byte;
} while (value);
return encoded;
}
uint64_t decode_unsigned_varint(const uint8_t *data, int *decoded_bytes)
{
int i = 0;
uint64_t decoded_value = 0;
int shift_amount = 0;
do {
decoded_value |= (uint64_t)(data[i] & 0x7F) << shift_amount;
shift_amount += 7;
} while ((data[i++] & 0x80) != 0);
*decoded_bytes = i;
return decoded_value;
}
int csk_Close(sqlite3_file *);
int csk_Lock(sqlite3_file *, int);
int csk_Unlock(sqlite3_file *, int);
int csk_Sync(sqlite3_file *, int);
int csk_Open(sqlite3_vfs *, const char *, sqlite3_file *, int, int *);
int csk_Read(sqlite3_file *, void *, int, sqlite3_int64);
int csk_Write(sqlite3_file *, const void *, int, sqlite3_int64);
int csk_Truncate(sqlite3_file *, sqlite3_int64);
int csk_Delete(sqlite3_vfs *, const char *, int);
int csk_FileSize(sqlite3_file *, sqlite3_int64 *);
int csk_Access(sqlite3_vfs *, const char *, int, int *);
int csk_FullPathname(sqlite3_vfs *, const char *, int, char *);
int csk_CheckReservedLock(sqlite3_file *, int *);
int csk_FileControl(sqlite3_file *, int, void *);
int csk_SectorSize(sqlite3_file *);
int csk_DeviceCharacteristics(sqlite3_file *);
void *csk_DlOpen(sqlite3_vfs *, const char *);
void csk_DlError(sqlite3_vfs *, int, char *);
void (*csk_DlSym(sqlite3_vfs *, void *, const char *))(void);
void csk_DlClose(sqlite3_vfs *, void *);
int csk_Randomness(sqlite3_vfs *, int, char *);
int csk_Sleep(sqlite3_vfs *, int);
int csk_CurrentTime(sqlite3_vfs *, double *);
int cskmem_Close(sqlite3_file *);
int cskmem_Read(sqlite3_file *, void *, int, sqlite3_int64);
int cskmem_Write(sqlite3_file *, const void *, int, sqlite3_int64);
int cskmem_FileSize(sqlite3_file *, sqlite3_int64 *);
int cskmem_Sync(sqlite3_file *, int);
typedef struct st_linkedlist {
uint16_t blockid;
struct st_linkedlist *next;
uint8_t data[CACHEBLOCKSZ];
} linkedlist_t, *pLinkedList_t;
typedef struct st_filecache {
uint32_t size;
linkedlist_t *list;
} filecache_t, *pFileCache_t;
typedef struct csk_file {
sqlite3_file base;
struct lsfs_file_t *fd;
filecache_t *cache;
char name[csk_DEFAULT_MAXNAMESIZE];
} csk_file;
sqlite3_vfs cskVfs = {
1, // iVersion
sizeof(csk_file), // szOsFile
101, // mxPathname
NULL, // pNext
"csk", // name
0, // pAppData
csk_Open, // xOpen
csk_Delete, // xDelete
csk_Access, // xAccess
csk_FullPathname, // xFullPathname
csk_DlOpen, // xDlOpen
csk_DlError, // xDlError
csk_DlSym, // xDlSym
csk_DlClose, // xDlClose
csk_Randomness, // xRandomness
csk_Sleep, // xSleep
csk_CurrentTime, // xCurrentTime
0 // xGetLastError
};
const sqlite3_io_methods cskIoMethods = { 1,
csk_Close,
csk_Read,
csk_Write,
csk_Truncate,
csk_Sync,
csk_FileSize,
csk_Lock,
csk_Unlock,
csk_CheckReservedLock,
csk_FileControl,
csk_SectorSize,
csk_DeviceCharacteristics };
const sqlite3_io_methods cskMemMethods = { 1,
cskmem_Close,
cskmem_Read,
cskmem_Write,
csk_Truncate,
cskmem_Sync,
cskmem_FileSize,
csk_Lock,
csk_Unlock,
csk_CheckReservedLock,
csk_FileControl,
csk_SectorSize,
csk_DeviceCharacteristics };
uint32_t linkedlist_store(linkedlist_t **leaf, uint32_t offset, uint32_t len, const uint8_t *data)
{
const uint8_t blank[CACHEBLOCKSZ] = { 0 };
uint16_t blockid = offset / CACHEBLOCKSZ;
linkedlist_t *block;
if (!memcmp(data, blank, CACHEBLOCKSZ))
return len;
block = *leaf;
if (!block || (block->blockid != blockid)) {
block = (linkedlist_t *)sqlite3_malloc(sizeof(linkedlist_t));
if (!block)
return SQLITE_NOMEM;
memset(block->data, 0, CACHEBLOCKSZ);
block->blockid = blockid;
}
if (!*leaf) {
*leaf = block;
block->next = NULL;
} else if (block != *leaf) {
if (block->blockid > (*leaf)->blockid) {
block->next = (*leaf)->next;
(*leaf)->next = block;
} else {
block->next = (*leaf);
(*leaf) = block;
}
}
memcpy(block->data + offset % CACHEBLOCKSZ, data, len);
return len;
}
uint32_t filecache_pull(pFileCache_t cache, uint32_t offset, uint32_t len, uint8_t *data)
{
uint16_t i;
float blocks;
uint32_t r = 0;
blocks = (offset % CACHEBLOCKSZ + len) / (float)CACHEBLOCKSZ;
if (blocks == 0.0)
return 0;
if (!cache->list)
return 0;
if ((blocks - (int)blocks) > 0.0)
blocks = blocks + 1.0;
for (i = 0; i < (uint16_t)blocks; i++) {
uint16_t round;
float relablock;
linkedlist_t *leaf;
uint32_t relaoffset, relalen;
uint8_t *reladata = (uint8_t *)data;
relalen = len - r;
reladata = reladata + r;
relaoffset = offset + r;
round = CACHEBLOCKSZ - relaoffset % CACHEBLOCKSZ;
if (relalen > round)
relalen = round;
for (leaf = cache->list; leaf && leaf->next; leaf = leaf->next) {
if ((leaf->next->blockid * CACHEBLOCKSZ) > relaoffset)
break;
}
relablock = relaoffset / ((float)CACHEBLOCKSZ) - leaf->blockid;
if ((relablock >= 0) && (relablock < 1))
memcpy(data + r, leaf->data + (relaoffset % CACHEBLOCKSZ), relalen);
r = r + relalen;
}
return 0;
}
uint32_t filecache_push(pFileCache_t cache, uint32_t offset, uint32_t len, const uint8_t *data)
{
uint16_t i;
float blocks;
uint32_t r = 0;
uint8_t updateroot = 0x1;
blocks = (offset % CACHEBLOCKSZ + len) / (float)CACHEBLOCKSZ;
if (blocks == 0.0)
return 0;
if ((blocks - (int)blocks) > 0.0)
blocks = blocks + 1.0;
for (i = 0; i < (uint16_t)blocks; i++) {
uint16_t round;
uint32_t localr;
linkedlist_t *leaf;
uint32_t relaoffset, relalen;
uint8_t *reladata = (uint8_t *)data;
relalen = len - r;
reladata = reladata + r;
relaoffset = offset + r;
round = CACHEBLOCKSZ - relaoffset % CACHEBLOCKSZ;
if (relalen > round)
relalen = round;
for (leaf = cache->list; leaf && leaf->next; leaf = leaf->next) {
if ((leaf->next->blockid * CACHEBLOCKSZ) > relaoffset)
break;
updateroot = 0x0;
}
localr = linkedlist_store(&leaf, relaoffset,
(relalen > CACHEBLOCKSZ) ? CACHEBLOCKSZ : relalen,
reladata);
if (localr == SQLITE_NOMEM)
return SQLITE_NOMEM;
r = r + localr;
if (updateroot & 0x1)
cache->list = leaf;
}
if (offset + len > cache->size)
cache->size = offset + len;
return r;
}
void filecache_free(pFileCache_t cache)
{
pLinkedList_t ll = cache->list, next;
while (ll != NULL) {
next = ll->next;
sqlite3_free(ll);
ll = next;
}
}
int cskmem_Close(sqlite3_file *id)
{
csk_file *file = (csk_file *)id;
// printf("cskmem_Close: file->fd %p\n", file->fd);
// lsfs_close(file->fd);
filecache_free(file->cache);
sqlite3_free(file->cache);
dbg_printf("cskmem_Close: %s OK\n", file->name);
return SQLITE_OK;
}
int cskmem_Read(sqlite3_file *id, void *buffer, int amount, sqlite3_int64 offset)
{
int32_t ofst;
csk_file *file = (csk_file *)id;
ofst = (int32_t)(offset & 0x7FFFFFFF);
filecache_pull(file->cache, ofst, amount, (uint8_t *)buffer);
dbg_printf("cskmem_Read: %s [%d] [%d] OK\n", file->name, ofst, amount);
return SQLITE_OK;
}
int cskmem_Write(sqlite3_file *id, const void *buffer, int amount, sqlite3_int64 offset)
{
int32_t ofst;
csk_file *file = (csk_file *)id;
ofst = (int32_t)(offset & 0x7FFFFFFF);
filecache_push(file->cache, ofst, amount, (const uint8_t *)buffer);
dbg_printf("cskmem_Write: %s [%d] [%d] OK\n", file->name, ofst, amount);
return SQLITE_OK;
}
int cskmem_Sync(sqlite3_file *id, int flags)
{
csk_file *file = (csk_file *)id;
UNUSED(file);
dbg_printf("cskmem_Sync: %s OK\n", file->name);
return SQLITE_OK;
}
int cskmem_FileSize(sqlite3_file *id, sqlite3_int64 *size)
{
csk_file *file = (csk_file *)id;
*size = 0LL | file->cache->size;
dbg_printf("cskmem_FileSize: %s [%d] OK\n", file->name, file->cache->size);
return SQLITE_OK;
}
int csk_Open(sqlite3_vfs *vfs, const char *path, sqlite3_file *file, int flags, int *outflags)
{
int rc;
csk_file *p = (csk_file *)file;
lsfs_mode_t mode = LSFS_O_READ;
if (path == NULL)
return SQLITE_IOERR;
dbg_printf("csk_Open: 0o %s %0x\n", path, mode);
if (flags & SQLITE_OPEN_CREATE) {
mode |= LSFS_O_CREATE;
}
if (flags & SQLITE_OPEN_READONLY)
mode |= LSFS_O_READ;
if (flags & SQLITE_OPEN_READWRITE || flags & SQLITE_OPEN_MAIN_JOURNAL) {
int result;
if (SQLITE_OK != csk_Access(vfs, path, flags, &result))
return SQLITE_CANTOPEN;
mode |= LSFS_O_RDWR;
}
dbg_printf("csk_Open: 1o %s %0x\n", path, mode);
memset(p, 0, sizeof(csk_file));
strncpy(p->name, path, csk_DEFAULT_MAXNAMESIZE);
p->name[csk_DEFAULT_MAXNAMESIZE - 1] = '\0';
if (flags & SQLITE_OPEN_MAIN_JOURNAL) {
p->fd = 0;
p->cache = (filecache_t *)sqlite3_malloc(sizeof(filecache_t));
if (!p->cache)
return SQLITE_NOMEM;
memset(p->cache, 0, sizeof(filecache_t));
p->base.pMethods = &cskMemMethods;
dbg_printf("csk_Open: 2o %s MEM OK\n", p->name);
return SQLITE_OK;
} else {
p->fd = (struct lsfs_file_t *)__sq_malloc(sizeof(struct lsfs_file_t));
if (!p->fd)
return SQLITE_NOMEM;
lsfs_file_t_init(p->fd);
}
rc = lsfs_open(p->fd, path, mode);
if (rc < 0) {
dbg_printf("FAIL: open %s: %d\n", path, rc);
return SQLITE_CANTOPEN;
}
p->base.pMethods = &cskIoMethods;
dbg_printf("csk_Open: 2o %s OK\n", p->name);
return SQLITE_OK;
}
int csk_Close(sqlite3_file *id)
{
csk_file *file = (csk_file *)id;
// int rc = fclose(file->fd);
int rc = lsfs_close(file->fd);
__sq_free(file->fd);
dbg_printf("csk_Close: %s %d\n", file->name, rc);
return rc ? SQLITE_IOERR_CLOSE : SQLITE_OK;
}
int csk_Read(sqlite3_file *id, void *buffer, int amount, sqlite3_int64 offset)
{
size_t nRead;
int32_t ofst, iofst;
csk_file *file = (csk_file *)id;
iofst = (int32_t)(offset & 0x7FFFFFFF);
dbg_printf("csk_Read: 1r %s %d %lld[%d] \n", file->name, amount, offset, iofst);
ofst = lsfs_seek(file->fd, iofst, SEEK_SET);
if (ofst != 0) {
dbg_printf("csk_Read: 2r %d != %d FAIL\n", ofst, iofst);
return SQLITE_IOERR_SHORT_READ /* SQLITE_IOERR_SEEK */;
}
nRead = lsfs_read(file->fd, buffer, amount);
if (nRead == amount) {
dbg_printf("csk_Read: 3r %s %u %d OK\n", file->name, nRead, amount);
return SQLITE_OK;
} else if (nRead >= 0) {
dbg_printf("csk_Read: 3r %s %u %d FAIL\n", file->name, nRead, amount);
return SQLITE_IOERR_SHORT_READ;
}
dbg_printf("csk_Read: 4r %s FAIL\n", file->name);
return SQLITE_IOERR_READ;
}
int csk_Write(sqlite3_file *id, const void *buffer, int amount, sqlite3_int64 offset)
{
size_t nWrite;
int32_t ofst, iofst;
csk_file *file = (csk_file *)id;
iofst = (int32_t)(offset & 0x7FFFFFFF);
dbg_printf("csk_Write: 1w %s %d %lld[%d] \n", file->name, amount, offset, iofst);
ofst = lsfs_seek(file->fd, iofst, SEEK_SET);
if (ofst != 0) {
return SQLITE_IOERR_SEEK;
}
dbg_printf("csk_Write: 1.1w %s %d %lld[%d] \n", file->name, amount, offset, iofst);
nWrite = lsfs_write(file->fd, buffer, amount);
if (nWrite != amount) {
dbg_printf("csk_Write: 2w %s %u %d\n", file->name, nWrite, amount);
return SQLITE_IOERR_WRITE;
}
dbg_printf("csk_Write: 3w %s OK\n", file->name);
return SQLITE_OK;
}
int csk_Truncate(sqlite3_file *id, sqlite3_int64 bytes)
{
csk_file *file = (csk_file *)id;
UNUSED(file);
int fno = lsfs_truncate(file->fd, bytes);
if (fno != 0)
return SQLITE_IOERR_TRUNCATE;
//if (ftruncate(fno, 0))
// return SQLITE_IOERR_TRUNCATE;
dbg_printf("csk_Truncate:\n");
return SQLITE_OK;
}
int csk_Delete(sqlite3_vfs *vfs, const char *path, int syncDir)
{
// dbg_printf("csk_Delete: start delete\n");
struct lsfs_dirent dirent;
int32_t rc = SQLITE_IOERR_DELETE;
if (lsfs_stat(path, &dirent) >= 0) {
rc = lsfs_unlink(path);
}
if (rc)
return SQLITE_IOERR_DELETE;
dbg_printf("csk_Delete: %s OK\n", path);
return SQLITE_OK;
}
int csk_FileSize(sqlite3_file *id, sqlite3_int64 *size)
{
csk_file *file = (csk_file *)id;
dbg_printf("csk_FileSize: %s: ", file->name);
struct lsfs_dirent st;
// int fno = fileno(file->fd);
// if (fno == -1)
// return SQLITE_IOERR_FSTAT;
if (lsfs_stat(file->name, &st))
return SQLITE_IOERR_FSTAT;
*size = st.size;
dbg_printf(" %d[%lld]\n", st.size, *size);
return SQLITE_OK;
}
int csk_Sync(sqlite3_file *id, int flags)
{
csk_file *file = (csk_file *)id;
// int rc = fflush( file->fd );
lsfs_sync(file->fd);
dbg_printf("csk_Sync( %s: ) \n", file->name);
return SQLITE_OK;
}
int csk_Access(sqlite3_vfs *vfs, const char *path, int flags, int *result)
{
struct lsfs_dirent st;
memset(&st, 0, sizeof(struct lsfs_dirent));
int rc = lsfs_stat(path, &st);
// *result = ( rc != -1 );
*result = (rc >= 0);
dbg_printf("csk_Access: %s %d %d %d\n", path, *result, rc, st.size);
return SQLITE_OK;
}
int csk_FullPathname(sqlite3_vfs *vfs, const char *path, int len, char *fullpath)
{
//structure stat does not have name.
//struct stat st;
//int32_t rc = stat( path, &st );
//if ( rc == 0 ){
// strncpy( fullpath, st.name, len );
//} else {
// strncpy( fullpath, path, len );
//}
// As now just copy the path
strncpy(fullpath, path, len);
fullpath[len - 1] = '\0';
dbg_printf("csk_FullPathname: %s\n", fullpath);
return SQLITE_OK;
}
int csk_Lock(sqlite3_file *id, int lock_type)
{
csk_file *file = (csk_file *)id;
UNUSED(file);
dbg_printf("csk_Lock:Not locked\n");
return SQLITE_OK;
}
int csk_Unlock(sqlite3_file *id, int lock_type)
{
csk_file *file = (csk_file *)id;
UNUSED(file);
dbg_printf("csk_Unlock:\n");
return SQLITE_OK;
}
int csk_CheckReservedLock(sqlite3_file *id, int *result)
{
csk_file *file = (csk_file *)id;
UNUSED(file);
*result = 0;
dbg_printf("csk_CheckReservedLock:\n");
return SQLITE_OK;
}
int csk_FileControl(sqlite3_file *id, int op, void *arg)
{
csk_file *file = (csk_file *)id;
UNUSED(file);
dbg_printf("csk_FileControl:\n");
return SQLITE_OK;
}
int csk_SectorSize(sqlite3_file *id)
{
// csk_file *file = (csk_file*) id;
// dbg_printf("csk_SectorSize:\n");
// return SPI_FLASH_SEC_SIZE;
return 1024; // todo
}
int csk_DeviceCharacteristics(sqlite3_file *id)
{
csk_file *file = (csk_file *)id;
UNUSED(file);
dbg_printf("csk_DeviceCharacteristics:\n");
return 0;
}
void *csk_DlOpen(sqlite3_vfs *vfs, const char *path)
{
dbg_printf("csk_DlOpen:\n");
return NULL;
}
void csk_DlError(sqlite3_vfs *vfs, int len, char *errmsg)
{
dbg_printf("csk_DlError:\n");
return;
}
void (*csk_DlSym(sqlite3_vfs *vfs, void *handle, const char *symbol))(void)
{
dbg_printf("csk_DlSym:\n");
return NULL;
}
void csk_DlClose(sqlite3_vfs *vfs, void *handle)
{
dbg_printf("csk_DlClose:\n");
return;
}
int csk_Randomness(sqlite3_vfs *vfs, int len, char *buffer)
{
long rdm;
int sz = 1 + (len / sizeof(long));
char a_rdm[sz * sizeof(long)];
while (sz--) {
rdm = rand();
memcpy(a_rdm + sz * sizeof(long), &rdm, sizeof(long));
}
memcpy(buffer, a_rdm, len);
dbg_printf("csk_Randomness\n");
return SQLITE_OK;
}
int csk_Sleep(sqlite3_vfs *vfs, int microseconds)
{
// ets_delay_us(microseconds);
dbg_printf("csk_Sleep:\n");
return SQLITE_OK;
}
int csk_CurrentTime(sqlite3_vfs *vfs, double *result)
{
// todo
// time_t t = time(NULL);
// *result = t / 86400.0 + 2440587.5;
// // This is stubbed out until we have a working RTCTIME solution;
// // as it stood, this would always have returned the UNIX epoch.
// //*result = 2440587.5;
// dbg_printf("csk_CurrentTime: %g\n", *result);
return SQLITE_OK;
}
static void shox96_0_2c(sqlite3_context *context, int argc, sqlite3_value **argv)
{
int nIn, nOut;
long int nOut2;
const unsigned char *inBuf;
unsigned char *outBuf;
unsigned char vInt[9];
int vIntLen;
// assert( argc==1 );
if (argc != 1) {
printf("shox96_0_2c: error\n");
return;
}
nIn = sqlite3_value_bytes(argv[0]);
inBuf = (unsigned char *)sqlite3_value_blob(argv[0]);
nOut = 13 + nIn + (nIn + 999) / 1000;
vIntLen = encode_unsigned_varint(vInt, (uint64_t)nIn);
outBuf = (unsigned char *)__sq_malloc(nOut + vIntLen);
memcpy(outBuf, vInt, vIntLen);
nOut2 = shox96_0_2_compress((const char *)inBuf, nIn, (char *)&outBuf[vIntLen], NULL);
sqlite3_result_blob(context, outBuf, nOut2 + vIntLen, __sq_free);
}
static void shox96_0_2d(sqlite3_context *context, int argc, sqlite3_value **argv)
{
unsigned int nIn, nOut;
const unsigned char *inBuf;
unsigned char *outBuf;
long int nOut2;
uint64_t inBufLen64;
int vIntLen;
// assert( argc==1 );
if (argc != 1) {
printf("shox96_0_2d: error\n");
return;
}
if (sqlite3_value_type(argv[0]) != SQLITE_BLOB)
return;
nIn = sqlite3_value_bytes(argv[0]);
if (nIn < 2) {
return;
}
inBuf = (unsigned char *)sqlite3_value_blob(argv[0]);
inBufLen64 = decode_unsigned_varint(inBuf, &vIntLen);
nOut = (unsigned int)inBufLen64;
outBuf = (unsigned char *)__sq_malloc(nOut);
//nOut2 = (long int)nOut;
nOut2 = shox96_0_2_decompress((const char *)(inBuf + vIntLen), nIn - vIntLen,
(char *)outBuf, NULL);
//if( rc!=Z_OK ){
// free(outBuf);
//}else{
sqlite3_result_blob(context, outBuf, nOut2, __sq_free);
//}
}
int registerShox96_0_2(sqlite3 *db, const char **pzErrMsg,
const struct sqlite3_api_routines *pThunk)
{
sqlite3_create_function(db, "shox96_0_2c", 1, SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
shox96_0_2c, 0, 0);
sqlite3_create_function(db, "shox96_0_2d", 1, SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
shox96_0_2d, 0, 0);
return SQLITE_OK;
}
int sqlite3_os_init(void)
{
sqlite3_vfs_register(&cskVfs, 1);
sqlite3_auto_extension((void (*)())registerShox96_0_2);
return SQLITE_OK;
}
int sqlite3_os_end(void)
{
return SQLITE_OK;
}

View File

@@ -0,0 +1,103 @@
#define BUILD_sqlite -DNDEBUG
#define SQLITE_CORE 1
#define SQLITE_NO_SYNC 1
#define YYSTACKDEPTH 20
#define SQLITE_TEMP_STORE 1
#define SQLITE_SYSTEM_MALLOC 1
#define SQLITE_OS_OTHER 1
#define SQLITE_THREADSAFE 0
#define SQLITE_MUTEX_APPDEF 1
#define SQLITE_SECURE_DELETE 0
#define SQLITE_SMALL_STACK 1
#define SQLITE_DISABLE_LFS 1
#define SQLITE_DISABLE_DIRSYNC 1
#define SQLITE_DISABLE_FTS3_UNICODE 1
#define SQLITE_DISABLE_FTS4_DEFERRED 1
#define SQLITE_DEFAULT_CACHE_SIZE -1
#define SQLITE_DEFAULT_FOREIGN_KEYS 0
#define SQLITE_DEFAULT_MEMSTATUS 0
#define SQLITE_DEFAULT_MMAP_SIZE 0
#define SQLITE_DEFAULT_LOCKING_MODE 1
#define SQLITE_DEFAULT_LOOKASIDE 512,128
#define SQLITE_DEFAULT_PAGE_SIZE 4096
#define SQLITE_DEFAULT_PCACHE_INITSZ 8
#define SQLITE_MAX_DEFAULT_PAGE_SIZE 32768
#define SQLITE_POWERSAFE_OVERWRITE 1
#define SQLITE_SORTER_PMASZ 4
#define SQLITE_MAX_EXPR_DEPTH 0
#undef SQLITE_OMIT_ALTERTABLE
#undef SQLITE_OMIT_ANALYZE
#undef SQLITE_OMIT_ATTACH
#define SQLITE_OMIT_AUTHORIZATION 1
#undef SQLITE_OMIT_AUTOINCREMENT
#define SQLITE_OMIT_AUTOINIT 1
#define SQLITE_OMIT_AUTOMATIC_INDEX 1
#define SQLITE_OMIT_AUTORESET 1
#define SQLITE_OMIT_AUTOVACUUM 1
#undef SQLITE_OMIT_BETWEEN_OPTIMIZATION
// #define SQLITE_OMIT_BLOB_LITERAL 1
// #define SQLITE_OMIT_BTREECOUNT 1
#define SQLITE_OMIT_BUILTIN_TEST 1
#define SQLITE_OMIT_CAST 1
// #define SQLITE_OMIT_CHECK 1
#define SQLITE_OMIT_COMPILEOPTION_DIAGS 1
// #define SQLITE_OMIT_COMPOUND_SELECT 1
#define SQLITE_OMIT_CONFLICT_CLAUSE 1
#undef SQLITE_OMIT_CTE
#define SQLITE_OMIT_DECLTYPE 1
#define SQLITE_OMIT_DEPRECATED 1
#undef SQLITE_OMIT_DISKIO
// #define SQLITE_OMIT_EXPLAIN 1
#define SQLITE_OMIT_FLAG_PRAGMAS 1
#define SQLITE_OMIT_FOREIGN_KEY 1
#define SQLITE_OMIT_GET_TABLE 1
#define SQLITE_OMIT_INCRBLOB 1
// #define SQLITE_OMIT_INTEGRITY_CHECK 1
#define SQLITE_OMIT_LOAD_EXTENSION 1
#define SQLITE_OMIT_LOCALTIME 1
#define SQLITE_OMIT_LOOKASIDE 1
#undef SQLITE_OMIT_MEMORYDB
#undef SQLITE_OMIT_OR_OPTIMIZATION
#undef SQLITE_OMIT_PAGER_PRAGMAS
#define SQLITE_OMIT_PARSER_TRACE 1
#undef SQLITE_OMIT_PRAGMA
#define SQLITE_OMIT_PROGRESS_CALLBACK 1
// #define SQLITE_OMIT_QUICKBALANCE 1
#undef SQLITE_OMIT_REINDEX
// #define SQLITE_OMIT_SCHEMA_PRAGMAS 1
// #define SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS 1
#define SQLITE_OMIT_SHARED_CACHE 1
#define SQLITE_OMIT_TCL_VARIABLE 1
#define SQLITE_OMIT_TEMPDB 1
#define SQLITE_OMIT_TRACE 1
#undef SQLITE_OMIT_TRIGGER
#define SQLITE_OMIT_TRUNCATE_OPTIMIZATION 1
#define SQLITE_OMIT_UTF16 1
#undef SQLITE_OMIT_VACUUM
#undef SQLITE_OMIT_VIEW
#undef SQLITE_OMIT_VIRTUALTABLE
#define SQLITE_OMIT_WAL 1
#undef SQLITE_OMIT_WSD
// #define SQLITE_OMIT_XFER_OPT 1
#define SQLITE_PERFORMANCE_TRACE 1
/* #define SQLITE_OMIT_COMPLETE 1 */
/* #define SQLITE_OMIT_SUBQUERY 1 */
/* #define SQLITE_OMIT_DATETIME_FUNCS 1 */
/* #define SQLITE_OMIT_FLOATING_POINT 1 */
#define SQLITE_COUNTOFVIEW_OPTIMIZATION 0
// support fts3/4
#undef SQLITE_OMIT_INCRBLOB
#define SQLITE_ENABLE_FTS3 1
#define SQLITE_ENABLE_FTS3_PARENTHESIS 1
#define SQLITE_ENABLE_FTS4 1
// support encrypted databasesqleet
// see: https://github.com/resilar/sqleet/tree/v0.25.2
#define SQLITE_HAS_CODEC 1
#define SQLITE_USE_URI 0
// support use like by index optimization
#undef SQLITE_LIKE_DOESNT_MATCH_BLOBS
#undef SQLITE_OMIT_LIKE_OPTIMIZATION
#define SQLITE_CASE_SENSITIVE_LIKE 1

View File

@@ -0,0 +1,768 @@
/* From: https://chromium.googlesource.com/chromium/src.git/+/4.1.249.1050/third_party/sqlite/src/os_symbian.cc
* https://github.com/spsoft/spmemvfs/tree/master/spmemvfs
* http://www.sqlite.org/src/doc/trunk/src/test_demovfs.c
* http://www.sqlite.org/src/doc/trunk/src/test_vfstrace.c
* http://www.sqlite.org/src/doc/trunk/src/test_onefile.c
* http://www.sqlite.org/src/doc/trunk/src/test_vfs.c
* https://github.com/nodemcu/nodemcu-firmware/blob/master/app/sqlite3/esp8266.c
**/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <time.h>
// #include <unistd.h>
#include <sqlite3.h>
#include <sys/stat.h>
#include "shox96_0_2.h"
#include <version.h>
#if (KERNEL_VERSION_MAJOR == 3)&& (KERNEL_VERSION_MINOR == 4)
#include <zephyr/kernel.h>
#include <zephyr/random/rand32.h>
#include <zephyr/device.h>
#include <zephyr/fs/fs.h>
#include <zephyr/storage/flash_map.h>
#else
#include <zephyr.h>
#include <random/rand32.h>
#include <device.h>
#include <fs/fs.h>
#include <storage/flash_map.h>
#endif
#define UNUSED(x) (void)(x)
#undef dbg_printf
// #define dbg_printf(...) printf(__VA_ARGS__)
#define dbg_printf(...)
#define CACHEBLOCKSZ 64
#define csk_DEFAULT_MAXNAMESIZE 100
// From https://stackoverflow.com/questions/19758270/read-varint-from-linux-sockets#19760246
// Encode an unsigned 64-bit varint. Returns number of encoded bytes.
// 'buffer' must have room for up to 10 bytes.
int encode_unsigned_varint(uint8_t *buffer, uint64_t value)
{
int encoded = 0;
do {
uint8_t next_byte = value & 0x7F;
value >>= 7;
if (value)
next_byte |= 0x80;
buffer[encoded++] = next_byte;
} while (value);
return encoded;
}
uint64_t decode_unsigned_varint(const uint8_t *data, int *decoded_bytes)
{
int i = 0;
uint64_t decoded_value = 0;
int shift_amount = 0;
do {
decoded_value |= (uint64_t)(data[i] & 0x7F) << shift_amount;
shift_amount += 7;
} while ((data[i++] & 0x80) != 0);
*decoded_bytes = i;
return decoded_value;
}
int csk_Close(sqlite3_file *);
int csk_Lock(sqlite3_file *, int);
int csk_Unlock(sqlite3_file *, int);
int csk_Sync(sqlite3_file *, int);
int csk_Open(sqlite3_vfs *, const char *, sqlite3_file *, int, int *);
int csk_Read(sqlite3_file *, void *, int, sqlite3_int64);
int csk_Write(sqlite3_file *, const void *, int, sqlite3_int64);
int csk_Truncate(sqlite3_file *, sqlite3_int64);
int csk_Delete(sqlite3_vfs *, const char *, int);
int csk_FileSize(sqlite3_file *, sqlite3_int64 *);
int csk_Access(sqlite3_vfs *, const char *, int, int *);
int csk_FullPathname(sqlite3_vfs *, const char *, int, char *);
int csk_CheckReservedLock(sqlite3_file *, int *);
int csk_FileControl(sqlite3_file *, int, void *);
int csk_SectorSize(sqlite3_file *);
int csk_DeviceCharacteristics(sqlite3_file *);
void *csk_DlOpen(sqlite3_vfs *, const char *);
void csk_DlError(sqlite3_vfs *, int, char *);
void (*csk_DlSym(sqlite3_vfs *, void *, const char *))(void);
void csk_DlClose(sqlite3_vfs *, void *);
int csk_Randomness(sqlite3_vfs *, int, char *);
int csk_Sleep(sqlite3_vfs *, int);
int csk_CurrentTime(sqlite3_vfs *, double *);
int cskmem_Close(sqlite3_file *);
int cskmem_Read(sqlite3_file *, void *, int, sqlite3_int64);
int cskmem_Write(sqlite3_file *, const void *, int, sqlite3_int64);
int cskmem_FileSize(sqlite3_file *, sqlite3_int64 *);
int cskmem_Sync(sqlite3_file *, int);
typedef struct st_linkedlist {
uint16_t blockid;
struct st_linkedlist *next;
uint8_t data[CACHEBLOCKSZ];
} linkedlist_t, *pLinkedList_t;
typedef struct st_filecache {
uint32_t size;
linkedlist_t *list;
} filecache_t, *pFileCache_t;
typedef struct csk_file {
sqlite3_file base;
struct fs_file_t *fd;
filecache_t *cache;
char name[csk_DEFAULT_MAXNAMESIZE];
} csk_file;
sqlite3_vfs cskVfs = {
1, // iVersion
sizeof(csk_file), // szOsFile
101, // mxPathname
NULL, // pNext
"csk", // name
0, // pAppData
csk_Open, // xOpen
csk_Delete, // xDelete
csk_Access, // xAccess
csk_FullPathname, // xFullPathname
csk_DlOpen, // xDlOpen
csk_DlError, // xDlError
csk_DlSym, // xDlSym
csk_DlClose, // xDlClose
csk_Randomness, // xRandomness
csk_Sleep, // xSleep
csk_CurrentTime, // xCurrentTime
0 // xGetLastError
};
const sqlite3_io_methods cskIoMethods = { 1,
csk_Close,
csk_Read,
csk_Write,
csk_Truncate,
csk_Sync,
csk_FileSize,
csk_Lock,
csk_Unlock,
csk_CheckReservedLock,
csk_FileControl,
csk_SectorSize,
csk_DeviceCharacteristics };
const sqlite3_io_methods cskMemMethods = { 1,
cskmem_Close,
cskmem_Read,
cskmem_Write,
csk_Truncate,
cskmem_Sync,
cskmem_FileSize,
csk_Lock,
csk_Unlock,
csk_CheckReservedLock,
csk_FileControl,
csk_SectorSize,
csk_DeviceCharacteristics };
uint32_t linkedlist_store(linkedlist_t **leaf, uint32_t offset, uint32_t len, const uint8_t *data)
{
const uint8_t blank[CACHEBLOCKSZ] = { 0 };
uint16_t blockid = offset / CACHEBLOCKSZ;
linkedlist_t *block;
if (!memcmp(data, blank, CACHEBLOCKSZ))
return len;
block = *leaf;
if (!block || (block->blockid != blockid)) {
block = (linkedlist_t *)sqlite3_malloc(sizeof(linkedlist_t));
if (!block)
return SQLITE_NOMEM;
memset(block->data, 0, CACHEBLOCKSZ);
block->blockid = blockid;
}
if (!*leaf) {
*leaf = block;
block->next = NULL;
} else if (block != *leaf) {
if (block->blockid > (*leaf)->blockid) {
block->next = (*leaf)->next;
(*leaf)->next = block;
} else {
block->next = (*leaf);
(*leaf) = block;
}
}
memcpy(block->data + offset % CACHEBLOCKSZ, data, len);
return len;
}
uint32_t filecache_pull(pFileCache_t cache, uint32_t offset, uint32_t len, uint8_t *data)
{
uint16_t i;
float blocks;
uint32_t r = 0;
blocks = (offset % CACHEBLOCKSZ + len) / (float)CACHEBLOCKSZ;
if (blocks == 0.0)
return 0;
if (!cache->list)
return 0;
if ((blocks - (int)blocks) > 0.0)
blocks = blocks + 1.0;
for (i = 0; i < (uint16_t)blocks; i++) {
uint16_t round;
float relablock;
linkedlist_t *leaf;
uint32_t relaoffset, relalen;
uint8_t *reladata = (uint8_t *)data;
relalen = len - r;
reladata = reladata + r;
relaoffset = offset + r;
round = CACHEBLOCKSZ - relaoffset % CACHEBLOCKSZ;
if (relalen > round)
relalen = round;
for (leaf = cache->list; leaf && leaf->next; leaf = leaf->next) {
if ((leaf->next->blockid * CACHEBLOCKSZ) > relaoffset)
break;
}
relablock = relaoffset / ((float)CACHEBLOCKSZ) - leaf->blockid;
if ((relablock >= 0) && (relablock < 1))
memcpy(data + r, leaf->data + (relaoffset % CACHEBLOCKSZ), relalen);
r = r + relalen;
}
return 0;
}
uint32_t filecache_push(pFileCache_t cache, uint32_t offset, uint32_t len, const uint8_t *data)
{
uint16_t i;
float blocks;
uint32_t r = 0;
uint8_t updateroot = 0x1;
blocks = (offset % CACHEBLOCKSZ + len) / (float)CACHEBLOCKSZ;
if (blocks == 0.0)
return 0;
if ((blocks - (int)blocks) > 0.0)
blocks = blocks + 1.0;
for (i = 0; i < (uint16_t)blocks; i++) {
uint16_t round;
uint32_t localr;
linkedlist_t *leaf;
uint32_t relaoffset, relalen;
uint8_t *reladata = (uint8_t *)data;
relalen = len - r;
reladata = reladata + r;
relaoffset = offset + r;
round = CACHEBLOCKSZ - relaoffset % CACHEBLOCKSZ;
if (relalen > round)
relalen = round;
for (leaf = cache->list; leaf && leaf->next; leaf = leaf->next) {
if ((leaf->next->blockid * CACHEBLOCKSZ) > relaoffset)
break;
updateroot = 0x0;
}
localr = linkedlist_store(&leaf, relaoffset,
(relalen > CACHEBLOCKSZ) ? CACHEBLOCKSZ : relalen,
reladata);
if (localr == SQLITE_NOMEM)
return SQLITE_NOMEM;
r = r + localr;
if (updateroot & 0x1)
cache->list = leaf;
}
if (offset + len > cache->size)
cache->size = offset + len;
return r;
}
void filecache_free(pFileCache_t cache)
{
pLinkedList_t ll = cache->list, next;
while (ll != NULL) {
next = ll->next;
sqlite3_free(ll);
ll = next;
}
}
int cskmem_Close(sqlite3_file *id)
{
csk_file *file = (csk_file *)id;
// printf("cskmem_Close: file->fd %p\n", file->fd);
// fs_close(file->fd);
filecache_free(file->cache);
sqlite3_free(file->cache);
dbg_printf("cskmem_Close: %s OK\n", file->name);
return SQLITE_OK;
}
int cskmem_Read(sqlite3_file *id, void *buffer, int amount, sqlite3_int64 offset)
{
int32_t ofst;
csk_file *file = (csk_file *)id;
ofst = (int32_t)(offset & 0x7FFFFFFF);
filecache_pull(file->cache, ofst, amount, (uint8_t *)buffer);
dbg_printf("cskmem_Read: %s [%d] [%d] OK\n", file->name, ofst, amount);
return SQLITE_OK;
}
int cskmem_Write(sqlite3_file *id, const void *buffer, int amount, sqlite3_int64 offset)
{
int32_t ofst;
csk_file *file = (csk_file *)id;
ofst = (int32_t)(offset & 0x7FFFFFFF);
filecache_push(file->cache, ofst, amount, (const uint8_t *)buffer);
dbg_printf("cskmem_Write: %s [%d] [%d] OK\n", file->name, ofst, amount);
return SQLITE_OK;
}
int cskmem_Sync(sqlite3_file *id, int flags)
{
csk_file *file = (csk_file *)id;
UNUSED(file);
dbg_printf("cskmem_Sync: %s OK\n", file->name);
return SQLITE_OK;
}
int cskmem_FileSize(sqlite3_file *id, sqlite3_int64 *size)
{
csk_file *file = (csk_file *)id;
*size = 0LL | file->cache->size;
dbg_printf("cskmem_FileSize: %s [%d] OK\n", file->name, file->cache->size);
return SQLITE_OK;
}
int csk_Open(sqlite3_vfs *vfs, const char *path, sqlite3_file *file, int flags, int *outflags)
{
int rc;
csk_file *p = (csk_file *)file;
fs_mode_t mode = FS_O_READ;
if (path == NULL)
return SQLITE_IOERR;
dbg_printf("csk_Open: 0o %s %0x\n", path, mode);
if (flags & SQLITE_OPEN_READONLY)
mode |= FS_O_READ;
if (flags & SQLITE_OPEN_READWRITE || flags & SQLITE_OPEN_MAIN_JOURNAL) {
int result;
if (SQLITE_OK != csk_Access(vfs, path, flags, &result))
return SQLITE_CANTOPEN;
mode |= FS_O_RDWR;
}
dbg_printf("csk_Open: 1o %s %0x\n", path, mode);
memset(p, 0, sizeof(csk_file));
strncpy(p->name, path, csk_DEFAULT_MAXNAMESIZE);
p->name[csk_DEFAULT_MAXNAMESIZE - 1] = '\0';
if (flags & SQLITE_OPEN_MAIN_JOURNAL) {
p->fd = 0;
p->cache = (filecache_t *)sqlite3_malloc(sizeof(filecache_t));
if (!p->cache)
return SQLITE_NOMEM;
memset(p->cache, 0, sizeof(filecache_t));
p->base.pMethods = &cskMemMethods;
dbg_printf("csk_Open: 2o %s MEM OK\n", p->name);
return SQLITE_OK;
} else {
p->fd = (struct fs_file_t *)k_malloc(sizeof(struct fs_file_t));
if (!p->fd)
return SQLITE_NOMEM;
fs_file_t_init(p->fd);
}
rc = fs_open(p->fd, path, mode);
if (rc < 0) {
dbg_printf("FAIL: open %s: %d\n", path, rc);
return SQLITE_CANTOPEN;
}
p->base.pMethods = &cskIoMethods;
dbg_printf("csk_Open: 2o %s OK\n", p->name);
return SQLITE_OK;
}
int csk_Close(sqlite3_file *id)
{
csk_file *file = (csk_file *)id;
// int rc = fclose(file->fd);
int rc = fs_close(file->fd);
k_free(file->fd);
dbg_printf("csk_Close: %s %d\n", file->name, rc);
return rc ? SQLITE_IOERR_CLOSE : SQLITE_OK;
}
int csk_Read(sqlite3_file *id, void *buffer, int amount, sqlite3_int64 offset)
{
size_t nRead;
int32_t ofst, iofst;
csk_file *file = (csk_file *)id;
iofst = (int32_t)(offset & 0x7FFFFFFF);
dbg_printf("csk_Read: 1r %s %d %lld[%d] \n", file->name, amount, offset, iofst);
ofst = fs_seek(file->fd, iofst, SEEK_SET);
if (ofst != 0) {
dbg_printf("csk_Read: 2r %d != %d FAIL\n", ofst, iofst);
return SQLITE_IOERR_SHORT_READ /* SQLITE_IOERR_SEEK */;
}
nRead = fs_read(file->fd, buffer, amount);
if (nRead == amount) {
dbg_printf("csk_Read: 3r %s %u %d OK\n", file->name, nRead, amount);
return SQLITE_OK;
} else if (nRead >= 0) {
dbg_printf("csk_Read: 3r %s %u %d FAIL\n", file->name, nRead, amount);
return SQLITE_IOERR_SHORT_READ;
}
dbg_printf("csk_Read: 4r %s FAIL\n", file->name);
return SQLITE_IOERR_READ;
}
int csk_Write(sqlite3_file *id, const void *buffer, int amount, sqlite3_int64 offset)
{
size_t nWrite;
int32_t ofst, iofst;
csk_file *file = (csk_file *)id;
iofst = (int32_t)(offset & 0x7FFFFFFF);
dbg_printf("csk_Write: 1w %s %d %lld[%d] \n", file->name, amount, offset, iofst);
ofst = fs_seek(file->fd, iofst, SEEK_SET);
if (ofst != 0) {
return SQLITE_IOERR_SEEK;
}
dbg_printf("csk_Write: 1.1w %s %d %lld[%d] \n", file->name, amount, offset, iofst);
nWrite = fs_write(file->fd, buffer, amount);
if (nWrite != amount) {
dbg_printf("csk_Write: 2w %s %u %d\n", file->name, nWrite, amount);
return SQLITE_IOERR_WRITE;
}
dbg_printf("csk_Write: 3w %s OK\n", file->name);
return SQLITE_OK;
}
int csk_Truncate(sqlite3_file *id, sqlite3_int64 bytes)
{
csk_file *file = (csk_file *)id;
UNUSED(file);
int fno = fs_truncate(file->fd, bytes);
if (fno != 0)
return SQLITE_IOERR_TRUNCATE;
//if (ftruncate(fno, 0))
// return SQLITE_IOERR_TRUNCATE;
dbg_printf("csk_Truncate:\n");
return SQLITE_OK;
}
int csk_Delete(sqlite3_vfs *vfs, const char *path, int syncDir)
{
// dbg_printf("csk_Delete: start delete\n");
struct fs_dirent dirent;
int32_t rc = SQLITE_IOERR_DELETE;
if (fs_stat(path, &dirent) >= 0) {
rc = fs_unlink(path);
}
if (rc)
return SQLITE_IOERR_DELETE;
dbg_printf("csk_Delete: %s OK\n", path);
return SQLITE_OK;
}
int csk_FileSize(sqlite3_file *id, sqlite3_int64 *size)
{
csk_file *file = (csk_file *)id;
dbg_printf("csk_FileSize: %s: ", file->name);
struct fs_dirent st;
// int fno = fileno(file->fd);
// if (fno == -1)
// return SQLITE_IOERR_FSTAT;
if (fs_stat(file->name, &st))
return SQLITE_IOERR_FSTAT;
*size = st.size;
dbg_printf(" %d[%lld]\n", st.size, *size);
return SQLITE_OK;
}
int csk_Sync(sqlite3_file *id, int flags)
{
csk_file *file = (csk_file *)id;
// int rc = fflush( file->fd );
fs_sync(file->fd);
dbg_printf("csk_Sync( %s: ) \n", file->name);
return SQLITE_OK;
}
int csk_Access(sqlite3_vfs *vfs, const char *path, int flags, int *result)
{
struct fs_dirent st;
memset(&st, 0, sizeof(struct stat));
int rc = fs_stat(path, &st);
// *result = ( rc != -1 );
*result = (rc >= 0);
dbg_printf("csk_Access: %s %d %d %d\n", path, *result, rc, st.size);
return SQLITE_OK;
}
int csk_FullPathname(sqlite3_vfs *vfs, const char *path, int len, char *fullpath)
{
//structure stat does not have name.
//struct stat st;
//int32_t rc = stat( path, &st );
//if ( rc == 0 ){
// strncpy( fullpath, st.name, len );
//} else {
// strncpy( fullpath, path, len );
//}
// As now just copy the path
strncpy(fullpath, path, len);
fullpath[len - 1] = '\0';
dbg_printf("csk_FullPathname: %s\n", fullpath);
return SQLITE_OK;
}
int csk_Lock(sqlite3_file *id, int lock_type)
{
csk_file *file = (csk_file *)id;
UNUSED(file);
dbg_printf("csk_Lock:Not locked\n");
return SQLITE_OK;
}
int csk_Unlock(sqlite3_file *id, int lock_type)
{
csk_file *file = (csk_file *)id;
UNUSED(file);
dbg_printf("csk_Unlock:\n");
return SQLITE_OK;
}
int csk_CheckReservedLock(sqlite3_file *id, int *result)
{
csk_file *file = (csk_file *)id;
UNUSED(file);
*result = 0;
dbg_printf("csk_CheckReservedLock:\n");
return SQLITE_OK;
}
int csk_FileControl(sqlite3_file *id, int op, void *arg)
{
csk_file *file = (csk_file *)id;
UNUSED(file);
dbg_printf("csk_FileControl:\n");
return SQLITE_OK;
}
int csk_SectorSize(sqlite3_file *id)
{
// csk_file *file = (csk_file*) id;
// dbg_printf("csk_SectorSize:\n");
// return SPI_FLASH_SEC_SIZE;
return 1024; // todo
}
int csk_DeviceCharacteristics(sqlite3_file *id)
{
csk_file *file = (csk_file *)id;
UNUSED(file);
dbg_printf("csk_DeviceCharacteristics:\n");
return 0;
}
void *csk_DlOpen(sqlite3_vfs *vfs, const char *path)
{
dbg_printf("csk_DlOpen:\n");
return NULL;
}
void csk_DlError(sqlite3_vfs *vfs, int len, char *errmsg)
{
dbg_printf("csk_DlError:\n");
return;
}
void (*csk_DlSym(sqlite3_vfs *vfs, void *handle, const char *symbol))(void)
{
dbg_printf("csk_DlSym:\n");
return NULL;
}
void csk_DlClose(sqlite3_vfs *vfs, void *handle)
{
dbg_printf("csk_DlClose:\n");
return;
}
int csk_Randomness(sqlite3_vfs *vfs, int len, char *buffer)
{
long rdm;
int sz = 1 + (len / sizeof(long));
char a_rdm[sz * sizeof(long)];
while (sz--) {
rdm = sys_rand32_get();
memcpy(a_rdm + sz * sizeof(long), &rdm, sizeof(long));
}
memcpy(buffer, a_rdm, len);
dbg_printf("csk_Randomness\n");
return SQLITE_OK;
}
int csk_Sleep(sqlite3_vfs *vfs, int microseconds)
{
// ets_delay_us(microseconds);
dbg_printf("csk_Sleep:\n");
return SQLITE_OK;
}
int csk_CurrentTime(sqlite3_vfs *vfs, double *result)
{
// todo
// time_t t = time(NULL);
// *result = t / 86400.0 + 2440587.5;
// // This is stubbed out until we have a working RTCTIME solution;
// // as it stood, this would always have returned the UNIX epoch.
// //*result = 2440587.5;
// dbg_printf("csk_CurrentTime: %g\n", *result);
return SQLITE_OK;
}
static void shox96_0_2c(sqlite3_context *context, int argc, sqlite3_value **argv)
{
int nIn, nOut;
long int nOut2;
const unsigned char *inBuf;
unsigned char *outBuf;
unsigned char vInt[9];
int vIntLen;
// assert( argc==1 );
if (argc != 1) {
printf("shox96_0_2c: error\n");
return;
}
nIn = sqlite3_value_bytes(argv[0]);
inBuf = (unsigned char *)sqlite3_value_blob(argv[0]);
nOut = 13 + nIn + (nIn + 999) / 1000;
vIntLen = encode_unsigned_varint(vInt, (uint64_t)nIn);
outBuf = (unsigned char *)k_malloc(nOut + vIntLen);
memcpy(outBuf, vInt, vIntLen);
nOut2 = shox96_0_2_compress((const char *)inBuf, nIn, (char *)&outBuf[vIntLen], NULL);
sqlite3_result_blob(context, outBuf, nOut2 + vIntLen, k_free);
}
static void shox96_0_2d(sqlite3_context *context, int argc, sqlite3_value **argv)
{
unsigned int nIn, nOut;
const unsigned char *inBuf;
unsigned char *outBuf;
long int nOut2;
uint64_t inBufLen64;
int vIntLen;
// assert( argc==1 );
if (argc != 1) {
printf("shox96_0_2d: error\n");
return;
}
if (sqlite3_value_type(argv[0]) != SQLITE_BLOB)
return;
nIn = sqlite3_value_bytes(argv[0]);
if (nIn < 2) {
return;
}
inBuf = (unsigned char *)sqlite3_value_blob(argv[0]);
inBufLen64 = decode_unsigned_varint(inBuf, &vIntLen);
nOut = (unsigned int)inBufLen64;
outBuf = (unsigned char *)k_malloc(nOut);
//nOut2 = (long int)nOut;
nOut2 = shox96_0_2_decompress((const char *)(inBuf + vIntLen), nIn - vIntLen,
(char *)outBuf, NULL);
//if( rc!=Z_OK ){
// free(outBuf);
//}else{
sqlite3_result_blob(context, outBuf, nOut2, k_free);
//}
}
int registerShox96_0_2(sqlite3 *db, const char **pzErrMsg,
const struct sqlite3_api_routines *pThunk)
{
sqlite3_create_function(db, "shox96_0_2c", 1, SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
shox96_0_2c, 0, 0);
sqlite3_create_function(db, "shox96_0_2d", 1, SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
shox96_0_2d, 0, 0);
return SQLITE_OK;
}
int sqlite3_os_init(void)
{
sqlite3_vfs_register(&cskVfs, 1);
sqlite3_auto_extension((void (*)())registerShox96_0_2);
return SQLITE_OK;
}
int sqlite3_os_end(void)
{
return SQLITE_OK;
}

View File

@@ -0,0 +1,695 @@
/*
* The little filesystem
*
* Copyright (c) 2017, Arm Limited. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef LFS_H
#define LFS_H
#include <stdint.h>
#include <stdbool.h>
#include "lfs_util.h"
#ifdef __cplusplus
extern "C"
{
#endif
/// Version info ///
// Software library version
// Major (top-nibble), incremented on backwards incompatible changes
// Minor (bottom-nibble), incremented on feature additions
#define LFS_VERSION 0x00020004
#define LFS_VERSION_MAJOR (0xffff & (LFS_VERSION >> 16))
#define LFS_VERSION_MINOR (0xffff & (LFS_VERSION >> 0))
// Version of On-disk data structures
// Major (top-nibble), incremented on backwards incompatible changes
// Minor (bottom-nibble), incremented on feature additions
#define LFS_DISK_VERSION 0x00020000
#define LFS_DISK_VERSION_MAJOR (0xffff & (LFS_DISK_VERSION >> 16))
#define LFS_DISK_VERSION_MINOR (0xffff & (LFS_DISK_VERSION >> 0))
/// Definitions ///
// Type definitions
typedef uint32_t lfs_size_t;
typedef uint32_t lfs_off_t;
typedef int32_t lfs_ssize_t;
typedef int32_t lfs_soff_t;
typedef uint32_t lfs_block_t;
// Maximum name size in bytes, may be redefined to reduce the size of the
// info struct. Limited to <= 1022. Stored in superblock and must be
// respected by other littlefs drivers.
#ifndef LFS_NAME_MAX
#define LFS_NAME_MAX 255
#endif
// Maximum size of a file in bytes, may be redefined to limit to support other
// drivers. Limited on disk to <= 4294967296. However, above 2147483647 the
// functions lfs_file_seek, lfs_file_size, and lfs_file_tell will return
// incorrect values due to using signed integers. Stored in superblock and
// must be respected by other littlefs drivers.
#ifndef LFS_FILE_MAX
#define LFS_FILE_MAX 2147483647
#endif
// Maximum size of custom attributes in bytes, may be redefined, but there is
// no real benefit to using a smaller LFS_ATTR_MAX. Limited to <= 1022.
#ifndef LFS_ATTR_MAX
#define LFS_ATTR_MAX 1022
#endif
// Possible error codes, these are negative to allow
// valid positive return values
enum lfs_error {
LFS_ERR_OK = 0, // No error
LFS_ERR_IO = -5, // Error during device operation
LFS_ERR_CORRUPT = -84, // Corrupted
LFS_ERR_NOENT = -2, // No directory entry
LFS_ERR_EXIST = -17, // Entry already exists
LFS_ERR_NOTDIR = -20, // Entry is not a dir
LFS_ERR_ISDIR = -21, // Entry is a dir
LFS_ERR_NOTEMPTY = -39, // Dir is not empty
LFS_ERR_BADF = -9, // Bad file number
LFS_ERR_FBIG = -27, // File too large
LFS_ERR_INVAL = -22, // Invalid parameter
LFS_ERR_NOSPC = -28, // No space left on device
LFS_ERR_NOMEM = -12, // No more memory available
LFS_ERR_NOATTR = -61, // No data/attr available
LFS_ERR_NAMETOOLONG = -36, // File name too long
};
// File types
enum lfs_type {
// file types
LFS_TYPE_REG = 0x001,
LFS_TYPE_DIR = 0x002,
// internally used types
LFS_TYPE_SPLICE = 0x400,
LFS_TYPE_NAME = 0x000,
LFS_TYPE_STRUCT = 0x200,
LFS_TYPE_USERATTR = 0x300,
LFS_TYPE_FROM = 0x100,
LFS_TYPE_TAIL = 0x600,
LFS_TYPE_GLOBALS = 0x700,
LFS_TYPE_CRC = 0x500,
// internally used type specializations
LFS_TYPE_CREATE = 0x401,
LFS_TYPE_DELETE = 0x4ff,
LFS_TYPE_SUPERBLOCK = 0x0ff,
LFS_TYPE_DIRSTRUCT = 0x200,
LFS_TYPE_CTZSTRUCT = 0x202,
LFS_TYPE_INLINESTRUCT = 0x201,
LFS_TYPE_SOFTTAIL = 0x600,
LFS_TYPE_HARDTAIL = 0x601,
LFS_TYPE_MOVESTATE = 0x7ff,
// internal chip sources
LFS_FROM_NOOP = 0x000,
LFS_FROM_MOVE = 0x101,
LFS_FROM_USERATTRS = 0x102,
};
// File open flags
enum lfs_open_flags {
// open flags
LFS_O_RDONLY = 1, // Open a file as read only
#ifndef LFS_READONLY
LFS_O_WRONLY = 2, // Open a file as write only
LFS_O_RDWR = 3, // Open a file as read and write
LFS_O_CREAT = 0x0100, // Create a file if it does not exist
LFS_O_EXCL = 0x0200, // Fail if a file already exists
LFS_O_TRUNC = 0x0400, // Truncate the existing file to zero size
LFS_O_APPEND = 0x0800, // Move to end of file on every write
#endif
// internally used flags
#ifndef LFS_READONLY
LFS_F_DIRTY = 0x010000, // File does not match storage
LFS_F_WRITING = 0x020000, // File has been written since last flush
#endif
LFS_F_READING = 0x040000, // File has been read since last flush
#ifndef LFS_READONLY
LFS_F_ERRED = 0x080000, // An error occurred during write
#endif
LFS_F_INLINE = 0x100000, // Currently inlined in directory entry
};
// File seek flags
enum lfs_whence_flags {
LFS_SEEK_SET = 0, // Seek relative to an absolute position
LFS_SEEK_CUR = 1, // Seek relative to the current file position
LFS_SEEK_END = 2, // Seek relative to the end of the file
};
// Configuration provided during initialization of the littlefs
struct lfs_config {
// Opaque user provided context that can be used to pass
// information to the block device operations
void *context;
// Read a region in a block. Negative error codes are propogated
// to the user.
int (*read)(const struct lfs_config *c, lfs_block_t block,
lfs_off_t off, void *buffer, lfs_size_t size);
// Program a region in a block. The block must have previously
// been erased. Negative error codes are propogated to the user.
// May return LFS_ERR_CORRUPT if the block should be considered bad.
int (*prog)(const struct lfs_config *c, lfs_block_t block,
lfs_off_t off, const void *buffer, lfs_size_t size);
// Erase a block. A block must be erased before being programmed.
// The state of an erased block is undefined. Negative error codes
// are propogated to the user.
// May return LFS_ERR_CORRUPT if the block should be considered bad.
int (*erase)(const struct lfs_config *c, lfs_block_t block);
// Sync the state of the underlying block device. Negative error codes
// are propogated to the user.
int (*sync)(const struct lfs_config *c);
#ifdef LFS_THREADSAFE
// Lock the underlying block device. Negative error codes
// are propogated to the user.
int (*lock)(const struct lfs_config *c);
// Unlock the underlying block device. Negative error codes
// are propogated to the user.
int (*unlock)(const struct lfs_config *c);
#endif
// Minimum size of a block read. All read operations will be a
// multiple of this value.
lfs_size_t read_size;
// Minimum size of a block program. All program operations will be a
// multiple of this value.
lfs_size_t prog_size;
// Size of an erasable block. This does not impact ram consumption and
// may be larger than the physical erase size. However, non-inlined files
// take up at minimum one block. Must be a multiple of the read
// and program sizes.
lfs_size_t block_size;
// Number of erasable blocks on the device.
lfs_size_t block_count;
// Number of erase cycles before littlefs evicts metadata logs and moves
// the metadata to another block. Suggested values are in the
// range 100-1000, with large values having better performance at the cost
// of less consistent wear distribution.
//
// Set to -1 to disable block-level wear-leveling.
int32_t block_cycles;
// Size of block caches. Each cache buffers a portion of a block in RAM.
// The littlefs needs a read cache, a program cache, and one additional
// cache per file. Larger caches can improve performance by storing more
// data and reducing the number of disk accesses. Must be a multiple of
// the read and program sizes, and a factor of the block size.
lfs_size_t cache_size;
// Size of the lookahead buffer in bytes. A larger lookahead buffer
// increases the number of blocks found during an allocation pass. The
// lookahead buffer is stored as a compact bitmap, so each byte of RAM
// can track 8 blocks. Must be a multiple of 8.
lfs_size_t lookahead_size;
// Optional statically allocated read buffer. Must be cache_size.
// By default lfs_malloc is used to allocate this buffer.
void *read_buffer;
// Optional statically allocated program buffer. Must be cache_size.
// By default lfs_malloc is used to allocate this buffer.
void *prog_buffer;
// Optional statically allocated lookahead buffer. Must be lookahead_size
// and aligned to a 32-bit boundary. By default lfs_malloc is used to
// allocate this buffer.
void *lookahead_buffer;
// Optional upper limit on length of file names in bytes. No downside for
// larger names except the size of the info struct which is controlled by
// the LFS_NAME_MAX define. Defaults to LFS_NAME_MAX when zero. Stored in
// superblock and must be respected by other littlefs drivers.
lfs_size_t name_max;
// Optional upper limit on files in bytes. No downside for larger files
// but must be <= LFS_FILE_MAX. Defaults to LFS_FILE_MAX when zero. Stored
// in superblock and must be respected by other littlefs drivers.
lfs_size_t file_max;
// Optional upper limit on custom attributes in bytes. No downside for
// larger attributes size but must be <= LFS_ATTR_MAX. Defaults to
// LFS_ATTR_MAX when zero.
lfs_size_t attr_max;
// Optional upper limit on total space given to metadata pairs in bytes. On
// devices with large blocks (e.g. 128kB) setting this to a low size (2-8kB)
// can help bound the metadata compaction time. Must be <= block_size.
// Defaults to block_size when zero.
lfs_size_t metadata_max;
};
// File info structure
struct lfs_info {
// Type of the file, either LFS_TYPE_REG or LFS_TYPE_DIR
uint8_t type;
// Size of the file, only valid for REG files. Limited to 32-bits.
lfs_size_t size;
// Name of the file stored as a null-terminated string. Limited to
// LFS_NAME_MAX+1, which can be changed by redefining LFS_NAME_MAX to
// reduce RAM. LFS_NAME_MAX is stored in superblock and must be
// respected by other littlefs drivers.
char name[LFS_NAME_MAX+1];
};
// Custom attribute structure, used to describe custom attributes
// committed atomically during file writes.
struct lfs_attr {
// 8-bit type of attribute, provided by user and used to
// identify the attribute
uint8_t type;
// Pointer to buffer containing the attribute
void *buffer;
// Size of attribute in bytes, limited to LFS_ATTR_MAX
lfs_size_t size;
};
// Optional configuration provided during lfs_file_opencfg
struct lfs_file_config {
// Optional statically allocated file buffer. Must be cache_size.
// By default lfs_malloc is used to allocate this buffer.
void *buffer;
// Optional list of custom attributes related to the file. If the file
// is opened with read access, these attributes will be read from disk
// during the open call. If the file is opened with write access, the
// attributes will be written to disk every file sync or close. This
// write occurs atomically with update to the file's contents.
//
// Custom attributes are uniquely identified by an 8-bit type and limited
// to LFS_ATTR_MAX bytes. When read, if the stored attribute is smaller
// than the buffer, it will be padded with zeros. If the stored attribute
// is larger, then it will be silently truncated. If the attribute is not
// found, it will be created implicitly.
struct lfs_attr *attrs;
// Number of custom attributes in the list
lfs_size_t attr_count;
};
/// internal littlefs data structures ///
typedef struct lfs_cache {
lfs_block_t block;
lfs_off_t off;
lfs_size_t size;
uint8_t *buffer;
} lfs_cache_t;
typedef struct lfs_mdir {
lfs_block_t pair[2];
uint32_t rev;
lfs_off_t off;
uint32_t etag;
uint16_t count;
bool erased;
bool split;
lfs_block_t tail[2];
} lfs_mdir_t;
// littlefs directory type
typedef struct lfs_dir {
struct lfs_dir *next;
uint16_t id;
uint8_t type;
lfs_mdir_t m;
lfs_off_t pos;
lfs_block_t head[2];
} lfs_dir_t;
// littlefs file type
typedef struct lfs_file {
struct lfs_file *next;
uint16_t id;
uint8_t type;
lfs_mdir_t m;
struct lfs_ctz {
lfs_block_t head;
lfs_size_t size;
} ctz;
uint32_t flags;
lfs_off_t pos;
lfs_block_t block;
lfs_off_t off;
lfs_cache_t cache;
const struct lfs_file_config *cfg;
} lfs_file_t;
typedef struct lfs_superblock {
uint32_t version;
lfs_size_t block_size;
lfs_size_t block_count;
lfs_size_t name_max;
lfs_size_t file_max;
lfs_size_t attr_max;
} lfs_superblock_t;
typedef struct lfs_gstate {
uint32_t tag;
lfs_block_t pair[2];
} lfs_gstate_t;
// The littlefs filesystem type
typedef struct lfs {
lfs_cache_t rcache;
lfs_cache_t pcache;
lfs_block_t root[2];
struct lfs_mlist {
struct lfs_mlist *next;
uint16_t id;
uint8_t type;
lfs_mdir_t m;
} *mlist;
uint32_t seed;
lfs_gstate_t gstate;
lfs_gstate_t gdisk;
lfs_gstate_t gdelta;
struct lfs_free {
lfs_block_t off;
lfs_block_t size;
lfs_block_t i;
lfs_block_t ack;
uint32_t *buffer;
} free;
const struct lfs_config *cfg;
lfs_size_t name_max;
lfs_size_t file_max;
lfs_size_t attr_max;
#ifdef LFS_MIGRATE
struct lfs1 *lfs1;
#endif
} lfs_t;
/// Filesystem functions ///
#ifndef LFS_READONLY
// Format a block device with the littlefs
//
// Requires a littlefs object and config struct. This clobbers the littlefs
// object, and does not leave the filesystem mounted. The config struct must
// be zeroed for defaults and backwards compatibility.
//
// Returns a negative error code on failure.
int lfs_format(lfs_t *lfs, const struct lfs_config *config);
#endif
// Mounts a littlefs
//
// Requires a littlefs object and config struct. Multiple filesystems
// may be mounted simultaneously with multiple littlefs objects. Both
// lfs and config must be allocated while mounted. The config struct must
// be zeroed for defaults and backwards compatibility.
//
// Returns a negative error code on failure.
int lfs_mount(lfs_t *lfs, const struct lfs_config *config);
// Unmounts a littlefs
//
// Does nothing besides releasing any allocated resources.
// Returns a negative error code on failure.
int lfs_unmount(lfs_t *lfs);
/// General operations ///
#ifndef LFS_READONLY
// Removes a file or directory
//
// If removing a directory, the directory must be empty.
// Returns a negative error code on failure.
int lfs_remove(lfs_t *lfs, const char *path);
#endif
#ifndef LFS_READONLY
// Rename or move a file or directory
//
// If the destination exists, it must match the source in type.
// If the destination is a directory, the directory must be empty.
//
// Returns a negative error code on failure.
int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath);
#endif
// Find info about a file or directory
//
// Fills out the info structure, based on the specified file or directory.
// Returns a negative error code on failure.
int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info);
// Get a custom attribute
//
// Custom attributes are uniquely identified by an 8-bit type and limited
// to LFS_ATTR_MAX bytes. When read, if the stored attribute is smaller than
// the buffer, it will be padded with zeros. If the stored attribute is larger,
// then it will be silently truncated. If no attribute is found, the error
// LFS_ERR_NOATTR is returned and the buffer is filled with zeros.
//
// Returns the size of the attribute, or a negative error code on failure.
// Note, the returned size is the size of the attribute on disk, irrespective
// of the size of the buffer. This can be used to dynamically allocate a buffer
// or check for existance.
lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path,
uint8_t type, void *buffer, lfs_size_t size);
#ifndef LFS_READONLY
// Set custom attributes
//
// Custom attributes are uniquely identified by an 8-bit type and limited
// to LFS_ATTR_MAX bytes. If an attribute is not found, it will be
// implicitly created.
//
// Returns a negative error code on failure.
int lfs_setattr(lfs_t *lfs, const char *path,
uint8_t type, const void *buffer, lfs_size_t size);
#endif
#ifndef LFS_READONLY
// Removes a custom attribute
//
// If an attribute is not found, nothing happens.
//
// Returns a negative error code on failure.
int lfs_removeattr(lfs_t *lfs, const char *path, uint8_t type);
#endif
/// File operations ///
// Open a file
//
// The mode that the file is opened in is determined by the flags, which
// are values from the enum lfs_open_flags that are bitwise-ored together.
//
// Returns a negative error code on failure.
int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
const char *path, int flags);
// Open a file with extra configuration
//
// The mode that the file is opened in is determined by the flags, which
// are values from the enum lfs_open_flags that are bitwise-ored together.
//
// The config struct provides additional config options per file as described
// above. The config struct must be allocated while the file is open, and the
// config struct must be zeroed for defaults and backwards compatibility.
//
// Returns a negative error code on failure.
int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file,
const char *path, int flags,
const struct lfs_file_config *config);
// Close a file
//
// Any pending writes are written out to storage as though
// sync had been called and releases any allocated resources.
//
// Returns a negative error code on failure.
int lfs_file_close(lfs_t *lfs, lfs_file_t *file);
// Synchronize a file on storage
//
// Any pending writes are written out to storage.
// Returns a negative error code on failure.
int lfs_file_sync(lfs_t *lfs, lfs_file_t *file);
// Read data from file
//
// Takes a buffer and size indicating where to store the read data.
// Returns the number of bytes read, or a negative error code on failure.
lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file,
void *buffer, lfs_size_t size);
#ifndef LFS_READONLY
// Write data to file
//
// Takes a buffer and size indicating the data to write. The file will not
// actually be updated on the storage until either sync or close is called.
//
// Returns the number of bytes written, or a negative error code on failure.
lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
const void *buffer, lfs_size_t size);
#endif
// Change the position of the file
//
// The change in position is determined by the offset and whence flag.
// Returns the new position of the file, or a negative error code on failure.
lfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file,
lfs_soff_t off, int whence);
#ifndef LFS_READONLY
// Truncates the size of the file to the specified size
//
// Returns a negative error code on failure.
int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size);
#endif
// Return the position of the file
//
// Equivalent to lfs_file_seek(lfs, file, 0, LFS_SEEK_CUR)
// Returns the position of the file, or a negative error code on failure.
lfs_soff_t lfs_file_tell(lfs_t *lfs, lfs_file_t *file);
// Change the position of the file to the beginning of the file
//
// Equivalent to lfs_file_seek(lfs, file, 0, LFS_SEEK_SET)
// Returns a negative error code on failure.
int lfs_file_rewind(lfs_t *lfs, lfs_file_t *file);
// Return the size of the file
//
// Similar to lfs_file_seek(lfs, file, 0, LFS_SEEK_END)
// Returns the size of the file, or a negative error code on failure.
lfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file);
/// Directory operations ///
#ifndef LFS_READONLY
// Create a directory
//
// Returns a negative error code on failure.
int lfs_mkdir(lfs_t *lfs, const char *path);
#endif
// Open a directory
//
// Once open a directory can be used with read to iterate over files.
// Returns a negative error code on failure.
int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path);
// Close a directory
//
// Releases any allocated resources.
// Returns a negative error code on failure.
int lfs_dir_close(lfs_t *lfs, lfs_dir_t *dir);
// Read an entry in the directory
//
// Fills out the info structure, based on the specified file or directory.
// Returns a positive value on success, 0 at the end of directory,
// or a negative error code on failure.
int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info);
// Change the position of the directory
//
// The new off must be a value previous returned from tell and specifies
// an absolute offset in the directory seek.
//
// Returns a negative error code on failure.
int lfs_dir_seek(lfs_t *lfs, lfs_dir_t *dir, lfs_off_t off);
// Return the position of the directory
//
// The returned offset is only meant to be consumed by seek and may not make
// sense, but does indicate the current position in the directory iteration.
//
// Returns the position of the directory, or a negative error code on failure.
lfs_soff_t lfs_dir_tell(lfs_t *lfs, lfs_dir_t *dir);
// Change the position of the directory to the beginning of the directory
//
// Returns a negative error code on failure.
int lfs_dir_rewind(lfs_t *lfs, lfs_dir_t *dir);
/// Filesystem-level filesystem operations
// Finds the current size of the filesystem
//
// Note: Result is best effort. If files share COW structures, the returned
// size may be larger than the filesystem actually is.
//
// Returns the number of allocated blocks, or a negative error code on failure.
lfs_ssize_t lfs_fs_size(lfs_t *lfs);
// Traverse through all blocks in use by the filesystem
//
// The provided callback will be called with each block address that is
// currently in use by the filesystem. This can be used to determine which
// blocks are in use or how much of the storage is available.
//
// Returns a negative error code on failure.
int lfs_fs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data);
#ifndef LFS_READONLY
#ifdef LFS_MIGRATE
// Attempts to migrate a previous version of littlefs
//
// Behaves similarly to the lfs_format function. Attempts to mount
// the previous version of littlefs and update the filesystem so it can be
// mounted with the current version of littlefs.
//
// Requires a littlefs object and config struct. This clobbers the littlefs
// object, and does not leave the filesystem mounted. The config struct must
// be zeroed for defaults and backwards compatibility.
//
// Returns a negative error code on failure.
int lfs_migrate(lfs_t *lfs, const struct lfs_config *cfg);
#endif
#endif
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif

View File

@@ -0,0 +1,244 @@
/*
* lfs utility functions
*
* Copyright (c) 2017, Arm Limited. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef LFS_UTIL_H
#define LFS_UTIL_H
// Users can override lfs_util.h with their own configuration by defining
// LFS_CONFIG as a header file to include (-DLFS_CONFIG=lfs_config.h).
//
// If LFS_CONFIG is used, none of the default utils will be emitted and must be
// provided by the config file. To start, I would suggest copying lfs_util.h
// and modifying as needed.
#ifdef LFS_CONFIG
#define LFS_STRINGIZE(x) LFS_STRINGIZE2(x)
#define LFS_STRINGIZE2(x) #x
#include LFS_STRINGIZE(LFS_CONFIG)
#else
// System includes
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <inttypes.h>
#ifndef LFS_NO_MALLOC
#include <stdlib.h>
#endif
#ifndef LFS_NO_ASSERT
#include <assert.h>
#endif
#if !defined(LFS_NO_DEBUG) || \
!defined(LFS_NO_WARN) || \
!defined(LFS_NO_ERROR) || \
defined(LFS_YES_TRACE)
#include <stdio.h>
#endif
#ifdef __cplusplus
extern "C"
{
#endif
// Macros, may be replaced by system specific wrappers. Arguments to these
// macros must not have side-effects as the macros can be removed for a smaller
// code footprint
// Logging functions
#ifndef LFS_TRACE
#ifdef LFS_YES_TRACE
#define LFS_TRACE_(fmt, ...) \
printf("%s:%d:trace: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
#define LFS_TRACE(...) LFS_TRACE_(__VA_ARGS__, "")
#else
#define LFS_TRACE(...)
#endif
#endif
#ifndef LFS_DEBUG
#ifndef LFS_NO_DEBUG
#define LFS_DEBUG_(fmt, ...) \
printf("%s:%d:debug: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
#define LFS_DEBUG(...) LFS_DEBUG_(__VA_ARGS__, "")
#else
#define LFS_DEBUG(...)
#endif
#endif
#ifndef LFS_WARN
#ifndef LFS_NO_WARN
#define LFS_WARN_(fmt, ...) \
printf("%s:%d:warn: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
#define LFS_WARN(...) LFS_WARN_(__VA_ARGS__, "")
#else
#define LFS_WARN(...)
#endif
#endif
#ifndef LFS_ERROR
#ifndef LFS_NO_ERROR
#define LFS_ERROR_(fmt, ...) \
printf("%s:%d:error: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
#define LFS_ERROR(...) LFS_ERROR_(__VA_ARGS__, "")
#else
#define LFS_ERROR(...)
#endif
#endif
// Runtime assertions
#ifndef LFS_ASSERT
#ifndef LFS_NO_ASSERT
#define LFS_ASSERT(test) assert(test)
#else
#define LFS_ASSERT(test)
#endif
#endif
// Builtin functions, these may be replaced by more efficient
// toolchain-specific implementations. LFS_NO_INTRINSICS falls back to a more
// expensive basic C implementation for debugging purposes
// Min/max functions for unsigned 32-bit numbers
static inline uint32_t lfs_max(uint32_t a, uint32_t b) {
return (a > b) ? a : b;
}
static inline uint32_t lfs_min(uint32_t a, uint32_t b) {
return (a < b) ? a : b;
}
// Align to nearest multiple of a size
static inline uint32_t lfs_aligndown(uint32_t a, uint32_t alignment) {
return a - (a % alignment);
}
static inline uint32_t lfs_alignup(uint32_t a, uint32_t alignment) {
return lfs_aligndown(a + alignment-1, alignment);
}
// Find the smallest power of 2 greater than or equal to a
static inline uint32_t lfs_npw2(uint32_t a) {
#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
return 32 - __builtin_clz(a-1);
#else
uint32_t r = 0;
uint32_t s;
a -= 1;
s = (a > 0xffff) << 4; a >>= s; r |= s;
s = (a > 0xff ) << 3; a >>= s; r |= s;
s = (a > 0xf ) << 2; a >>= s; r |= s;
s = (a > 0x3 ) << 1; a >>= s; r |= s;
return (r | (a >> 1)) + 1;
#endif
}
// Count the number of trailing binary zeros in a
// lfs_ctz(0) may be undefined
static inline uint32_t lfs_ctz(uint32_t a) {
#if !defined(LFS_NO_INTRINSICS) && defined(__GNUC__)
return __builtin_ctz(a);
#else
return lfs_npw2((a & -a) + 1) - 1;
#endif
}
// Count the number of binary ones in a
static inline uint32_t lfs_popc(uint32_t a) {
#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
return __builtin_popcount(a);
#else
a = a - ((a >> 1) & 0x55555555);
a = (a & 0x33333333) + ((a >> 2) & 0x33333333);
return (((a + (a >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24;
#endif
}
// Find the sequence comparison of a and b, this is the distance
// between a and b ignoring overflow
static inline int lfs_scmp(uint32_t a, uint32_t b) {
return (int)(unsigned)(a - b);
}
// Convert between 32-bit little-endian and native order
static inline uint32_t lfs_fromle32(uint32_t a) {
#if !defined(LFS_NO_INTRINSICS) && ( \
(defined( BYTE_ORDER ) && defined( ORDER_LITTLE_ENDIAN ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \
(defined(__BYTE_ORDER ) && defined(__ORDER_LITTLE_ENDIAN ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \
(defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
return a;
#elif !defined(LFS_NO_INTRINSICS) && ( \
(defined( BYTE_ORDER ) && defined( ORDER_BIG_ENDIAN ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \
(defined(__BYTE_ORDER ) && defined(__ORDER_BIG_ENDIAN ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \
(defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
return __builtin_bswap32(a);
#else
return (((uint8_t*)&a)[0] << 0) |
(((uint8_t*)&a)[1] << 8) |
(((uint8_t*)&a)[2] << 16) |
(((uint8_t*)&a)[3] << 24);
#endif
}
static inline uint32_t lfs_tole32(uint32_t a) {
return lfs_fromle32(a);
}
// Convert between 32-bit big-endian and native order
static inline uint32_t lfs_frombe32(uint32_t a) {
#if !defined(LFS_NO_INTRINSICS) && ( \
(defined( BYTE_ORDER ) && defined( ORDER_LITTLE_ENDIAN ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \
(defined(__BYTE_ORDER ) && defined(__ORDER_LITTLE_ENDIAN ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \
(defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
return __builtin_bswap32(a);
#elif !defined(LFS_NO_INTRINSICS) && ( \
(defined( BYTE_ORDER ) && defined( ORDER_BIG_ENDIAN ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \
(defined(__BYTE_ORDER ) && defined(__ORDER_BIG_ENDIAN ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \
(defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
return a;
#else
return (((uint8_t*)&a)[0] << 24) |
(((uint8_t*)&a)[1] << 16) |
(((uint8_t*)&a)[2] << 8) |
(((uint8_t*)&a)[3] << 0);
#endif
}
static inline uint32_t lfs_tobe32(uint32_t a) {
return lfs_frombe32(a);
}
// Calculate CRC-32 with polynomial = 0x04c11db7
uint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size);
// Allocate memory, only used if buffers are not provided to littlefs
// Note, memory must be 64-bit aligned
static inline void *lfs_malloc(size_t size) {
#ifndef LFS_NO_MALLOC
return malloc(size);
#else
(void)size;
return NULL;
#endif
}
// Deallocate memory, only used if buffers are not provided to littlefs
static inline void lfs_free(void *p) {
#ifndef LFS_NO_MALLOC
free(p);
#else
(void)p;
#endif
}
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,29 @@
/*
* Copyright (C) 2019 Siara Logics (cc)
*
* 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.
*
* @author Arundale R.
*
*/
#ifndef shox96_0_2_0
#define shox96_0_2_0
struct lnk_lst {
char *data;
struct lnk_lst *previous;
};
extern int shox96_0_2_compress(const char *in, int len, char *out, struct lnk_lst *prev_lines);
extern int shox96_0_2_decompress(const char *in, int len, char *out, struct lnk_lst *prev_lines);
#endif

View File

@@ -0,0 +1,512 @@
/*
* Copyright (C) 2019 Siara Logics (cc)
*
* 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.
*
* @author Arundale R.
*
*/
#include <time.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include "shox96_0_2.h"
typedef unsigned char byte;
unsigned int c_95[95] = { 16384, 16256, 15744, 16192, 15328, 15344, 15360, 16064, 15264, 15296,
15712, 15200, 14976, 15040, 14848, 15104, 14528, 14592, 14656, 14688,
14720, 14752, 14784, 14816, 14832, 14464, 15552, 15488, 15616, 15168,
15680, 16000, 15872, 10752, 8576, 8192, 8320, 9728, 8672, 8608,
8384, 11264, 9024, 8992, 12160, 8544, 11520, 11008, 8512, 9008,
12032, 11776, 10240, 8448, 8960, 8640, 9040, 8688, 9048, 15840,
16288, 15856, 16128, 16224, 16368, 40960, 6144, 0, 2048, 24576,
7680, 6656, 3072, 49152, 13312, 12800, 63488, 5632, 53248, 45056,
5120, 13056, 61440, 57344, 32768, 4096, 12288, 7168, 13568, 7936,
13696, 15776, 16320, 15808, 16352 };
unsigned char l_95[95] = { 3, 11, 11, 11, 12, 12, 9, 10, 11, 11, 11, 11, 10, 10, 9, 10,
10, 10, 11, 11, 11, 11, 11, 12, 12, 10, 10, 10, 10, 11, 11, 10,
9, 8, 11, 9, 10, 7, 12, 11, 10, 8, 12, 12, 9, 11, 8, 8,
11, 12, 9, 8, 7, 10, 11, 11, 13, 12, 13, 12, 11, 12, 10, 11,
12, 4, 7, 5, 6, 3, 8, 7, 6, 4, 8, 8, 5, 7, 4, 4,
7, 8, 5, 4, 3, 6, 7, 7, 9, 8, 9, 11, 11, 11, 12 };
//unsigned char c[] = { ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~'};
char SET2_STR[] = { '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '.', ',', '-', '/', '=',
'+', ' ', '(', ')', '$', '%', '&', ';', ':', '<', '>', '*', '"', '{', '}',
'[', ']', '@', '?', '\'', '^', '#', '_', '!', '\\', '|', '~', '`', '\0' };
enum { SHX_STATE_1 = 1, SHX_STATE_2 };
byte to_match_repeats_earlier = 1;
byte to_match_repeats_within = 1;
#define USE_64K_LOOKUP 0
#if USE_64K_LOOKUP == 1
byte lookup[65536];
#endif
#define NICE_LEN_FOR_PRIOR 7
#define NICE_LEN_FOR_OTHER 12
unsigned int mask[] = { 0x8000, 0xC000, 0xE000, 0xF000, 0xF800, 0xFC00, 0xFE00, 0xFF00 };
int append_bits(char *out, int ol, unsigned int code, int clen, byte state)
{
byte cur_bit;
byte blen;
unsigned char a_byte;
if (state == SHX_STATE_2) {
// remove change state prefix
if ((code >> 9) == 0x1C) {
code <<= 7;
clen -= 7;
}
//if (code == 14272 && clen == 10) {
// code = 9084;
// clen = 14;
//}
}
while (clen > 0) {
cur_bit = ol % 8;
blen = (clen > 8 ? 8 : clen);
a_byte = (code & mask[blen - 1]) >> 8;
a_byte >>= cur_bit;
if (blen + cur_bit > 8)
blen = (8 - cur_bit);
if (cur_bit == 0)
out[ol / 8] = a_byte;
else
out[ol / 8] |= a_byte;
code <<= blen;
ol += blen;
clen -= blen;
}
return ol;
}
int encodeCount(char *out, int ol, int count)
{
const byte codes[7] = { 0x01, 0x82, 0xC3, 0xE5, 0xED, 0xF5, 0xFD };
const byte bit_len[7] = { 2, 5, 7, 9, 12, 16, 17 };
const uint16_t adder[7] = { 0, 4, 36, 164, 676, 4772, 0 };
int till = 0;
for (int i = 0; i < 6; i++) {
till += (1 << bit_len[i]);
if (count < till) {
ol = append_bits(out, ol, (codes[i] & 0xF8) << 8, codes[i] & 0x07, 1);
ol = append_bits(out, ol, (count - adder[i]) << (16 - bit_len[i]),
bit_len[i], 1);
return ol;
}
}
return ol;
}
int matchOccurance(const char *in, int len, int l, char *out, int *ol)
{
int j, k;
for (j = 0; j < l; j++) {
for (k = j; k < l && (l + k - j) < len; k++) {
if (in[k] != in[l + k - j])
break;
}
if ((k - j) > (NICE_LEN_FOR_PRIOR - 1)) {
*ol = append_bits(out, *ol, 14144, 10, 1);
*ol = encodeCount(out, *ol, k - j - NICE_LEN_FOR_PRIOR); // len
*ol = encodeCount(out, *ol, l - j - NICE_LEN_FOR_PRIOR + 1); // dist
l += (k - j);
l--;
return l;
}
}
return -l;
}
int matchLine(const char *in, int len, int l, char *out, int *ol, struct lnk_lst *prev_lines)
{
int last_ol = *ol;
int last_len = 0;
int last_dist = 0;
int last_ctx = 0;
int line_ctr = 0;
do {
int i, j, k;
int line_len = strlen(prev_lines->data);
for (j = 0; j < line_len; j++) {
for (i = l, k = j; k < line_len && i < len; k++, i++) {
if (prev_lines->data[k] != in[i])
break;
}
if ((k - j) >= NICE_LEN_FOR_OTHER) {
if (last_len) {
if (j > last_dist)
continue;
//int saving = ((k - j) - last_len) + (last_dist - j) + (last_ctx - line_ctr);
//if (saving < 0) {
// //printf("No savng: %d\n", saving);
// continue;
//}
*ol = last_ol;
}
last_len = (k - j);
last_dist = j;
last_ctx = line_ctr;
*ol = append_bits(out, *ol, 14080, 10, 1);
*ol = encodeCount(out, *ol, last_len - NICE_LEN_FOR_OTHER);
*ol = encodeCount(out, *ol, last_dist);
*ol = encodeCount(out, *ol, last_ctx);
/*
if ((*ol - last_ol) > (last_len * 4)) {
last_len = 0;
*ol = last_ol;
}*/
//printf("Len: %d, Dist: %d, Line: %d\n", last_len, last_dist, last_ctx);
}
}
line_ctr++;
prev_lines = prev_lines->previous;
} while (prev_lines && prev_lines->data != NULL);
if (last_len) {
l += last_len;
l--;
return l;
}
return -l;
}
int shox96_0_2_compress(const char *in, int len, char *out, struct lnk_lst *prev_lines)
{
char *ptr;
byte bits;
byte state;
int l, ll, ol;
char c_in, c_next, c_prev;
byte is_upper, is_all_upper;
ol = 0;
c_prev = 0;
#if USE_64K_LOOKUP == 1
memset(lookup, 0, sizeof(lookup));
#endif
state = SHX_STATE_1;
is_all_upper = 0;
for (l = 0; l < len; l++) {
c_in = in[l];
if (l < len - 4) {
if (c_in == c_prev && c_in == in[l + 1] && c_in == in[l + 2] &&
c_in == in[l + 3]) {
int rpt_count = l + 4;
while (rpt_count < len && in[rpt_count] == c_in)
rpt_count++;
rpt_count -= l;
ol = append_bits(out, ol, 14208, 10, 1);
ol = encodeCount(out, ol, rpt_count - 4);
l += rpt_count;
l--;
continue;
}
}
if (l < (len - NICE_LEN_FOR_PRIOR) && to_match_repeats_within) {
#if USE_64K_LOOKUP == 1
uint16_t to_lookup = c_in ^ in[l + 1] + ((in[l + 2] ^ in[l + 3]) << 8);
if (lookup[to_lookup]) {
#endif
l = matchOccurance(in, len, l, out, &ol);
if (l > 0) {
c_prev = in[l - 1];
continue;
}
l = -l;
#if USE_64K_LOOKUP == 1
} else
lookup[to_lookup] = 1;
#endif
}
if (l < (len - NICE_LEN_FOR_OTHER) && to_match_repeats_earlier) {
if (prev_lines != NULL) {
l = matchLine(in, len, l, out, &ol, prev_lines);
if (l > 0) {
c_prev = in[l - 1];
continue;
}
l = -l;
}
}
if (state == SHX_STATE_2) {
if (c_in == ' ' && len - 1 > l)
ptr = (char *)memchr(SET2_STR, in[l + 1], 42);
else
ptr = (char *)memchr(SET2_STR, c_in, 42);
if (ptr == NULL) {
state = SHX_STATE_1;
ol = append_bits(out, ol, 8192, 4, 1);
}
}
is_upper = 0;
if (c_in >= 'A' && c_in <= 'Z')
is_upper = 1;
else {
if (is_all_upper) {
is_all_upper = 0;
ol = append_bits(out, ol, 8192, 4, state);
}
}
if (is_upper && !is_all_upper) {
for (ll = l + 5; ll >= l && ll < len; ll--) {
if (in[ll] >= 'a' && in[ll] <= 'z')
break;
}
if (ll == l - 1) {
ol = append_bits(out, ol, 8704, 8, state);
is_all_upper = 1;
}
}
if (state == SHX_STATE_1 && c_in >= '0' && c_in <= '9') {
ol = append_bits(out, ol, 14336, 7, state);
state = SHX_STATE_2;
}
c_next = 0;
if (l + 1 < len)
c_next = in[l + 1];
c_prev = c_in;
if (c_in >= 32 && c_in <= 126) {
c_in -= 32;
if (is_all_upper && is_upper)
c_in += 32;
if (c_in == 0 && state == SHX_STATE_2)
ol = append_bits(out, ol, 15232, 11, state);
else
ol = append_bits(out, ol, c_95[(int)c_in], l_95[(int)c_in], state);
} else if (c_in == 13 && c_next == 10) {
ol = append_bits(out, ol, 13824, 9, state);
l++;
c_prev = 10;
} else if (c_in == 10) {
ol = append_bits(out, ol, 13952, 9, state);
} else if (c_in == 13) {
ol = append_bits(out, ol, 9064, 13, state);
} else if (c_in == '\t') {
ol = append_bits(out, ol, 9216, 7, state);
}
}
bits = ol % 8;
if (bits) {
ol = append_bits(out, ol, 14272, 8 - bits, 1);
}
//printf("\n%ld\n", ol);
return ol / 8 + (ol % 8 ? 1 : 0);
}
// Decoder is designed for using less memory, not speed
// Decode lookup table for code index and length
// First 2 bits 00, Next 3 bits indicate index of code from 0,
// last 3 bits indicate code length in bits
// 0, 1, 2, 3, 4,
char vcode[32] = { 2 + (0 << 3), 3 + (3 << 3), 3 + (1 << 3), 4 + (6 << 3), 0,
// 5, 6, 7, 8, 9, 10
4 + (4 << 3), 3 + (2 << 3), 4 + (8 << 3), 0, 0, 0,
// 11, 12, 13, 14, 15
4 + (7 << 3), 0, 4 + (5 << 3), 0, 5 + (9 << 3),
// 16, 17, 18, 19, 20, 21, 22, 23
0, 0, 0, 0, 0, 0, 0, 0,
// 24, 25, 26, 27, 28, 29, 30, 31
0, 0, 0, 0, 0, 0, 0, 5 + (10 << 3) };
// 0, 1, 2, 3, 4, 5, 6, 7,
char hcode[32] = { 1 + (1 << 3), 2 + (0 << 3), 0, 3 + (2 << 3), 0, 0, 0, 5 + (3 << 3),
// 8, 9, 10, 11, 12, 13, 14, 15,
0, 0, 0, 0, 0, 0, 0, 5 + (5 << 3),
// 16, 17, 18, 19, 20, 21, 22, 23
0, 0, 0, 0, 0, 0, 0, 5 + (4 << 3),
// 24, 25, 26, 27, 28, 29, 30, 31
0, 0, 0, 0, 0, 0, 0, 5 + (6 << 3) };
enum { SHX_SET1 = 0, SHX_SET1A, SHX_SET1B, SHX_SET2, SHX_SET3, SHX_SET4, SHX_SET4A };
char sets[][11] = { { ' ', ' ', 'e', 't', 'a', 'o', 'i', 'n', 's', 'r', 'l' },
{ 'c', 'd', 'h', 'u', 'p', 'm', 'b', 'g', 'w', 'f', 'y' },
{ 'v', 'k', 'q', 'j', 'x', 'z', ' ', ' ', ' ', ' ', ' ' },
{ ' ', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8' },
{ '.', ',', '-', '/', '=', '+', ' ', '(', ')', '$', '%' },
{ '&', ';', ':', '<', '>', '*', '"', '{', '}', '[', ']' },
{ '@', '?', '\'', '^', '#', '_', '!', '\\', '|', '~', '`' } };
int getBitVal(const char *in, int bit_no, int count)
{
return (in[bit_no >> 3] & (0x80 >> (bit_no % 8)) ? 1 << count : 0);
}
int getCodeIdx(char *code_type, const char *in, int len, int *bit_no_p)
{
int code = 0;
int count = 0;
do {
if (*bit_no_p >= len)
return 199;
code += getBitVal(in, *bit_no_p, count);
(*bit_no_p)++;
count++;
if (code_type[code] && (code_type[code] & 0x07) == count) {
return code_type[code] >> 3;
}
} while (count < 5);
return 1; // skip if code not found
}
int getNumFromBits(const char *in, int bit_no, int count)
{
int ret = 0;
while (count--) {
ret += getBitVal(in, bit_no++, count);
}
return ret;
}
int readCount(const char *in, int *bit_no_p, int len)
{
const byte bit_len[7] = { 5, 2, 7, 9, 12, 16, 17 };
const uint16_t adder[7] = { 4, 0, 36, 164, 676, 4772, 0 };
int idx = getCodeIdx(hcode, in, len, bit_no_p);
if (idx > 6)
return 0;
int count = getNumFromBits(in, *bit_no_p, bit_len[idx]) + adder[idx];
(*bit_no_p) += bit_len[idx];
return count;
}
int shox96_0_2_decompress(const char *in, int len, char *out, struct lnk_lst *prev_lines)
{
int dstate;
int bit_no;
byte is_all_upper;
int ol = 0;
bit_no = 0;
dstate = SHX_SET1;
is_all_upper = 0;
len <<= 3;
out[ol] = 0;
while (bit_no < len) {
int h, v;
char c = 0;
byte is_upper = is_all_upper;
int orig_bit_no = bit_no;
v = getCodeIdx(vcode, in, len, &bit_no);
if (v == 199) {
bit_no = orig_bit_no;
break;
}
h = dstate;
if (v == 0) {
h = getCodeIdx(hcode, in, len, &bit_no);
if (h == 199) {
bit_no = orig_bit_no;
break;
}
if (h == SHX_SET1) {
if (dstate == SHX_SET1) {
if (is_all_upper) {
is_upper = is_all_upper = 0;
continue;
}
v = getCodeIdx(vcode, in, len, &bit_no);
if (v == 199) {
bit_no = orig_bit_no;
break;
}
if (v == 0) {
h = getCodeIdx(hcode, in, len, &bit_no);
if (h == 199) {
bit_no = orig_bit_no;
break;
}
if (h == SHX_SET1) {
is_all_upper = 1;
continue;
}
}
is_upper = 1;
} else {
dstate = SHX_SET1;
continue;
}
} else if (h == SHX_SET2) {
if (dstate == SHX_SET1)
dstate = SHX_SET2;
continue;
}
if (h != SHX_SET1) {
v = getCodeIdx(vcode, in, len, &bit_no);
if (v == 199) {
bit_no = orig_bit_no;
break;
}
}
}
if (h < 64 && v < 32)
c = sets[h][v];
if (c >= 'a' && c <= 'z') {
if (is_upper)
c -= 32;
} else {
if (is_upper && dstate == SHX_SET1 && v == 1)
c = '\t';
if (h == SHX_SET1B) {
switch (v) {
case 6:
out[ol++] = '\r';
c = '\n';
break;
case 7:
c = is_upper ? '\r' : '\n';
break;
case 8:
if (getBitVal(in, bit_no++, 0)) {
int dict_len = readCount(in, &bit_no, len) +
NICE_LEN_FOR_PRIOR;
int dist = readCount(in, &bit_no, len) +
NICE_LEN_FOR_PRIOR - 1;
memcpy(out + ol, out + ol - dist, dict_len);
ol += dict_len;
} else {
int dict_len = readCount(in, &bit_no, len) +
NICE_LEN_FOR_OTHER;
int dist = readCount(in, &bit_no, len);
int ctx = readCount(in, &bit_no, len);
struct lnk_lst *cur_line = prev_lines;
while (ctx--)
cur_line = cur_line->previous;
memmove(out + ol, cur_line->data + dist, dict_len);
ol += dict_len;
}
continue;
case 9: {
int count = readCount(in, &bit_no, len);
count += 4;
char rpt_c = out[ol - 1];
while (count--)
out[ol++] = rpt_c;
continue;
}
case 10:
continue;
}
}
}
out[ol++] = c;
}
return ol;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,106 @@
#if (CONFIG_CSK_SQLITE_SDK_CSK6)
#ifdef CONFIG_CSK_SQLITE_CSK_MEM
#include <csk_malloc.h>
static void* __sq_malloc(uint32_t size){
return csk_malloc(size);
}
static void* __sq_realloc(void* ptr,uint32_t sz){
return csk_realloc( ptr, sz);
}
static void __sq_free(void* ptr){
csk_free(ptr);
}
#else
extern void *k_malloc(size_t size);
extern void *k_calloc(size_t nmemb, size_t size);
extern void k_free(void *ptr);
static void *k_realloc(void *ptr, size_t size)
{
void *ptr_new = NULL;
if(ptr == NULL){
ptr_new = k_calloc(1, size);
}else if(size == 0){
k_free(ptr);
return NULL;
}else {
ptr_new = k_calloc(1, size);
}
if(ptr_new && ptr){
// fixme: 这里对 ptr 进行拷贝有可能存在地址越界的问题。暂时没有找到ptr指针长度的方法
memcpy(ptr_new, ptr, size);
k_free(ptr);
}
return ptr_new;
}
static void* __sq_malloc(uint32_t size){
return k_malloc(size);
}
static void* __sq_realloc(void* ptr,uint32_t sz){
return k_realloc( ptr, sz);
}
static void __sq_free(void* ptr){
k_free(ptr);
}
#endif
#elif (CONFIG_CSK_SQLITE_SDK_ARCS)
//use psram
#include "esp_heap_caps.h"
#if (CONFIG_CSK_SQLITE_ARCS_MEM_RAM)
static void* __sq_malloc(uint32_t size){
return heap_caps_malloc(size, MALLOC_CAP_INTERNAL | MALLOC_CAP_32BIT);
}
static void* __sq_realloc(void* ptr,uint32_t sz){
return heap_caps_realloc( ptr, sz, MALLOC_CAP_INTERNAL | MALLOC_CAP_32BIT);
}
static void __sq_free(void* ptr){
heap_caps_free(ptr);
}
#else
static void* __sq_malloc(uint32_t size){
return heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_32BIT);
}
static void* __sq_realloc(void* ptr,uint32_t sz){
return heap_caps_realloc( ptr, sz, MALLOC_CAP_SPIRAM | MALLOC_CAP_32BIT);
}
static void __sq_free(void* ptr){
heap_caps_free(ptr);
}
#endif
#else
#error "Unsupport the sdk type"
#endif

View File

@@ -0,0 +1,4 @@
name: csk_sqlite3
build:
cmake: .
kconfig: Kconfig