Initial community commit

This commit is contained in:
Jef 2024-09-24 14:54:57 +02:00
parent 537bcbc862
commit fc06254474
16440 changed files with 4239995 additions and 2 deletions

15
Src/nde/Android.mk Normal file
View file

@ -0,0 +1,15 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := nde
LOCAL_CFLAGS += -D__ANDROID__
LOCAL_C_INCLUDES := $(LOCAL_PATH)/..
# make base stuff
LOCAL_SRC_FILES := Crc.cpp Database.cpp DBUtils.cpp Field.cpp Filter.cpp Index.cpp Int64Field.cpp Int128Field.cpp LinkedList.cpp NDEString.cpp
# make platform-specific field classes
LOCAL_SRC_FILES += android/Binary32Field.cpp android/BinaryField.cpp android/ColumnField.cpp android/FilenameField.cpp android/IndexField.cpp
LOCAL_SRC_FILES += android/IntegerField.cpp android/StringField.cpp
# make rest of platform-specific classes
LOCAL_SRC_FILES += android/IndexRecord.cpp android/nde_c.cpp android/nde_init.cpp android/Query.cpp android/Record.cpp android/Scanner.cpp android/Table.cpp android/Vfs.cpp
include $(BUILD_SHARED_LIBRARY)

8
Src/nde/Binary32Field.h Normal file
View file

@ -0,0 +1,8 @@
#pragma once
#ifdef __APPLE__
#include "osx/Binary32Field.h"
#elif defined(_WIN32)
#include "win/Binary32Field.h"
#elif defined(__ANDROID__)
#include "android/Binary32Field.h"
#endif

8
Src/nde/BinaryField.h Normal file
View file

@ -0,0 +1,8 @@
#pragma once
#ifdef __APPLE__
#include "osx/BinaryField.h"
#elif defined(_WIN32)
#include "win/BinaryField.h"
#elif defined(__ANDROID__)
#include "android/BinaryField.h"
#endif

7
Src/nde/CRC.H Normal file
View file

@ -0,0 +1,7 @@
#ifndef __CRC_H
#define __CRC_H
unsigned long int crc32file(char *name);
unsigned long int crc32str(char *name);
#endif

8
Src/nde/ColumnField.h Normal file
View file

@ -0,0 +1,8 @@
#pragma once
#ifdef __APPLE__
#include "osx/ColumnField.h"
#elif defined(_WIN32)
#include "win/ColumnField.h"
#elif defined(__ANDROID__)
#include "android/ColumnField.h"
#endif

88
Src/nde/Crc.cpp Normal file
View file

@ -0,0 +1,88 @@
#include "nde.h"
#include <stdio.h>
static unsigned int crc_32_tab[] = {
0xD202Ef8dL, 0xA505DF1BL, 0x3C0C8EA1L, 0x4B0BBE37L, 0xD56F2B94L, 0xA2681B02L, 0x3B614AB8L, 0x4C667A2EL,
0xDCD967BFL, 0xABDE5729L, 0x32D70693L, 0x45D03605L, 0xDBB4A3A6L, 0xACB39330L, 0x35BAC28AL, 0x42BDF21CL,
0xCFB5FFE9L, 0xB8B2CF7FL, 0x21BB9EC5L, 0x56BCAE53L, 0xC8D83BF0L, 0xBFDF0B66L, 0x26D65ADCL, 0x51D16A4AL,
0xC16E77DBL, 0xB669474DL, 0x2F6016F7L, 0x58672661L, 0xC603B3C2L, 0xB1048354L, 0x280DD2EEL, 0x5F0AE278L,
0xE96CCF45L, 0x9E6BFFD3L, 0x0762AE69L, 0x70659EFFL, 0xEE010B5CL, 0x99063BCAL, 0x000F6A70L, 0x77085AE6L,
0xE7B74777L, 0x90B077E1L, 0x09B9265BL, 0x7EBE16CDL, 0xE0DA836EL, 0x97DDB3F8L, 0x0ED4E242L, 0x79D3D2D4L,
0xF4DBDF21L, 0x83DCEFB7L, 0x1AD5BE0DL, 0x6DD28E9BL, 0xF3B61B38L, 0x84B12BAEL, 0x1DB87A14L, 0x6ABF4A82L,
0xFA005713L, 0x8D076785L, 0x140E363FL, 0x630906A9L, 0xFD6D930AL, 0x8A6AA39CL, 0x1363F226L, 0x6464C2B0L,
0xA4DEAE1DL, 0xD3D99E8BL, 0x4AD0CF31L, 0x3DD7FFA7L, 0xA3B36A04L, 0xD4B45A92L, 0x4DBD0B28L, 0x3ABA3BBEL,
0xAA05262FL, 0xDD0216B9L, 0x440B4703L, 0x330C7795L, 0xAD68E236L, 0xDA6FD2A0L, 0x4366831AL, 0x3461B38CL,
0xB969BE79L, 0xCE6E8EEFL, 0x5767DF55L, 0x2060EFC3L, 0xBE047A60L, 0xC9034AF6L, 0x500A1B4CL, 0x270D2BDAL,
0xB7B2364BL, 0xC0B506DDL, 0x59BC5767L, 0x2EBB67F1L, 0xB0DFF252L, 0xC7D8C2C4L, 0x5ED1937EL, 0x29D6A3E8L,
0x9FB08ED5L, 0xE8B7BE43L, 0x71BEEFF9L, 0x06B9DF6FL, 0x98DD4ACCL, 0xEFDA7A5AL, 0x76D32BE0L, 0x01D41B76L,
0x916B06E7L, 0xE66C3671L, 0x7F6567CBL, 0x0862575DL, 0x9606C2FEL, 0xE101F268L, 0x7808A3D2L, 0x0F0F9344L,
0x82079EB1L, 0xF500AE27L, 0x6C09FF9DL, 0x1B0ECF0BL, 0x856A5AA8L, 0xF26D6A3EL, 0x6B643B84L, 0x1C630B12L,
0x8CDC1683L, 0xFBDB2615L, 0x62D277AFL, 0x15D54739L, 0x8BB1D29AL, 0xFCB6E20CL, 0x65BFB3B6L, 0x12B88320L,
0x3FBA6CADL, 0x48BD5C3BL, 0xD1B40D81L, 0xA6B33D17L, 0x38D7A8B4L, 0x4FD09822L, 0xD6D9C998L, 0xA1DEF90EL,
0x3161E49FL, 0x4666D409L, 0xDF6F85B3L, 0xA868B525L, 0x360C2086L, 0x410B1010L, 0xD80241AAL, 0xAF05713CL,
0x220D7CC9L, 0x550A4C5FL, 0xCC031DE5L, 0xBB042D73L, 0x2560B8D0L, 0x52678846L, 0xCB6ED9FCL, 0xBC69E96AL,
0x2CD6F4FBL, 0x5BD1C46DL, 0xC2D895D7L, 0xB5DFA541L, 0x2BBB30E2L, 0x5CBC0074L, 0xC5B551CEL, 0xB2B26158L,
0x04D44C65L, 0x73D37CF3L, 0xEADA2D49L, 0x9DDD1DDFL, 0x03B9887CL, 0x74BEB8EAL, 0xEDB7E950L, 0x9AB0D9C6L,
0x0A0FC457L, 0x7D08F4C1L, 0xE401A57BL, 0x930695EDL, 0x0D62004EL, 0x7A6530D8L, 0xE36C6162L, 0x946B51F4L,
0x19635C01L, 0x6E646C97L, 0xF76D3D2DL, 0x806A0DBBL, 0x1E0E9818L, 0x6909A88EL, 0xF000F934L, 0x8707C9A2L,
0x17B8D433L, 0x60BFE4A5L, 0xF9B6B51FL, 0x8EB18589L, 0x10D5102AL, 0x67D220BCL, 0xFEDB7106L, 0x89DC4190L,
0x49662D3DL, 0x3E611DABL, 0xA7684C11L, 0xD06F7C87L, 0x4E0BE924L, 0x390CD9B2L, 0xA0058808L, 0xD702B89EL,
0x47BDA50FL, 0x30BA9599L, 0xA9B3C423L, 0xDEB4F4B5L, 0x40D06116L, 0x37D75180L, 0xAEDE003AL, 0xD9D930ACL,
0x54D13D59L, 0x23D60DCFL, 0xBADF5C75L, 0xCDD86CE3L, 0x53BCF940L, 0x24BBC9D6L, 0xBDB2986CL, 0xCAB5A8FAL,
0x5A0AB56BL, 0x2D0D85FDL, 0xB404D447L, 0xC303E4D1L, 0x5D677172L, 0x2A6041E4L, 0xB369105EL, 0xC46E20C8L,
0x72080DF5L, 0x050F3D63L, 0x9C066CD9L, 0xEB015C4FL, 0x7565C9ECL, 0x0262F97AL, 0x9B6BA8C0L, 0xEC6C9856L,
0x7CD385C7L, 0x0BD4B551L, 0x92DDE4EBL, 0xE5DAD47DL, 0x7BBE41DEL, 0x0CB97148L, 0x95B020F2L, 0xE2B71064L,
0x6FBF1D91L, 0x18B82D07L, 0x81B17CBDL, 0xF6B64C2BL, 0x68D2D988L, 0x1FD5E91EL, 0x86DCB8A4L, 0xF1DB8832L,
0x616495A3L, 0x1663A535L, 0x8F6AF48FL, 0xF86DC419L, 0x660951BAL, 0x110E612CL, 0x88073096L, 0xFF000000L
};
#define UPDC32(octet, crc) (crc_32_tab[((crc) ^ (octet)) & 0xff] ^ ((crc) >> 8))
unsigned long int crc32file(char *name)
{
register FILE *fin;
register unsigned int oldcrc32;
register unsigned int crc32;
register unsigned int oldcrc;
register unsigned char c;
oldcrc32 = 0;
if ((fin=fopen(name, "rb"))==NULL)
return 0;
while (1) {
c=getc(fin);
if (feof(fin)) break;
oldcrc32 = UPDC32(c, oldcrc32);
}
if (ferror(fin)){
fclose(fin);
return 0;
}
else {
crc32 = oldcrc32; oldcrc = oldcrc32 = ~oldcrc32;
fclose(fin);
return crc32;
}
}
unsigned long int crc32str(char *name)
{
register unsigned int oldcrc32;
register unsigned int crc32;
register unsigned char c;
register int a=0;
oldcrc32 = 0;
while (name[a] != 0) {
c=name[a];
oldcrc32 = UPDC32(c, oldcrc32);
a++;
}
crc32 = oldcrc32; oldcrc32 = oldcrc32;
return crc32;
}

573
Src/nde/DBUtils.cpp Normal file
View file

@ -0,0 +1,573 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
All Purposes Functions
--------------------------------------------------------------------------- */
#include "nde.h"
#include "BinaryField.h"
#include "Binary32Field.h"
#include "vfs.h"
#include "ColumnField.h"
#include "IndexField.h"
#include "StringField.h"
#include "FilenameField.h"
#include "IntegerField.h"
#include "Int64Field.h"
#include "Int128Field.h"
#include <stdio.h>
#include <string.h>
#ifdef _WIN32
int (WINAPI *findNLSString)(LCID Locale, DWORD dwFindNLSStringFlags, LPCWSTR lpStringSource, int cchSource, LPCWSTR lpStringValue, int cchValue, LPINT pcchFound) = NDE_FindNLSString;
#endif
//---------------------------------------------------------------------------
bool CompatibleFields(unsigned char oldType, unsigned char newType)
{
if (oldType == newType) // duh :)
return true;
// going from an int field to another int equivalent field is OK
if ((oldType == FIELD_INTEGER || oldType == FIELD_BOOLEAN || oldType == FIELD_DATETIME || oldType == FIELD_LENGTH || oldType == FIELD_INT64) &&
(newType == FIELD_INTEGER || newType == FIELD_BOOLEAN || newType == FIELD_DATETIME || newType == FIELD_LENGTH || newType == FIELD_INT64)) {
return true;
}
// going from string to filename or filename to string is OK
if ((oldType == FIELD_FILENAME && newType == FIELD_STRING)
|| (oldType == FIELD_STRING && newType == FIELD_FILENAME))
{
return true;
}
return false;
}
//---------------------------------------------------------------------------
uint32_t AllocNewPos(VFILE *Handle)
{
Vfseek(Handle, 0, SEEK_END);
return Vftell(Handle);
}
//---------------------------------------------------------------------------
Field *TranslateObject(unsigned char Type, Table *tbl)
{
switch (Type)
{
case FIELD_COLUMN: //0
return new ColumnField();
case FIELD_INDEX: //1
return new IndexField();
case FIELD_STRING: // 3
return new StringField();
case FIELD_INTEGER: // 4
return new IntegerField();
case FIELD_BINARY: // 6
return new BinaryField();
case FIELD_DATETIME: // 10
return new DateTimeField();
case FIELD_LENGTH: // 11
return new LengthField();
case FIELD_FILENAME: // 12
return new FilenameField();
case FIELD_INT64: // 13
return new Int64Field();
case FIELD_BINARY32: // 14
return new Binary32Field();
case FIELD_INT128: // 15
return new Int128Field();
default:
#ifdef WIN32
if (!tbl->HasErrors())
{
//MessageBox(plugin.hwndParent, "Your database has been corrupted!\n\nWinamp will try to continue, but some of the library metadata may be lost :(", "Database Error", 0);
}
#else
printf("NDE Error: unknown field type encountered\n");
#endif
tbl->IncErrorCount();
return new Field();
}
}
//---------------------------------------------------------------------------
#ifndef __ANDROID__
const void *memmem(const void *a, const void *b, size_t s, size_t l)
{
size_t n = s - l;
while (n--)
{
if (!memcmp(a, b, l))
return a;
a = (const uint8_t *)a + 1;
}
return NULL;
}
#endif
#ifdef _WIN32
// a faster way of doing min(wcslen(str), _len)
static size_t nde_wcsnlen(const wchar_t *str, size_t _len)
{
size_t len = 0;
while (str && *str++)
{
if (_len == len)
return len;
len++;
}
return len;
}
// len must be <= wcslen(b)
static int nde_wcsnicmp(const wchar_t *a, const wchar_t *b, size_t len)
{
return CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE, a, (int)nde_wcsnlen(a, len), b, (int)len) - 2;
}
/* this is a VERY LIMITED emulation of the vista only function. it ONLY supports the ways we're currently call it. it's also slow. */
int WINAPI NDE_FindNLSString(LCID Locale, DWORD dwFindNLSStringFlags, LPCWSTR lpStringSource, int cchSource, LPCWSTR lpStringValue, int cchValue, LPINT pcchFound)
{
dwFindNLSStringFlags &= ~NORM_LINGUISTIC_CASING; // remove on XP and below, not supported
if (dwFindNLSStringFlags & FIND_STARTSWITH)
{
dwFindNLSStringFlags &= ~FIND_STARTSWITH; // clear flag
size_t len = wcslen(lpStringValue);
if (CompareStringW(Locale, dwFindNLSStringFlags, lpStringSource, (int)nde_wcsnlen(lpStringSource, len), lpStringValue, (int)len) == CSTR_EQUAL)
return 0;
else
return -1;
}
else if (dwFindNLSStringFlags & FIND_ENDSWITH)
{
dwFindNLSStringFlags &= ~FIND_ENDSWITH; // clear flag
int lenp = (int)wcslen(lpStringValue), lend = (int)wcslen(lpStringSource);
if (lend < lenp) return -1; // too short
if (CompareStringW(Locale, dwFindNLSStringFlags, lpStringSource+lend-lenp, -1, lpStringValue, -1) == CSTR_EQUAL)
return 0;
else
return -1;
}
else if (dwFindNLSStringFlags & FIND_FROMSTART)
{
dwFindNLSStringFlags &= ~FIND_FROMSTART; // clear flag
int s2len = (int)wcslen(lpStringValue);
int s1len = (int)wcslen(lpStringSource);
const wchar_t *p;
for (p = lpStringSource;*p && s1len >= s2len;p++,s1len--)
if (CompareStringW(Locale, dwFindNLSStringFlags, p, min(s1len, s2len), lpStringValue, (int)s2len) == CSTR_EQUAL)
return 0;
return -1;
}
return -1;
}
int nde_wcsicmp(const wchar_t *a, const wchar_t *b)
{
return CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE|NORM_IGNORENONSPACE, a, -1, b, -1) - 2;
}
bool nde_wcsbegins(const wchar_t *a, const wchar_t *b)
{
int index = findNLSString(LOCALE_USER_DEFAULT, FIND_STARTSWITH|NORM_LINGUISTIC_CASING|NORM_IGNORECASE|NORM_IGNORENONSPACE, a, -1, b, -1, 0);
return (index != -1);
}
bool nde_wcsends(const wchar_t *a, const wchar_t *b)
{
int index = findNLSString(LOCALE_USER_DEFAULT, FIND_ENDSWITH|NORM_LINGUISTIC_CASING|NORM_IGNORECASE|NORM_IGNORENONSPACE, a, -1, b, -1, 0);
return (index != -1);
}
bool nde_wcscontains(const wchar_t *a, const wchar_t *b)
{
int index = findNLSString(LOCALE_USER_DEFAULT, FIND_FROMSTART|NORM_LINGUISTIC_CASING|NORM_IGNORECASE|NORM_IGNORENONSPACE, a, -1, b, -1, 0);
return index != -1;
}
//---------------------------------------------------------------------------
int mywcsicmp(const wchar_t *a, const wchar_t *b)
{
if (!a && !b) return 0;
if (!a && b) return 1;
if (!b) return -1;
int r = nde_wcsicmp(a, b);
return min(max(r, -1), 1);
}
int mywcsicmp_fn(const wchar_t *a, const wchar_t *b)
{
if (!a && !b) return 0;
if (!a && b) return 1;
if (!b) return -1;
int r = nde_wcsicmp_fn(a, b);
return min(max(r, -1), 1);
}
int nde_wcsicmp_fn(const wchar_t *a, const wchar_t *b)
{
return CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE, a, -1, b, -1) - 2;
}
bool nde_fnbegins(const wchar_t *a, const wchar_t *b)
{
int index = findNLSString(LOCALE_USER_DEFAULT, FIND_STARTSWITH|NORM_IGNORECASE, a, -1, b, -1, 0);
return (index != -1);
}
bool nde_fnends(const wchar_t *a, const wchar_t *b)
{
int index = findNLSString(LOCALE_USER_DEFAULT, FIND_ENDSWITH|NORM_IGNORECASE, a, -1, b, -1, 0);
return (index != -1);
}
bool nde_fncontains(const wchar_t *a, const wchar_t *b)
{
int index = findNLSString(LOCALE_USER_DEFAULT, FIND_FROMSTART|NORM_IGNORECASE, a, -1, b, -1, 0);
return index != -1;
}
#endif
#ifdef __ANDROID__
//---------------------------------------------------------------------------
// a faster way of doing min(wcslen(str), _len)
size_t nde_strnlen(const char *str, size_t _len)
{
size_t len = 0;
while (str && *str++)
{
if (_len == len)
return len;
len++;
}
return len;
}
// len must be <= strlen(b)
int nde_strnicmp(const char *a, const char *b, size_t len)
{
return strncasecmp(a,b,len);
}
int nde_strnicmp_ignore(const char *a, const char *b, size_t len)
{
return strncasecmp(a,b,len);
}
char *stristr(const char *s1, const char *s2)
{
size_t s2len = strlen(s2);
const char *p;
for (p = s1;*p;p++)
if (!nde_strnicmp(p, s2, s2len))
return (char *)p;
return NULL;
}
char *stristr_ignore(const char *s1, const char *s2)
{
size_t s2len = strlen(s2);
const char *p;
for (p = s1;*p;p++)
if (!nde_strnicmp_ignore(p, s2, s2len))
return (char *)p;
return NULL;
}
//---------------------------------------------------------------------------
int nde_stricmp(const char *a, const char *b)
{
return strcasecmp(a,b);
}
int nde_stricmp_ignore(const char *a, const char *b)
{
return strcasecmp(a,b); // TODO: maybe strcoll?
}
int mystricmp(const char *a, const char *b)
{
if (!a && !b) return 0;
if (!a && b) return 1;
if (!b) return -1;
int r = nde_stricmp(a, b);
return min(max(r, -1), 1);
}
char* mystristr(const char *a, const char *b)
{
return (!a || !b) ? NULL : stristr(a, b);
}
char* mystristr_fn(const char *a, const char *b)
{
return (!a || !b) ? NULL : stristr_fn(a, b);
}
int mystricmp_fn(const char *a, const char *b)
{
if (!a && !b) return 0;
if (!a && b) return 1;
if (!b) return -1;
int r = nde_stricmp_fn(a, b);
return min(max(r, -1), 1);
}
char *stristr_fn(const char *s1, const char *s2)
{
size_t s2len = strlen(s2);
const char *p;
for (p = s1;*p;p++)
if (!nde_strnicmp_fn(p, s2, s2len))
return (char *)p;
return NULL;
}
int nde_stricmp_fn(const char *a, const char *b)
{
return strcasecmp(a,b);
}
int nde_strnicmp_fn(const char *a, const char *b, size_t len)
{
return strncasecmp(a,b, len);
}
static uint16_t swap_utf16LE(uint16_t value)
{
#ifdef BIG_ENDIAN
return (value >> 8) | (value << 8);
#else
return value;
#endif
}
static uint16_t swap_utf16BE(uint16_t value)
{
#ifdef LITTLE_ENDIAN
return (value >> 8) | (value << 8);
#else
return value;
#endif
}
static size_t utf16LE_to_ucs4_character(const uint16_t *utf16_string, size_t len, uint32_t *codepoint)
{
uint16_t lead = swap_utf16LE(utf16_string[0]);
if (lead < 0xD800 || lead >= 0xE000)
{
return lead;
}
if (lead < 0xDC00)
{
if (len >= 2)
{
uint16_t trail = swap_utf16LE(utf16_string[1]);
if (trail >= 0xDC00 && trail < 0xE000)
{
*codepoint = 0x10000 + ((lead - 0xD800) << 10) + (trail - 0xDC00);
return 2;
}
}
}
*codepoint=0xFFFD; // invalid
return 1;
}
static size_t utf16BE_to_ucs4_character(const uint16_t *utf16_string, size_t len, uint32_t *codepoint)
{
uint16_t lead = swap_utf16LE(utf16_string[0]);
if (lead < 0xD800 || lead >= 0xE000)
{
return lead;
}
if (lead < 0xDC00)
{
if (len >= 2)
{
uint16_t trail = swap_utf16LE(utf16_string[1]);
if (trail >= 0xDC00 && trail < 0xE000)
{
*codepoint = 0x10000 + ((lead - 0xD800) << 10) + (trail - 0xDC00);
return 2;
}
}
}
*codepoint=0xFFFD; // invalid
return 1;
}
static size_t ucs4count(uint32_t codepoint)
{
if (codepoint < 0x80)
return 1;
else if (codepoint < 0x800)
return 2;
else if (codepoint < 0x10000)
return 3;
else if (codepoint < 0x200000)
return 4;
else if (codepoint < 0x4000000)
return 5;
else if (codepoint <= 0x7FFFFFFF)
return 6;
else
return 0;
}
static size_t ucs4_to_utf8_character(char *target, uint32_t codepoint, size_t max)
{
size_t count = ucs4count(codepoint);
if (!count)
return 0;
if (count>max) return 0;
if (target == 0)
return count;
switch (count)
{
case 6:
target[5] = 0x80 | (codepoint & 0x3F);
codepoint = codepoint >> 6;
codepoint |= 0x4000000;
case 5:
target[4] = 0x80 | (codepoint & 0x3F);
codepoint = codepoint >> 6;
codepoint |= 0x200000;
case 4:
target[3] = 0x80 | (codepoint & 0x3F);
codepoint = codepoint >> 6;
codepoint |= 0x10000;
case 3:
target[2] = 0x80 | (codepoint & 0x3F);
codepoint = codepoint >> 6;
codepoint |= 0x800;
case 2:
target[1] = 0x80 | (codepoint & 0x3F);
codepoint = codepoint >> 6;
codepoint |= 0xC0;
case 1:
target[0] = codepoint;
}
return count;
}
size_t utf16LE_to_utf8(const uint16_t *src, size_t source_len, char *dst, size_t out_len)
{
uint32_t codepoint=0xFFFD;
size_t position=0;
size_t characters_processed=0;
if (!dst) // they just want the size
{
while (source_len)
{
characters_processed = utf16LE_to_ucs4_character(src, source_len, &codepoint);
if (codepoint == 0xFFFD)
break;
if (!codepoint)
break;
source_len -= characters_processed;
characters_processed = ucs4count(codepoint);
if (!characters_processed)
break;
position+=characters_processed;
}
return position;
}
while(source_len && position<out_len)
{
characters_processed = utf16LE_to_ucs4_character(src, source_len, &codepoint);
if (codepoint == 0xFFFD)
break;
if (!codepoint)
break;
source_len -= characters_processed;
characters_processed=ucs4_to_utf8_character(&dst[position], codepoint, out_len-position);
if (!characters_processed)
break;
position+=characters_processed;
}
if (position<out_len)
dst[position]=0;
return position;
}
size_t utf16BE_to_utf8(const uint16_t *src, size_t source_len, char *dst, size_t out_len)
{
uint32_t codepoint=0xFFFD;
size_t position=0;
size_t characters_processed=0;
if (!dst) // they just want the size
{
while (source_len)
{
characters_processed = utf16BE_to_ucs4_character(src, source_len, &codepoint);
if (codepoint == 0xFFFD)
break;
if (!codepoint)
break;
source_len -= characters_processed;
characters_processed = ucs4count(codepoint);
if (!characters_processed)
break;
position+=characters_processed;
}
return position;
}
while(source_len && position<out_len)
{
characters_processed = utf16BE_to_ucs4_character(src, source_len, &codepoint);
if (codepoint == 0xFFFD)
break;
if (!codepoint)
break;
source_len -= characters_processed;
characters_processed=ucs4_to_utf8_character(&dst[position], codepoint, out_len-position);
if (!characters_processed)
break;
position+=characters_processed;
}
if (position<out_len)
dst[position]=0;
return position;
}
#endif

73
Src/nde/DBUtils.h Normal file
View file

@ -0,0 +1,73 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
All Purposes Functions Prototypes
--------------------------------------------------------------------------- */
#ifndef __DBUTILS_H
#define __DBUTILS_H
#include <stdio.h>
#include "vfs.h"
#include "field.h"
bool CompatibleFields(unsigned char oldType, unsigned char newType);
uint32_t AllocNewPos(VFILE *Handle);
Field *TranslateObject(unsigned char Type, Table *tbl);
#ifndef __ANDROID__
const void *memmem(const void *a, const void *b, size_t s, size_t l);
#endif
#ifdef __ANDROID__
char *stristr(const char *s1, const char *s2);
int mystricmp(const char *a, const char *b);
char* mystristr(const char *a, const char *b);
int nde_stricmp(const char *a, const char *b);
int nde_stricmp_ignore(const char *a, const char *b); // ignores accents
int nde_strnicmp(const char *a, const char *b, size_t len); // len must be <= strlen(b)
int nde_strnicmp_ignore(const char *a, const char *b, size_t len); // ignores accents
char *stristr_ignore(const char *s1, const char *s2);
// filesystem safe versions
char* mystristr_fn(const char *a, const char *b);
int mystricmp_fn(const char *a, const char *b);
char *stristr_fn(const char *s1, const char *s2);
extern "C" int NDE_API nde_stricmp_fn(const char *a, const char *b);
int nde_strnicmp_fn(const char *a, const char *b, size_t len); // len must be <= strlen(b)
size_t utf16LE_to_utf8(const uint16_t *src, size_t source_len, char *dst, size_t out_len);
size_t utf16BE_to_utf8(const uint16_t *src, size_t source_len, char *dst, size_t out_len);
#endif
#ifdef _WIN32
#include <windows.h>
int WINAPI NDE_FindNLSString(LCID Locale, DWORD dwFindNLSStringFlags, LPCWSTR lpStringSource, int cchSource, LPCWSTR lpStringValue, int cchValue, LPINT pcchFound);
extern int (WINAPI *findNLSString)(LCID Locale, DWORD dwFindNLSStringFlags, LPCWSTR lpStringSource, int cchSource, LPCWSTR lpStringValue, int cchValue, LPINT pcchFound);
bool nde_wcsbegins(const wchar_t *a, const wchar_t *b);
bool nde_wcsends(const wchar_t *a, const wchar_t *b);
bool nde_wcscontains(const wchar_t *a, const wchar_t *b);
int mywcsicmp(const wchar_t *a, const wchar_t *b);
int nde_wcsicmp(const wchar_t *a, const wchar_t *b);
// filesystem safe versions
bool nde_fnbegins(const wchar_t *a, const wchar_t *b);
bool nde_fnends(const wchar_t *a, const wchar_t *b);
bool nde_fncontains(const wchar_t *a, const wchar_t *b);
const wchar_t* mywcsistr_fn(const wchar_t *a, const wchar_t *b);
int mywcsicmp_fn(const wchar_t *a, const wchar_t *b);
extern "C" int NDE_API nde_wcsicmp_fn(const wchar_t *a, const wchar_t *b);
#endif
#ifdef __APPLE__
wchar_t *_wcsdup(const wchar_t *val);
#endif
#endif

76
Src/nde/Database.cpp Normal file
View file

@ -0,0 +1,76 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
Database Class
--------------------------------------------------------------------------- */
#include "Database.h"
#include "Table.h"
//---------------------------------------------------------------------------
Database::Database()
{
#ifdef WIN32
hInstance = (HINSTANCE)0;
#endif
}
#ifdef WIN32
//---------------------------------------------------------------------------
Database::Database(HINSTANCE hinst)
{
hInstance = hinst;
}
#endif
//---------------------------------------------------------------------------
Database::~Database()
{
}
#ifdef WIN32
//---------------------------------------------------------------------------
void Database::SetInstance(HINSTANCE inst) {
hInstance = inst;
}
HINSTANCE Database::GetInstance() {
return hInstance;
}
#endif
//--------------------------------------------------------------------------
#ifdef _WIN32
Table *Database::OpenTable(const wchar_t *TableName, const wchar_t *IdxName, BOOL Create, BOOL Cached)
#else
Table *Database::OpenTable(const char *TableName, const char *IdxName, BOOL Create, BOOL Cached)
#endif
//char *tablefn, char*indexfn, BOOL create)
{
Table *table = new Table(TableName, IdxName, Create, this, Cached);
if (table)
{
if (table->Open())
return table;
table->Close();
delete table;
}
return NULL;
}
//---------------------------------------------------------------------------
void Database::CloseTable(Table *table)
{
if (table)
{
table->Close();
delete table;
}
}

48
Src/nde/Database.h Normal file
View file

@ -0,0 +1,48 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
Database Class Prototypes
--------------------------------------------------------------------------- */
#ifndef __DATABASE_H
#define __DATABASE_H
#include "nde.h"
#ifdef WIN32
#include <io.h>
#else
#include <unistd.h>
#endif
#include <stdio.h>
class Database
{
public:
Database();
#ifdef WIN32
Database(HINSTANCE hinst);
HINSTANCE GetInstance();
void SetInstance(HINSTANCE hinst);
#endif
~Database();
#ifdef _WIN32
Table *OpenTable(const wchar_t *table, const wchar_t *index, BOOL create, BOOL cached);
#else
Table *OpenTable(const char *table, const char *index, BOOL create, BOOL cached);
#endif
void CloseTable(Table *table);
private:
#ifdef WIN32
HINSTANCE hInstance;
#endif
};
#endif

281
Src/nde/Field.cpp Normal file
View file

@ -0,0 +1,281 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
Field Class
--------------------------------------------------------------------------- */
#include "field.h"
#include "vfs.h"
#include "table.h"
#include "nde.h"
#include "dbutils.h"
#ifdef WIN32
#include <malloc.h>
#elif defined(__APPLE__)
#include <alloca.h>
#endif
//---------------------------------------------------------------------------
void PUT_BINARY(uint8_t *dest, const uint8_t *src, size_t size, size_t pos)
{
if (src && dest && size > 0)
memcpy(dest+pos, src, size);
}
//---------------------------------------------------------------------------
void GET_BINARY(uint8_t *dest, const uint8_t *src, size_t size, size_t pos)
{
if (dest && src && size > 0)
memcpy(dest, src+pos, size);
}
//---------------------------------------------------------------------------
void PUT_FLOAT(float f, uint8_t *data, size_t pos)
{
unsigned int y = *(const unsigned int *)&f;
data[pos]=(unsigned char)(y&255); data[pos+1]=(unsigned char)((y>>8)&255); data[pos+2]=(unsigned char)((y>>16)&255); data[pos+3]=(unsigned char)((y>>24)&255);
}
//---------------------------------------------------------------------------
float GET_FLOAT(const uint8_t *data, size_t pos)
{
int a = data[pos]|(data[pos+1]<<8)|(data[pos+2]<<16)|(data[pos+3]<<24);
float f = *(const float *)&a;
return f;
}
//---------------------------------------------------------------------------
Field::Field(int FieldPos)
{
InitField();
Pos = FieldPos;
}
//---------------------------------------------------------------------------
void Field::InitField(void)
{
Type = FIELD_UNKNOWN;
Pos = 0;
ID = 0;
MaxSizeOnDisk = 0;
}
//---------------------------------------------------------------------------
Field::Field()
{
InitField();
}
//---------------------------------------------------------------------------
Field::~Field()
{
}
//---------------------------------------------------------------------------
Field *Field::ReadField(Table *pTable, int pos, uint32_t *next_position)
{
return ReadField(pTable, pos, false, next_position);
}
//---------------------------------------------------------------------------
Field *Field::ReadField(Table *pTable, int pos, bool Quick, uint32_t *next_position)
{
VFILE *HTable = pTable->Handle;
int newPos = pos;
int rType = FIELD_REDIRECTOR;
unsigned char oType;
if (!Vflock(HTable, false))
return 0;
while (rType == FIELD_REDIRECTOR)
{
Vfseek(HTable, Pos, SEEK_SET);
if (Vfread(&ID, sizeof(ID), HTable) != 1 ||
Vfread(&oType, sizeof(oType), HTable) != 1)
{
Vfunlock(HTable, false);
return NULL;
}
if (oType == FIELD_REDIRECTOR)
{
if (Vfread(&newPos, sizeof(newPos), HTable) != 1)
{
Vfunlock(HTable, false);
return NULL;
}
Pos = newPos;
}
rType = oType;
}
if (Quick)
Vfseek(HTable, sizeof(MaxSizeOnDisk), SEEK_CUR);
else
{
if (Vfread(&MaxSizeOnDisk, sizeof(MaxSizeOnDisk), HTable) != 1)
{
Vfunlock(HTable, false);
return NULL;
}
}
uint32_t NextFieldPos = 0;
if (Vfread(&NextFieldPos, sizeof(NextFieldPos), HTable) != 1)
{
Vfunlock(HTable, false);
return NULL;
}
if (next_position) *next_position = NextFieldPos;
if (Quick)
{
Vfunlock(HTable, false);
return this;
}
uint32_t PreviousFieldPos = 0;
if (Vfread(&PreviousFieldPos, sizeof(PreviousFieldPos), HTable) != 1)
{
Vfunlock(HTable, false);
return NULL;
}
Field *O=NULL;
O = TranslateObject(oType, pTable);
if (O)
{
O->ID = ID;
O->Type = oType;
O->Pos = Pos;
O->MaxSizeOnDisk = MaxSizeOnDisk;
uint8_t *data = NULL;
if (HTable->cached && MaxSizeOnDisk > VFILE_INC)
{
pTable->IncErrorCount();
MaxSizeOnDisk = (uint32_t)GetDataSize();
O->MaxSizeOnDisk = MaxSizeOnDisk;
}
else if (HTable->cached)
{
data = HTable->data+HTable->ptr; // benski> uber-hack
Vfseek(HTable, MaxSizeOnDisk, SEEK_CUR);
}
else
{
data = (uint8_t *)_malloca(MaxSizeOnDisk);
Vfread(data, MaxSizeOnDisk, HTable);
}
if (data)
{
O->ReadTypedData(data, MaxSizeOnDisk);
if (!HTable->cached)
{
_freea(data);
}
}
Vfunlock(HTable, false);
return O;
}
Vfunlock(HTable, false);
return NULL;
}
//---------------------------------------------------------------------------
void Field::WriteField(Table *pTable, Field *previous_field, Field *next_field)
{
VFILE *HTable = pTable->Handle;
if (Pos == -1) return;
size_t data_size = GetDataSize();
if (HTable->cached && MaxSizeOnDisk > VFILE_INC) {
pTable->IncErrorCount();
MaxSizeOnDisk = (uint32_t)data_size;
}
if (Pos == 0 || (uint32_t)data_size > MaxSizeOnDisk)
{
MaxSizeOnDisk = (uint32_t)data_size;
uint32_t newPos = AllocNewPos(HTable);
if (Pos != 0)
{
unsigned char v = 0;
Vfseek(HTable, Pos, SEEK_SET);
Vfwrite(&v, sizeof(v), HTable);
v = FIELD_REDIRECTOR;
Vfwrite(&v, sizeof(v), HTable);
Vfwrite(&newPos, sizeof(newPos), HTable);
}
Pos = newPos;
if (previous_field)
{
//previous_field->NextFieldPos = Pos;
if (previous_field->Pos)
{
Vfseek(HTable, previous_field->Pos+sizeof(ID)+sizeof(MaxSizeOnDisk)+sizeof(Type), SEEK_SET);
Vfwrite(&Pos, sizeof(Pos), HTable);
}
}
if (next_field)
{
if (next_field->Pos)
{
Vfseek(HTable, next_field->Pos+sizeof(ID)+sizeof(uint32_t/*NextFieldPos*/)+sizeof(Type)+sizeof(MaxSizeOnDisk), SEEK_SET);
Vfwrite(&Pos, sizeof(Pos), HTable);
}
}
}
uint32_t PreviousFieldPos = 0, NextFieldPos = 0;
if (previous_field) PreviousFieldPos = previous_field->GetFieldPos(); else PreviousFieldPos = NULL;
if (next_field) NextFieldPos = next_field->GetFieldPos(); else NextFieldPos = NULL;
Vfseek(HTable, Pos, SEEK_SET);
Vfwrite(&ID, sizeof(ID), HTable);
Vfwrite(&Type, sizeof(Type), HTable);
Vfwrite(&MaxSizeOnDisk, sizeof(MaxSizeOnDisk), HTable);
Vfwrite(&NextFieldPos, sizeof(NextFieldPos), HTable);
Vfwrite(&PreviousFieldPos, sizeof(PreviousFieldPos), HTable);
uint8_t *data = (unsigned char*)_malloca(MaxSizeOnDisk);
WriteTypedData(data, MaxSizeOnDisk);
Vfwrite(data, MaxSizeOnDisk, HTable);
_freea(data);
}
//---------------------------------------------------------------------------
uint32_t Field::GetFieldPos(void)
{
return Pos;
}
//---------------------------------------------------------------------------
Field *Field::Clone(Table *pTable)
{
Field *clone = TranslateObject(Type, pTable);
size_t size = GetDataSize();
uint8_t *data = (unsigned char*)_malloca(size);
WriteTypedData(data, size);
clone->ReadTypedData(data, size);
if (data) _freea(data);
clone->Type = Type;
//clone->HTable = HTable;
clone->Pos = FIELD_CLONE;
clone->ID = ID;
//clone->NextFieldPos = 0;
clone->MaxSizeOnDisk=(uint32_t)size;
return clone;
}
//---------------------------------------------------------------------------
int Field::GetType() {
return Type;
}
size_t Field::GetTotalSize()
{
return GetDataSize() + sizeof(ID)+sizeof(Type)+sizeof(MaxSizeOnDisk)+sizeof(uint32_t/*NextFieldPos*/)+sizeof(uint32_t /*PreviousFieldPos*/);
}

110
Src/nde/Field.h Normal file
View file

@ -0,0 +1,110 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
Field Class Prototypes
--------------------------------------------------------------------------- */
#ifndef __FIELD_H
#define __FIELD_H
#ifdef __ANDROID__
#include <foundation/types.h> // TODO
#else
#include <bfc/platform/types.h>
#endif
class Table;
#include <stdio.h>
#define PUT_INT(y) data[pos]=(uint8_t)(y&255); data[pos+1]=(uint8_t)((y>>8)&255); data[pos+2]=(uint8_t)((y>>16)&255); data[pos+3]=(uint8_t)((y>>24)&255)
#define GET_INT() (int)(data[pos]|(data[pos+1]<<8)|(data[pos+2]<<16)|(data[pos+3]<<24))
#define PUT_SHORT(y) data[pos]=(uint8_t)(y&255); data[pos+1]=(uint8_t)((y>>8)&255);
#define GET_SHORT() (uint16_t)(data[pos]|(data[pos+1]<<8))
#define PUT_PINT(y) data[*pos]=(uint8_t)(y&255); data[*pos+1]=(uint8_t)((y>>8)&255); data[*pos+2]=(uint8_t)((y>>16)&255); data[*pos+3]=(uint8_t)((y>>24)&255)
extern float GET_FLOAT(const uint8_t *data, size_t pos);
extern void PUT_FLOAT(float f, uint8_t *data, size_t pos);
extern void PUT_BINARY(uint8_t *dest, const uint8_t *src, size_t size, size_t pos);
extern void GET_BINARY(uint8_t *dest, const uint8_t *src, size_t size, size_t pos);
#define PUT_CHAR(y) data[pos]=y
#define GET_CHAR() data[pos]
#define CHECK_CHAR(l) { if (l < 1) return; l--; }
#define CHECK_INT(l) { if (l < 4) return; l-=4; }
#define CHECK_INT64(l) { if (l < 8) return; l-=8; }
#define CHECK_SHORT(l) { if (l < 2) return; l-=2; }
#define CHECK_BIN(l, size) { if (l < size) return; l-=size; }
#ifdef ASSERT
#undef ASSERT
#endif
#define ASSERT(x) { \
if (!(x)) \
OutputDebugString("Assertion failed "); \
}
#define _CHECK_CHAR(l) { ASSERT(l >= 1); l-=1; }
#define _CHECK_INT(l) { ASSERT(l >= 4); l-=4; }
#define _CHECK_SHORT(l) { ASSERT(l >= 2); l-=2; }
#define _CHECK_BIN(l, size) { ASSERT(l >= size); l-=size; }
class Field //: public wa::lists::node_ptr
{
public:
Field();
virtual ~Field();
virtual Field *Clone(Table *pTable);
unsigned char GetFieldId(void)
{
return ID;
}
int GetType();
size_t GetTotalSize();
Field(int FieldPos);
Field *ReadField(Table *pTable, int pos, uint32_t *next_position=0);
Field *ReadField(Table *pTable, int pos, bool readTyped, uint32_t *next_position=0);
void WriteField(Table *pTable, Field *previous_field, Field *next_field);
virtual void ReadTypedData(const uint8_t *, size_t /*len*/) { };
virtual void WriteTypedData(uint8_t *, size_t) { };
virtual size_t GetDataSize(void)
{
return 0;
}
virtual int Compare(Field * /*Entry*/)
{
return 0;
}
virtual int Starts(Field * /*Entry*/)
{
return 0;
}
virtual int Contains(Field * /*Entry*/)
{
return 0;
}
virtual bool ApplyFilter(Field * /*Data*/, int /*flags*/)
{
return false;
}
uint32_t GetFieldPos(void);
void InitField(void);
union
{
struct
{
uint8_t ID;
uint8_t Type;
};
uint32_t _dummy_union_thingy;
};
protected:
uint32_t Pos;
uint32_t MaxSizeOnDisk;
};
#endif

8
Src/nde/FilenameField.h Normal file
View file

@ -0,0 +1,8 @@
#pragma once
#ifdef __APPLE__
#include "osx/FilenameField.h"
#elif defined(_WIN32)
#include "win/FilenameField.h"
#elif defined(__ANDROID__)
#include "android/FilenameField.h"
#endif

69
Src/nde/Filter.cpp Normal file
View file

@ -0,0 +1,69 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
Filter Class
--------------------------------------------------------------------------- */
// Filters can now be a test on a field or a single operator that will pop
// one operation from the filters stack. upon AddFilter*, return value will
#include "Filter.h"
#include "Field.h"
//---------------------------------------------------------------------------
Filter::Filter(unsigned char _Op)
{
DataField = 0;
Op = _Op;
Id = -1;
}
//---------------------------------------------------------------------------
Filter::Filter(Field *Data, unsigned char _Id, unsigned char _Op)
{
DataField = Data;
Op = _Op;
Id = _Id;
}
//---------------------------------------------------------------------------
Filter::~Filter()
{
delete DataField;
}
//---------------------------------------------------------------------------
unsigned char Filter::GetOp(void) const
{
return Op;
}
//---------------------------------------------------------------------------
void Filter::SetOp(unsigned char _Op)
{
Op = _Op;
}
//---------------------------------------------------------------------------
Field *Filter::Data(void) const
{
return DataField;
}
//---------------------------------------------------------------------------
void Filter::SetData(Field *data)
{
DataField = data;
}
//---------------------------------------------------------------------------
int Filter::GetId(void) const
{
return Id;
}

37
Src/nde/Filter.h Normal file
View file

@ -0,0 +1,37 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
Filter Class Prototypes
--------------------------------------------------------------------------- */
#ifndef __FILTER_H
#define __FILTER_H
#include "LinkedList.h"
class Field;
class Filter : public LinkedListEntry
{
private:
Field* DataField;
unsigned char Op;
unsigned char Id;
public:
unsigned char GetOp(void) const;
void SetOp(unsigned char Op);
Field *Data(void) const;
int GetId(void) const;
Filter(unsigned char _Op);
Filter(Field *Data, unsigned char Id, unsigned char Op);
void SetData(Field *data);
~Filter() ;
};
#endif

787
Src/nde/Index.cpp Normal file
View file

@ -0,0 +1,787 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
Raw Index Class
--------------------------------------------------------------------------- */
#include "nde.h"
#include <stdio.h>
const char *iSign="NDEINDEX";
//---------------------------------------------------------------------------
Index::Index(VFILE *H, unsigned char id, int pos, int type, bool newindex, int nentries, Table *parentTable)
{
Handle = H;
IndexTable = NULL;
MaxSize=0;
locateUpToDate = false;
Id = id;
Position = pos;
// DataType = type;
SecIndex = NULL;
InChain=false;
InInsert=false;
InChainIdx = -1;
pTable = parentTable;
TableHandle = pTable->Handle;
SetGlobalLocateUpToDate(false);
if (!newindex)
{
Vfseek(Handle, (int)strlen(__INDEX_SIGNATURE__), SEEK_SET);
Vfread(&NEntries, sizeof(NEntries), Handle);
}
else
NEntries = nentries;
LoadIndex(newindex);
}
//---------------------------------------------------------------------------
Index::~Index()
{
if (IndexTable)
free(IndexTable);
}
//---------------------------------------------------------------------------
int Index::Insert(int N)
{
return Insert(NULL, N, false);
}
//---------------------------------------------------------------------------
int Index::Insert(Index *parindex, int N, bool localonly)
{
if (InChain) return -1;
Index *p = parindex;
IndexField *f = 0;
locateUpToDate = false;
SetGlobalLocateUpToDate(false);
InInsert=true;
if (N > NEntries) N = NEntries;
if ((NEntries+1) > (int)MaxSize)
{
MaxSize *=2;//+= BLOCK_SIZE;
int *newBlock = (int *)calloc(MaxSize, sizeof(int)*2);
memcpy(newBlock, IndexTable, NEntries*sizeof(int)*2);
free(IndexTable);
IndexTable = newBlock;
}
if (N < NEntries && Id == PRIMARY_INDEX)
{
memmove(IndexTable+(N+1)*2, IndexTable+(N*2), (NEntries-N)*sizeof(int)*2);
NEntries++;
}
else
{
N=NEntries;
NEntries++;
}
Update(N, 0, NULL, localonly);
// Should be always safe to cat the new record since if we are primary index,
// then secondary is sorted, so value will be moved at update
// if we are a secondary index, then an insertion will insert at the end of the primary index anyway
if (!localonly && SecIndex)
{
InChain=true;
int pp = SecIndex->index->Insert(this, N, false);
InChain=false;
IndexTable[N*2+1] = pp == -1 ? N : pp;
if (N < NEntries-1 && Id == PRIMARY_INDEX)
{
int pidx = -1;
if (!parindex)
{
int v = pp;
f = SecIndex;
if (f)
{
while (f->index->SecIndex->index != this)
{
v = f->index->GetCooperative(v);
f = f->index->SecIndex;
}
p = f->index;
pidx = v;
}
}
if (p && pidx != -1)
{
p->SetCooperative(pidx, N);
UpdateMe(p, N, NEntries);
}
}
}
InInsert=false;
return N;
}
//---------------------------------------------------------------------------
void Index::LoadIndex(bool newindex)
{
if (IndexTable)
free(IndexTable);
MaxSize = ((NEntries) / BLOCK_SIZE + 1) * BLOCK_SIZE;
IndexTable = (int *)calloc(MaxSize, sizeof(int)*2);
if (!newindex)
{
Vfseek(Handle, (int)strlen(__INDEX_SIGNATURE__)+4+((NEntries*4*2)+4)*(Position+1), SEEK_SET);
int v = 0;
Vfread(&v, sizeof(v), Handle);
Id = (unsigned char)v;
Vfread(IndexTable, NEntries*2*sizeof(int), Handle);
}
}
//---------------------------------------------------------------------------
int Index::Update(int Idx, int Pos, RecordBase *record, bool localonly)
{
return Update(NULL, -1, Idx, Pos, record, false, localonly);
}
//---------------------------------------------------------------------------
int Index::Update(Index *parindex, int paridx, int Idx, int Pos, RecordBase *record, bool forceLast, bool localonly)
{
if (InChain) return InChainIdx;
int NewIdx=Idx;
int oldSecPtr = IndexTable[Idx*2+1];
if (!forceLast && Id == PRIMARY_INDEX || record == NULL || Idx < NUM_SPECIAL_RECORDS)
{
if (Idx < NEntries && Idx >= 0)
{
IndexTable[Idx*2] = Pos;
if (!localonly && SecIndex && SecIndex->index != this && !InInsert)
{
InChain=true;
InChainIdx = Idx;
SecIndex->index->Update(this, Idx, IndexTable[Idx*2+1], Pos, record, forceLast, false);
InChainIdx = -1;
InChain=false;
}
}
else
{
#ifdef WIN32
MessageBox(NULL, L"Updating outside range", L"Oops", 16);
#else
printf("NDE Error: updating outside range!\n");
#endif
}
}
else
{
if (forceLast)
NewIdx = NEntries;
else
{
if (Pos != Get(Idx) || Id != PRIMARY_INDEX)
{
int state = 0;
NewIdx = FindSortedPlace(record->GetField(Id), Idx, &state, QFIND_ENTIRE_SCOPE);
}
}
if (NewIdx <= NEntries && NewIdx >= NUM_SPECIAL_RECORDS)
{
if (NewIdx != Idx)
{
Index *p = parindex;
IndexField *f = 0;
int pidx = paridx;
NewIdx = MoveIndex(Idx, NewIdx);
if (SecIndex->index != this)
{
if (!parindex)
{
int v = GetCooperative(NewIdx);
f = SecIndex;
if (f)
{
while (f->index->SecIndex->index != this)
{
v = f->index->GetCooperative(v);
f = f->index->SecIndex;
}
p = f->index;
pidx = v;
}
}
if (p)
{
p->SetCooperative(pidx, NewIdx);
UpdateMe(p, NewIdx, Idx);
}
}
}
IndexTable[NewIdx*2] = Pos;
if (!localonly && SecIndex && SecIndex->index != this && !InInsert) // Actually, we should never be InInsert and here, but lets cover our ass
{
InChain=true;
InChainIdx = oldSecPtr;
SecIndex->index->Update(this, NewIdx, oldSecPtr, Pos, record, forceLast, false);
InChainIdx = -1;
InChain=false;
}
}
else
{
#ifdef WIN32
MessageBox(NULL, L"QSort failed and tried to update index outside range", L"Oops", 16);
#else
printf("NDE Error: qsort failed and tried to update index outside range!\n");
#endif
}
}
locateUpToDate = false;
SetGlobalLocateUpToDate(false);
pTable->IndexModified();
return NewIdx;
}
//---------------------------------------------------------------------------
int Index::Get(int Idx)
{
if (Idx < NEntries)
return IndexTable[Idx*2];
else
{
#ifdef WIN32
MessageBox(NULL, L"Requested index outside range", L"Oops", 16);
#else
printf("NDE Error: requested index outside range!\n");
#endif
return -1;
}
}
//---------------------------------------------------------------------------
void Index::Set(int Idx, int P)
{
if (Idx < NEntries)
IndexTable[Idx*2]=P;
else
{
#ifdef WIN32
MessageBox(NULL, L"Updating index outside range", L"Oops", 16);
#else
printf("NDE Error: updating index outside range!\n");
#endif
}
}
//---------------------------------------------------------------------------
void Index::WriteIndex(void)
{
if (Id == PRIMARY_INDEX)
{
Vfseek(Handle, (int)strlen(__INDEX_SIGNATURE__), SEEK_SET);
Vfwrite(&NEntries, sizeof(NEntries), Handle);
}
Vfseek(Handle, (int)strlen(__INDEX_SIGNATURE__)+4+((NEntries*4*2)+4)*(Position+1), SEEK_SET);
int v=(int)Id;
Vfwrite(&v, sizeof(v), Handle);
Vfwrite(IndexTable, NEntries*2*sizeof(int), Handle);
}
//---------------------------------------------------------------------------
int Index::MoveIndex(int idx, int newidx)
{
if (idx == newidx)
return newidx;
int oldPos=IndexTable[idx*2], oldPtr=IndexTable[idx*2+1];
if (NEntries > idx+1)
memmove(IndexTable+idx*2, IndexTable+(idx+1)*2, (NEntries-idx)*sizeof(int)*2);
if (newidx > idx)
newidx--;
if (NEntries > newidx)
memmove(IndexTable+(newidx+1)*2, IndexTable+newidx*2, (NEntries-newidx-1)*sizeof(int)*2);
IndexTable[newidx*2] = oldPos;
IndexTable[newidx*2+1] = oldPtr;
return newidx;
}
//---------------------------------------------------------------------------
void Index::Colaborate(IndexField *secindex)
{
SecIndex = secindex;
for (int i=0;i<NUM_SPECIAL_RECORDS;i++)
/*secindex->index->*/SetCooperative(i, i);
}
//---------------------------------------------------------------------------
void Index::Propagate(void)
{
int i;
if (!SecIndex || SecIndex->ID == PRIMARY_INDEX) return;
SecIndex->index->NEntries=NUM_SPECIAL_RECORDS;
for (i=0;i<NUM_SPECIAL_RECORDS;i++)
{
SecIndex->index->Set(i, Get(i));
SecIndex->index->SetCooperative(i, GetCooperative(i));
}
Scanner *s = pTable->NewScanner();
if (!s)
{
#ifdef WIN32
MessageBox(NULL, L"Failed to create a scanner in reindex", L"Oops", 16);
#else
printf("NDE Error: failed to create a scanner in reindex!\n");
#endif
return;
}
int *coopSave = (int *)calloc(NEntries, sizeof(int));
if (!coopSave)
{
#ifdef WIN32
MessageBox(NULL, L"Alloc failed in reindex", L"Oops", 16);
#else
printf("NDE Error: alloc failed in reindex!\n");
#endif
return;
}
for (i=0;i<NEntries;i++)
{
coopSave[i] = GetCooperative(i);
SetCooperative(i, i);
}
if (SecIndex->index->SecIndex->index->Id != PRIMARY_INDEX)
{
#ifdef WIN32
MessageBox(NULL, L"Propagating existing index", L"Oops", 16);
#else
printf("NDE Error: propagating existing index!\n");
#endif
free(coopSave);
return;
}
s->SetWorkingIndexById(-1);
for (i=NUM_SPECIAL_RECORDS;i<NEntries;i++)
{
Record *rec = s->GetRecord(coopSave[i]);
if (rec)
{
SecIndex->index->NEntries++;
// SecIndex->index->Insert(NULL, i, true);
SecIndex->index->SetCooperative(i, coopSave[i]);
SecIndex->index->Set(i, Get(i));
SecIndex->index->Update(i, SecIndex->index->Get(i), rec, true);
/* SecIndex->index->SetCooperative(i, q);*/
rec->Release();
}
else
{
#ifdef WIN32
MessageBox(NULL, L"Unable to read record in reindex", L"Oops", 16);
#else
printf("NDE Error: unable to read record in reindex!\n");
#endif
}
}
free(coopSave);
if (NEntries != SecIndex->index->NEntries) {
#ifdef WIN32
MessageBox(NULL, L"Secindex->NEntries desynchronized in reindex", L"Oops", 16);
#else
printf("NDE Error: Secindex->NEntries desynchronized in reindex!\n");
#endif
}
pTable->DeleteScanner(s);
}
//---------------------------------------------------------------------------
void Index::SetCooperative(int Idx, int secpos)
{
if (Idx < NEntries && Idx >= 0)
IndexTable[Idx*2+1] = secpos;
else
{
#ifdef WIN32
MessageBox(NULL, L"Cooperative update outside range", L"Oops", 16);
#else
printf("NDE Error: cooperative update outside range!\n");
#endif
}
}
//---------------------------------------------------------------------------
int Index::GetCooperative(int Idx)
{
if (Idx < NEntries && Idx >= 0)
return IndexTable[Idx*2+1];
else
{
#ifdef WIN32
MessageBox(NULL, L"Cooperative request outside range", L"Oops", 16);
#else
printf("NDE Error: cooperative request outside range!\n");
#endif
}
return -1;
}
//---------------------------------------------------------------------------
int Index::NeedFix() {
for (int i=NUM_SPECIAL_RECORDS;i<NEntries;i++) {
if (IndexTable[i*2+1] <= 0) return 1;
}
return 0;
}
//---------------------------------------------------------------------------
void Index::UpdateMe(Index *Me, int NewIdx, int OldIdx)
{
int j=NewIdx > OldIdx ? -1 : 1;
for (int i=min(NewIdx, OldIdx);i<=max(NewIdx, OldIdx)&&i<NEntries;i++)
{
if (i == NewIdx) continue;
int v = GetCooperative(i);
IndexField *f = SecIndex;
while (f->index->SecIndex->index != this)
{
v = f->index->GetCooperative(v);
f = f->index->SecIndex;
}
Me->SetCooperative(v, Me->GetCooperative(v)+j);
}
}
//---------------------------------------------------------------------------
Field *Index::QuickFindField(unsigned char Idx, int Pos)
{
int ThisPos = Pos;
while (ThisPos)
{
Vfseek(TableHandle, ThisPos, SEEK_SET);
Field entry(ThisPos);
uint32_t next_pos;
entry.ReadField(pTable, ThisPos, true, &next_pos);
if (entry.GetFieldId() == Idx)
{
return entry.ReadField(pTable, ThisPos);
}
ThisPos = next_pos;
}
return NULL;
}
//---------------------------------------------------------------------------
// Dynamic qsort (i definitly rule)
int Index::FindSortedPlace(Field *thisField, int curIdx, int *laststate, int start)
{
return FindSortedPlaceEx(thisField, curIdx, laststate, start, COMPARE_MODE_EXACT);
}
//---------------------------------------------------------------------------
// and here again ugly switch
int Index::FindSortedPlaceEx(Field *thisField, int curIdx, int *laststate, int start, int comp_mode)
{
int top=start != QFIND_ENTIRE_SCOPE ? start : NUM_SPECIAL_RECORDS;
int bottom=NEntries-1;
int compEntry = 0;
int cePos = 0;
Field *compField=NULL;
int i = 0;
Field *cfV=NULL;
if (NEntries <= NUM_SPECIAL_RECORDS) return NUM_SPECIAL_RECORDS;
switch(comp_mode)
{
case COMPARE_MODE_EXACT:
while (bottom-top >= 1)
{
compEntry=(bottom-top)/2+top;
if (compEntry == curIdx) compEntry++;
if (compEntry == bottom) break;
cePos = Get(compEntry);
if (!cePos) bottom = compEntry;
else
{
compField = QuickFindField(Id, Get(compEntry));
cfV = compField;
if (!thisField)
{
if (!compField) i = 0;
else i = 1;
}
else i = thisField->Compare(cfV);
switch (i)
{
case 1:
top = compEntry+1;
break;
case -1:
bottom = compEntry-1;
break;
case 0:
*laststate=0;
delete compField;
return compEntry+1;
}
delete compField;
}
}
compEntry=(bottom-top)/2+top;
if (compEntry == curIdx) return curIdx;
compField = QuickFindField(Id, Get(compEntry));
cfV = compField;
if (thisField) *laststate = thisField->Compare(cfV);
else
{
if (!compField) *laststate = 0;
else *laststate = 1;
}
break;
case COMPARE_MODE_CONTAINS:
while (bottom-top >= 1)
{
compEntry=(bottom-top)/2+top;
if (compEntry == curIdx) compEntry++;
if (compEntry == bottom) break;
cePos = Get(compEntry);
if (!cePos) bottom = compEntry;
else
{
compField = QuickFindField(Id, Get(compEntry));
cfV = compField;
if (!thisField)
{
if (!compField) i = 0;
else i = 1;
}
else i = thisField->Contains(cfV);
switch (i)
{
case 1:
top = compEntry+1;
break;
case -1:
bottom = compEntry-1;
break;
case 0:
*laststate=0;
delete compField;
return compEntry+1;
}
if (compField)
{
delete compField;
}
}
}
compEntry=(bottom-top)/2+top;
if (compEntry == curIdx) return curIdx;
compField = QuickFindField(Id, Get(compEntry));
cfV = compField;
if (thisField) *laststate = thisField->Contains(cfV);
else
{
if (!compField) *laststate = 0;
else *laststate = 1;
}
break;
case COMPARE_MODE_STARTS:
while (bottom-top >= 1)
{
compEntry=(bottom-top)/2+top;
if (compEntry == curIdx) compEntry++;
if (compEntry == bottom) break;
cePos = Get(compEntry);
if (!cePos) bottom = compEntry;
else
{
compField = QuickFindField(Id, Get(compEntry));
cfV = compField;
if (!thisField)
{
if (!compField) i = 0;
else i = 1;
}
else i = thisField->Starts(cfV);
switch (i)
{
case 1:
top = compEntry+1;
break;
case -1:
bottom = compEntry-1;
break;
case 0:
*laststate=0;
delete compField;
return compEntry+1;
}
if (compField)
{
delete compField;
}
}
}
compEntry=(bottom-top)/2+top;
if (compEntry == curIdx) return curIdx;
compField = QuickFindField(Id, Get(compEntry));
cfV = compField;
if (thisField) *laststate = thisField->Starts(cfV);
else
{
if (!compField) *laststate = 0;
else *laststate = 1;
}
break;
}
switch (*laststate)
{
case -1:
delete compField;
return compEntry;
case 1:
case 0:
delete compField;
return /*compEntry==NEntries-1 ? compEntry : */compEntry+1;
}
return NUM_SPECIAL_RECORDS; // we're not supposed to be here :/
}
int Index::QuickFind(int Id, Field *field, int start)
{
return QuickFindEx(Id, field, start, COMPARE_MODE_EXACT);
}
//---------------------------------------------------------------------------
int Index::QuickFindEx(int Id, Field *field, int start, int comp_mode)
{
int laststate = 0;
Field *compField=NULL, *cfV=NULL;
int i = FindSortedPlaceEx(field, Id, &laststate, start, comp_mode)-1; // -1 because we don't insert but just search
if (laststate != 0)
return FIELD_NOT_FOUND;
if (i < start)
return FIELD_NOT_FOUND;
switch(comp_mode)
{
case COMPARE_MODE_CONTAINS:
while (--i>=NUM_SPECIAL_RECORDS)
{
compField = QuickFindField(Id, Get(i));
cfV = compField;
if (field->Contains(cfV) != 0)
{
if (compField)
{
delete compField;
}
return i+1;
}
if (compField)
{
delete compField;
}
}
break;
case COMPARE_MODE_EXACT:
while (--i>=NUM_SPECIAL_RECORDS)
{
compField = QuickFindField(Id, Get(i));
cfV = compField;
if (field->Compare(cfV) != 0)
{
if (compField)
{
delete compField;
}
return i+1;
}
if (compField)
{
delete compField;
}
}
break;
case COMPARE_MODE_STARTS:
while (--i>=NUM_SPECIAL_RECORDS)
{
compField = QuickFindField(Id, Get(i));
cfV = compField;
if (field->Starts(cfV) != 0)
{
delete compField;
return i+1;
}
delete compField;
}
break;
}
return i+1;
}
//---------------------------------------------------------------------------
int Index::TranslateIndex(int Pos, Index *index)
{
int v = GetCooperative(Pos);
IndexField *f = SecIndex;
while (f->index != this && f->index != index)
{
v = f->index->GetCooperative(v);
f = f->index->SecIndex;
}
return v;
}
//---------------------------------------------------------------------------
void Index::Delete(int Idx, int Pos, Record *record)
{
Update(NULL, -1, Idx, Pos, record, true, false);
Shrink();
}
//---------------------------------------------------------------------------
void Index::Shrink(void)
{
if (InChain) return;
if (SecIndex && SecIndex->index != this) // Actually, we should never be InInsert and here, but lets cover our ass
{
InChain=true;
SecIndex->index->Shrink();
InChain=false;
}
NEntries--;
}
//---------------------------------------------------------------------------
void Index::SetGlobalLocateUpToDate(bool isUptodate) {
if (!pTable) return;
pTable->SetGlobalLocateUpToDate(isUptodate);
}
unsigned char Index::GetId() {
return Id;
}

83
Src/nde/Index.h Normal file
View file

@ -0,0 +1,83 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
Raw Index Class Prototypes
--------------------------------------------------------------------------- */
#ifndef __RAWINDEX_H
#define __RAWINDEX_H
#include <stdio.h>
#ifdef WIN32
#include <io.h>
#else
#include <unistd.h>
#endif
#include "vfs.h"
#include "Table.h"
class IndexField;
#define BLOCK_SIZE 2048 // 8192 entries blocks
class RecordBase;
class Index
{
public:
Index(VFILE *Handle, unsigned char id, int pos, int type, bool newindex, int nentries, Table *parentTable);
~Index();
int Get(int Idx);
void Set(int Idx, int P);
void LoadIndex(bool newindex);
void WriteIndex(void);
int Insert(Index *parindex, int N, bool localonly);
int Insert(int N);
int Update(int Idx, int Pos, RecordBase *record, bool localonly);
int Update(Index *parindex, int paridx, int Idx, int Pos, RecordBase *record, bool forceLast, bool localonly);
unsigned char GetId();
int FindSortedPlace(Field *field, int idx, int *laststate, int start);
int FindSortedPlaceEx(Field *field, int idx, int *laststate, int start, int comp_mode);
int MoveIndex(int idx, int newidx);
void Colaborate(IndexField *secindex);
void SetCooperative(int Idx, int secpos);
int GetCooperative(int Idx);
void UpdateMe(Index *Me, int newidx, int oldidx);
Field *QuickFindField(unsigned char Id, int Pos);
int QuickFind(int Id, Field *field, int start);
int QuickFindEx(int Id, Field *field, int start, int comp_mode);
int TranslateIndex(int Pos, Index *index);
void Delete(int Idx, int Pos, Record *record);
void Shrink(void);
void Propagate(void);
void SetGlobalLocateUpToDate(bool isUptodate);
int NeedFix();
public:
// TODO: make these protected
int NEntries;
IndexField *SecIndex;
bool locateUpToDate;
protected:
VFILE *Handle;
VFILE *TableHandle;
Table *pTable;
int *IndexTable;
size_t MaxSize;
unsigned char Id;
bool InChain;
int Position;
bool InInsert;
int InChainIdx;
};
#endif

8
Src/nde/IndexField.h Normal file
View file

@ -0,0 +1,8 @@
#pragma once
#ifdef __APPLE__
#include "osx/IndexField.h"
#elif defined(_WIN32)
#include "win/IndexField.h"
#elif defined(__ANDROID__)
#include "android/IndexField.h"
#endif

8
Src/nde/IndexRecord.h Normal file
View file

@ -0,0 +1,8 @@
#pragma once
#ifdef __APPLE__
#include "osx/IndexRecord.h"
#elif defined(_WIN32)
#include "win/IndexRecord.h"
#elif defined(__ANDROID__)
#include "android/IndexRecord.h"
#endif

126
Src/nde/Int128Field.cpp Normal file
View file

@ -0,0 +1,126 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
Int128Field Class
Field data layout:
[16 bytes] value
--------------------------------------------------------------------------- */
#include "nde.h"
#include "Int128Field.h"
#include <time.h>
//---------------------------------------------------------------------------
Int128Field::Int128Field(void *data)
{
InitField();
Type = FIELD_INT128;
memcpy(Value, data, 16);
}
//---------------------------------------------------------------------------
void Int128Field::InitField(void)
{
Type = FIELD_INT128;
memset(Value, 0, 16);
}
//---------------------------------------------------------------------------
Int128Field::Int128Field()
{
InitField();
}
//---------------------------------------------------------------------------
Int128Field::~Int128Field()
{
}
//---------------------------------------------------------------------------
void Int128Field::ReadTypedData(const uint8_t *data, size_t len)
{
if (len < 16) return;
memcpy(Value, data, 16);
}
//---------------------------------------------------------------------------
void Int128Field::WriteTypedData(uint8_t *data, size_t len)
{
if (len < 16) return;
memcpy(data, Value, 16);
}
//---------------------------------------------------------------------------
void *Int128Field::GetValue(void)
{
return Value;
}
//---------------------------------------------------------------------------
void Int128Field::SetValue(const void *Val)
{
memcpy(Value, Val, 16);
}
//---------------------------------------------------------------------------
size_t Int128Field::GetDataSize(void)
{
return 16;
}
//---------------------------------------------------------------------------
int Int128Field::Compare(Field *Entry)
{
if (!Entry) return -1;
return memcmp(Value, ((Int128Field*)Entry)->GetValue(), 16);
}
static char zerobuf[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
//---------------------------------------------------------------------------
bool Int128Field::ApplyFilter(Field *Data, int op)
{
void *p = ((Int128Field *)Data)->GetValue();
void *d = Value;
if (!p)
p = zerobuf;
if (!d)
d = zerobuf;
bool r;
switch (op)
{
case FILTER_EQUALS:
r = !memcmp(d, p, 16);
break;
case FILTER_CONTAINS:
r = !memcmp(d, p, 16);
break;
case FILTER_ABOVE:
r = (memcmp(d, p, 16) > 0);
break;
case FILTER_BELOW:
r = (memcmp(d, p, 16) < 0);
break;
case FILTER_BELOWOREQUAL:
r = (memcmp(d, p, 16) <= 0);
break;
case FILTER_ABOVEOREQUAL:
r = (memcmp(d, p, 16) >= 0);
break;
case FILTER_ISEMPTY:
r = !d || (!memcmp(d, zerobuf, 16));
break;
case FILTER_ISNOTEMPTY:
r = d && (memcmp(d, zerobuf, 16));
break;
default:
r = true;
break;
}
return r;
}

38
Src/nde/Int128Field.h Normal file
View file

@ -0,0 +1,38 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
Int128Field Class Prototypes
--------------------------------------------------------------------------- */
#ifndef NULLSOFT_NDE_INT128FIELD_H
#define NULLSOFT_NDE_INT128FIELD_H
#include "Field.h"
class Int128Field : public Field
{
protected:
virtual void ReadTypedData(const uint8_t *, size_t len);
virtual void WriteTypedData(uint8_t *, size_t len);
virtual size_t GetDataSize(void);
virtual int Compare(Field *Entry);
virtual bool ApplyFilter(Field *Data, int op);
void InitField(void);
char Value[16];
public:
~Int128Field();
Int128Field(void *value);
Int128Field();
void *GetValue(void);
void SetValue(const void *value);
};
#endif

124
Src/nde/Int64Field.cpp Normal file
View file

@ -0,0 +1,124 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
Int64Field Class
Field data layout:
[8 bytes] value
--------------------------------------------------------------------------- */
#include "nde.h"
#include "Int64Field.h"
#include <time.h>
//---------------------------------------------------------------------------
Int64Field::Int64Field(int64_t Val)
{
InitField();
Type = FIELD_INT64;
Value = Val;
}
//---------------------------------------------------------------------------
void Int64Field::InitField(void)
{
Type = FIELD_INT64;
Value = 0;
}
//---------------------------------------------------------------------------
Int64Field::Int64Field()
{
InitField();
}
//---------------------------------------------------------------------------
Int64Field::~Int64Field()
{
}
//---------------------------------------------------------------------------
void Int64Field::ReadTypedData(const uint8_t *data, size_t len)
{
CHECK_INT64(len);
Value = *((int64_t *)data);
}
//---------------------------------------------------------------------------
void Int64Field::WriteTypedData(uint8_t *data, size_t len)
{
CHECK_INT64(len);
*((int64_t *)data) = Value;
}
//---------------------------------------------------------------------------
int64_t Int64Field::GetValue(void)
{
return Value;
}
//---------------------------------------------------------------------------
void Int64Field::SetValue(int64_t Val)
{
Value = Val;
}
//---------------------------------------------------------------------------
size_t Int64Field::GetDataSize(void)
{
return sizeof(int64_t);
}
//---------------------------------------------------------------------------
int Int64Field::Compare(Field *Entry)
{
if (!Entry) return -1;
return GetValue() < ((Int64Field*)Entry)->GetValue() ? -1 : (GetValue() > ((Int64Field*)Entry)->GetValue() ? 1 : 0);
}
//---------------------------------------------------------------------------
bool Int64Field::ApplyFilter(Field *Data, int op)
{
bool r;
switch (op)
{
case FILTER_EQUALS:
r = Value == ((Int64Field *)Data)->GetValue();
break;
case FILTER_NOTEQUALS:
r = Value != ((Int64Field *)Data)->GetValue();
break;
case FILTER_NOTCONTAINS:
r = (bool)!(Value & ((Int64Field *)Data)->GetValue());
break;
case FILTER_CONTAINS:
r = !!(Value & ((Int64Field *)Data)->GetValue());
break;
case FILTER_ABOVE:
r = (bool)(Value > ((Int64Field *)Data)->GetValue());
break;
case FILTER_BELOW:
r = (bool)(Value < ((Int64Field *)Data)->GetValue());
break;
case FILTER_BELOWOREQUAL:
r = (bool)(Value <= ((Int64Field *)Data)->GetValue());
break;
case FILTER_ABOVEOREQUAL:
r = (bool)(Value >= ((Int64Field *)Data)->GetValue());
break;
case FILTER_ISEMPTY:
r = (Value == 0 || Value == -1);
break;
case FILTER_ISNOTEMPTY:
r = !(Value == 0 || Value == -1);
break;
default:
r = true;
break;
}
return r;
}

39
Src/nde/Int64Field.h Normal file
View file

@ -0,0 +1,39 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
Int64Field Class Prototypes
--------------------------------------------------------------------------- */
#ifndef NULLSOFT_NDE_INT64FIELD_H
#define NULLSOFT_NDE_INT64FIELD_H
#include "Field.h"
class Int64Field : public Field
{
protected:
virtual void ReadTypedData(const uint8_t *, size_t len);
virtual void WriteTypedData(uint8_t *, size_t len);
virtual size_t GetDataSize(void);
virtual int Compare(Field *Entry);
virtual bool ApplyFilter(Field *Data, int op);
void InitField(void);
int64_t Value;
public:
~Int64Field();
Int64Field(int64_t);
Int64Field();
int64_t GetValue(void);
void SetValue(int64_t);
};
#endif

8
Src/nde/IntegerField.h Normal file
View file

@ -0,0 +1,8 @@
#pragma once
#ifdef __APPLE__
#include "osx/IntegerField.h"
#elif defined(_WIN32)
#include "win/IntegerField.h"
#elif defined(__ANDROID__)
#include "android/IntegerField.h"
#endif

126
Src/nde/LinkedList.cpp Normal file
View file

@ -0,0 +1,126 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
Double-Linked List Class
Caution: The entire library relies on this base class. Modify with care!
--------------------------------------------------------------------------- */
#include "nde.h"
#include "LinkedList.h"
//---------------------------------------------------------------------------
LinkedListEntry *LinkedListEntry::GetNext(void) const
{
return Next;
}
//---------------------------------------------------------------------------
LinkedListEntry *LinkedListEntry::GetPrevious(void) const
{
return Previous;
}
//---------------------------------------------------------------------------
LinkedListEntry::LinkedListEntry()
{
//Int=0;
Next=NULL;
Previous=NULL;
}
//---------------------------------------------------------------------------
LinkedListEntry::~LinkedListEntry()
{
}
//---------------------------------------------------------------------------
LinkedList::LinkedList()
{
Head = NULL;
Foot = NULL;
NElements=0;
}
//---------------------------------------------------------------------------
LinkedList::~LinkedList()
{
while (Head)
RemoveEntry(Head);
}
//---------------------------------------------------------------------------
void LinkedList::AddEntry(LinkedListEntry *Entry, bool Cat)
{
#ifdef WIN32
//EnterCriticalSection(&Critical);
#endif
if (!Cat)
{
if (Head)
Head->Previous = Entry;
Entry->Next = Head;
Entry->Previous = NULL;
Head = Entry;
if (!Foot)
Foot = Entry;
}
else
{
if (Foot)
Foot->Next = Entry;
Entry->Previous = Foot;
Entry->Next = NULL;
Foot = Entry;
if (!Head)
Head = Entry;
}
NElements++;
#ifdef WIN32
//LeaveCriticalSection(&Critical);
#endif
}
//---------------------------------------------------------------------------
void LinkedList::RemoveEntry(LinkedListEntry *Entry)
{
if (!Entry) return;
#ifdef WIN32
//EnterCriticalSection(&Critical);
#endif
if (Entry->Next)
Entry->Next->Previous = Entry->Previous;
else
Foot = Entry->Previous;
if (Entry->Previous)
Entry->Previous->Next = Entry->Next;
else
Head = Entry->Next;
if (NElements > 0)
{
delete Entry;
NElements--;
}
#ifdef WIN32
//LeaveCriticalSection(&Critical);
#endif
}
//---------------------------------------------------------------------------
void LinkedList::WalkList(WalkListProc WalkProc, int ID, void *Data1, void *Data2)
{
if (!WalkProc) return;
LinkedListEntry *Entry = Head;
while (Entry)
{
if (!WalkProc(Entry, ID, Data1, Data2)) break;
Entry = Entry->Next;
}
}

82
Src/nde/LinkedList.h Normal file
View file

@ -0,0 +1,82 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
Double-Linked List Class Prototypes
--------------------------------------------------------------------------- */
#ifndef __LINKEDLIST_H
#define __LINKEDLIST_H
class LinkedListEntry
{
public:
LinkedListEntry *Next;
LinkedListEntry *Previous;
public:
LinkedListEntry *GetNext() const;
LinkedListEntry *GetPrevious() const;
LinkedListEntry();
virtual ~LinkedListEntry();
};
template <class T> class VListEntry : public LinkedListEntry
{
public:
void SetVal(T val)
{
Val = val;
}
T GetVal(void)
{
return Val;
}
private:
T Val;
};
template <class T> class PListEntry : public LinkedListEntry
{
public:
void SetVal(T *val)
{
Val = val;
}
T *GetVal(void)
{
return Val;
}
private:
T *Val;
};
typedef bool (*WalkListProc)(LinkedListEntry *Entry, int, void*, void*);
class LinkedList
{
protected:
int NElements;
LinkedListEntry *Head;
LinkedListEntry *Foot;
public:
LinkedList();
~LinkedList();
void AddEntry(LinkedListEntry *Entry, bool Cat);
void RemoveEntry(LinkedListEntry *Entry);
void WalkList(WalkListProc WalkProc, int ID, void *Data1, void *Data2);
int GetNElements(void) { return NElements; }
LinkedListEntry *GetHead(void) { return Head; }
LinkedListEntry *GetFoot(void) { return Foot; }
};
#endif

84
Src/nde/NDEString.cpp Normal file
View file

@ -0,0 +1,84 @@
#include "NDEString.h"
#include "foundation/error.h"
#include <windows.h>
typedef BOOL (WINAPI *HEAPSETINFORMATION)(HANDLE HeapHandle, HEAP_INFORMATION_CLASS HeapInformationClass, PVOID HeapInformation, SIZE_T HeapInformationLength);
static HANDLE string_heap=0;
static HMODULE kernel=0;
extern "C" void NDE_HeapInit()
{
if (!string_heap)
{
string_heap=HeapCreate(0, 0, 0);
kernel = LoadLibraryW(L"kernel32.dll");
if (kernel)
{
HEAPSETINFORMATION hsi = (HEAPSETINFORMATION)GetProcAddress(kernel, "HeapSetInformation");
if (hsi)
{
ULONG argh = 2;
hsi(string_heap, HeapCompatibilityInformation, &argh, sizeof(ULONG));
}
}
NXStringSetHeap(string_heap);
}
}
extern "C" void NDE_HeapQuit()
{
if (kernel)
FreeLibrary(kernel);
}
nx_string_t ndestring_get_string(wchar_t *str)
{
if (!str)
return 0;
nx_string_t self = (nx_string_t)((uint8_t *)str - sizeof(size_t) - sizeof(size_t));
return self;
}
wchar_t *ndestring_wcsdup(const wchar_t *str)
{
NDE_HeapInit();
if (!str)
return 0;
nx_string_t value;
if (NXStringCreateWithUTF16(&value, str) != NErr_Success)
return 0;
return value->string;
}
wchar_t *ndestring_wcsndup(const wchar_t *str, size_t len)
{
NDE_HeapInit();
if (!str)
return 0;
nx_string_t value;
if (NXStringCreateWithBytes(&value, str, len*2, nx_charset_utf16le) != NErr_Success)
return 0;
return value->string;
}
wchar_t *ndestring_malloc(size_t str_size)
{
NDE_HeapInit();
nx_string_t value=NXStringMalloc((str_size+1)/2 - 1);
if (!value)
return 0;
return value->string;
}
void ndestring_release(wchar_t *str)
{
nx_string_t value = ndestring_get_string(str);
NXStringRelease(value);
}
void ndestring_retain(wchar_t *str)
{
nx_string_t value = ndestring_get_string(str);
NXStringRetain(value);
}

31
Src/nde/NDEString.h Normal file
View file

@ -0,0 +1,31 @@
/*
Ben Allison benski@winamp.com Nov 14 2007
Simple reference counted string, to avoid a whole bunch of _wcsdup's in NDE and ml_local
*/
#pragma once
#include "foundation/types.h"
#include "nx/nxstring.h"
enum
{
STRING_IS_WCHAR=0,
STRING_IS_NDESTRING=1,
};
#include "nde_defines.h"
#ifdef __cplusplus
extern "C" {
#endif
NDE_API wchar_t *ndestring_wcsdup(const wchar_t *str);
NDE_API wchar_t *ndestring_wcsndup(const wchar_t *str, size_t n);
NDE_API wchar_t *ndestring_malloc(size_t str_size);
NDE_API void ndestring_release(wchar_t *str);
NDE_API void ndestring_retain(wchar_t *str);
NDE_API nx_string_t ndestring_get_string(wchar_t *str);
#ifdef __cplusplus
}
#endif

8
Src/nde/Query.h Normal file
View file

@ -0,0 +1,8 @@
#pragma once
#ifdef __APPLE__
#include "osx/Query.h"
#elif defined(_WIN32)
#include "win/Query.h"
#elif defined(__ANDROID__)
#include "android/Query.h"
#endif

8
Src/nde/Record.h Normal file
View file

@ -0,0 +1,8 @@
#pragma once
#ifdef __APPLE__
#include "osx/Record.h"
#elif defined(_WIN32)
#include "win/Record.h"
#elif defined(__ANDROID__)
#include "android/Record.h"
#endif

8
Src/nde/Scanner.h Normal file
View file

@ -0,0 +1,8 @@
#pragma once
#ifdef __APPLE__
#include "osx/Scanner.h"
#elif defined(_WIN32)
#include "win/Scanner.h"
#elif defined(__ANDROID__)
#include "android/Scanner.h"
#endif

8
Src/nde/StringField.h Normal file
View file

@ -0,0 +1,8 @@
#pragma once
#ifdef __APPLE__
#include "osx/StringField.h"
#elif defined(_WIN32)
#include "win/StringField.h"
#elif defined(__ANDROID__)
#include "android/StringField.h"
#endif

8
Src/nde/Table.h Normal file
View file

@ -0,0 +1,8 @@
#pragma once
#ifdef __APPLE__
#include "osx/Table.h"
#elif defined(_WIN32)
#include "win/Table.h"
#elif defined(__ANDROID__)
#include "android/Table.h"
#endif

8
Src/nde/Vfs.h Normal file
View file

@ -0,0 +1,8 @@
#pragma once
#ifdef __APPLE__
#include "osx/Vfs.h"
#elif defined(_WIN32)
#include "win/Vfs.h"
#elif defined(__ANDROID__)
#include "android/vfs.h"
#endif

View file

@ -0,0 +1,79 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
Binary32Field Class
Field data layout:
[4 bytes] length
[length bytes] binary data
--------------------------------------------------------------------------- */
#include "../nde.h"
#include "Binary32Field.h"
#include "../ndestring.h"
//---------------------------------------------------------------------------
Binary32Field::Binary32Field(const uint8_t *_Data, size_t len) : BinaryField(_Data, len)
{
InitField();
}
//---------------------------------------------------------------------------
void Binary32Field::InitField(void)
{
Type = FIELD_BINARY32;
}
//---------------------------------------------------------------------------
Binary32Field::Binary32Field()
{
InitField();
}
//---------------------------------------------------------------------------
void Binary32Field::ReadTypedData(const uint8_t *data, size_t len)
{
uint32_t c;
size_t pos = 0;
CHECK_INT(len); //len-=4;
c = GET_INT(); pos += 4;
if (c && c<=len)
{
Size = c;
ndestring_release((ndestring_t)Data);
Data = (uint8_t *)ndestring_malloc(c);
GET_BINARY(Data, data, c, pos);
}
}
//---------------------------------------------------------------------------
void Binary32Field::WriteTypedData(uint8_t *data, size_t len)
{
uint32_t c;
size_t pos = 0;
CHECK_INT(len); //len-=4;
if (Data && Size<=len)
{
c = (uint32_t)Size;
PUT_INT(c); pos += 4;
if (Data)
PUT_BINARY(data, (unsigned char*)Data, c, pos);
}
else
{
PUT_INT(0);
}
}
//---------------------------------------------------------------------------
size_t Binary32Field::GetDataSize(void)
{
if (!Data) return 4;
return Size + 4;
}

View file

@ -0,0 +1,33 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
Binary32Field Class Prototypes
Android (linux) implementation
--------------------------------------------------------------------------- */
#ifndef __NDE_BINARY32FIELD_H
#define __NDE_BINARY32FIELD_H
#include "BinaryField.h"
#include <foundation/types.h>
class Binary32Field : public BinaryField
{
protected:
virtual void ReadTypedData(const uint8_t *, size_t len);
virtual void WriteTypedData(uint8_t *, size_t len);
virtual size_t GetDataSize(void);
void InitField(void);
public:
Binary32Field(const uint8_t *Data, size_t len);
Binary32Field();
};
#endif

View file

@ -0,0 +1,173 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
BinaryField Class
Field data layout:
[2 bytes] length
[length bytes] binary data
--------------------------------------------------------------------------- */
#include "../nde.h"
#include "BinaryField.h"
#include "../NDEString.h"
//---------------------------------------------------------------------------
BinaryField::BinaryField(const uint8_t *_Data, int len)
{
InitField();
Type = FIELD_BINARY;
if (_Data && len > 0)
{
Data = (uint8_t *)ndestring_malloc(len);
memcpy(Data, _Data, len);
Size = len;
}
}
//---------------------------------------------------------------------------
void BinaryField::InitField(void)
{
Type = FIELD_BINARY;
Data = NULL;
Size = 0;
}
//---------------------------------------------------------------------------
BinaryField::BinaryField()
{
InitField();
}
//---------------------------------------------------------------------------
BinaryField::~BinaryField()
{
ndestring_release((ndestring_t)Data);
}
//---------------------------------------------------------------------------
void BinaryField::ReadTypedData(const uint8_t *data, size_t len)
{
unsigned short c;
int pos = 0;
CHECK_SHORT(len);
c = GET_SHORT(); pos += 2;
if (c && c<=len)
{
Size = c;
ndestring_release((ndestring_t)Data);
Data = (uint8_t *)ndestring_malloc(c);
GET_BINARY(Data, data, c, pos);
}
}
//---------------------------------------------------------------------------
void BinaryField::WriteTypedData(uint8_t *data, size_t len)
{
size_t pos = 0;
CHECK_SHORT(len);
if (Data && Size<=len)
{
unsigned short c = (unsigned short)Size;
PUT_SHORT(c); pos += 2;
if (Data)
PUT_BINARY(data, (unsigned char*)Data, c, pos);
}
else
{
PUT_SHORT(0);
}
}
//---------------------------------------------------------------------------
const uint8_t *BinaryField::GetData(size_t *len)
{
if (len)
*len = Size;
return Data;
}
//---------------------------------------------------------------------------
void BinaryField::SetData(const uint8_t *_Data, size_t len)
{
if (!_Data || !len) return;
ndestring_release((ndestring_t)Data);
Size = 0;
Data = (uint8_t *)ndestring_malloc(len);
memcpy(Data, _Data, len);
Size = len;
}
//---------------------------------------------------------------------------
size_t BinaryField::GetDataSize(void)
{
if (!Data) return 2;
return Size + 2;
}
//---------------------------------------------------------------------------
int BinaryField::Compare(Field *Entry)
{
if (!Entry) return -1;
size_t compare_length;
const uint8_t *compare_data = ((BinaryField*)Entry)->GetData(&compare_length);
return memcmp(Data, compare_data, min(compare_length, Size));
}
//---------------------------------------------------------------------------
bool BinaryField::ApplyFilter(Field *FilterData, int op)
{
size_t l, s;
const uint8_t *p = ((BinaryField *)FilterData)->GetData(&l);
const uint8_t *d = GetData(&s);
if (!p)
p = (const uint8_t *)"";
if (!d)
d = (const uint8_t *)"";
bool r;
switch (op)
{
case FILTER_EQUALS:
if (l != s)
r = false;
else
r = !memcmp(d, p, min(s, l));
break;
case FILTER_CONTAINS:
if (l > s)
r = FALSE;
else
r = !!memmem(d, s, p, l);
break;
case FILTER_ABOVE:
r = (memcmp(d, p, min(s, l)) > 0);
break;
case FILTER_BELOW:
r = (memcmp(d, p, min(s, l)) < 0);
break;
case FILTER_BELOWOREQUAL:
r = (memcmp(d, p, min(s, l)) <= 0);
break;
case FILTER_ABOVEOREQUAL:
r = (memcmp(d, p, min(s, l)) >= 0);
break;
case FILTER_ISEMPTY:
r = (s == 0);
break;
case FILTER_ISNOTEMPTY:
r = (s != 0);
break;
default:
r = true;
break;
}
return r;
}

View file

@ -0,0 +1,38 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
BinaryField Class Prototypes
--------------------------------------------------------------------------- */
#ifndef __BINARYFIELD_H
#define __BINARYFIELD_H
#include "../Field.h"
#include <foundation/types.h>
class BinaryField : public Field
{
protected:
virtual void ReadTypedData(const uint8_t *, size_t len);
virtual void WriteTypedData(uint8_t *, size_t len);
virtual size_t GetDataSize(void);
virtual int Compare(Field *Entry);
virtual bool ApplyFilter(Field *Data, int flags);
void InitField(void);
uint8_t *Data;
size_t Size;
public:
~BinaryField();
BinaryField(const uint8_t *Data, int len);
BinaryField();
const uint8_t *GetData(size_t *len);
void SetData(const uint8_t *Data, size_t len);
};
#endif

View file

@ -0,0 +1,175 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
ColumnField Class
Android (linux) implementation
Field data layout:
[1 byte] Field Type
[1 byte] Unused (maybe convert to 'searchable')
[1 byte] Name Length
[Name Length bytes] Name (UTF-8)
--------------------------------------------------------------------------- */
#include "ColumnField.h"
#include "../NDEString.h"
#include "../nde.h"
//---------------------------------------------------------------------------
ColumnField::ColumnField(unsigned char FieldID, const char *FieldName, unsigned char FieldType, Table *parentTable)
{
InitField();
Type = FIELD_COLUMN;
MyType = FieldType;
Name = ndestring_wcsdup(FieldName);
ID = FieldID;
}
//---------------------------------------------------------------------------
void ColumnField::InitField(void)
{
searchable = false;
MyType = FIELD_UNKNOWN;
Type = FIELD_COLUMN;
Name = NULL;
ID = 0;
}
//---------------------------------------------------------------------------
ColumnField::ColumnField()
{
InitField();
}
//---------------------------------------------------------------------------
ColumnField::~ColumnField()
{
if (Name) free(Name);
}
void ColumnField::SetSearchable(bool val)
{
searchable=val;
}
bool ColumnField::IsSearchableField() const
{
return searchable;
}
//---------------------------------------------------------------------------
void ColumnField::ReadTypedData(const uint8_t *data, size_t len)
{
unsigned char c;
int pos=0;
// [1 byte] Field Type
CHECK_CHAR(len);
MyType = GET_CHAR();
pos++;
// [1 byte] unused
CHECK_CHAR(len);
//cut: indexUnique = (BOOL)GET_CHAR();
pos++;
// [1 byte] string length
CHECK_CHAR(len);
c = GET_CHAR();
pos++;
if (c)
{
CHECK_BIN(len, c);
Name = ndestring_wcsndup((const char *)(data+pos), c);
}
}
//---------------------------------------------------------------------------
void ColumnField::WriteTypedData(uint8_t *data, size_t len)
{
int pos = 0;
// [1 byte] Field Type
CHECK_CHAR(len);
PUT_CHAR(MyType);
pos++;
// [1 byte] unused
CHECK_CHAR(len);
PUT_CHAR(0/*(char)indexUnique*/);
pos++;
CHECK_CHAR(len);
if (Name)
{
int string_length = strlen(Name);
if (string_length)
{
PUT_CHAR(string_length);
pos++;
CHECK_BIN(len, string_length);
PUT_BINARY(data, (const uint8_t *)Name, string_length, pos);
}
else
{
PUT_CHAR(0);
}
}
else
{
PUT_CHAR(0);
}
}
//---------------------------------------------------------------------------
unsigned char ColumnField::GetDataType(void)
{
return MyType;
}
//---------------------------------------------------------------------------
void ColumnField::SetDataType(unsigned char type)
{
if ((MyType == FIELD_INTEGER || MyType == FIELD_BOOLEAN || MyType == FIELD_DATETIME || MyType == FIELD_LENGTH) &&
(type == FIELD_INTEGER || type == FIELD_BOOLEAN || type == FIELD_DATETIME || type == FIELD_LENGTH)) {
MyType = type;
}
// going from string to filename or filename to string is OK
if ((MyType == FIELD_FILENAME && type == FIELD_STRING)
|| (MyType == FIELD_STRING && type == FIELD_FILENAME))
{
MyType = type;
}
}
//---------------------------------------------------------------------------
char *ColumnField::GetFieldName(void)
{
return Name;
}
//---------------------------------------------------------------------------
size_t ColumnField::GetDataSize(void)
{
size_t s=3;
if (Name)
{
s+=strlen(Name);
}
return s;
}
//---------------------------------------------------------------------------
int ColumnField::Compare(Field * /*Entry*/)
{
return 0;
}

View file

@ -0,0 +1,47 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
ColumnField Class Prototypes
Android (linux) implementation
--------------------------------------------------------------------------- */
#ifndef __COLUMNFIELD_H
#define __COLUMNFIELD_H
#include "../Field.h"
#include "../LinkedList.h"
#include "Table.h"
#include "Scanner.h"
class ColumnField : public Field
{
public:
ColumnField(unsigned char FieldID, const char *FieldName, unsigned char FieldType, Table *parentTable);
ColumnField();
~ColumnField();
virtual void ReadTypedData(const uint8_t *, size_t len);
virtual void WriteTypedData(uint8_t *, size_t len);
virtual size_t GetDataSize(void);
virtual int Compare(Field *Entry);
void InitField(void);
void SetDataType(unsigned char type);
bool IsSearchableField() const;
void SetSearchable(bool val);
public:
unsigned char GetDataType(void);
char *GetFieldName(void); // not const because it's an NDE string
protected:
bool searchable;
char *Name;
unsigned char MyType;
};
#endif

View file

@ -0,0 +1,128 @@
#include "FilenameField.h"
#include "../nde.h"
//---------------------------------------------------------------------------
FilenameField::FilenameField(const char *Str, int strkind) : StringField(Str, strkind)
{
Type = FIELD_FILENAME;
}
//---------------------------------------------------------------------------
FilenameField::FilenameField()
{
Type = FIELD_FILENAME;
}
//---------------------------------------------------------------------------
int FilenameField::Compare(Field *Entry)
{
if (!Entry) return -1;
if (!CompatibleFields(Entry->GetType(), GetType()))
return 0;
return mystricmp_fn(GetString(), ((FilenameField*)Entry)->GetString());
}
//---------------------------------------------------------------------------
int FilenameField::Starts(Field *Entry)
{
if (!Entry) return -1;
if (!CompatibleFields(Entry->GetType(), GetType()))
return 0;
return (mystristr_fn(GetString(), ((FilenameField*)Entry)->GetString()) == GetString());
}
//---------------------------------------------------------------------------
int FilenameField::Contains(Field *Entry)
{
if (!Entry) return -1;
if (!CompatibleFields(Entry->GetType(), GetType()))
return 0;
return (mystristr_fn(GetString(), ((FilenameField*)Entry)->GetString()) != NULL);
}
Field *FilenameField::Clone(Table *pTable)
{
FilenameField *clone = new FilenameField(String, STRING_IS_NDESTRING);
clone->Pos = FIELD_CLONE;
clone->ID = ID;
clone->MaxSizeOnDisk = GetDataSize();
return clone;
}
// TODO: make file system string comparison functions
//---------------------------------------------------------------------------
bool FilenameField::ApplyFilter(Field *Data, int op)
{
// TODO: maybe do this?
if (op == FILTER_ISEMPTY || op == FILTER_ISNOTEMPTY)
{
bool r = (op == FILTER_ISEMPTY);
if (!String)
return r;
if (String && String[0] == 0)
return r;
return !r;
}
//
bool r;
const char *p=0;
if (Data->GetType() == FIELD_STRING)
p = ((StringField *)Data)->GetString();
else
p = ((FilenameField *)Data)->GetString();
const char *d = GetString();
if (!p)
p = "";
if (!d)
d = "";
switch (op)
{
case FILTER_EQUALS:
r = !nde_stricmp_fn(d, p);
break;
case FILTER_NOTEQUALS:
r = !!nde_stricmp_fn(d, p);
break;
case FILTER_CONTAINS:
r = (NULL != stristr_fn(d, p));
break;
case FILTER_NOTCONTAINS:
r = (NULL == stristr_fn(d, p));
break;
case FILTER_ABOVE:
r = (bool)(nde_stricmp_fn(d, p) > 0);
break;
case FILTER_ABOVEOREQUAL:
r = (bool)(nde_stricmp_fn(d, p) >= 0);
break;
case FILTER_BELOW:
r = (bool)(nde_stricmp_fn(d, p) < 0);
break;
case FILTER_BELOWOREQUAL:
r = (bool)(nde_stricmp_fn(d, p) <= 0);
break;
case FILTER_BEGINS:
r = (bool)(nde_strnicmp_fn(d, p, strlen(p)) == 0);
break;
case FILTER_ENDS:
{
int lenp = (int)strlen(p), lend = (int)strlen(d);
if (lend < lenp) return 0; // too short
r = (bool)(nde_stricmp_fn((d + lend) - lenp, p) == 0);
}
break;
case FILTER_LIKE:
r = (bool)(nde_stricmp_fn(d, p) == 0);
break;
default:
r = true;
break;
}
return r;
}

View file

@ -0,0 +1,26 @@
#ifndef NDE_FILENAMEFIELD_H
#define NDE_FILENAMEFIELD_H
/*
Mostly the same as StringField
but this implements OS-dependent string comparisons that make sense for the file system
*/
#include "../nde.h"
#include "../NDEString.h"
class FilenameField : public StringField
{
protected:
virtual int Compare(Field *Entry);
virtual int Starts(Field *Entry);
virtual int Contains(Field *Entry);
virtual bool ApplyFilter(Field *Data, int op);
virtual Field *Clone(Table *pTable);
public:
FilenameField(const char *Str, int strkind=STRING_IS_WCHAR);
FilenameField();
};
#endif

View file

@ -0,0 +1,142 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
IndexField Class
Android (linux) implementation
Field data layout
[4 bytes] Position
[4 bytes] Data Type
[1 byte] Name Length
[Name Length bytes] Name (UTF-8)
--------------------------------------------------------------------------- */
#include "../nde.h"
#include "../ndestring.h"
//---------------------------------------------------------------------------
IndexField::IndexField(unsigned char id, int Pos, int type, const char *FieldName)
{
InitField();
Type = FIELD_INDEX;
Name = ndestring_wcsdup(FieldName);
ID = id;
Position = Pos;
DataType = type;
}
//---------------------------------------------------------------------------
void IndexField::InitField(void)
{
index = 0;
Type = FIELD_INDEX;
Name = NULL;
ID = 0;
Position = -1;
DataType = FIELD_UNKNOWN;
}
//---------------------------------------------------------------------------
IndexField::IndexField()
{
InitField();
}
//---------------------------------------------------------------------------
IndexField::~IndexField()
{
ndestring_release(Name);
delete index;
}
//---------------------------------------------------------------------------
void IndexField::ReadTypedData(const uint8_t *data, size_t len)
{
unsigned char c;
int pos=0;
CHECK_INT(len);
Position = GET_INT(); pos += 4;
CHECK_INT(len);
DataType = GET_INT(); pos += 4;
CHECK_CHAR(len);
c = GET_CHAR(); pos++;
if (c)
{
CHECK_BIN(len, c);
Name = ndestring_wcsndup((const char *)(data+pos), c);
}
}
//---------------------------------------------------------------------------
void IndexField::WriteTypedData(uint8_t *data, size_t len)
{
int pos=0;
CHECK_INT(len);
PUT_INT(Position); pos += 4;
CHECK_INT(len);
PUT_INT(DataType); pos += 4;
CHECK_CHAR(len);
CHECK_CHAR(len);
if (Name)
{
int string_length = strlen(Name);
if (string_length)
{
PUT_CHAR(string_length);
pos++;
CHECK_BIN(len, string_length);
PUT_BINARY(data, (const uint8_t *)Name, string_length, pos);
}
else
{
PUT_CHAR(0);
}
}
else
{
PUT_CHAR(0);
}
}
//---------------------------------------------------------------------------
char *IndexField::GetIndexName(void)
{
return Name;
}
//---------------------------------------------------------------------------
size_t IndexField::GetDataSize(void)
{
size_t s=9;
if (Name)
{
s+=strlen(Name);
}
s++;
return s;
}
//---------------------------------------------------------------------------
int IndexField::Compare(Field * /*Entry*/)
{
return 0;
}
//---------------------------------------------------------------------------
int IndexField::TranslateToIndex(int Id, IndexField *toindex)
{
if (index && toindex && toindex->index)
return index->TranslateIndex(Id, toindex->index);
return -1;
}

View file

@ -0,0 +1,37 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
IndexField Class Prototypes
--------------------------------------------------------------------------- */
#ifndef __INDEXFIELD_H
#define __INDEXFIELD_H
class IndexField : public Field
{
public:
IndexField(unsigned char id, int Pos, int type, const char *FieldName);
IndexField();
~IndexField();
virtual void ReadTypedData(const uint8_t *, size_t len);
virtual void WriteTypedData(uint8_t *, size_t len);
virtual size_t GetDataSize(void);
virtual int Compare(Field *Entry);
void InitField(void);
char *GetIndexName(void);
int TranslateToIndex(int Id, IndexField *index);
Index *index; // TODO: make protected
protected:
int Position;
int DataType;
char *Name;
};
#endif

View file

@ -0,0 +1,148 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
IndexRecord Class
--------------------------------------------------------------------------- */
#include "IndexRecord.h"
#include "../nde.h"
#include <stdio.h>
IndexRecord::IndexRecord(int RecordPos, int insertionPoint, VFILE *TableHandle, Table *ParentTable)
{
InsertionPoint = insertionPoint;
if (RecordPos != 0)
{
int n=0;
uint32_t ThisPos = RecordPos;
while (ThisPos)
{
if (n >= 128)
break;
Vfseek(TableHandle, ThisPos, SEEK_SET);
Field Entry (ThisPos);
Field *TypedEntry = Entry.ReadField(ParentTable, ThisPos, &ThisPos);
if (!TypedEntry) break; // some db error?
AddField(TypedEntry);
// ThisPos = TypedEntry->GetNextFieldPos();
n++;
}
}
}
void IndexRecord::BuildCollaboration()
{
for (FieldList::iterator itr=Fields.begin();itr!=Fields.end();itr++)
{
IndexField *p = (IndexField *)*itr;
if (p->next)
p->index->Colaborate((IndexField *)p->next);
else
p->index->Colaborate((IndexField *)*Fields.begin());
}
}
bool IndexRecord::NeedFix()
{
for (FieldList::iterator itr=Fields.begin();itr!=Fields.end();itr++)
{
IndexField *p = (IndexField *)*itr;
if (p->index->NeedFix())
return true;
}
return false;
}
IndexField *IndexRecord::GetIndexByName(const char *name)
{
for (FieldList::iterator itr=Fields.begin();itr!=Fields.end();itr++)
{
IndexField *p = (IndexField *)*itr;
if (!strcasecmp(p->GetIndexName(), name))
return p;
}
return NULL;
}
bool IndexRecord::CheckIndexing(int v)
{
int i = v;
for (FieldList::iterator itr=Fields.begin();itr!=Fields.end();itr++)
{
IndexField *p = (IndexField *)*itr;
v = p->index->GetCooperative(v);
}
return v == i;
}
Field *RecordBase::GetField(unsigned char ID)
{
for (FieldList::iterator itr=Fields.begin();itr!=Fields.end();itr++)
{
IndexField *p = (IndexField *)*itr;
if (p->GetFieldId() == ID)
return p;
}
return NULL;
}
void RecordBase::AddField(Field *field)
{
if (!field) return;
if (GetField(field->ID))
return;
Fields.push_back(field);
}
int IndexRecord::WriteFields(Table *ParentTable)
{
Field *previous = 0;
for (FieldList::iterator itr=Fields.begin();itr!=Fields.end();itr++)
{
IndexField *p = (IndexField *)*itr;
p->WriteField(ParentTable, previous, (Field *)p->next);
previous = p;
}
return WriteIndex(ParentTable);
}
int IndexRecord::WriteIndex(Table *ParentTable)
{
int P=0;
if (!Fields.empty())
P=(*Fields.begin())->GetFieldPos();
return ParentTable->index->Update(INDEX_RECORD_NUM, P, this, false);
}
void RecordBase::RemoveField(Field *field)
{
if (!field)
return;
Fields.erase(field);
delete field;
}
void IndexRecord::WalkFields(FieldsWalker callback, void *context)
{
if (callback)
{
for (FieldList::iterator itr=Fields.begin();itr!=Fields.end();itr++)
{
if (!callback(this, *itr, context))
break;
}
}
}

View file

@ -0,0 +1,23 @@
#pragma once
/*
Android (linux) implementation
*/
#include <stdio.h>
#include "Record.h"
#include <nu/PtrDeque2.h>
class IndexField;
class IndexRecord : public RecordBase
{
public:
IndexRecord(int RecordPos, int insertionPoint, VFILE *FileHandle, Table *p);
void BuildCollaboration();
bool NeedFix();
IndexField *GetIndexByName(const char *name);
int GetColumnCount() { return Fields.size() - 1; }
bool CheckIndexing(int v);
int WriteFields(Table *ParentTable);
int WriteIndex(Table *ParentTable);
typedef bool (*FieldsWalker)(IndexRecord *record, Field *entry, void *context);
void WalkFields(FieldsWalker callback, void *context);
};

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,93 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
IntegerField Class Prototypes
Android (linux) implementation
--------------------------------------------------------------------------- */
#ifndef __INTEGERFIELD_H
#define __INTEGERFIELD_H
#include <foundation/types.h>
class TimeParse {
public:
int is_relative; // ago/after/before used
int absolute_datetime; // if not is_relative, this is the date/time, otherwise it's the resulting date/time if the query was ran now
int absolute_hasdate; // if not, use only the time portion of absolute_datetime, the rest is now
int absolute_hastime; // if not, use only the date portion of absolute_datetime, the rest is now
int relative_year; // -1 = this year
int relative_month; // -1 = this month
int relative_day; // -1 = this day, -2 = this week
int relative_hour; // -1 = this hour
int relative_min; // -1 = this minute
int relative_sec; // -1 = this second
int relative_kwday; // not used(-1), 0 to 6 for sunday to saturday, yesterday(7), today(8), tomorrow(9)
int offset_value; // timeago/offsetby numerical edit field
int offset_what; // not used(-1) years(0), months(1), weeks(2), days(3), hours(4), minutes(5), seconds(6)
int offset_whence; // not used(-1), after(0), ago/before(1)
int offset_used; // if 1, 'time ago' / 'offset by' should be checked
};
class IntegerField : public Field
{
protected:
virtual void ReadTypedData(const uint8_t *, size_t len);
virtual void WriteTypedData(uint8_t *, size_t len);
virtual size_t GetDataSize(void);
virtual int Compare(Field *Entry);
virtual bool ApplyFilter(Field *Data, int op);
void InitField(void);
int Value;
enum {
WHAT_YEARS,
WHAT_MONTHS,
WHAT_WEEKS,
WHAT_DAYS,
WHAT_HOURS,
WHAT_MINUTES,
WHAT_SECONDS,
};
enum {
FROM_BARE,
FROM_AGO,
FROM_SINCE,
};
public:
~IntegerField();
IntegerField(int);
IntegerField();
int GetValue(void);
void SetValue(int);
int ApplyConversion(const char *format, TimeParse *tp=NULL);
static int LookupToken(const char *t);
};
class DateTimeField : public IntegerField {
public:
DateTimeField();
DateTimeField(int Val);
virtual ~DateTimeField();
};
class LengthField : public IntegerField {
public:
LengthField();
LengthField(int Val);
virtual ~LengthField();
};
#endif

973
Src/nde/android/Query.cpp Normal file
View file

@ -0,0 +1,973 @@
#include "../nde.h"
#include "../NDEString.h"
#include "Query.h"
//---------------------------------------------------------------------------
bool Scanner::Query(const char *query)
{
if (!query) return false;
ndestring_release(last_query);
last_query = ndestring_wcsdup(query);
RemoveFilters();
in_query_parser = 1;
bool r = Query_Parse(query);
if (r == false)
{
if (!disable_date_resolution) RemoveFilters();
last_query_failed = true;
}
in_query_parser = 0;
Query_CleanUp();
return r & CheckFilters();
}
const char *Scanner::GetLastQuery()
{
return last_query;
}
typedef struct
{
const char *token;
int tid;
} tokenstruct;
tokenstruct Tokens[] = // Feel free to add more...
{
{"AND", TOKEN_AND },
{"OR", TOKEN_OR },
{"HAS", TOKEN_CONTAINS },
{"NOTHAS",TOKEN_NOTCONTAINS},
{"BEGINS", TOKEN_BEGINS },
{"ENDS", TOKEN_ENDS },
{"ISEMPTY", TOKEN_ISEMPTY},
{"ISNOTEMPTY",TOKEN_ISNOTEMPTY},
{"LIKE", TOKEN_LIKE},
{"BEGINSLIKE", TOKEN_BEGINSLIKE},
};
typedef struct
{
int Op;
int Level;
} OpLevel;
static int Query_ParseLength(const char *str)
{
int i = atoi(str);
const char *p;
if ((p=strstr(str,":")))
{
i*=60;
i+=atoi(++p);
if ((p=strstr(p,":")))
{
i*=60;
i+=atoi(++p);
}
}
return i;
}
/*
our state machine
&, |
----------<-------------------------<----------------------<-----------
| |
v ID (Col) =, >, <... ID / Data / [f] ) |
---->(0) ----->-----> (1) ------>-----> (2) ------>------> (3) ------>-----> (4) <--
| |^ \isempty------------->------------/ |^ | |
| !( || ||---- | ) |
--<-- ---------<---------------------------<-------------<-| | -->--
&, | v [f] |
-->--
*/
//---------------------------------------------------------------------------
bool Scanner::Query_Parse(const char *query)
{
const char *p = query; // pointer on next token to read
int size;
int state = 0;
int pcount = 0;
VListEntry<OpLevel> *entry;
if (pstack.GetNElements() > 0)
Query_CleanUp();
while (1)
{
p = Query_EatSpace(p);
int t = Query_GetNextToken(p, &size, &token);
if (t == TOKEN_UNKNOWN)
{
Query_SyntaxError((int)(p-query));
return false;
}
if (t == TOKEN_EOQ)
break;
switch (state)
{
case 0:
switch (t)
{
case TOKEN_PAROPEN:
state = 0;
// check too many parenthesis open
if (pcount == 255)
{
Query_SyntaxError((int)(p-query)); // should not be _syntax_ error
return false;
}
// up one level
pcount++;
break;
case TOKEN_NOT:
// push not in this level
OpLevel o;
o.Op = FILTER_NOT;
o.Level = pcount;
entry = new VListEntry<OpLevel>;
entry->SetVal(o);
pstack.AddEntry(entry, true);
state = 0;
break;
case TOKEN_IDENTIFIER:
state = 1;
// create filter column
if (AddFilterByName(token, NULL, FILTER_NONE) == ADDFILTER_FAILED)
{
Query_SyntaxError((int)(p-query));
return false;
}
break;
default:
Query_SyntaxError((int)(p-query));
return false;
}
break;
case 1:
switch (t)
{
case TOKEN_EQUAL:
{
state = 2;
// set filter op
Filter *f = GetLastFilter();
f->SetOp(FILTER_EQUALS);
break;
}
case TOKEN_ABOVE:
{
state = 2;
// set filter op
Filter *f = GetLastFilter();
f->SetOp(FILTER_ABOVE);
break;
}
case TOKEN_BELOW:
{
state = 2;
// set filter op
Filter *f = GetLastFilter();
f->SetOp(FILTER_BELOW);
break;
}
case TOKEN_CONTAINS:
{
state = 2;
// set filter op
Filter *f = GetLastFilter();
f->SetOp(FILTER_CONTAINS);
break;
}
case TOKEN_NOTCONTAINS:
{
state = 2;
// set filter op
Filter *f = GetLastFilter();
f->SetOp(FILTER_NOTCONTAINS);
break;
}
case TOKEN_AOREQUAL:
{
state = 2;
// set filter op
Filter *f = GetLastFilter();
f->SetOp(FILTER_ABOVEOREQUAL);
break;
}
case TOKEN_BOREQUAL:
{
state = 2;
// set filter op
Filter *f = GetLastFilter();
f->SetOp(FILTER_BELOWOREQUAL);
break;
}
case TOKEN_NOTEQUAL:
{
state = 2;
// set filter op
Filter *f = GetLastFilter();
f->SetOp(FILTER_NOTEQUALS);
break;
}
case TOKEN_BEGINS:
{
state = 2;
Filter *f = GetLastFilter();
f->SetOp(FILTER_BEGINS);
}
break;
case TOKEN_ENDS:
{
state = 2;
Filter *f = GetLastFilter();
f->SetOp(FILTER_ENDS);
}
break;
case TOKEN_LIKE:
{
state = 2;
// set filter op
Filter *f = GetLastFilter();
f->SetOp(FILTER_LIKE);
break;
}
case TOKEN_BEGINSLIKE:
{
state = 2;
// set filter op
Filter *f = GetLastFilter();
f->SetOp(FILTER_BEGINSLIKE);
break;
}
case TOKEN_ISNOTEMPTY:
case TOKEN_ISEMPTY:
{
state = 3;
Filter *f = GetLastFilter();
f->SetOp(t==TOKEN_ISEMPTY ? FILTER_ISEMPTY : FILTER_ISNOTEMPTY);
// pop all operators in this level beginning by the last inserted
entry = (VListEntry<OpLevel> *)pstack.GetFoot();
while (entry)
{
if (entry->GetVal().Level == pcount)
{
AddFilterOp(entry->GetVal().Op);
VListEntry<OpLevel> *_entry = (VListEntry<OpLevel> *)entry->GetPrevious();
pstack.RemoveEntry(entry);
entry = _entry;
}
else
break;
}
}
break;
default:
Query_SyntaxError((int)(p-query));
return false;
}
break;
case 2:
if (t == TOKEN_SQBRACKETOPEN)
{
state = 3;
const char *s = strchr(p, ']');
if (!s)
{
Query_SyntaxError((int)(p-query));
return false;
}
p = Query_EatSpace(p);
if (*p == '[') p++;
char *format = ndestring_malloc((s-p+1)*sizeof(char));
strncpy(format, p, s-p);
format[s-p] = 0;
Filter *f = GetLastFilter();
int id = f->GetId();
ColumnField *c = GetColumnById(id);
int tt = c ? c->GetDataType() : -1;
if (disable_date_resolution || !c || (tt != FIELD_INTEGER && tt != FIELD_DATETIME && tt != FIELD_LENGTH && tt != FIELD_BOOLEAN))
{
if (disable_date_resolution)
{
StringField *field = (StringField *)f->Data();
if (!field)
{
// format was used without a value, assume value is 0
f->SetData(new StringField(""));
entry = (VListEntry<OpLevel> *)pstack.GetFoot();
while (entry)
{
if (entry->GetVal().Level == pcount)
{
AddFilterOp(entry->GetVal().Op);
VListEntry<OpLevel> *_entry = (VListEntry<OpLevel> *)entry->GetPrevious();
pstack.RemoveEntry(entry);
entry = _entry;
}
else
break;
}
field = (StringField*)f->Data();
}
field->SetNDEString(format);
ndestring_release(format);
p = s+1;
continue;
}
ndestring_release(format);
Query_SyntaxError((int)(p-query));
return false;
}
IntegerField *field = (IntegerField *)f->Data();
if (!field)
{
// format was used without a value, assume value is 0
f->SetData(new IntegerField(0));
entry = (VListEntry<OpLevel> *)pstack.GetFoot();
while (entry)
{
if (entry->GetVal().Level == pcount)
{
AddFilterOp(entry->GetVal().Op);
VListEntry<OpLevel> *_entry = (VListEntry<OpLevel> *)entry->GetPrevious();
pstack.RemoveEntry(entry);
entry = _entry;
}
else
break;
}
field = (IntegerField *)f->Data();
}
int r = field->ApplyConversion(format);
ndestring_release(format);
if (!r)
{
Query_SyntaxError((int)(p-query));
return false;
}
p = s+1;
continue;
}
// switch (t) {
// case TOKEN_IDENTIFIER:
else // JF> we make this relaxed, so anything is valid as a value
{
state = 3;
// set filter data
Filter *f = GetLastFilter();
int id = f->GetId();
ColumnField *c = GetColumnById(id);
switch (c ? c->GetDataType() : -1)
{
case FIELD_DATETIME:
if (disable_date_resolution)
goto field_string_override;
case FIELD_LENGTH:
{
int i;
IntegerField *i_f = new IntegerField();
i = Query_ParseLength(token);
i_f->SetValue(i);
f->SetData(i_f);
}
break;
case FIELD_BOOLEAN:
case FIELD_INTEGER:
{
int i;
IntegerField *i_f = new IntegerField();
i = atoi(token);
i_f->SetValue(i);
f->SetData(i_f);
}
break;
case FIELD_INT64:
{
int64_t i;
Int64Field *i_f = new Int64Field();
i = strtoull(token, 0, 10); // todo: Replace with own conversion and error checking
i_f->SetValue(i);
f->SetData(i_f);
}
break;
case FIELD_FILENAME:
{
FilenameField *s_f = new FilenameField();
s_f->SetNDEString(token);
f->SetData(s_f);
}
break;
case FIELD_STRING:
field_string_override:
{
StringField *s_f = new StringField();
s_f->SetNDEString(token);
f->SetData(s_f);
}
break;
default:
Query_SyntaxError((int)(p-query));
return false;
break;
}
// pop all operators in this level beginning by the last inserted
entry = (VListEntry<OpLevel> *)pstack.GetFoot();
while (entry)
{
if (entry->GetVal().Level == pcount)
{
AddFilterOp(entry->GetVal().Op);
VListEntry<OpLevel> *_entry = (VListEntry<OpLevel> *)entry->GetPrevious();
pstack.RemoveEntry(entry);
entry = _entry;
}
else
break;
}
break;
}
// default:
// Query_SyntaxError(p-query);
// return false;
// }
break;
case 3:
switch (t)
{
case TOKEN_SQBRACKETOPEN:
{
const char *s = strchr(p, ']');
if (!s)
{
Query_SyntaxError((int)(p-query));
return false;
}
p = Query_EatSpace(p);
if (*p == '[') p++;
char *format = ndestring_malloc((s-p+1)*sizeof(char));
strncpy(format, p, s-p);
format[s-p] = 0;
Filter *f = GetLastFilter();
int id = f->GetId();
ColumnField *c = GetColumnById(id);
int tt = c ? c->GetDataType() : -1;
if (disable_date_resolution || !c || (tt != FIELD_INTEGER && tt != FIELD_DATETIME && tt != FIELD_LENGTH && tt != FIELD_BOOLEAN))
{
if (disable_date_resolution)
{
StringField *field = (StringField *)f->Data();
if (!field)
{
// format was used without a value, assume value is 0
f->SetData(new StringField(""));
entry = (VListEntry<OpLevel> *)pstack.GetFoot();
while (entry)
{
if (entry->GetVal().Level == pcount)
{
AddFilterOp(entry->GetVal().Op);
VListEntry<OpLevel> *_entry = (VListEntry<OpLevel> *)entry->GetPrevious();
pstack.RemoveEntry(entry);
entry = _entry;
}
else
break;
}
field = (StringField *)f->Data();
}
field->SetNDEString(format);
ndestring_release(format);
p = s+1;
continue;
}
ndestring_release(format);
Query_SyntaxError((int)(p-query));
return false;
}
IntegerField *field = (IntegerField *)f->Data();
if (!field)
{
// format was used without a value, assume value is 0
f->SetData(new IntegerField(0));
entry = (VListEntry<OpLevel> *)pstack.GetFoot();
while (entry)
{
if (entry->GetVal().Level == pcount)
{
AddFilterOp(entry->GetVal().Op);
VListEntry<OpLevel> *_entry = (VListEntry<OpLevel> *)entry->GetPrevious();
pstack.RemoveEntry(entry);
entry = _entry;
}
else
break;
}
field = (IntegerField *)f->Data();
}
int r = field->ApplyConversion(format);
ndestring_release(format);
if (!r)
{
Query_SyntaxError((int)(p-query));
return false;
}
p = s+1;
continue;
}
break;
case TOKEN_PARCLOSE:
state = 4;
// check parenthesis count
if (pcount == 0)
{
Query_SyntaxError((int)(p-query));
return false;
}
// down one level
pcount--;
// pop all operators in this level, beginning by the last inserted
while (entry)
{
if (entry->GetVal().Level == pcount)
{
AddFilterOp(entry->GetVal().Op);
VListEntry<OpLevel> *_entry = (VListEntry<OpLevel> *)entry->GetPrevious();
pstack.RemoveEntry(entry);
entry = _entry;
}
else
break;
}
break;
case TOKEN_AND:
{
state = 0;
// push and
OpLevel o;
o.Op = FILTER_AND;
o.Level = pcount;
entry = new VListEntry<OpLevel>;
entry->SetVal(o);
pstack.AddEntry(entry, true);
break;
}
case TOKEN_OR:
{
state = 0;
// push or
OpLevel o;
o.Op = FILTER_OR;
o.Level = pcount;
entry = new VListEntry<OpLevel>;
entry->SetVal(o);
pstack.AddEntry(entry, true);
break;
}
default:
Query_SyntaxError((int)(p-query));
return false;
}
break;
case 4:
switch (t)
{
case TOKEN_AND:
{
state = 0;
// push and
OpLevel o;
o.Op = FILTER_AND;
o.Level = pcount;
entry = new VListEntry<OpLevel>;
entry->SetVal(o);
pstack.AddEntry(entry, true);
break;
}
case TOKEN_OR:
{
state = 0;
// push or
OpLevel o;
o.Op = FILTER_OR;
o.Level = pcount;
entry = new VListEntry<OpLevel>;
entry->SetVal(o);
pstack.AddEntry(entry, true);
break;
}
case TOKEN_PARCLOSE:
state = 4;
// check parenthesis count
if (pcount == 0)
{
Query_SyntaxError((int)(p-query));
return false;
}
// down one level
pcount--;
// pop all operators in this level, beginning by the last inserted
while (entry)
{
if (entry->GetVal().Level == pcount)
{
AddFilterOp(entry->GetVal().Op);
VListEntry<OpLevel> *_entry = (VListEntry<OpLevel> *)entry->GetPrevious();
pstack.RemoveEntry(entry);
entry = _entry;
}
else
break;
}
break;
default:
Query_SyntaxError((int)(p-query));
return false;
}
break;
default:
// Ahem... :/
break;
}
p += size;
}
if (pcount > 0)
{
Query_SyntaxError((int)(p-query));
return false;
}
return true;
}
//---------------------------------------------------------------------------
void Scanner::Query_SyntaxError(int c)
{
}
//---------------------------------------------------------------------------
void Scanner::Query_CleanUp()
{
while (pstack.GetNElements() > 0)
{
VListEntry<int> *e;
e = (VListEntry<int> *)pstack.GetHead();
pstack.RemoveEntry(e);
}
}
//---------------------------------------------------------------------------
const char *Scanner::Query_EatSpace(const char *p)
{
while (*p && *p == ' ') p++;
return p;
}
//---------------------------------------------------------------------------
const char *Scanner::Query_ProbeNonAlphaNum(const char *p)
{
int inquote=0;
while (*p && (!Query_isControlChar(*p) || (inquote)))
{
if (*p == '\"')
{
if (!inquote)
inquote = 1;
else
return p+1;
}
p++;
}
return p;
}
//---------------------------------------------------------------------------
int Scanner::Query_isControlChar(char p)
{
switch (p)
{
case '&':
case '|':
case '!':
case '(':
case '[':
case ')':
case ']':
case '>':
case '<':
case '=':
case ',':
case ' ':
return true;
}
return false;
}
//---------------------------------------------------------------------------
char *Scanner::Query_ProbeAlphaNum(char *p)
{
while (*p && Query_isControlChar(*p)) p++;
return p;
}
//---------------------------------------------------------------------------
char *Scanner::Query_ProbeSpace(char *p)
{
while (*p && *p != ' ') p++;
return p;
}
//---------------------------------------------------------------------------
int Scanner::Query_LookupToken(const char *t)
{
for (int i=0;i<sizeof(Tokens)/sizeof(tokenstruct);i++)
{
if (!_stricmp(Tokens[i].token, t))
return Tokens[i].tid;
}
return TOKEN_IDENTIFIER;
}
//---------------------------------------------------------------------------
int Scanner::Query_GetNextToken(const char *p, int *size, char **_token, int tokentable)
{
int t = TOKEN_EOQ;
const char *startptr = p;
if (!*p) return TOKEN_EOQ;
p = Query_EatSpace(p);
const char *e = Query_ProbeNonAlphaNum(p);
if (e != p) // We have a word
{
size_t token_length = e-p;
if (*_token) ndestring_release(*_token);
*_token = ndestring_wcsndup(p, token_length);
if (*(*_token) == '\"' && (*_token)[token_length-1] == '\"') // check for quoted string
{
size_t l=token_length-2;
if (l>0)
{
memcpy(*_token,(*_token)+1,l*sizeof(char));
(*_token)[l]=0;
Query_Unescape(*_token);
}
else
(*_token)[0]=0;// we have an empty string
}
switch (tokentable)
{
case -1:
t = TOKEN_IDENTIFIER;
break;
case 0:
t = Query_LookupToken(*_token);
break;
case 1:
t = IntegerField::LookupToken(*_token);
}
p = e;
}
else // We have a symbol
{
switch (*p)
{
case '&':
if (*(p+1) == '&') p++;
t = TOKEN_AND;
break;
case '|':
if (*(p+1) == '|') p++;
t = TOKEN_OR;
break;
case '!':
if (*(p+1) == '=')
{
p++;
t = TOKEN_NOTEQUAL;
break;
}
t = TOKEN_NOT;
break;
case '(':
t = TOKEN_PAROPEN;
break;
case ')':
t = TOKEN_PARCLOSE;
break;
case '[':
t = TOKEN_SQBRACKETOPEN;
break;
case ']':
t = TOKEN_SQBRACKETCLOSE;
break;
case ',':
t = TOKEN_COMMA;
break;
case '>':
if (*(p+1) == '=')
{
p++;
t = TOKEN_AOREQUAL;
break;
}
if (*(p+1) == '<')
{
p++;
t = TOKEN_NOTEQUAL;
break;
}
t = TOKEN_ABOVE;
break;
case '<':
if (*(p+1) == '=')
{
p++;
t = TOKEN_BOREQUAL;
break;
}
if (*(p+1) == '>')
{
p++;
t = TOKEN_NOTEQUAL;
break;
}
t = TOKEN_BELOW;
break;
case '=':
if (*(p+1) == '>')
{
p++;
t = TOKEN_AOREQUAL;
break;
}
if (*(p+1) == '<')
{
p++;
t = TOKEN_BOREQUAL;
break;
}
if (*(p+1) == '!')
{
p++;
t = TOKEN_NOTEQUAL;
break;
}
if (*(p+1) == '=') p++;
t = TOKEN_EQUAL;
break;
default:
t = TOKEN_UNKNOWN;
break;
}
p++;
}
*size = (int)(p - startptr);
return t;
}
static uint8_t quickhex(char c)
{
int hexvalue = c;
if (hexvalue & 0x10)
hexvalue &= ~0x30;
else
{
hexvalue &= 0xF;
hexvalue += 9;
}
return hexvalue;
}
static uint8_t DecodeEscape(const char *&str)
{
uint8_t a = quickhex(*++str);
uint8_t b = quickhex(*++str);
str++;
return a * 16 + b;
}
static void DecodeEscapedUTF8(char *&output, const char *&input)
{
bool error=false;
while (*input == '%')
{
if (isxdigit(input[1]) && isxdigit(input[2]))
{
*output++=DecodeEscape(input);
}
else if (input[1] == '%')
{
input+=2;
*output++='%';
}
else
{
error = true;
break;
}
}
if (error)
{
*output++ = *input++;
}
}
// benski> We have the luxury of knowing that decoding will ALWAYS produce smaller strings
// so we can do it in-place
void Query_Unescape(char *str)
{
const char *itr = str;
while (*itr)
{
switch (*itr)
{
case '%':
DecodeEscapedUTF8(str, itr);
break;
default:
*str++ = *itr++;
break;
}
}
*str = 0;
}

30
Src/nde/android/Query.h Normal file
View file

@ -0,0 +1,30 @@
#pragma once
#define TOKEN_UNKNOWN -1 // BLAAAAA!!!!!!!!
#define TOKEN_EOQ 0 // End of Query
#define TOKEN_IDENTIFIER 1 // Column name or data to match against
#define TOKEN_EQUAL 2 // =, ==, IS
#define TOKEN_NOTEQUAL 3 // !=, =!, <>, ><
#define TOKEN_BELOW 4 // <
#define TOKEN_ABOVE 5 // >
#define TOKEN_BOREQUAL 6 // <=, =<
#define TOKEN_AOREQUAL 7 // >=, =>
#define TOKEN_NOT 8 // !, NOT
#define TOKEN_AND 9 // &, &&, AND
#define TOKEN_OR 10 // |, ||, OR
#define TOKEN_PAROPEN 11 // (
#define TOKEN_PARCLOSE 12 // )
#define TOKEN_CONTAINS 13 // HAS
#define TOKEN_BEGINS 14 // string starts with...
#define TOKEN_ENDS 15 // string ends with...
#define TOKEN_LIKE 16 // string is nearly (excluding "the " and whitespace etc)
#define TOKEN_ISEMPTY 17 // field does not exists
#define TOKEN_SQBRACKETOPEN 18 // [
#define TOKEN_SQBRACKETCLOSE 19 // ]
#define TOKEN_COMMA 20 // ,
#define TOKEN_NOTCONTAINS 21 // NOTHAS
#define TOKEN_ISNOTEMPTY 22 // field does not exists
#define TOKEN_BEGINSLIKE 23 // string is nearly starts with (excluding "the " and whitespace etc)
// in-place
void Query_Unescape(char *p);

124
Src/nde/android/Record.cpp Normal file
View file

@ -0,0 +1,124 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
Record Class
--------------------------------------------------------------------------- */
//#include "record.h"
#include "../nde.h"
#include <stdio.h>
void RecordBase::Retain()
{
ref_count++;
}
void RecordBase::Release()
{
if (--ref_count == 0)
delete this;
}
RecordBase::RecordBase()
{
ref_count = 1;
InsertionPoint = 0;
}
//---------------------------------------------------------------------------
Record::Record(int RecordPos, int insertionPoint, VFILE *TableHandle, Table *ParentTable)
{
InsertionPoint = insertionPoint;
Record *columns = ParentTable->GetColumns();
int max=columns ? columns->Fields.size() : 128;
if (RecordPos != 0)
{
int n=0;
uint32_t ThisPos = RecordPos;
while (ThisPos)
{
if (n >= max)
break;
Vfseek(TableHandle, ThisPos, SEEK_SET);
Field Entry (ThisPos);
Field *TypedEntry = Entry.ReadField(ParentTable, ThisPos, &ThisPos);
if (!TypedEntry) break; // some db error?
AddField(TypedEntry);
n++;
}
}
}
//---------------------------------------------------------------------------
RecordBase::~RecordBase()
{
Fields.deleteAll();
}
ColumnField *Record::GetColumnByName(const char *name)
{
for (FieldList::iterator itr=Fields.begin();itr!=Fields.end();itr++)
{
ColumnField *p = (ColumnField *)*itr;
if (!strcasecmp(p->GetFieldName(), name))
return p;
}
return NULL;
}
//---------------------------------------------------------------------------
int Record::WriteFields(Table *ParentTable, int RecordIndex)
{
Field *previous = 0;
for (FieldList::iterator itr=Fields.begin();itr!=Fields.end();itr++)
{
Field *p = *itr;
p->WriteField(ParentTable, previous, (Field *)p->next);
previous = p;
}
return WriteIndex(ParentTable, RecordIndex);
}
//---------------------------------------------------------------------------
int Record::WriteIndex(Table *ParentTable, int RecordIndex)
{
int P=0;
if (RecordIndex == NEW_RECORD)
RecordIndex = ParentTable->index->Insert(InsertionPoint);
if (!Fields.empty())
{
Field *f = *Fields.begin();
P=f->GetFieldPos();
}
return ParentTable->index->Update(RecordIndex, P, this, FALSE);
}
//---------------------------------------------------------------------------
void Record::Delete(Table *ParentTable, int RecordIndex)
{
ParentTable->index->Delete(RecordIndex, ParentTable->index->Get(RecordIndex), this);
}
void Record::WalkFields(FieldsWalker callback, void *context)
{
if (callback)
{
for (FieldList::iterator itr=Fields.begin();itr!=Fields.end();itr++)
{
if (!callback(this, *itr, context))
break;
}
}
}

1196
Src/nde/android/Scanner.cpp Normal file

File diff suppressed because it is too large Load diff

148
Src/nde/android/Scanner.h Normal file
View file

@ -0,0 +1,148 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
Scanner Class Prototypes
Android (linux) implementation
--------------------------------------------------------------------------- */
#ifndef __SCANNER_H
#define __SCANNER_H
#include "../nde.h"
#include "record.h"
#include "../index.h"
#include <nu/Vector.h>
#include <nu/ValueSet.h>
#include "../LinkedList.h"
class Table;
class Index;
class Scanner : public LinkedListEntry
{
public:
Record *GetRecord(int Idx);
Scanner(Table *parentTable);
void IndexModified(void);
Index *GetIndex() { return index; }
Index *index; // TODO: make protected
protected:
~Scanner();
Table *pTable;
bool iModified;
typedef Vector<StringField *> SearchStrings;
SearchStrings search_strings;
typedef ValueSet<unsigned char> SearchFields;
SearchFields search_fields;
bool search_any;
void GetCurrentRecord(void);
bool MatchFilters(void);
bool MatchSearches();
bool MatchSearch(const SearchFields &fields, StringField *search_field);
//BOOL MatchJoins(void);
bool CheckFilters(void);
void CacheLastLocate(int Id, int From, Field *field, Index *i, int j);
static int Query_LookupToken(const char *token);
void Query_CleanUp(void);
void Query_SyntaxError(int c);
public:
static int Query_GetNextToken(const char *p, int *size, char **token, int tokentable=0);
static const char *Query_EatSpace(const char *p);
static char *Query_ProbeSpace(char *p);
static const char *Query_ProbeNonAlphaNum(const char *p);
static char *Query_ProbeAlphaNum(char *p);
static int Query_isControlChar(char p);
bool Query(const char *query);
bool Query_Parse(const char *query);
const char *GetLastQuery();
public://fucko: protected
LinkedList pstack;
char *token;
char *last_query;
int last_query_failed;
protected:
Record *CurrentRecord;
int CurrentRecordIdx;
LinkedList FilterList;
Index *lastLocateIndex;
int lastLocateIdx;
Field *lastLocateFieldClone;
int lastLocateFrom;
int lastLocateId;
bool Edition;
int ResultPtr;
bool FiltersOK;
public:
bool MatchFilter(Filter *filter);
typedef bool (*FilterWalker)(Scanner *scanner, Filter *filter, void *context);
void WalkFilters(FilterWalker walker, void *context);
ColumnField *GetColumnByName(const char *FieldName);
ColumnField *GetColumnById(unsigned char id);
Field *NewFieldByName(const char *fieldName, unsigned char Perm);
Field *NewFieldById(unsigned char Id, unsigned char Perm);
void DeleteField(Field *field);
void DeleteFieldByName(const char *name);
void DeleteFieldById(unsigned char Id);
void Cancel(void);
void Insert(void);
void Edit(void);
void Post(void);
void Delete(void);
Field *GetFieldByName(const char *FieldName);
Field *GetFieldById(unsigned char Id);
void First(int *killswitch=0);
void Last(int *killswitch=0);
int Next(int *killswitch=0);
int Previous(int *killswitch=0);
bool Eof(void);
bool Bof(void);
void New(void);
int GetRecordsCount(void);
void GetRecordById(int Id, bool checkFilters=true);
int GetRecordId(void);
void Sync(void);
bool LocateByName(const char *column, int From, Field *field, int *nskip=NULL);
bool LocateById(int Id, int From, Field *field, int *nskip=NULL);
bool LocateByIdEx(int Id, int From, Field *field, int *nskip, int comp_mode);
// Filters
int AddFilterByName(const char *name, Field *Data, unsigned char Op);
int AddFilterById(unsigned char Id, Field *Data, unsigned char Op);
int AddFilterOp(unsigned char Op);
void RemoveFilters(void);
Filter *GetLastFilter(void);
bool SetWorkingIndexByName(const char *desc);
bool SetWorkingIndexById(unsigned char Id);
void Search(const char *search_string);
bool HasIndexChanged(void) { return iModified; }
void ClearDirtyBit(void);
float FragmentationLevel(void);
Table *GetTable();
int in_query_parser;
int disable_date_resolution;
};
#endif

View file

@ -0,0 +1,292 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
StringField Class
Android (linux) specific version
Field data layout:
[2 bytes] string length (bytes)
[length bytes] String data. UTF-16 data will start with a BOM
--------------------------------------------------------------------------- */
#include "../nde.h"
#include "StringField.h"
//---------------------------------------------------------------------------
StringField::StringField(const char *Str, int strkind)
{
InitField();
Type = FIELD_STRING;
if (Str)
{
if (strkind == STRING_IS_WCHAR)
String = ndestring_wcsdup(Str);
else
{
String = const_cast<char *>(Str);
ndestring_retain(String);
}
}
}
//---------------------------------------------------------------------------
void StringField::InitField(void)
{
Type = FIELD_STRING;
// String = NULL;
String = NULL;
}
//---------------------------------------------------------------------------
StringField::StringField()
{
InitField();
}
//---------------------------------------------------------------------------
StringField::~StringField()
{
ndestring_release(String);
String=0;
}
//---------------------------------------------------------------------------
void StringField::ReadTypedData(const uint8_t *data, size_t len)
{
size_t pos=0;
unsigned short c;
CHECK_SHORT(len);
c = GET_SHORT();
pos+=2;
if (c)
{
bool unicode=false;
bool utf16BE=false;
if (c >= 2 // enough room for BOM
&& (c & 1) == 0) // can't be unicode if it's not an even multiple of 2
{
uint16_t BOM=GET_SHORT();
if (BOM == 0xFEFF)
{
pos+=2;
c-=2;
unicode=true;
}
else if (BOM == 0xFFFE)
{
pos+=2;
c-=2;
unicode=true;
utf16BE=true;
}
}
CHECK_BIN(len, c);
if (unicode)
{
ndestring_release(String);
if (utf16BE)
{
size_t bytes = utf16BE_to_utf8((uint16_t *)(data+pos), c>>1, 0, 0);
String = ndestring_malloc(bytes+1);
utf16BE_to_utf8((uint16_t *)(data+pos), c>>1, String, bytes);
String[bytes]=0;
}
else
{
size_t bytes = utf16LE_to_utf8((uint16_t *)(data+pos), c>>1, 0, 0);
String = ndestring_malloc(bytes+1);
utf16LE_to_utf8((uint16_t *)(data+pos), c>>1, String, bytes);
String[bytes]=0;
}
}
else
{
// TODO: check for utf-8 byte marker
String = ndestring_malloc(c+1);
GET_BINARY((uint8_t *)String, data, c, pos);
String[c]=0;
}
}
}
//---------------------------------------------------------------------------
void StringField::WriteTypedData(uint8_t *data, size_t len)
{
int pos=0;
if (String)
{
unsigned short c = (unsigned short)strlen(String);
// write size
CHECK_SHORT(len);
PUT_SHORT(c); pos+=2;
// write string
CHECK_BIN(len, c);
PUT_BINARY(data, (uint8_t *)String, c, pos);
}
else
{
CHECK_SHORT(len);
PUT_SHORT(0); pos+=2;
}
}
//---------------------------------------------------------------------------
char *StringField::GetString(void)
{
return String;
}
//---------------------------------------------------------------------------
void StringField::SetString(const char *Str)
{
if (!Str) return;
ndestring_release(String);
String = NULL;
String = ndestring_wcsdup(Str);
}
//---------------------------------------------------------------------------
void StringField::SetNDEString(char *Str)
{
if (!Str) return;
// copy and then release, just in case we're copying into ourselves
char *oldStr = String;
String = Str;
ndestring_retain(String);
ndestring_release(oldStr);
}
//---------------------------------------------------------------------------
size_t StringField::GetDataSize(void)
{
if (String)
{
return strlen(String) + 2;
}
else
{
return 2;
}
}
//---------------------------------------------------------------------------
int StringField::Compare(Field *Entry)
{
if (!Entry) return -1;
if (Entry->GetType() != GetType()) return 0;
return mystricmp(GetString(), ((StringField*)Entry)->GetString());
}
//---------------------------------------------------------------------------
int StringField::Starts(Field *Entry)
{
if (!Entry) return -1;
if (Entry->GetType() != GetType()) return 0;
return (mystristr(GetString(), ((StringField*)Entry)->GetString()) == GetString());
}
//---------------------------------------------------------------------------
int StringField::Contains(Field *Entry)
{
if (!Entry) return -1;
if (Entry->GetType() != GetType()) return 0;
return (mystristr(GetString(), ((StringField*)Entry)->GetString()) != NULL);
}
Field *StringField::Clone(Table *pTable)
{
StringField *clone = new StringField(String, STRING_IS_NDESTRING);
clone->Pos = FIELD_CLONE;
clone->ID = ID;
clone->MaxSizeOnDisk = GetDataSize();
return clone;
}
bool StringField::ApplyFilter(Field *Data, int op)
{
// TODO: maybe do this?
if (op == FILTER_ISEMPTY || op == FILTER_ISNOTEMPTY)
{
bool r = (op == FILTER_ISEMPTY);
if (!String)
return r;
if (String && String[0] == 0)
return r;
return !r;
}
//
bool r;
StringField *compField = (StringField *)Data;
const char *p = compField->GetString();
const char *d = GetString();
if (!p)
p = "";
if (!d)
d = "";
switch (op)
{
case FILTER_EQUALS:
r = !nde_stricmp(d, p);
break;
case FILTER_NOTEQUALS:
r = !!nde_stricmp(d, p);
break;
case FILTER_CONTAINS:
r = (NULL != stristr_ignore(d, p));
break;
case FILTER_NOTCONTAINS:
r = (NULL == stristr_ignore(d, p));
break;
case FILTER_ABOVE:
r = (bool)(nde_stricmp(d, p) > 0);
break;
case FILTER_ABOVEOREQUAL:
r = (bool)(nde_stricmp(d, p) >= 0);
break;
case FILTER_BELOW:
r = (bool)(nde_stricmp(d, p) < 0);
break;
case FILTER_BELOWOREQUAL:
r = (bool)(nde_stricmp(d, p) <= 0);
break;
case FILTER_BEGINS:
r = (bool)(nde_strnicmp(d, p, strlen(p)) == 0);
break;
case FILTER_ENDS:
{
size_t lenp = strlen(p), lend = strlen(d);
if (lend < lenp) return 0; // too short
r = (bool)(nde_stricmp((d + lend) - lenp, p) == 0);
}
break;
case FILTER_LIKE:
r = (bool)(nde_stricmp(d, p) == 0);
break;
case FILTER_BEGINSLIKE:
r = (bool)(nde_strnicmp_ignore(d, p, strlen(p)) == 0);
break;
default:
r = true;
break;
}
return r;
}

View file

@ -0,0 +1,50 @@
/*
---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
---------------------------------------------------------------------------
*/
/*
---------------------------------------------------------------------------
StringField Class Prototypes
Android (linux) implementation
---------------------------------------------------------------------------
*/
#ifndef __STRINGFIELD_H
#define __STRINGFIELD_H
#include "../NDEString.h"
class StringField : public Field
{
public:
StringField();
~StringField();
StringField(const char *Str, int strkind=STRING_IS_WCHAR);
char *GetString(void);
void SetString(const char *Str);
void SetNDEString(char *Str);
protected:
virtual void ReadTypedData(const uint8_t *, size_t len);
virtual void WriteTypedData(uint8_t *, size_t len);
virtual size_t GetDataSize(void);
virtual int Compare(Field *Entry);
virtual int Starts(Field *Entry);
virtual int Contains(Field *Entry);
virtual bool ApplyFilter(Field *Data, int op);
virtual Field *Clone(Table *pTable);
void InitField(void);
char *String;
};
#endif

846
Src/nde/android/Table.cpp Normal file
View file

@ -0,0 +1,846 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
Table Class
Android (linux) implementation
--------------------------------------------------------------------------- */
#include "Table.h"
#include "../nde.h"
#include <stdio.h>
#include <string.h>
#include "../CRC.H"
#include "../NDEString.h"
#include "IndexField.h"
#include "ColumnField.h"
#include "../DBUtils.h"
const char *tSign="NDETABLE";
//---------------------------------------------------------------------------
Table::Table(const char *TableName, const char *Idx, int Create, Database *_db, int _Cached)
: Scanner(this), use_row_cache(false), columns_cached(false)
{
Handle = 0;
memset(column_ids, FIELD_UNKNOWN, 255);
Cached = _Cached;
db = _db;
AutoCreate = Create;
Name = ndestring_wcsdup(TableName);
IdxName = ndestring_wcsdup(Idx);
Init();
}
//---------------------------------------------------------------------------
void Table::Init()
{
numErrors = 0;
Scanners = new LinkedList();
// benski> cut: Handle=NULL;
IdxHandle=NULL;
FieldsRecord=NULL;
IndexList=NULL;
GLocateUpToDate = FALSE;
}
//---------------------------------------------------------------------------
Table::~Table()
{
Reset();
if (Handle) // Reset doesn't completely destroy Handle
Vfdestroy(Handle);
Handle = 0;
ndestring_release(Name);
ndestring_release(IdxName);
}
//---------------------------------------------------------------------------
void Table::Reset()
{
if (IndexList) IndexList->Release();
IndexList=0;
if (FieldsRecord) FieldsRecord->Release();
FieldsRecord=0;
delete Scanners;
Scanners=0;
if (Handle)
Vfclose(Handle); // close (but don't destroy) to keep mutex open.
if (IdxHandle)
Vfdestroy(IdxHandle);
IdxHandle = 0;
for (RowCache::iterator itr=rowCache.begin();itr!=rowCache.end();itr++)
{
if (itr->second)
itr->second->Release();
}
rowCache.clear();
memset(column_ids, FIELD_UNKNOWN, 255);
columns_cached=false;
}
struct IndexNewWalkerContext
{
IndexNewWalkerContext(Table *_table)
{
N = -1;
table = _table;
}
int N;
Table *table;
};
bool Table::IndexNewWalker(IndexRecord *record, Field *entry, void *context_in)
{
IndexNewWalkerContext *context = (IndexNewWalkerContext *)context_in;
IndexField *p = (IndexField *)entry;
p->index = new Index(context->table->IdxHandle, p->ID, context->N++, p->Type, FALSE, 0, context->table);
return true;
}
//---------------------------------------------------------------------------
bool Table::Open()
{
bool Valid;
int justcreated = 0;
if (!Handle)
Handle = Vfnew(Name, "r+b", Cached);
if (!Handle) return FALSE;
if (!Vflock(Handle))
{
Vfdestroy(Handle);
Handle = 0;
return FALSE;
}
Handle = Vfopen(Handle, Name, "r+b", Cached);
IdxHandle = Vfopen(0, IdxName, "r+b", 1);
Valid = (Handle && IdxHandle);
// unlock
if (Valid || !AutoCreate)
{
//if (Handle)
//Vfunlock(Handle);
}
else
{
if (Handle)
{
Vfclose(Handle);
if (IdxHandle)
Vfdestroy(IdxHandle);
IdxHandle = 0;
}
else
{
if (IdxHandle)
Vfdestroy(IdxHandle);
IdxHandle = 0;
Handle = Vfnew(Name, "w+b", Cached);
if (!Vflock(Handle))
{
Vfdestroy(Handle);
return FALSE;
}
}
Handle = Vfopen(Handle, Name, "w+b", Cached);
IdxHandle = Vfopen(0, IdxName, "w+b", 1);
Valid = (Handle && IdxHandle);
if (Valid)
{
Vfwrite(__TABLE_SIGNATURE__, strlen(__TABLE_SIGNATURE__), Handle);
Vfwrite(__INDEX_SIGNATURE__, strlen(__TABLE_SIGNATURE__), IdxHandle);
// TODO bensk> change if NUM_SPECIAL_RECORDS ever increases
int v=NUM_SPECIAL_RECORDS;//strlen(__TABLE_SIGNATURE__);
Vfwrite(&v, sizeof(v), IdxHandle);
// v = 0; fwrite(&v, sizeof(v), 1, IdxHandle);
v = -1; Vfwrite(&v, sizeof(v), IdxHandle); // write ID
v = 0;
for (int i=0;i<NUM_SPECIAL_RECORDS;i++)
{
Vfwrite(&v, sizeof(v), IdxHandle);
Vfwrite(&v, sizeof(v), IdxHandle);
}
Sync();
justcreated = 1;
}
}
if (!Valid)
{
if (Handle) Vfdestroy(Handle);
if (IdxHandle) Vfdestroy(IdxHandle);
Handle = NULL;
IdxHandle = NULL;
}
else
{
int Ptr;
char test1[9]={0,};
char test2[9]={0,};
Vfseek(Handle, 0, SEEK_SET);
Vfread(test1, strlen(__TABLE_SIGNATURE__), Handle);
Vfseek(IdxHandle, 0, SEEK_SET);
Vfread(test2, strlen(__INDEX_SIGNATURE__), IdxHandle);
test1[8]=0;
test2[8]=0;
if (strcmp(test1, __TABLE_SIGNATURE__) || strcmp(test2, __INDEX_SIGNATURE__))
{
if (Handle) Vfdestroy(Handle);
Handle = 0;
if (IdxHandle) Vfdestroy(IdxHandle);
IdxHandle = 0;
return FALSE;
}
// Load default index
IndexField *field;
field = new IndexField(PRIMARY_INDEX, -1, -1, "None");
field->index = new Index(IdxHandle, PRIMARY_INDEX, -1, -1, FALSE, 0, this);
// Get indexes
Ptr = field->index->Get(INDEX_RECORD_NUM);
IndexList = new IndexRecord(Ptr, INDEX_RECORD_NUM, Handle, this);
if (!IndexList)
{
delete field;
if (Handle) Vfdestroy(Handle);
Handle = 0;
if (IdxHandle) Vfdestroy(IdxHandle);
IdxHandle = 0;
return FALSE;
}
// Init them
IndexNewWalkerContext newContext(this);
IndexList->WalkFields(IndexNewWalker, &newContext);
// Add default in case its not there (if it is it won't be added by addfield)
IndexList->AddField(field);
// Get the default index (whether loaded or preloaded)
Scanner::index = ((IndexField*)IndexList->GetField(PRIMARY_INDEX))->index;
// If it's different from preloaded, delete preloaded
if (field->index != Scanner::index)
{
delete field;
field=0;
}
// Set up colaboration
IndexList->BuildCollaboration();
// Get columns
Ptr = Scanner::index->Get(FIELDS_RECORD_NUM);
FieldsRecord = new Record(Ptr, FIELDS_RECORD_NUM, Handle, this);
if (!FieldsRecord)
{
IndexList->Release();
IndexList=0;
if (Handle) Vfdestroy(Handle);
Handle = 0;
if (IdxHandle) Vfdestroy(IdxHandle);
IdxHandle = 0;
return FALSE;
}
// update the column cache
FieldsRecord->WalkFields(BuildColumnCache, this);
columns_cached=true;
}
#if 0 // TODO
if (Valid && !justcreated)
{
if (IndexList->NeedFix())
Compact();
}
#endif
if (Valid) First();
if (Handle)
Vfunlock(Handle);
return Valid;
}
//---------------------------------------------------------------------------
void Table::Close(void)
{
int v=0;
if (Handle && IndexList && Vflock(Handle, 0))
{
IndexList->WalkFields(IndexWriteWalker, 0);
}
delete Scanners;
Scanners = NULL;
Vsync(Handle);
if (IdxHandle)
{
Vfdestroy(IdxHandle);
IdxHandle = NULL;
v |= 2;
}
if (Handle)
{
Vfdestroy(Handle);
Handle = NULL;
v |= 1;
}
if (v != 3)
return;
}
bool Table::IndexWriteWalker(IndexRecord *record, Field *entry, void *context)
{
IndexField *field = (IndexField *)entry;
field->index->WriteIndex();
return true;
}
//---------------------------------------------------------------------------
void Table::Sync(void)
{
if (!Vflock(Handle))
return;
if (IndexList)
IndexList->WalkFields(IndexWriteWalker, 0);
int err=0;
if (!err && Handle) err|=Vsync(Handle);
if (!err && IdxHandle) err|=Vsync(IdxHandle);
Vfunlock(Handle);
}
//---------------------------------------------------------------------------
ColumnField *Table::NewColumn(unsigned char FieldID, const char *FieldName, unsigned char FieldType, bool indexUnique)
{
columns_cached=false; // if they start writing new columns, kill the columns cache until they PostColumns()
ColumnField *f = GetColumnById(FieldID);
if (f) {
int t = f->GetDataType();
if (t != FieldType) {
if (CompatibleFields(t, FieldType))
{
f->SetDataType(FieldType);
goto aok;
}
}
return NULL;
}
aok:
if (GetColumnByName(FieldName))
return NULL;
ColumnField *field = new ColumnField(FieldID, FieldName, FieldType, this);
column_ids[FieldID]=FieldType;
FieldsRecord->AddField(field);
return field;
}
void Table::SetFieldSearchableById(unsigned char field_id, bool searchable)
{
ColumnField *column = GetColumnById(field_id);
if (column)
column->SetSearchable(searchable);
if (searchable)
{
search_fields.insert(field_id);
}
else
{
search_fields.erase(field_id);
}
}
//---------------------------------------------------------------------------
bool Table::BuildColumnCache(Record *record, Field *entry, void *context)
{
Table *table = (Table *)context;
ColumnField *column = (ColumnField *)entry;
unsigned char field_id=column->GetFieldId();
table->column_ids[field_id] = column->GetDataType();
if (column->IsSearchableField())
{
table->search_fields.insert(field_id);
}
else
{
table->search_fields.erase(field_id);
}
return true;
}
//---------------------------------------------------------------------------
void Table::PostColumns(void)
{
FieldsRecord->WriteFields(this, FIELDS_RECORD_NUM);
memset(column_ids, FIELD_UNKNOWN, 255);
FieldsRecord->WalkFields(BuildColumnCache, this);
columns_cached=true;
}
unsigned char Table::GetColumnType(unsigned char Id)
{
if (columns_cached)
{
return column_ids[Id];
}
else
{
return GetColumnById(Id)->GetDataType();
}
}
//---------------------------------------------------------------------------
IndexField *Table::GetIndexByName(const char *name)
{
if (!IndexList)
return NULL;
return IndexList->GetIndexByName(name);
}
//---------------------------------------------------------------------------
IndexField *Table::GetIndexById(unsigned char Id)
{
if (!IndexList)
return NULL;
return (IndexField *)IndexList->GetField(Id);
}
//---------------------------------------------------------------------------
void Table::AddIndexByName(const char *name, const char *desc)
{
ColumnField *header = GetColumnByName(name);
if (header)
{
unsigned char Idx = header->ID;
AddIndexById(Idx, desc);
}
}
//---------------------------------------------------------------------------
void Table::AddIndexById(unsigned char Id, const char *desc)
{
if (GetIndexById(Id)) return;
ColumnField *col = GetColumnById(Id);
if (!col)
return;
IndexField *newindex = new IndexField(Id, IndexList->GetColumnCount(), col->GetDataType(), desc);
newindex->index = new Index(IdxHandle, Id, IndexList->GetColumnCount(), col->GetDataType(), true, Scanner::index->NEntries, this);
IndexList->AddField(newindex);
IndexField *previous = (IndexField *)newindex->prev;
previous->index->Colaborate(newindex);
IndexField *primary_index = (IndexField *)IndexList->GetField(PRIMARY_INDEX);
newindex->index->Colaborate(primary_index);
previous->index->Propagate();
IndexList->WriteFields(this);
}
//---------------------------------------------------------------------------
bool Table::CheckIndexing(void)
{
if (IndexList->GetColumnCount() == 0) return true;
for (int i=0;i<Scanner::index->NEntries;i++)
{
if (!IndexList->CheckIndexing(i))
return FALSE;
}
return true;
}
struct IndexWalkerThunkContext
{
void *context;
Table *_this;
Table::IndexWalker callback;
};
bool Table::IndexWalkerThunk(IndexRecord *record, Field *entry, void *context_in)
{
IndexWalkerThunkContext *context = (IndexWalkerThunkContext *)context_in;
return context->callback(context->_this, (IndexField *)entry, context->context);
}
//---------------------------------------------------------------------------
void Table::WalkIndices(IndexWalker callback, void *context)
{
if (IndexList && callback)
{
IndexWalkerThunkContext walkerContext = { context, this, callback };
IndexList->WalkFields(IndexWalkerThunk, &walkerContext);
}
}
//---------------------------------------------------------------------------
void Table::DropIndex(IndexField *Ptr)
{
if (!Ptr || Ptr->Type != FIELD_INDEX) return;
if (Scanner::index == Ptr->index)
{
Scanner::index = ((IndexField*)IndexList->GetField(PRIMARY_INDEX))->index;
IndexList->BuildCollaboration();
}
IndexList->RemoveField(Ptr);
if (Scanner::index->SecIndex == Ptr)
Scanner::index->SecIndex = 0;
IndexList->WriteFields(this);
}
//---------------------------------------------------------------------------
void Table::DropIndexByName(const char *desc)
{
IndexField *indx = GetIndexByName(desc);
if (!strcasecmp(desc, "None")) return;
if (indx)
DropIndex(indx);
}
//---------------------------------------------------------------------------
void Table::DropIndexById(unsigned char Id)
{
if (!IndexList)
return;
if (Id == (unsigned char)PRIMARY_INDEX) return;
IndexField *indx=(IndexField *)IndexList->GetField(Id);
if (indx)
DropIndex(indx);
}
//---------------------------------------------------------------------------
bool Table::LocateByIdEx(int Id, int From, Field *field, int comp_mode)
{
return Scanner::LocateByIdEx(Id, From, field, NULL, comp_mode);
}
//---------------------------------------------------------------------------
Record *Table::GetColumns(void)
{
if (!FieldsRecord)
return NULL;
return FieldsRecord;
}
//---------------------------------------------------------------------------
Scanner *Table::NewScanner()
{
Scanner *s = new Scanner(this);
/*if (Scanners->GetNElements() > 0)*/
s->index = Scanner::index;
Scanners->AddEntry(s, true);
return s;
}
//---------------------------------------------------------------------------
Scanner *Table::GetDefaultScanner()
{
return this;
}
//---------------------------------------------------------------------------
void Table::DeleteScanner(Scanner *scan)
{
if (!scan) return;
Scanners->RemoveEntry(scan);
}
//---------------------------------------------------------------------------
void Table::IndexModified(void)
{
Scanner *s = (Scanner *)Scanners->GetHead();
while (s)
{
s->IndexModified();
s = (Scanner *)s->GetNext();
}
}
//---------------------------------------------------------------------------
void Table::SetGlobalLocateUpToDate(bool is) {
GLocateUpToDate = is;
}
struct ColumnWalkContext
{
Table *ctable;
};
bool Table::Compact_ColumnWalk(Record *record, Field *entry, void *context_in)
{
ColumnField *field = static_cast<ColumnField *>(entry);
ColumnWalkContext *context = (ColumnWalkContext *)context_in;
Table *ctable = context->ctable;
ctable->NewColumn(field->GetFieldId(), field->GetFieldName(), field->GetDataType(), FALSE);
return true;
}
struct ColumnWalk2Context
{
Table *ctable;
Table *thisTable;
uint8_t *data;
size_t data_size;
int gotstuff;
};
bool Table::Compact_ColumnWalk2(Record *record, Field *entry, void *context_in)
{
ColumnField *colfield = (ColumnField *)entry;
ColumnWalk2Context *context = (ColumnWalk2Context *)context_in;
unsigned char fieldid = colfield->GetFieldId();
//char *fieldname = colfield->GetFieldName();
Field *mfield = context->thisTable->GetFieldById(fieldid);
//Field *mfield = GetFieldByName(fieldname);
if (mfield != NULL) {
if (!context->gotstuff) {
context->ctable->New();
context->gotstuff = 1;
}
Field *cfield = context->ctable->NewFieldById(fieldid, 0);
//Field *cfield = ctable->NewFieldByName(fieldname, mfield->GetPerm());
size_t len = mfield->GetDataSize();
if (len > context->data_size)
{
context->data_size = len;
context->data = (uint8_t *)realloc(context->data, context->data_size);
}
mfield->WriteTypedData(context->data, len);
cfield->ReadTypedData(context->data, len);
}
return true;
}
bool Table::Compact_IndexWalk(Table *table, IndexField *field, void *context)
{
Table *ctable = (Table *)context;
if (strcasecmp(field->GetIndexName(), "None"))
ctable->AddIndexById(field->GetFieldId(), field->GetIndexName());
return true;
}
#if 0 // TODO
//---------------------------------------------------------------------------
void Table::Compact(int *progress) {
// ok so we're gonna be cheating a bit, instead of figuring out how to safely modify all those
// nifty indexes that cross reference themselves and blablabla, we're just gonna duplicate the
// whole table from scratch, overwrite ourselves, and reopen the table. duh.
if (!Vflock(Handle))
{
if (progress != NULL) *progress = 100;
return;
}
// create a temporary table in windows temp dir
wchar_t temp_table[MAX_PATH+12];
wchar_t temp_index[MAX_PATH+12];
wchar_t old_table[MAX_PATH+12];
wchar_t old_index[MAX_PATH+12];
DWORD pid=GetCurrentProcessId();
StringCbPrintfW(temp_table, sizeof(temp_table), L"%s.new%08X", Name,pid);
StringCbPrintfW(temp_index, sizeof(temp_index),L"%s.new%08X", IdxName,pid);
StringCbPrintfW(old_table, sizeof(old_table),L"%s.old%08X", Name,pid);
StringCbPrintfW(old_index, sizeof(old_index),L"%s.old%08X", IdxName,pid);
// delete them, in case we crashed while packing
DeleteFileW(temp_table);
DeleteFileW(temp_index);
DeleteFileW(old_table);
DeleteFileW(old_index);
// create a brand new db and a brand new table
Table *ctable = db->OpenTable(temp_table, temp_index, NDE_OPEN_ALWAYS, Cached);
// duplicate the columns
Record *record = GetColumns();
if (record != NULL)
{
ColumnWalkContext context;
context.ctable = ctable;
record->WalkFields(Compact_ColumnWalk, &context);
}
ctable->PostColumns();
// duplicate the indexes
WalkIndices(Compact_IndexWalk, (void *)ctable);
// duplicate the data
int reccount = GetRecordsCount();
int count = 0;
First();
ColumnWalk2Context context;
context.data_size = 65536;
context.data = (uint8_t *)malloc(65536);
context.ctable = ctable;
context.thisTable = this;
while (1) {
int lasterr = NumErrors();
GetDefaultScanner()->GetRecordById(count, FALSE);
count++;
if (Eof() || count > reccount) break;
if (NumErrors() > lasterr)
continue;
Index *idx = GetDefaultScanner()->GetIndex();
int pos = idx->Get(GetDefaultScanner()->GetRecordId());
if (pos == 0) continue;
int pr = (int)((float)GetRecordId()/(float)reccount*100.0f);
if (progress != NULL) *progress = pr;
context.gotstuff = 0;
if (record != NULL)
record->WalkFields(Compact_ColumnWalk2, &context);
if (context.gotstuff)
ctable->Post();
}
free(context.data);
// done creating temp table
db->CloseTable(ctable);
// reset the data structures and close underlying file handles
Reset();
if (MoveFileW(Name,old_table))
{
if (MoveFileW(IdxName,old_index))
{
if (!MoveFileW(temp_table,Name) || !MoveFileW(temp_index,IdxName))
{
// failed, try to copy back
DeleteFileW(Name);
DeleteFileW(IdxName);
MoveFileW(old_table,Name); // restore old file
MoveFileW(old_index,IdxName); // restore old file
}
}
else
{
MoveFileW(old_table,Name); // restore old file
}
}
// clean up our temp files
DeleteFileW(temp_table);
DeleteFileW(temp_index);
DeleteFileW(old_table);
DeleteFileW(old_index);
if (progress != NULL) *progress = 100;
// reopen our table
Init();
Open();
}
#endif
ColumnField *Table::GetColumnById(unsigned char Idx)
{
if (!FieldsRecord)
return NULL;
return (ColumnField *)FieldsRecord->GetField(Idx);
}
ColumnField *Table::GetColumnByName(const char *FieldName)
{
return FieldsRecord->GetColumnByName(FieldName);
}
void Table::RowCache_Delete(int position)
{
if (use_row_cache)
{
RowCache::iterator found = rowCache.find(position);
if (found != rowCache.end())
{
if (found->second)
found->second->Release();
rowCache.erase(found);
}
}
}
void Table::RowCache_Remove(int position)
{
if (use_row_cache)
{
Record *&row = rowCache[position];
if (row)
{
row->Release();
}
row = 0;
}
}
void Table::RowCache_Add(Record *record, int position)
{
if (use_row_cache)
{
record->Retain();
Record *&row = rowCache[position];
if (row)
{
row->Release();
}
row = record;
}
}
Record *Table::RowCache_Get(int position)
{
if (!use_row_cache)
return 0;
Record *row = rowCache[position];
if (row)
row->Retain();
return row;
}
void Table::EnableRowCache()
{
use_row_cache=true;
}

166
Src/nde/android/Table.h Normal file
View file

@ -0,0 +1,166 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
Table Class Prototypes
Android (linux) implementation
--------------------------------------------------------------------------- */
#ifndef __TABLE_H
#define __TABLE_H
#include <stdio.h>
#include "Scanner.h"
#include <map>
#include "IndexRecord.h"
class Table : private Scanner
{
public:
// TODO: move these back to protected
VFILE *Handle;
using Scanner::index;
bool use_row_cache;
bool GLocateUpToDate;
private:
void Init();
void Reset();
private:
LinkedList *Scanners;
protected:
char *Name;
char *IdxName;
VFILE *IdxHandle;
int AutoCreate;
Record *FieldsRecord;
IndexRecord *IndexList;
Database *db;
int Cached;
int numErrors;
using Scanner::Edition;
bool columns_cached;
unsigned char column_ids[256];
typedef std::map<int, Record*> RowCache;
RowCache rowCache;
// Tables
static bool Compact_ColumnWalk(Record *record, Field *entry, void *context_in);
static bool Compact_ColumnWalk2(Record *record, Field *entry, void *context_in);
static bool Compact_IndexWalk(Table *table, IndexField *entry, void *context);
static bool IndexWriteWalker(IndexRecord *record, Field *entry, void *context);
static bool IndexWalkerThunk(IndexRecord *record, Field *entry, void *context);
static bool IndexNewWalker(IndexRecord *record, Field *entry, void *context);
static bool BuildColumnCache(Record *record, Field *entry, void *context);
public:
typedef bool (*IndexWalker)(Table *table, IndexField *entry, void *context);
Table(const char *TableName, const char *IdxName, int Create, Database *db, int Cached);
~Table();
bool Open();
void Close();
// Columns
ColumnField *NewColumn(unsigned char Id, const char *name, unsigned char type, bool indexUniques);
void DeleteColumn(ColumnField *field); // todo
void DeleteColumnByName(const char *name); // todo
void DeleteColumnById(unsigned char Id); // todo
void PostColumns(void);
NDE_API Record *GetColumns(void);
ColumnField *GetColumnByName(const char *FieldName);
ColumnField *GetColumnById(unsigned char Idx);
unsigned char GetColumnType(unsigned char Id);
// Fields
using Scanner::NewFieldByName;
using Scanner::NewFieldById;
using Scanner::GetFieldByName;
using Scanner::GetFieldById;
using Scanner::DeleteField;
using Scanner::DeleteFieldByName;
using Scanner::DeleteFieldById;
// Records
using Scanner::First;
using Scanner::Last;
using Scanner::Next;
using Scanner::Previous;
using Scanner::Eof;
using Scanner::Bof;
using Scanner::New;
using Scanner::Insert;
using Scanner::Edit;
using Scanner::Cancel;
using Scanner::Post;
using Scanner::Delete;
using Scanner::GetRecordsCount;
using Scanner::GetRecordById;
using Scanner::GetRecordId;
void Sync(void);
using Scanner::LocateByName;
using Scanner::LocateById;
bool LocateByIdEx(int Id, int From, Field *field, int comp_mode);
// Indexes
void AddIndexByName(const char *FieldName, const char *KeyName);
void AddIndexById(unsigned char Id, const char *KeyName);
void WalkIndices(IndexWalker callback, void *context);
IndexField *GetIndexByName(const char *name);
IndexField *GetIndexById(unsigned char Id);
using Scanner::SetWorkingIndexByName;
using Scanner::SetWorkingIndexById;
bool CheckIndexing(void);
void DropIndexByName(const char *desc);
void DropIndexById(unsigned char Id);
void DropIndex(IndexField *Ptr);
void IndexModified(void);
// Filters
using Scanner::AddFilterByName;
using Scanner::AddFilterById;
using Scanner::AddFilterOp;
using Scanner::RemoveFilters;
// Scanners
Scanner *NewScanner();
Scanner *GetDefaultScanner();
void DeleteScanner(Scanner *scan);
// Misc
using Scanner::FragmentationLevel;
void Compact(int *progress = NULL);
void SetGlobalLocateUpToDate(bool is);
// Row Cache
void RowCache_Delete(int position);
void RowCache_Remove(int position);
void RowCache_Add(Record *record, int position);
Record *RowCache_Get(int position);
NDE_API void EnableRowCache();
// Searching
void SetFieldSearchableById(unsigned char field_id, bool searchable);
int HasErrors()
{
return numErrors > 0;
}
int NumErrors()
{
return numErrors;
}
void IncErrorCount()
{
numErrors++;
}
};
#endif

539
Src/nde/android/Vfs.cpp Normal file
View file

@ -0,0 +1,539 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
Virtual File System
--------------------------------------------------------------------------- */
#include "../nde.h"
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "Vfs.h"
#ifndef EOF
#define EOF -1
#endif
/* the FILE (fopen/fwrite/etc) implementation for Mac and Linux */
VFILE *Vfnew(const char *fl, const char *mode, int Cached)
{
if (!fl) return NULL;
VFILE *f = (VFILE *)malloc(sizeof(VFILE));
if (!f)
return NULL;
memset(f, 0, sizeof(VFILE));
#ifdef NDE_ALLOW_NONCACHED
f->cached = Cached;
#else
f->cached = 1;
#endif
if (!strchr(mode, '+'))
{
if (strchr(mode, 'r'))
f->mode = VFS_READ | VFS_MUSTEXIST;
if (strchr(mode, 'w'))
f->mode = VFS_WRITE | VFS_CREATE | VFS_NEWCONTENT;
if (strchr(mode, 'a'))
f->mode = VFS_WRITE | VFS_CREATE | VFS_SEEKEOF;
}
else
{
if (strstr(mode, "r+"))
f->mode = VFS_WRITE | VFS_MUSTEXIST;
if (strstr(mode, "w+"))
f->mode = VFS_WRITE | VFS_CREATE | VFS_NEWCONTENT;
if (strstr(mode, "a+"))
f->mode = VFS_WRITE | VFS_CREATE | VFS_SEEKEOF;
}
if (f->mode == 0 || ((f->mode & VFS_READ) && (f->mode & VFS_WRITE)))
{
free(f);
return NULL;
}
snprintf(f->lockname, sizeof(f->lockname), "%s.lock", fl);
return f;
}
//----------------------------------------------------------------------------
VFILE *Vfopen(VFILE *f, const char *fl, const char *mode, int Cached)
{
if (!f)
{
f = Vfnew(fl, mode, Cached);
if (!f)
return 0;
}
if (!f && !fl) return NULL;
#ifdef NDE_ALLOW_NONCACHED
if (!f->cached)
{
f->rfile = fopen(fl, mode);
if (f->rfile)
f->filename = _strdup(fl);
}
else
{
free(f);
return NULL;
}
return f;
}
#endif
if (f->mode & VFS_MUSTEXIST)
{
if (access(fl, 0) != 0)
{
free(f);
return NULL;
}
}
if (!(f->mode & VFS_NEWCONTENT))
{
FILE *pf;
pf = fopen(fl, "rb");
if (!pf)
{
f->data = (unsigned char *)calloc(VFILE_INC, 1);
if (f->data == NULL)
{
free(f);
return NULL;
}
f->filesize = 0;
f->maxsize = VFILE_INC;
}
else
{
fseek(pf, 0, SEEK_END);
f->filesize = ftell(pf);
fseek(pf, 0, SEEK_SET);
f->data = (unsigned char *)calloc(f->filesize, 1);
if (f->data == NULL)
{
free(f);
return NULL;
}
f->maxsize = f->filesize;
fread(f->data, f->filesize, 1, pf);
fclose(pf);
}
}
if (f->mode & VFS_SEEKEOF)
f->ptr = f->filesize;
f->filename = strdup(fl);
return f;
}
//----------------------------------------------------------------------------
void Vfclose(VFILE *f)
{
if (!f) return;
#ifdef NDE_ALLOW_NONCACHED
if (!f->cached)
{
free(f->filename);
if (f->rfile)
fclose(f->rfile);
f->rfile=0;
// free(f);
return;
}
#endif
if (!(f->mode & VFS_WRITE))
{
free(f->filename);
free(f->data);
//free(f);
return;
}
Vsync(f);
while (f->locks)
Vfunlock(f, 1);
free(f->filename);
free(f->data);
//free(f);
}
//----------------------------------------------------------------------------
size_t Vfread(void *ptr, size_t size, VFILE *f)
{
if (!ptr || !f) return 0;
#ifdef NDE_ALLOW_NONCACHED
if (!f->cached)
{
return fread(ptr, 1, size, f->rfile);
}
#endif
size_t s = size;
if (!s) return 0;
if (s + f->ptr > f->filesize)
{
//FUCKO: remove this
if (!(f->ptr < f->filesize))
{
// if (!f->flushtable) // this would be ideal, if we could figure out f->flushtable
// f->flushtable=MessageBox(g_hwnd,"DB read failed, DB may be corrupted.\r\n\r\n"
// "Hit Retry to continue, or Cancel to clear the DB and start over","Winamp Library Error",MB_RETRYCANCEL) == IDCANCEL; //fucko
//MessageBox(g_hwnd,"DB read failed, DB may be corrupted. If this error persists, remove all files from the library.",
// "Winamp Library Error",MB_OK);
return 0;
}
s = f->filesize - f->ptr;
}
memcpy(ptr, f->data+f->ptr, s);
f->ptr += s;
return (s/size);
}
//----------------------------------------------------------------------------
void Vfwrite(const void *ptr, size_t size, VFILE *f)
{
if (!ptr || !f) return;
#ifdef NDE_ALLOW_NONCACHED
if (!f->cached)
{
fwrite(ptr, size*n, f->rfile);
return;
}
#endif
f->dirty=1;
if (size + f->ptr > f->maxsize)
{
// grow f->data,f->maxsize to be (size + f->ptr + VFILE_INC-1)&~(VFILE_INC-1)
// instead of calling Vgrow again which gets kinda slow
size_t newsize=(size + f->ptr + VFILE_INC-1)&~(VFILE_INC-1);
f->data=(unsigned char *)realloc(f->data,newsize);
if (f->data == NULL) return;
memset(f->data+f->maxsize,0,newsize-f->maxsize);
f->maxsize=newsize;
}
memcpy(f->data + f->ptr, ptr, size);
f->ptr += size;
if (f->ptr > f->filesize)
f->filesize = f->ptr;
}
//----------------------------------------------------------------------------
void Vgrow(VFILE *f)
{
if (!f) return;
#ifdef NDE_ALLOW_NONCACHED
if (!f->cached) return;
#endif
f->data = (unsigned char *)realloc(f->data, f->maxsize + VFILE_INC);
f->maxsize += VFILE_INC;
}
//----------------------------------------------------------------------------
void Vfputs(char *str, VFILE *f)
{
if (!f) return;
#ifdef NDE_ALLOW_NONCACHED
if (!f->cached)
{
fputs(str, f->rfile);
return;
}
#endif
Vfwrite(str, strlen(str), f);
}
//----------------------------------------------------------------------------
void Vfputc(char c, VFILE *f)
{
if (!f) return;
#ifdef NDE_ALLOW_NONCACHED
if (!f->cached)
{
fputc(c, f->rfile);
return;
}
#endif
Vfwrite(&c, 1, f);
}
/* benski> unused:
// not mac compliant
//----------------------------------------------------------------------------
char *Vfgets(char *dest, int n, VFILE *f) {
if (!f) return NULL;
#ifdef NDE_ALLOW_NONCACHED
if (!f->cached)
{
#ifdef NDE_NOWIN32FILEIO
return fgets(dest, n, f->rfile);
#else
#error port me!
#endif
}
#endif
unsigned char c=0;
char *p;
int l=0;
p = dest;
while (l < n && !Vfeof(f)) {
c = f->data[f->ptr];
f->ptr++;
*p = c;
p++;
l++;
if (c == '\n') {
if (!Vfeof(f) && f->data[f->ptr] == '\r') {
f->ptr++;
}
break;
}
}
*p=0;
return dest;
}
*/
/* benski> unused:
//----------------------------------------------------------------------------
char Vfgetc(VFILE *f) {
if (!f) return EOF;
#ifdef NDE_ALLOW_NONCACHED
if (!f->cached)
#ifdef NDE_NOWIN32FILEIO
return fgetc(f->rfile);
#else
#error port me#
#endif
#endif
if (!Vfeof(f))
return f->data[f->ptr++];
return EOF;
}
*/
//----------------------------------------------------------------------------
unsigned long Vftell(VFILE *f)
{
if (!f) return (unsigned)-1;
#ifdef NDE_ALLOW_NONCACHED
if (!f->cached)
{
return ftell(f->rfile);
}
#endif
return f->ptr;
}
//----------------------------------------------------------------------------
void Vfseek(VFILE *f, long i, int whence)
{
if (!f) return;
#ifdef NDE_ALLOW_NONCACHED
if (!f->cached)
{
fseek(f->rfile, i, whence);
return;
}
#endif
switch (whence)
{
case SEEK_SET:
f->ptr = i;
break;
case SEEK_CUR:
f->ptr += i;
break;
case SEEK_END:
f->ptr = f->filesize+i;
break;
}
}
//----------------------------------------------------------------------------
int Vfeof(VFILE *f)
{
if (!f) return -1;
#ifdef NDE_ALLOW_NONCACHED
if (!f->cached)
{
return feof(f->rfile);
}
#endif
return (f->ptr >= f->filesize);
}
//----------------------------------------------------------------------------
int Vsync(VFILE *f)
{
if (!f) return 0;
if (!f->dirty) return 0;
if (f->mode & VFS_WRITE)
{
#ifdef NDE_ALLOW_NONCACHED
if (!f->cached)
{
int p=ftell(f->rfile);
fclose(f->rfile);
f->rfile = fopen(f->filename, "r+b");
if (!f->rfile)
return 1;
fseek(f->rfile, p, SEEK_SET);
return 0;
}
#endif
char newfn[1024], oldfn[1024];
DWORD mypid=getpid();
snprintf(newfn,sizeof(newfn), "%s.n3w%08X",f->filename,mypid);
snprintf(oldfn,sizeof(oldfn), "%s.o1d%08X",f->filename,mypid);
unlink(newfn);
unlink(oldfn);
tryagain:
FILE *pf = fopen(newfn, "wb");
if (!pf || fwrite(f->data, f->filesize, 1, pf) != 1)
{
if (pf) fclose(pf);
printf("Error flushing DB to disk (is your drive full?)\n\nHit (R)etry to try again (recommended), or (C)ancel to abort (NOT recommended, and may leave the DB in an unuseable state)");
fflush(stdout);
char c;
while (1)
{
scanf("%c", &c);
// clear_stdin();
c = toupper(c);
if (c == 'R') goto tryagain;
else if (c == 'C') break;
}
unlink(newfn);
return 1;
}
fclose(pf);
rename(f->filename,oldfn); // save old file
int rv=0;
tryagain2:
if (rename(newfn,f->filename))
{
printf("Error updating DB file on disk. This should never really happen\n\nHit (R)etry to try again (recommended), or (C)ancel to abort (NOT recommended, and may leave the DB in an unuseable state)");
fflush(stdout);
char c;
while (1)
{
scanf("%c", &c);
// clear_stdin();
c = toupper(c);
if (c == 'R') goto tryagain2;
else if (c == 'C') break;
}
rename(oldfn,f->filename); // restore old file
rv=1;
}
// clean up our temp files
unlink(oldfn);
unlink(newfn);
//free(newfn);
//free(oldfn);
return rv;
}
f->dirty=0;
return 0;
}
void Vfdestroy(VFILE *f)
{
// benski> TODO:
if (f)
{
Vfclose(f);
while (f->locks)
Vfunlock(f, 1);
// TODO if (f->mutex) CloseHandle(f->mutex);
free(f);
}
}
// benski> TODO implement these with fopen
// returns 0 on failure
int Vflock(VFILE *fl, bool is_sync)
{
#ifndef NO_TABLE_WIN32_LOCKING
if (!fl) return 0;
if (!is_sync && fl->cached)
return 1;
if (fl->locks++ == 0)
{
int retry_cnt=0;
FILE *fFile;
do
{
fFile = fopen(fl->lockname, "wb");
if (fFile == 0) Sleep(100);
}
while (fFile == 0 && retry_cnt++ < 100); // try for 10 seconds
if (fFile == INVALID_HANDLE_VALUE) return 0; // db already locked, fail gracefully
fl->lockFile = fFile;
}
#endif
return 1;
}
void Vfunlock(VFILE *fl, bool is_sync)
{
#ifndef NO_TABLE_WIN32_LOCKING
if (!is_sync && fl->cached)
return;
if (--fl->locks == 0)
{
if (fl && fl->lockFile && fl->lockFile != INVALID_HANDLE_VALUE)
{
fclose(fl->lockFile);
unlink(fl->lockname);
}
}
#endif
}

480
Src/nde/android/nde_c.cpp Normal file
View file

@ -0,0 +1,480 @@
#include "nde_c.h"
#include "../nde.h"
/* Database */
nde_database_t NDE_CreateDatabase()
{
return (nde_database_t)new Database();
}
void NDE_DestroyDatabase(nde_database_t db)
{
delete (Database *)db;
}
nde_table_t NDE_Database_OpenTable(nde_database_t db, const char *filename, const char *indexname, int create, int cache)
{
Database *database = (Database *)db;
if (database && filename)
return (nde_table_t)database->OpenTable(filename, indexname, (BOOL)create, (BOOL)cache);
else
return 0;
}
void NDE_Database_CloseTable(nde_database_t db, nde_table_t t)
{
Database *database = (Database *)db;
Table *table = (Table *)t;
if (database && table)
{
database->CloseTable(table);
}
}
/* Table */
nde_field_t NDE_Table_NewColumn(nde_table_t t, unsigned char id, const char *name, unsigned char type)
{
Table *table = (Table *)t;
if (table)
return (nde_field_t)table->NewColumn(id, name, type, FALSE);
else
return 0;
}
void NDE_Table_PostColumns(nde_table_t t)
{
Table *table = (Table *)t;
if (table)
table->PostColumns();
}
void NDE_Table_AddIndexByID(nde_table_t t, unsigned char id, const char *name)
{
Table *table = (Table *)t;
if (table)
table->AddIndexById(id, name);
}
nde_scanner_t NDE_Table_CreateScanner(nde_table_t t)
{
Table *table = (Table *)t;
if (table)
return (nde_scanner_t)table->NewScanner();
else
return 0;
}
void NDE_Table_DestroyScanner(nde_table_t t, nde_scanner_t s)
{
Table *table = (Table *)t;
Scanner *scanner = (Scanner *)s;
if (table && scanner)
table->DeleteScanner(scanner);
}
void NDE_Table_Sync(nde_table_t t)
{
Table *table = (Table *)t;
if (table)
table->Sync();
}
int NDE_Table_GetRecordsCount(nde_table_t t)
{
Table *table = (Table *)t;
if (table)
return table->GetRecordsCount();
else
return 0;
}
nde_field_t NDE_Table_GetColumnByID(nde_table_t t, unsigned char id)
{
Table *table = (Table *)t;
if (table)
return (nde_field_t)table->GetColumnById(id);
else
return 0;
}
nde_field_t NDE_Table_GetColumnByName(nde_table_t t, const char *name)
{
Table *table = (Table *)t;
if (table && name)
return (nde_field_t)table->GetColumnByName(name);
else
return 0;
}
void NDE_Table_SetColumnSearchableByID(nde_table_t t, unsigned char id, int searchable)
{
Table *table = (Table *)t;
if (table)
table->SetFieldSearchableById(id, !!searchable);
}
/* Scanner */
int NDE_Scanner_Query(nde_scanner_t s, const char *query)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
return scanner->Query(query);
else
return 0;
}
void NDE_Scanner_Search(nde_scanner_t s, const char *search_term)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
scanner->Search(search_term);
}
const char *NDE_Scanner_GetLastQuery(nde_scanner_t s)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
return scanner->GetLastQuery();
else
return 0;
}
int NDE_Scanner_GetRecordsCount(nde_scanner_t s)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
return scanner->GetRecordsCount();
else
return 0;
}
void NDE_Scanner_New(nde_scanner_t s)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
scanner->New();
}
void NDE_Scanner_Post(nde_scanner_t s)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
scanner->Post();
}
void NDE_Scanner_First(nde_scanner_t s, int *killswitch)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
scanner->First(killswitch);
}
void NDE_Scanner_Delete(nde_scanner_t s)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
scanner->Delete();
}
void NDE_Scanner_Edit(nde_scanner_t s)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
scanner->Edit();
}
int NDE_Scanner_EOF(nde_scanner_t s)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
return scanner->Eof();
else
return 1;
}
int NDE_Scanner_BOF(nde_scanner_t s)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
return scanner->Bof();
else
return 1;
}
nde_field_t NDE_Scanner_NewFieldByID(nde_scanner_t s, unsigned char id)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
return (nde_field_t)scanner->NewFieldById(id, PERM_READWRITE);
else
return 0;
}
nde_field_t NDE_Scanner_NewFieldByName(nde_scanner_t s, const char *name)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
return (nde_field_t)scanner->NewFieldByName(name, PERM_READWRITE);
else
return 0;
}
nde_field_t NDE_Scanner_GetFieldByID(nde_scanner_t s, unsigned char id)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
return (nde_field_t)scanner->GetFieldById(id);
else
return 0;
}
nde_field_t NDE_Scanner_GetFieldByName(nde_scanner_t s, const char *name)
{
Scanner *scanner = (Scanner *)s;
if (scanner && name)
return (nde_field_t)scanner->GetFieldByName(name);
else
return 0;
}
void NDE_Scanner_AddFilterByID(nde_scanner_t s, unsigned char id, nde_field_t f, unsigned char filter_operation)
{
Scanner *scanner = (Scanner *)s;
Field *field = (Field *)f;
if (scanner && field)
scanner->AddFilterById(id, field, filter_operation);
}
int NDE_Scanner_LocateInteger(nde_scanner_t s, unsigned char id, int from, int value, int *nskip, int compare_mode)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
{
IntegerField field(value);
return scanner->LocateByIdEx(id, from, &field, nskip, compare_mode);
}
else
return 0;
}
int NDE_Scanner_LocateString(nde_scanner_t s, unsigned char id, int from, const char *value, int *nskip, int compare_mode)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
{
StringField field(value);
return scanner->LocateByIdEx(id, from, &field, nskip, compare_mode);
}
else
return 0;
}
int NDE_Scanner_LocateNDEString(nde_scanner_t s, unsigned char id, int from, char *value, int *nskip, int compare_mode)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
{
StringField field(value, STRING_IS_NDESTRING);
return scanner->LocateByIdEx(id, from, &field, nskip, compare_mode);
}
else
return 0;
}
int NDE_Scanner_LocateFilename(nde_scanner_t s, unsigned char id, int from, const char *value, int *nskip, int compare_mode)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
{
FilenameField field(value);
return scanner->LocateByIdEx(id, from, &field, nskip, compare_mode);
}
else
return 0;
}
int NDE_Scanner_LocateNDEFilename(nde_scanner_t s, unsigned char id, int from, char *value, int *nskip, int compare_mode)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
{
FilenameField field(value, STRING_IS_NDESTRING);
return scanner->LocateByIdEx(id, from, &field, nskip, compare_mode);
}
else
return 0;
}
int NDE_Scanner_LocateField(nde_scanner_t s, unsigned char id, int from, nde_field_t f, int *nskip, int compare_mode)
{
Scanner *scanner = (Scanner *)s;
Field *field = (Field *)f;
if (scanner && field)
{
return scanner->LocateByIdEx(id, from, field, nskip, compare_mode);
}
else
return 0;
}
void NDE_Scanner_DeleteField(nde_scanner_t s, nde_field_t f)
{
Scanner *scanner = (Scanner *)s;
Field *field = (Field *)f;
if (scanner && field)
{
scanner->DeleteField(field);
}
}
void NDE_Scanner_RemoveFilters(nde_scanner_t s)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
scanner->RemoveFilters();
}
int NDE_Scanner_Next(nde_scanner_t s, int *killswitch)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
return scanner->Next(killswitch);
else
return 0;
}
/* Filter functions */
unsigned char NDE_Filter_GetID(nde_filter_t f)
{
Filter *filter = (Filter *)f;
if (filter)
return filter->GetId();
else
return FILTERS_INVALID; // right value but I'm not sure if it's the best constant name to use
}
NDE_API unsigned char NDE_Filter_GetOp(nde_filter_t f)
{
Filter *filter = (Filter *)f;
if (filter)
return filter->GetOp();
else
return FILTERS_INVALID; // right value but I'm not sure if it's the best constant name to use
}
NDE_API nde_field_t NDE_Filter_GetData(nde_filter_t f)
{
Filter *filter = (Filter *)f;
if (filter)
return (nde_field_t)filter->Data();
else
return 0;
}
/* Field functions */
unsigned char NDE_Field_GetType(nde_field_t f)
{
Field *field = (Field *)f;
if (field)
return field->GetType();
else
return FIELD_UNKNOWN;
}
unsigned char NDE_Field_GetID(nde_field_t f)
{
Field *field = (Field *)f;
if (field)
return field->GetFieldId();
else
return FIELD_UNKNOWN;
}
/* StringField functions */
void NDE_StringField_SetNDEString(nde_field_t f, char *nde_string)
{
StringField *field = (StringField *)(Field *)f;
if (field)
field->SetNDEString(nde_string);
}
char *NDE_StringField_GetString(nde_field_t f)
{
StringField *field = (StringField *)(Field *)f;
if (field)
return field->GetString();
else
return 0;
}
void NDE_StringField_SetString(nde_field_t f, const char *str)
{
StringField *field = (StringField *)(Field *)f;
if (field)
field->SetString(str);
}
/* IntegerField functions */
void NDE_IntegerField_SetValue(nde_field_t f, int value)
{
IntegerField *field = (IntegerField *)(Field *)f;
if (field)
field->SetValue(value);
}
int NDE_IntegerField_GetValue(nde_field_t f)
{
IntegerField *field = (IntegerField *)(Field *)f;
if (field)
return field->GetValue();
else
return 0;
}
nde_field_t NDE_IntegerField_Create(int value)
{
return (nde_field_t)new IntegerField(value);
}
/* BinaryField */
void *NDE_BinaryField_GetData(nde_field_t f, size_t *length)
{
BinaryField *field = (BinaryField *)(Field *)f;
if (field)
return (void *)field->GetData(length);
else
return 0;
}
void NDE_BinaryField_SetData(nde_field_t f, const void *data, size_t length)
{
BinaryField *field = (BinaryField *)(Field *)f;
if (field)
field->SetData((const uint8_t *)data, length);
}
/* Int128Field */
void NDE_Int128Field_SetValue(nde_field_t f, const void *value)
{
Int128Field *field = (Int128Field *)(Field *)f;
if (field && value)
field->SetValue(value);
}
/* ColumnField */
const char *NDE_ColumnField_GetFieldName(nde_field_t f)
{
ColumnField *field = (ColumnField *)(Field *)f;
if (field)
return field->GetFieldName();
else
return 0;
}
unsigned char NDE_ColumnField_GetDataType(nde_field_t f)
{
ColumnField *field = (ColumnField *)(Field *)f;
if (field)
return field->GetDataType();
else
return FIELD_UNKNOWN;
}

122
Src/nde/android/nde_c.h Normal file
View file

@ -0,0 +1,122 @@
#pragma once
/* C style API.
We'll eventually deprecate the C++ API as it presents a lot of linking challenges
*/
#include "../nde_defines.h"
#include "../NDEString.h"
#include <foundation/types.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct nde_database_struct_t { } *nde_database_t;
typedef struct nde_table_struct_t { } *nde_table_t;
typedef struct nde_scanner_t_struct_t { } *nde_scanner_t;
typedef struct nde_field_t_struct_t { } *nde_field_t;
typedef struct nde_filter_struct_t { } *nde_filter_t;
/* Database functions */
NDE_API void NDE_Init();
NDE_API void NDE_Quit();
NDE_API nde_database_t NDE_CreateDatabase();
NDE_API void NDE_DestroyDatabase(nde_database_t db);
NDE_API nde_table_t NDE_Database_OpenTable(nde_database_t db, const char *filename, const char *filename_index, int create, int cache);
NDE_API void NDE_Database_CloseTable(nde_database_t db, nde_table_t table);
/* Table functions */
NDE_API nde_field_t NDE_Table_NewColumn(nde_table_t table, unsigned char id, const char *name, unsigned char type);
NDE_API void NDE_Table_PostColumns(nde_table_t table);
NDE_API void NDE_Table_AddIndexByID(nde_table_t table, unsigned char id, const char *name);
NDE_API nde_scanner_t NDE_Table_CreateScanner(nde_table_t table);
NDE_API void NDE_Table_DestroyScanner(nde_table_t table, nde_scanner_t scanner);
NDE_API void NDE_Table_Sync(nde_table_t table);
#ifdef __cplusplus
NDE_API void NDE_Table_Compact(nde_table_t table, int *progress=0);
#else
NDE_API void NDE_Table_Compact(nde_table_t table, int *progress);
#endif
NDE_API int NDE_Table_GetRecordsCount(nde_table_t table);
NDE_API nde_field_t NDE_Table_GetColumnByID(nde_table_t table, unsigned char id);
NDE_API nde_field_t NDE_Table_GetColumnByName(nde_table_t table, const char *name);
NDE_API void NDE_Table_SetColumnSearchableByID(nde_table_t table, unsigned char id, int searchable);
/* Scanner functions */
NDE_API int NDE_Scanner_Query(nde_scanner_t scanner, const char *query);
NDE_API void NDE_Scanner_Search(nde_scanner_t scanner, const char *search_term);
NDE_API const char *NDE_Scanner_GetLastQuery(nde_scanner_t scanner);
NDE_API int NDE_Scanner_GetRecordsCount(nde_scanner_t scanner);
NDE_API void NDE_Scanner_New(nde_scanner_t scanner);
NDE_API void NDE_Scanner_Post(nde_scanner_t scanner);
#ifdef __cplusplus
NDE_API void NDE_Scanner_First(nde_scanner_t scanner, int *killswitch=0);
NDE_API int NDE_Scanner_Next(nde_scanner_t scanner, int *killswitch=0);
#else
NDE_API void NDE_Scanner_First(nde_scanner_t scanner, int *killswitch);
NDE_API int NDE_Scanner_Next(nde_scanner_t scanner, int *killswitch);
#endif
NDE_API void NDE_Scanner_Delete(nde_scanner_t scanner);
NDE_API void NDE_Scanner_Edit(nde_scanner_t scanner);
NDE_API int NDE_Scanner_EOF(nde_scanner_t scanner);
NDE_API int NDE_Scanner_BOF(nde_scanner_t scanner);
NDE_API nde_field_t NDE_Scanner_NewFieldByID(nde_scanner_t scanner, unsigned char id);
NDE_API nde_field_t NDE_Scanner_NewFieldByName(nde_scanner_t scanner, const char *name);
NDE_API nde_field_t NDE_Scanner_GetFieldByID(nde_scanner_t scanner, unsigned char id);
NDE_API nde_field_t NDE_Scanner_GetFieldByName(nde_scanner_t scanner, const char *name);
NDE_API void NDE_Scanner_AddFilterByID(nde_scanner_t scanner, unsigned char id, nde_field_t field, unsigned char filter_operation);
#ifdef __cplusplus
NDE_API int NDE_Scanner_LocateInteger(nde_scanner_t scanner, unsigned char id, int from, int value, int *nskip=0, int compare_mode=COMPARE_MODE_EXACT);
NDE_API int NDE_Scanner_LocateString(nde_scanner_t scanner, unsigned char id, int from, const char *value, int *nskip=0, int compare_mode=COMPARE_MODE_EXACT);
NDE_API int NDE_Scanner_LocateNDEString(nde_scanner_t scanner, unsigned char id, int from, char *value, int *nskip=0, int compare_mode=COMPARE_MODE_EXACT);
NDE_API int NDE_Scanner_LocateFilename(nde_scanner_t scanner, unsigned char id, int from, const char *value, int *nskip=0, int compare_mode=COMPARE_MODE_EXACT);
NDE_API int NDE_Scanner_LocateNDEFilename(nde_scanner_t scanner, unsigned char id, int from, char *value, int *nskip=0, int compare_mode=COMPARE_MODE_EXACT);
NDE_API int NDE_Scanner_LocateField(nde_scanner_t scanner, unsigned char id, int from, nde_field_t field, int *nskip=0, int compare_mode=COMPARE_MODE_EXACT);
#else
NDE_API int NDE_Scanner_LocateInteger(nde_scanner_t scanner, unsigned char id, int from, int value, int *nskip, int compare_mode);
NDE_API int NDE_Scanner_LocateString(nde_scanner_t scanner, unsigned char id, int from, const char *value, int *nskip, int compare_mode);
NDE_API int NDE_Scanner_LocateNDEString(nde_scanner_t scanner, unsigned char id, int from, char *value, int *nskip, int compare_mode);
NDE_API int NDE_Scanner_LocateFilename(nde_scanner_t scanner, unsigned char id, int from, const char *value, int *nskip, int compare_mode);
NDE_API int NDE_Scanner_LocateNDEFilename(nde_scanner_t scanner, unsigned char id, int from, char *value, int *nskip, int compare_mode);
NDE_API int NDE_Scanner_LocateField(nde_scanner_t scanner, unsigned char id, int from, nde_field_t field, int *nskip, int compare_mode);
#endif
NDE_API void NDE_Scanner_DeleteField(nde_scanner_t scanner, nde_field_t field);
NDE_API void NDE_Scanner_RemoveFilters(nde_scanner_t scanner);
/* Filter functions */
NDE_API unsigned char NDE_Filter_GetID(nde_filter_t filter);
NDE_API unsigned char NDE_Filter_GetOp(nde_filter_t filter);
NDE_API nde_field_t NDE_Filter_GetData(nde_filter_t filter);
/* Field functions */
NDE_API unsigned char NDE_Field_GetType(nde_field_t field);
NDE_API unsigned char NDE_Field_GetID(nde_field_t field);
/* String Field functions */
NDE_API char *NDE_StringField_GetString(nde_field_t field); /* returns non-const because it's an NDE string (reference counted, see ndestring.h) */
NDE_API void NDE_StringField_SetNDEString(nde_field_t field, char *nde_string);
NDE_API void NDE_StringField_SetString(nde_field_t field, const char *str);
/* IntegerField functions */
NDE_API void NDE_IntegerField_SetValue(nde_field_t field, int value);
NDE_API int NDE_IntegerField_GetValue(nde_field_t field);
NDE_API nde_field_t NDE_IntegerField_Create(int value); /* mainly used for NDE_Scanner_AddFilterByID */
/* BinaryField functions */
// on windows, the data pointer is optionally reference counted via ndestring (ndestring_retain if you plan on keeping it)
NDE_API void *NDE_BinaryField_GetData(nde_field_t field, size_t *length);
NDE_API void NDE_BinaryField_SetData(nde_field_t field, const void *data, size_t length);
/* Int128Field functions */
NDE_API void NDE_Int128Field_SetValue(nde_field_t field, const void *value);
/* ColumnField functions */
NDE_API const char *NDE_ColumnField_GetFieldName(nde_field_t field);
NDE_API unsigned char NDE_ColumnField_GetDataType(nde_field_t field);
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,12 @@
#include "../nde_c.h"
/* NDE_Init isn't thread safe, be aware
best to call on the main thread during initialization
*/
void NDE_Init()
{
}
void NDE_Quit()
{
}

48
Src/nde/android/record.h Normal file
View file

@ -0,0 +1,48 @@
#pragma once
/*
android (linux) implementation
*/
#include "../field.h"
#include "Vfs.h"
#include <stdio.h>
class ColumnField;
class RecordBase
{
public:
RecordBase();
virtual ~RecordBase();
Field *GetField(unsigned char ID);
void Retain();
void Release();
void RemoveField(Field *field);
void AddField(Field *field);
protected:
void Undelete(void);
int InsertionPoint; // TODO: benski> might be able to pass this into WriteFields/WriteIndex
int ref_count;
typedef nu::PtrDeque2<Field> FieldList;
FieldList Fields;
};
class Record : public RecordBase
{
public:
Record(int RecordPos, int insertionPoint, VFILE *FileHandle,Table *p);
bool InCache() { return ref_count > 1; }
ColumnField *GetColumnByName(const char *name);
int WriteFields(Table *ParentTable, int RecordIndex);
int WriteIndex(Table *ParentTable, int RecordIndex);
void Delete(Table *ParentTable, int RecordIndex);
typedef bool (*FieldsWalker)(Record *record, Field *entry, void *context);
void WalkFields(FieldsWalker callback, void *context);
};

67
Src/nde/android/vfs.h Normal file
View file

@ -0,0 +1,67 @@
#ifndef __NDE_VFS_H
#define __NDE_VFS_H
#include <foundation/types.h>
#include <stdio.h>
//#define NDE_ALLOW_NONCACHED
/*
#ifdef NDE_ALLOW_NONCACHED
#ifndef NDE_NOWIN32FILEIO
#error NDE_ALLOW_NONCACHED at least for now requires NDE_NOWIN32FILEIO
#endif
#endif
*/
#define VFILE_INC 65536
#define VFS_READ 1
#define VFS_WRITE 2
#define VFS_SEEKEOF 4
#define VFS_CREATE 8
#define VFS_NEWCONTENT 16
#define VFS_MUSTEXIST 32
typedef struct {
uint8_t *data;
unsigned long ptr;
unsigned long filesize;
unsigned long maxsize;
char *filename;
char mode;
int cached;
int dirty;
#ifdef NDE_ALLOW_NONCACHED
FILE *rfile;
#endif
FILE *lockFile;
char lockname[1024];
int locks;
} VFILE;
#ifdef __cplusplus
extern "C" {
#endif
VFILE *Vfnew(const char *fl, const char *mode, int Cached);
VFILE *Vfopen(VFILE *f, const char *fl, const char *mode, int Cached);
size_t Vfread(void *ptr, size_t size, VFILE *buf);
void Vfseek(VFILE *fl, long i, int whence);
unsigned long Vftell(VFILE *fl);
void Vfclose(VFILE *fl);
void Vfdestroy(VFILE *fl); // benski> TODO:
void Vfwrite(const void *ptr, size_t size, VFILE *f);
int Vfeof(VFILE *fl);
int Vsync(VFILE *fl); // 1 on error updating
int Vflock(VFILE *fl, bool is_sync=true); // returns 0 on failure
void Vfunlock(VFILE *fl, bool is_sync=true);
#ifdef __cplusplus
}
#endif
#endif

33
Src/nde/nde.def Normal file
View file

@ -0,0 +1,33 @@
EXPORTS
LinkedListEntry
LinkedList
Field
ColumnField
~ColumnField
Compare
ColumnField::GetDataType
ColumnField::Compare
ColumnField::GetFieldName
ColumnField::GetUniqueDataScanner
ColumnField::NewScanner
ColumnField::DeleteScanner
ColumnField::GetUnique
IndexField
StringField
IntegerField
GUIDField
FloatField
BooleanField
BinaryField
BitmapField
PrivateField
Record
Scanner
Table
Index
Filter
Database
~Database
Database
OpenTable
NdeApi

168
Src/nde/nde.h Normal file
View file

@ -0,0 +1,168 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine - Codename: Neutrino
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
Global Include File
--------------------------------------------------------------------------- */
#ifndef __NDE_H
#define __NDE_H
// TODO: find better Mac preproc symbol
#include "nde_defines.h"
extern const char *tSign;
extern const char *iSign;
// Magic headers
#define __TABLE_SIGNATURE__ tSign
#define __INDEX_SIGNATURE__ iSign
// Linked list entry types
#define UNKNOWN 0
#define FIELD 1
#define FILTER 2
#define SCANNER 3
// Records constants
#define NEW_RECORD -128
#define FIELD_NOT_FOUND -1
#define INVALID_RECORD -1
#define NUM_SPECIAL_RECORDS 2 //
#define FIELDS_RECORD_NUM 0
#define INDEX_RECORD_NUM 1
// Index constants
#define PRIMARY_INDEX 255
#define QFIND_ENTIRE_SCOPE -1
#define throwException(x) {}
#define FILTER_NOT 0
#define FILTER_AND 1
#define FILTER_OR 2
#define FILTERS_INVALID -1
#define FILTERS_INCOMPLETE 1
#define FILTERS_COMPLETE 1
#define ADDFILTER_FAILED 2
// Permissions
#define PERM_DENYALL 0
#define PERM_READ 1
#define PERM_READWRITE 3
// All our classes so we can foreward reference
class NDE_API LinkedListEntry;
class LinkedList;
class Field;
class ColumnField;
class IndexField;
class StringField;
class IntegerField;
class Int64Field;
class Int128Field;
class GUIDField;
class FloatField;
class BooleanField;
class BinaryField;
class Binary32Field;
class BitmapField;
class PrivateField;
class FilenameField;
class Record;
class NDE_API Scanner;
class Table;
class Index;
class Filter;
class Database;
#if !defined (WIN32) && !defined(WIN64)
#define NDE_NOWIN32FILEIO
#define NO_TABLE_WIN32_LOCKING
typedef int BOOL;
typedef void* HANDLE;
#define TRUE 1
#define FALSE 0
#ifdef __APPLE__
#include <bfc/platform/types.h>
#else
#include <foundation/types.h> // TODO
#endif
#define HINSTANCE int
//#define HWND int
#define DWORD int
#define wsprintf sprintf
#define OutputDebugString(x) ;
#define GetCurrentProcessId() getpid()
#include <stdlib.h>
#include <ctype.h>
#include <strings.h>
#include <string.h>
#include <wchar.h>
#include <sys/stat.h>
void clear_stdin(void);
void CopyFile(const char *filename, const char *destfilename, BOOL b);
void DeleteFile(const char *filename);
BOOL MoveFile(const char *filename, const char *destfilename);
void Sleep(int ms);
#define _stricmp strcasecmp
#define strcmpi strcasecmp
#define _strnicmp strncasecmp
#define strncmpi strncasecmp
#define _wtoi(x) wcstol(x,0,10)
// TODO: find case insensitive compare on Mac OS X
#define _wcsicmp wcscmp
#define _wcsnicmp wcsncmp
#define _MAX_PATH 8192
#define _MAX_DRIVE 256
#define _MAX_DIR 7424
#define _MAX_FNAME 256
#define _MAX_EXT 256
#define min(x,y) ((x > y) ? y : x)
#define max(x,y) ((x < y) ? y : x)
#endif
// All our includes+
#include "Vfs.h"
#include "LinkedList.h"
#include "Field.h"
#include "ColumnField.h"
#include "IndexField.h"
#include "StringField.h"
#include "IntegerField.h"
#include "Int64Field.h"
#include "Int128Field.h"
#include "BinaryField.h"
#include "Binary32Field.h"
#include "FilenameField.h"
#include "Record.h"
#include "Scanner.h"
#include "Table.h"
#include "Database.h"
#include "Index.h"
#include "Filter.h"
#include "DBUtils.h"
#endif

76
Src/nde/nde.rc Normal file
View file

@ -0,0 +1,76 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// English (U.K.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"#include ""version.rc2""\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#endif // English (U.K.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
#include "version.rc2"
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

77
Src/nde/nde.sln Normal file
View file

@ -0,0 +1,77 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29509.3
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nde", "nde.vcxproj", "{4D25C321-7F8B-424E-9899-D80A364BAF1A}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nx", "..\replicant\nx\nx.vcxproj", "{57C90706-B25D-4ACA-9B33-95CDB2427C27}"
ProjectSection(ProjectDependencies) = postProject
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A} = {0F9730E4-45DA-4BD2-A50A-403A4BC9751A}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nu", "..\replicant\nu\nu.vcxproj", "{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jnetlib", "..\replicant\jnetlib\jnetlib.vcxproj", "{E105A0A2-7391-47C5-86AC-718003524C3D}"
ProjectSection(ProjectDependencies) = postProject
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A} = {0F9730E4-45DA-4BD2-A50A-403A4BC9751A}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "..\replicant\zlib\zlib.vcxproj", "{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{4D25C321-7F8B-424E-9899-D80A364BAF1A}.Debug|Win32.ActiveCfg = Debug|Win32
{4D25C321-7F8B-424E-9899-D80A364BAF1A}.Debug|Win32.Build.0 = Debug|Win32
{4D25C321-7F8B-424E-9899-D80A364BAF1A}.Debug|x64.ActiveCfg = Debug|x64
{4D25C321-7F8B-424E-9899-D80A364BAF1A}.Debug|x64.Build.0 = Debug|x64
{4D25C321-7F8B-424E-9899-D80A364BAF1A}.Release|Win32.ActiveCfg = Release|Win32
{4D25C321-7F8B-424E-9899-D80A364BAF1A}.Release|Win32.Build.0 = Release|Win32
{4D25C321-7F8B-424E-9899-D80A364BAF1A}.Release|x64.ActiveCfg = Release|x64
{4D25C321-7F8B-424E-9899-D80A364BAF1A}.Release|x64.Build.0 = Release|x64
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Debug|Win32.ActiveCfg = Debug|Win32
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Debug|Win32.Build.0 = Debug|Win32
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Debug|x64.ActiveCfg = Debug|x64
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Debug|x64.Build.0 = Debug|x64
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Release|Win32.ActiveCfg = Release|Win32
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Release|Win32.Build.0 = Release|Win32
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Release|x64.ActiveCfg = Release|x64
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Release|x64.Build.0 = Release|x64
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Debug|Win32.ActiveCfg = Debug|Win32
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Debug|Win32.Build.0 = Debug|Win32
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Debug|x64.ActiveCfg = Debug|x64
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Debug|x64.Build.0 = Debug|x64
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Release|Win32.ActiveCfg = Release|Win32
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Release|Win32.Build.0 = Release|Win32
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Release|x64.ActiveCfg = Release|x64
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Release|x64.Build.0 = Release|x64
{E105A0A2-7391-47C5-86AC-718003524C3D}.Debug|Win32.ActiveCfg = Debug|Win32
{E105A0A2-7391-47C5-86AC-718003524C3D}.Debug|Win32.Build.0 = Debug|Win32
{E105A0A2-7391-47C5-86AC-718003524C3D}.Debug|x64.ActiveCfg = Debug|x64
{E105A0A2-7391-47C5-86AC-718003524C3D}.Debug|x64.Build.0 = Debug|x64
{E105A0A2-7391-47C5-86AC-718003524C3D}.Release|Win32.ActiveCfg = Release|Win32
{E105A0A2-7391-47C5-86AC-718003524C3D}.Release|Win32.Build.0 = Release|Win32
{E105A0A2-7391-47C5-86AC-718003524C3D}.Release|x64.ActiveCfg = Release|x64
{E105A0A2-7391-47C5-86AC-718003524C3D}.Release|x64.Build.0 = Release|x64
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Debug|Win32.ActiveCfg = Debug|Win32
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Debug|Win32.Build.0 = Debug|Win32
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Debug|x64.ActiveCfg = Debug|x64
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Debug|x64.Build.0 = Debug|x64
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Release|Win32.ActiveCfg = Release|Win32
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Release|Win32.Build.0 = Release|Win32
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Release|x64.ActiveCfg = Release|x64
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C4E799C1-027B-487B-8E1A-31F2D26A1AFE}
EndGlobalSection
EndGlobal

321
Src/nde/nde.vcxproj Normal file
View file

@ -0,0 +1,321 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{4D25C321-7F8B-424E-9899-D80A364BAF1A}</ProjectGuid>
<RootNamespace>nde</RootNamespace>
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Label="Vcpkg">
<VcpkgEnableManifest>false</VcpkgEnableManifest>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgConfiguration>Debug</VcpkgConfiguration>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
<VcpkgConfiguration>Debug</VcpkgConfiguration>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>../Wasabi;../replicant;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;NDE_EXPORTS;_WIN32_WINNT=0x601;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ImportLibrary>$(ProjectDir)x86_Debug\$(ProjectName).lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\
xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>../Wasabi;../replicant;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN64;_DEBUG;_WINDOWS;_USRDLL;NDE_EXPORTS;_WIN32_WINNT=0x601;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ImportLibrary>$(ProjectDir)x64_Debug\$(ProjectName).lib</ImportLibrary>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\
xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MinSpace</Optimization>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<AdditionalIncludeDirectories>../Wasabi;../replicant;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;NDE_EXPORTS;_WIN32_WINNT=0x601;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<BufferSecurityCheck>false</BufferSecurityCheck>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<DisableSpecificWarnings>4244;4018;4355;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>false</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ImportLibrary>$(ProjectDir)x86_Release\$(ProjectName).lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<Optimization>MinSpace</Optimization>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<AdditionalIncludeDirectories>../Wasabi;../replicant;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;_USRDLL;NDE_EXPORTS;_WIN32_WINNT=0x601;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<BufferSecurityCheck>false</BufferSecurityCheck>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<DisableSpecificWarnings>4244;4018;4355;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>false</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ImportLibrary>$(ProjectDir)x64_Release\$(ProjectName).lib</ImportLibrary>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ProjectReference Include="..\replicant\nx\nx.vcxproj">
<Project>{57c90706-b25d-4aca-9b33-95cdb2427c27}</Project>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include="..\Wasabi\Wasabi.vcxproj">
<Project>{3e0bfa8a-b86a-42e9-a33f-ec294f823f7f}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\nu\RingBuffer.cpp" />
<ClCompile Include="Database.cpp" />
<ClCompile Include="DBUtils.cpp" />
<ClCompile Include="Field.cpp" />
<ClCompile Include="Filter.cpp" />
<ClCompile Include="Index.cpp" />
<ClCompile Include="Int128Field.cpp" />
<ClCompile Include="Int64Field.cpp" />
<ClCompile Include="LinkedList.cpp" />
<ClCompile Include="NDEString.cpp" />
<ClCompile Include="win\Binary32Field.cpp" />
<ClCompile Include="win\BinaryField.cpp" />
<ClCompile Include="win\ColumnField.cpp" />
<ClCompile Include="win\FilenameField.cpp" />
<ClCompile Include="win\IndexField.cpp" />
<ClCompile Include="win\IndexRecord.cpp" />
<ClCompile Include="win\IntegerField.cpp" />
<ClCompile Include="win\nde_c.cpp" />
<ClCompile Include="win\nde_init.cpp" />
<ClCompile Include="win\Query.cpp" />
<ClCompile Include="win\Record.cpp" />
<ClCompile Include="win\Scanner.cpp" />
<ClCompile Include="win\StringField.cpp" />
<ClCompile Include="win\Table.cpp" />
<ClCompile Include="win\Vfs.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="Database.h" />
<ClInclude Include="DBUtils.h" />
<ClInclude Include="Field.h" />
<ClInclude Include="Filter.h" />
<ClInclude Include="Index.h" />
<ClInclude Include="Int128Field.h" />
<ClInclude Include="Int64Field.h" />
<ClInclude Include="LinkedList.h" />
<ClInclude Include="nde.h" />
<ClInclude Include="NDEString.h" />
<ClInclude Include="nde_defines.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="win\Binary32Field.h" />
<ClInclude Include="win\BinaryField.h" />
<ClInclude Include="win\ColumnField.h" />
<ClInclude Include="win\FilenameField.h" />
<ClInclude Include="win\IndexField.h" />
<ClInclude Include="win\IndexRecord.h" />
<ClInclude Include="win\IntegerField.h" />
<ClInclude Include="win\nde_c.h" />
<ClInclude Include="win\Query.h" />
<ClInclude Include="win\Record.h" />
<ClInclude Include="win\Scanner.h" />
<ClInclude Include="win\StringField.h" />
<ClInclude Include="win\Table.h" />
<ClInclude Include="win\Vfs.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="nde.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

176
Src/nde/nde.vcxproj.filters Normal file
View file

@ -0,0 +1,176 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="win\Binary32Field.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="win\BinaryField.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="win\ColumnField.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Database.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DBUtils.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Field.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="win\FilenameField.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Filter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Index.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="win\IndexField.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="win\IndexRecord.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Int64Field.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Int128Field.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="win\IntegerField.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="LinkedList.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="win\nde_c.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="win\nde_init.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="NDEString.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="win\Query.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="win\Record.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\nu\RingBuffer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="win\Scanner.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="win\StringField.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="win\Table.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="win\Vfs.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="win\Binary32Field.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="win\BinaryField.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="win\ColumnField.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Database.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DBUtils.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Field.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="win\FilenameField.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Filter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Index.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="win\IndexField.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="win\IndexRecord.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Int64Field.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Int128Field.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="win\IntegerField.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="LinkedList.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="nde.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="win\nde_c.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="nde_defines.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="NDEString.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="win\Query.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="win\Record.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="win\Scanner.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="win\StringField.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="win\Table.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="win\Vfs.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="Header Files">
<UniqueIdentifier>{9547ac55-c20b-484a-875b-0e9f6787c1f9}</UniqueIdentifier>
</Filter>
<Filter Include="Ressource Files">
<UniqueIdentifier>{4278bf6e-44fa-4a76-a1e7-f3d3c96d4df0}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files">
<UniqueIdentifier>{e61e1158-723a-449b-b09f-bd63c3c611a7}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="nde.rc">
<Filter>Ressource Files</Filter>
</ResourceCompile>
</ItemGroup>
</Project>

View file

@ -0,0 +1,427 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 42;
objects = {
/* Begin PBXBuildFile section */
0C0879F512A2D8AC001B1FD2 /* NDEString.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C0879F412A2D8AC001B1FD2 /* NDEString.h */; };
0C087AB412A2DB4C001B1FD2 /* IndexRecord.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C087AB212A2DB4C001B1FD2 /* IndexRecord.cpp */; };
0C087AB512A2DB4C001B1FD2 /* IndexRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C087AB312A2DB4C001B1FD2 /* IndexRecord.h */; };
0C087AC312A2DB85001B1FD2 /* nde_c.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C087AC012A2DB85001B1FD2 /* nde_c.cpp */; };
0C087AC412A2DB85001B1FD2 /* nde_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C087AC112A2DB85001B1FD2 /* nde_c.h */; };
0C087AC512A2DB85001B1FD2 /* nde_defines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C087AC212A2DB85001B1FD2 /* nde_defines.h */; };
0C087BCA12A2E962001B1FD2 /* Field.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C087BB612A2E962001B1FD2 /* Field.cpp */; };
0C087BCB12A2E962001B1FD2 /* Field.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C087BB712A2E962001B1FD2 /* Field.h */; };
0C087BD012A2E962001B1FD2 /* Int64Field.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C087BBC12A2E962001B1FD2 /* Int64Field.cpp */; };
0C087BD112A2E962001B1FD2 /* Int64Field.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C087BBD12A2E962001B1FD2 /* Int64Field.h */; };
0C087BD212A2E962001B1FD2 /* Int128Field.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C087BBE12A2E962001B1FD2 /* Int128Field.cpp */; };
0C087BD312A2E962001B1FD2 /* Int128Field.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C087BBF12A2E962001B1FD2 /* Int128Field.h */; };
0C89CB7912A5EFFA00366857 /* IndexField.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C89CB7712A5EFFA00366857 /* IndexField.cpp */; };
0C89CB7A12A5EFFA00366857 /* IndexField.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C89CB7812A5EFFA00366857 /* IndexField.h */; };
0C99F2380B93CE4C00AB7751 /* Crc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C99F2140B93CE4C00AB7751 /* Crc.cpp */; };
0C99F2390B93CE4C00AB7751 /* CRC.H in Headers */ = {isa = PBXBuildFile; fileRef = 0C99F2150B93CE4C00AB7751 /* CRC.H */; };
0C99F23A0B93CE4C00AB7751 /* Database.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C99F2160B93CE4C00AB7751 /* Database.cpp */; };
0C99F23B0B93CE4C00AB7751 /* Database.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C99F2170B93CE4C00AB7751 /* Database.h */; };
0C99F23C0B93CE4C00AB7751 /* DBUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C99F2180B93CE4C00AB7751 /* DBUtils.cpp */; };
0C99F23D0B93CE4C00AB7751 /* DBUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C99F2190B93CE4C00AB7751 /* DBUtils.h */; };
0C99F2410B93CE4C00AB7751 /* Filter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C99F21D0B93CE4C00AB7751 /* Filter.cpp */; };
0C99F2420B93CE4C00AB7751 /* Filter.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C99F21E0B93CE4C00AB7751 /* Filter.h */; };
0C99F2430B93CE4C00AB7751 /* Index.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C99F21F0B93CE4C00AB7751 /* Index.cpp */; };
0C99F2440B93CE4C00AB7751 /* Index.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C99F2200B93CE4C00AB7751 /* Index.h */; };
0C99F2490B93CE4C00AB7751 /* LinkedList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C99F2250B93CE4C00AB7751 /* LinkedList.cpp */; };
0C99F24A0B93CE4C00AB7751 /* LinkedList.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C99F2260B93CE4C00AB7751 /* LinkedList.h */; };
0C99F24B0B93CE4C00AB7751 /* nde.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C99F2270B93CE4C00AB7751 /* nde.h */; };
0C99F24E0B93CE4C00AB7751 /* Record.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C99F22A0B93CE4C00AB7751 /* Record.cpp */; };
0C99F24F0B93CE4C00AB7751 /* Record.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C99F22B0B93CE4C00AB7751 /* Record.h */; };
0C99F2500B93CE4C00AB7751 /* Scanner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0C99F22C0B93CE4C00AB7751 /* Scanner.cpp */; };
0C99F2510B93CE4C00AB7751 /* Scanner.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C99F22D0B93CE4C00AB7751 /* Scanner.h */; };
0CBA4FEF12A5DD6D008056C7 /* Binary32Field.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0CBA4FE912A5DD6D008056C7 /* Binary32Field.cpp */; };
0CBA4FF012A5DD6D008056C7 /* Binary32Field.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CBA4FEA12A5DD6D008056C7 /* Binary32Field.h */; };
0CBA4FF112A5DD6D008056C7 /* BinaryField.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0CBA4FEB12A5DD6D008056C7 /* BinaryField.cpp */; };
0CBA4FF212A5DD6D008056C7 /* BinaryField.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CBA4FEC12A5DD6D008056C7 /* BinaryField.h */; };
0CBA4FF312A5DD6D008056C7 /* ColumnField.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0CBA4FED12A5DD6D008056C7 /* ColumnField.cpp */; };
0CBA4FF412A5DD6D008056C7 /* ColumnField.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CBA4FEE12A5DD6D008056C7 /* ColumnField.h */; };
0CBA4FF912A5DD77008056C7 /* FilenameField.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0CBA4FF512A5DD77008056C7 /* FilenameField.cpp */; };
0CBA4FFA12A5DD77008056C7 /* FilenameField.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CBA4FF612A5DD77008056C7 /* FilenameField.h */; };
0CBA4FFB12A5DD77008056C7 /* StringField.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0CBA4FF712A5DD77008056C7 /* StringField.cpp */; };
0CBA4FFC12A5DD77008056C7 /* StringField.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CBA4FF812A5DD77008056C7 /* StringField.h */; };
0CBA4FFF12A5DD80008056C7 /* Vfs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0CBA4FFD12A5DD80008056C7 /* Vfs.cpp */; };
0CBA500012A5DD80008056C7 /* Vfs.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CBA4FFE12A5DD80008056C7 /* Vfs.h */; };
0CC9A3A712A723F500BCFEA6 /* IntegerField.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0CC9A3A512A723F500BCFEA6 /* IntegerField.cpp */; };
0CC9A3A812A723F500BCFEA6 /* IntegerField.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CC9A3A612A723F500BCFEA6 /* IntegerField.h */; };
0CC9A3AB12A7240400BCFEA6 /* Table.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0CC9A3A912A7240400BCFEA6 /* Table.cpp */; };
0CC9A3AC12A7240400BCFEA6 /* Table.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CC9A3AA12A7240400BCFEA6 /* Table.h */; };
0CC9A3AF12A7240900BCFEA6 /* Query.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0CC9A3AD12A7240900BCFEA6 /* Query.cpp */; };
0CC9A3B012A7240900BCFEA6 /* Query.h in Headers */ = {isa = PBXBuildFile; fileRef = 0CC9A3AE12A7240900BCFEA6 /* Query.h */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
0C0879F412A2D8AC001B1FD2 /* NDEString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NDEString.h; sourceTree = "<group>"; };
0C087AB212A2DB4C001B1FD2 /* IndexRecord.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IndexRecord.cpp; sourceTree = "<group>"; };
0C087AB312A2DB4C001B1FD2 /* IndexRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IndexRecord.h; sourceTree = "<group>"; };
0C087AC012A2DB85001B1FD2 /* nde_c.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = nde_c.cpp; sourceTree = "<group>"; };
0C087AC112A2DB85001B1FD2 /* nde_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nde_c.h; sourceTree = "<group>"; };
0C087AC212A2DB85001B1FD2 /* nde_defines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nde_defines.h; sourceTree = "<group>"; };
0C087BB612A2E962001B1FD2 /* Field.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Field.cpp; sourceTree = "<group>"; };
0C087BB712A2E962001B1FD2 /* Field.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Field.h; sourceTree = "<group>"; };
0C087BBC12A2E962001B1FD2 /* Int64Field.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Int64Field.cpp; sourceTree = "<group>"; };
0C087BBD12A2E962001B1FD2 /* Int64Field.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Int64Field.h; sourceTree = "<group>"; };
0C087BBE12A2E962001B1FD2 /* Int128Field.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Int128Field.cpp; sourceTree = "<group>"; };
0C087BBF12A2E962001B1FD2 /* Int128Field.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Int128Field.h; sourceTree = "<group>"; };
0C89CB7712A5EFFA00366857 /* IndexField.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IndexField.cpp; path = osx/IndexField.cpp; sourceTree = "<group>"; };
0C89CB7812A5EFFA00366857 /* IndexField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IndexField.h; path = osx/IndexField.h; sourceTree = "<group>"; };
0C99F2140B93CE4C00AB7751 /* Crc.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Crc.cpp; sourceTree = "<group>"; };
0C99F2150B93CE4C00AB7751 /* CRC.H */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = CRC.H; sourceTree = "<group>"; };
0C99F2160B93CE4C00AB7751 /* Database.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Database.cpp; sourceTree = "<group>"; };
0C99F2170B93CE4C00AB7751 /* Database.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Database.h; sourceTree = "<group>"; };
0C99F2180B93CE4C00AB7751 /* DBUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DBUtils.cpp; sourceTree = "<group>"; };
0C99F2190B93CE4C00AB7751 /* DBUtils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DBUtils.h; sourceTree = "<group>"; };
0C99F21D0B93CE4C00AB7751 /* Filter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Filter.cpp; sourceTree = "<group>"; };
0C99F21E0B93CE4C00AB7751 /* Filter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Filter.h; sourceTree = "<group>"; };
0C99F21F0B93CE4C00AB7751 /* Index.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Index.cpp; sourceTree = "<group>"; };
0C99F2200B93CE4C00AB7751 /* Index.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Index.h; sourceTree = "<group>"; };
0C99F2250B93CE4C00AB7751 /* LinkedList.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LinkedList.cpp; sourceTree = "<group>"; };
0C99F2260B93CE4C00AB7751 /* LinkedList.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = LinkedList.h; sourceTree = "<group>"; };
0C99F2270B93CE4C00AB7751 /* nde.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = nde.h; sourceTree = "<group>"; };
0C99F22A0B93CE4C00AB7751 /* Record.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Record.cpp; sourceTree = "<group>"; };
0C99F22B0B93CE4C00AB7751 /* Record.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Record.h; sourceTree = "<group>"; };
0C99F22C0B93CE4C00AB7751 /* Scanner.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Scanner.cpp; sourceTree = "<group>"; };
0C99F22D0B93CE4C00AB7751 /* Scanner.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Scanner.h; sourceTree = "<group>"; };
0CBA4FE912A5DD6D008056C7 /* Binary32Field.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Binary32Field.cpp; path = osx/Binary32Field.cpp; sourceTree = "<group>"; };
0CBA4FEA12A5DD6D008056C7 /* Binary32Field.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Binary32Field.h; path = osx/Binary32Field.h; sourceTree = "<group>"; };
0CBA4FEB12A5DD6D008056C7 /* BinaryField.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BinaryField.cpp; path = osx/BinaryField.cpp; sourceTree = "<group>"; };
0CBA4FEC12A5DD6D008056C7 /* BinaryField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BinaryField.h; path = osx/BinaryField.h; sourceTree = "<group>"; };
0CBA4FED12A5DD6D008056C7 /* ColumnField.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ColumnField.cpp; path = osx/ColumnField.cpp; sourceTree = "<group>"; };
0CBA4FEE12A5DD6D008056C7 /* ColumnField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ColumnField.h; path = osx/ColumnField.h; sourceTree = "<group>"; };
0CBA4FF512A5DD77008056C7 /* FilenameField.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FilenameField.cpp; path = osx/FilenameField.cpp; sourceTree = "<group>"; };
0CBA4FF612A5DD77008056C7 /* FilenameField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FilenameField.h; path = osx/FilenameField.h; sourceTree = "<group>"; };
0CBA4FF712A5DD77008056C7 /* StringField.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringField.cpp; path = osx/StringField.cpp; sourceTree = "<group>"; };
0CBA4FF812A5DD77008056C7 /* StringField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StringField.h; path = osx/StringField.h; sourceTree = "<group>"; };
0CBA4FFD12A5DD80008056C7 /* Vfs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Vfs.cpp; path = osx/Vfs.cpp; sourceTree = "<group>"; };
0CBA4FFE12A5DD80008056C7 /* Vfs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Vfs.h; path = osx/Vfs.h; sourceTree = "<group>"; };
0CC9A3A512A723F500BCFEA6 /* IntegerField.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IntegerField.cpp; path = osx/IntegerField.cpp; sourceTree = "<group>"; };
0CC9A3A612A723F500BCFEA6 /* IntegerField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IntegerField.h; path = osx/IntegerField.h; sourceTree = "<group>"; };
0CC9A3A912A7240400BCFEA6 /* Table.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Table.cpp; path = osx/Table.cpp; sourceTree = "<group>"; };
0CC9A3AA12A7240400BCFEA6 /* Table.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Table.h; path = osx/Table.h; sourceTree = "<group>"; };
0CC9A3AD12A7240900BCFEA6 /* Query.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Query.cpp; path = osx/Query.cpp; sourceTree = "<group>"; };
0CC9A3AE12A7240900BCFEA6 /* Query.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Query.h; path = osx/Query.h; sourceTree = "<group>"; };
D2AAC046055464E500DB518D /* libnde.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libnde.a; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
D289987405E68DCB004EDB86 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
08FB7794FE84155DC02AAC07 /* nde */ = {
isa = PBXGroup;
children = (
0C087BAD12A2E93E001B1FD2 /* Fields */,
0C087ABE12A2DB7A001B1FD2 /* API */,
0C087AA212A2DB0E001B1FD2 /* Records */,
08FB7795FE84155DC02AAC07 /* Source */,
C6A0FF2B0290797F04C91782 /* Documentation */,
1AB674ADFE9D54B511CA2CBB /* Products */,
);
name = nde;
sourceTree = "<group>";
};
08FB7795FE84155DC02AAC07 /* Source */ = {
isa = PBXGroup;
children = (
0C99F2140B93CE4C00AB7751 /* Crc.cpp */,
0C99F2150B93CE4C00AB7751 /* CRC.H */,
0C99F2160B93CE4C00AB7751 /* Database.cpp */,
0C99F2170B93CE4C00AB7751 /* Database.h */,
0C99F2180B93CE4C00AB7751 /* DBUtils.cpp */,
0C99F2190B93CE4C00AB7751 /* DBUtils.h */,
0C99F21D0B93CE4C00AB7751 /* Filter.cpp */,
0C99F21E0B93CE4C00AB7751 /* Filter.h */,
0C99F21F0B93CE4C00AB7751 /* Index.cpp */,
0C99F2200B93CE4C00AB7751 /* Index.h */,
0C99F2250B93CE4C00AB7751 /* LinkedList.cpp */,
0C99F2260B93CE4C00AB7751 /* LinkedList.h */,
0CC9A3AD12A7240900BCFEA6 /* Query.cpp */,
0CC9A3AE12A7240900BCFEA6 /* Query.h */,
0C99F2270B93CE4C00AB7751 /* nde.h */,
0CC9A3A912A7240400BCFEA6 /* Table.cpp */,
0CC9A3AA12A7240400BCFEA6 /* Table.h */,
0C0879F412A2D8AC001B1FD2 /* NDEString.h */,
0C99F22C0B93CE4C00AB7751 /* Scanner.cpp */,
0C99F22D0B93CE4C00AB7751 /* Scanner.h */,
0CBA4FFD12A5DD80008056C7 /* Vfs.cpp */,
0CBA4FFE12A5DD80008056C7 /* Vfs.h */,
);
name = Source;
sourceTree = "<group>";
};
0C087AA212A2DB0E001B1FD2 /* Records */ = {
isa = PBXGroup;
children = (
0C087AB212A2DB4C001B1FD2 /* IndexRecord.cpp */,
0C087AB312A2DB4C001B1FD2 /* IndexRecord.h */,
0C99F22A0B93CE4C00AB7751 /* Record.cpp */,
0C99F22B0B93CE4C00AB7751 /* Record.h */,
);
name = Records;
sourceTree = "<group>";
};
0C087ABE12A2DB7A001B1FD2 /* API */ = {
isa = PBXGroup;
children = (
0C087AC012A2DB85001B1FD2 /* nde_c.cpp */,
0C087AC112A2DB85001B1FD2 /* nde_c.h */,
0C087AC212A2DB85001B1FD2 /* nde_defines.h */,
);
name = API;
sourceTree = "<group>";
};
0C087BAD12A2E93E001B1FD2 /* Fields */ = {
isa = PBXGroup;
children = (
0CC9A3A512A723F500BCFEA6 /* IntegerField.cpp */,
0CC9A3A612A723F500BCFEA6 /* IntegerField.h */,
0C89CB7712A5EFFA00366857 /* IndexField.cpp */,
0C89CB7812A5EFFA00366857 /* IndexField.h */,
0CBA4FE912A5DD6D008056C7 /* Binary32Field.cpp */,
0CBA4FEA12A5DD6D008056C7 /* Binary32Field.h */,
0CBA4FEB12A5DD6D008056C7 /* BinaryField.cpp */,
0CBA4FEC12A5DD6D008056C7 /* BinaryField.h */,
0CBA4FED12A5DD6D008056C7 /* ColumnField.cpp */,
0CBA4FEE12A5DD6D008056C7 /* ColumnField.h */,
0C087BB612A2E962001B1FD2 /* Field.cpp */,
0C087BB712A2E962001B1FD2 /* Field.h */,
0CBA4FF512A5DD77008056C7 /* FilenameField.cpp */,
0CBA4FF612A5DD77008056C7 /* FilenameField.h */,
0C087BBE12A2E962001B1FD2 /* Int128Field.cpp */,
0C087BBF12A2E962001B1FD2 /* Int128Field.h */,
0C087BBC12A2E962001B1FD2 /* Int64Field.cpp */,
0C087BBD12A2E962001B1FD2 /* Int64Field.h */,
0CBA4FF712A5DD77008056C7 /* StringField.cpp */,
0CBA4FF812A5DD77008056C7 /* StringField.h */,
);
name = Fields;
sourceTree = "<group>";
};
1AB674ADFE9D54B511CA2CBB /* Products */ = {
isa = PBXGroup;
children = (
D2AAC046055464E500DB518D /* libnde.a */,
);
name = Products;
sourceTree = "<group>";
};
C6A0FF2B0290797F04C91782 /* Documentation */ = {
isa = PBXGroup;
children = (
);
name = Documentation;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
D2AAC043055464E500DB518D /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
0C99F2390B93CE4C00AB7751 /* CRC.H in Headers */,
0C99F23B0B93CE4C00AB7751 /* Database.h in Headers */,
0C99F23D0B93CE4C00AB7751 /* DBUtils.h in Headers */,
0C99F2420B93CE4C00AB7751 /* Filter.h in Headers */,
0C99F2440B93CE4C00AB7751 /* Index.h in Headers */,
0C99F24A0B93CE4C00AB7751 /* LinkedList.h in Headers */,
0C99F24B0B93CE4C00AB7751 /* nde.h in Headers */,
0C99F24F0B93CE4C00AB7751 /* Record.h in Headers */,
0C99F2510B93CE4C00AB7751 /* Scanner.h in Headers */,
0C0879F512A2D8AC001B1FD2 /* NDEString.h in Headers */,
0C087AB512A2DB4C001B1FD2 /* IndexRecord.h in Headers */,
0C087AC412A2DB85001B1FD2 /* nde_c.h in Headers */,
0C087AC512A2DB85001B1FD2 /* nde_defines.h in Headers */,
0C087BCB12A2E962001B1FD2 /* Field.h in Headers */,
0C087BD112A2E962001B1FD2 /* Int64Field.h in Headers */,
0C087BD312A2E962001B1FD2 /* Int128Field.h in Headers */,
0CBA4FF012A5DD6D008056C7 /* Binary32Field.h in Headers */,
0CBA4FF212A5DD6D008056C7 /* BinaryField.h in Headers */,
0CBA4FF412A5DD6D008056C7 /* ColumnField.h in Headers */,
0CBA4FFA12A5DD77008056C7 /* FilenameField.h in Headers */,
0CBA4FFC12A5DD77008056C7 /* StringField.h in Headers */,
0CBA500012A5DD80008056C7 /* Vfs.h in Headers */,
0C89CB7A12A5EFFA00366857 /* IndexField.h in Headers */,
0CC9A3A812A723F500BCFEA6 /* IntegerField.h in Headers */,
0CC9A3AC12A7240400BCFEA6 /* Table.h in Headers */,
0CC9A3B012A7240900BCFEA6 /* Query.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
D2AAC045055464E500DB518D /* nde */ = {
isa = PBXNativeTarget;
buildConfigurationList = 1DEB91EB08733DB70010E9CD /* Build configuration list for PBXNativeTarget "nde" */;
buildPhases = (
D2AAC043055464E500DB518D /* Headers */,
D2AAC044055464E500DB518D /* Sources */,
D289987405E68DCB004EDB86 /* Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = nde;
productName = nde;
productReference = D2AAC046055464E500DB518D /* libnde.a */;
productType = "com.apple.product-type.library.static";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject;
attributes = {
ORGANIZATIONNAME = "Nullsoft, Inc.";
};
buildConfigurationList = 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "nde" */;
compatibilityVersion = "Xcode 2.4";
developmentRegion = English;
hasScannedForEncodings = 1;
knownRegions = (
English,
Japanese,
French,
German,
);
mainGroup = 08FB7794FE84155DC02AAC07 /* nde */;
projectDirPath = "";
projectRoot = "";
targets = (
D2AAC045055464E500DB518D /* nde */,
);
};
/* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
D2AAC044055464E500DB518D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
0C99F2380B93CE4C00AB7751 /* Crc.cpp in Sources */,
0C99F23A0B93CE4C00AB7751 /* Database.cpp in Sources */,
0C99F23C0B93CE4C00AB7751 /* DBUtils.cpp in Sources */,
0C99F2410B93CE4C00AB7751 /* Filter.cpp in Sources */,
0C99F2430B93CE4C00AB7751 /* Index.cpp in Sources */,
0C99F2490B93CE4C00AB7751 /* LinkedList.cpp in Sources */,
0C99F24E0B93CE4C00AB7751 /* Record.cpp in Sources */,
0C99F2500B93CE4C00AB7751 /* Scanner.cpp in Sources */,
0C087AB412A2DB4C001B1FD2 /* IndexRecord.cpp in Sources */,
0C087AC312A2DB85001B1FD2 /* nde_c.cpp in Sources */,
0C087BCA12A2E962001B1FD2 /* Field.cpp in Sources */,
0C087BD012A2E962001B1FD2 /* Int64Field.cpp in Sources */,
0C087BD212A2E962001B1FD2 /* Int128Field.cpp in Sources */,
0CBA4FEF12A5DD6D008056C7 /* Binary32Field.cpp in Sources */,
0CBA4FF112A5DD6D008056C7 /* BinaryField.cpp in Sources */,
0CBA4FF312A5DD6D008056C7 /* ColumnField.cpp in Sources */,
0CBA4FF912A5DD77008056C7 /* FilenameField.cpp in Sources */,
0CBA4FFB12A5DD77008056C7 /* StringField.cpp in Sources */,
0CBA4FFF12A5DD80008056C7 /* Vfs.cpp in Sources */,
0C89CB7912A5EFFA00366857 /* IndexField.cpp in Sources */,
0CC9A3A712A723F500BCFEA6 /* IntegerField.cpp in Sources */,
0CC9A3AB12A7240400BCFEA6 /* Table.cpp in Sources */,
0CC9A3AF12A7240900BCFEA6 /* Query.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
1DEB91EC08733DB70010E9CD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
COPY_PHASE_STRIP = NO;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_FIX_AND_CONTINUE = YES;
GCC_MODEL_TUNING = G5;
GCC_OPTIMIZATION_LEVEL = 0;
INSTALL_PATH = /usr/local/lib;
PRODUCT_NAME = nde;
ZERO_LINK = YES;
};
name = Debug;
};
1DEB91ED08733DB70010E9CD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
GCC_MODEL_TUNING = G5;
INSTALL_PATH = /usr/local/lib;
PRODUCT_NAME = nde;
};
name = Release;
};
1DEB91F008733DB70010E9CD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
GCC_ENABLE_CPP_EXCEPTIONS = NO;
GCC_ENABLE_CPP_RTTI = NO;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = ../Wasabi;
PREBINDING = NO;
SDKROOT = /Developer/SDKs/MacOSX10.5.sdk;
};
name = Debug;
};
1DEB91F108733DB70010E9CD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_64_BIT_PRE_XCODE_3_1)";
ARCHS_STANDARD_64_BIT_PRE_XCODE_3_1 = x86_64;
GCC_ENABLE_CPP_EXCEPTIONS = NO;
GCC_ENABLE_CPP_RTTI = NO;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = ../Wasabi;
PREBINDING = NO;
SDKROOT = /Developer/SDKs/MacOSX10.5.sdk;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
1DEB91EB08733DB70010E9CD /* Build configuration list for PBXNativeTarget "nde" */ = {
isa = XCConfigurationList;
buildConfigurations = (
1DEB91EC08733DB70010E9CD /* Debug */,
1DEB91ED08733DB70010E9CD /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "nde" */ = {
isa = XCConfigurationList;
buildConfigurations = (
1DEB91F008733DB70010E9CD /* Debug */,
1DEB91F108733DB70010E9CD /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
}

8
Src/nde/nde_c.h Normal file
View file

@ -0,0 +1,8 @@
#pragma once
#ifdef __APPLE__
#include "osx/nde_c.h"
#elif defined(_WIN32)
#include "win/nde_c.h"
#elif defined(__ANDROID__)
#include "android/nde_c.h"
#endif

69
Src/nde/nde_defines.h Normal file
View file

@ -0,0 +1,69 @@
#pragma once
/* important defines and enums that are shared between the C++ api and the C api */
#define NDE_CACHE TRUE
#define NDE_NOCACHE FALSE
#define NDE_OPEN_ALWAYS TRUE
#define NDE_OPEN_EXISTING FALSE
#if defined(WIN32_NOLIB) || !defined(WIN32) && !defined(WIN64)
#define NDE_API
#else
#ifdef NDE_EXPORTS
#define NDE_API __declspec(dllexport)
#else
#define NDE_API __declspec(dllimport)
#endif
#endif
// Field types
enum
{
FIELD_COLUMN = 0,
FIELD_INDEX = 1,
FIELD_REDIRECTOR =2,
FIELD_STRING =3,
FIELD_INTEGER = 4,
FIELD_BOOLEAN = 5,
FIELD_BINARY =6, // max size 65536
FIELD_GUID =7,
FIELD_PRIVATE = 8,
FIELD_BITMAP =6,
FIELD_FLOAT = 9,
FIELD_DATETIME =10,
FIELD_LENGTH =11,
FIELD_FILENAME =12,
FIELD_INT64 = 13,
FIELD_BINARY32 =14, // binary field, but 32bit sizes instead of 16bit
FIELD_INT128 = 15, // mainly for storing MD5 hashes
FIELD_UNKNOWN = 255,
FIELD_CLONE = 255,// internal use
};
// Filter types
enum {
FILTER_NONE = 100,
FILTER_EQUALS,
FILTER_NOTEQUALS,
FILTER_CONTAINS,
FILTER_NOTCONTAINS,
FILTER_ABOVE,
FILTER_BELOW,
FILTER_ABOVEOREQUAL,
FILTER_BELOWOREQUAL,
FILTER_BEGINS,
FILTER_ENDS,
FILTER_LIKE,
FILTER_ISEMPTY,
FILTER_ISNOTEMPTY,
FILTER_BEGINSLIKE,
};
// compare modes
#define COMPARE_MODE_CONTAINS 1
#define COMPARE_MODE_EXACT 2
#define COMPARE_MODE_STARTS 3
// scanner 'from' special constant
#define FIRST_RECORD -1

View file

@ -0,0 +1,78 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
Binary32Field Class
--------------------------------------------------------------------------- */
#include "nde.h"
#include "Binary32Field.h"
#include "ndestring.h"
//---------------------------------------------------------------------------
Binary32Field::Binary32Field(const uint8_t *_Data, size_t len) : BinaryField(_Data, len)
{
InitField();
}
//---------------------------------------------------------------------------
void Binary32Field::InitField(void)
{
Type = FIELD_BINARY32;
}
//---------------------------------------------------------------------------
Binary32Field::Binary32Field()
{
InitField();
}
//---------------------------------------------------------------------------
void Binary32Field::ReadTypedData(const uint8_t *data, size_t len)
{
uint32_t c;
size_t pos = 0;
CHECK_INT(len); //len-=4;
c = GET_INT(); pos += 4;
if (c && c<=len)
{
size_t size = c;
uint8_t *buf = (uint8_t *)malloc(size);
GET_BINARY(buf, data, c, pos);
Data = CFDataCreateWithBytesNoCopy(NULL, buf, size, kCFAllocatorMalloc);
}
}
//---------------------------------------------------------------------------
void Binary32Field::WriteTypedData(uint8_t *data, size_t len)
{
uint32_t c;
size_t pos = 0;
CHECK_INT(len); //len-=4;
size_t Size = CFDataGetLength(Data);
if (Data && Size<=len)
{
c = CFDataGetLength(Data);
PUT_INT(c); pos += 4;
CFDataGetBytes(Data, CFRangeMake(0, Size), data+pos);
}
else
{
PUT_INT(0);
}
}
//---------------------------------------------------------------------------
size_t Binary32Field::GetDataSize(void)
{
if (!Data)
return 4;
return CFDataGetLength(Data) + 4;
}

View file

@ -0,0 +1,32 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
Binary32Field Class Prototypes
--------------------------------------------------------------------------- */
#ifndef __NDE_BINARY32FIELD_H
#define __NDE_BINARY32FIELD_H
#include "BinaryField.h"
#include <bfc/platform/types.h>
class Binary32Field : public BinaryField
{
protected:
virtual void ReadTypedData(const uint8_t *, size_t len);
virtual void WriteTypedData(uint8_t *, size_t len);
virtual size_t GetDataSize(void);
void InitField(void);
public:
Binary32Field(const uint8_t *Data, size_t len);
Binary32Field();
};
#endif

172
Src/nde/osx/BinaryField.cpp Normal file
View file

@ -0,0 +1,172 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
BinaryField Class
--------------------------------------------------------------------------- */
#include "../nde.h"
#include "BinaryField.h"
//---------------------------------------------------------------------------
BinaryField::BinaryField(const uint8_t *_Data, int len)
{
InitField();
Type = FIELD_BINARY;
if (_Data && len > 0)
{
Data = CFDataCreate(NULL, _Data, len);
}
}
//---------------------------------------------------------------------------
void BinaryField::InitField(void)
{
Type = FIELD_BINARY;
Data = NULL;
}
//---------------------------------------------------------------------------
BinaryField::BinaryField()
{
InitField();
}
//---------------------------------------------------------------------------
BinaryField::~BinaryField()
{
CFRelease(Data);
}
//---------------------------------------------------------------------------
void BinaryField::ReadTypedData(const uint8_t *data, size_t len)
{
unsigned short c;
int pos = 0;
CHECK_SHORT(len);
c = GET_SHORT(); pos += 2;
if (c && c<=len)
{
Data = CFDataCreate(NULL, data+pos, c);
}
}
//---------------------------------------------------------------------------
void BinaryField::WriteTypedData(uint8_t *data, size_t len)
{
unsigned short c;
size_t pos = 0;
CHECK_SHORT(len);
size_t Size = CFDataGetLength(Data);
if (Data && Size<=len)
{
c = CFDataGetLength(Data);
PUT_SHORT(c); pos += 2;
CFDataGetBytes(Data, CFRangeMake(0, Size), data+pos);
}
else
{
PUT_SHORT(0);
}
}
//---------------------------------------------------------------------------
const uint8_t *BinaryField::GetData(size_t *len)
{
if (len)
*len = CFDataGetLength(Data);
return CFDataGetBytePtr(Data);
}
//---------------------------------------------------------------------------
void BinaryField::SetData(const uint8_t *_Data, size_t len)
{
if (!_Data || !len) return;
if (Data)
CFRelease(Data);
Data = CFDataCreate(NULL, _Data, len);
}
CFDataRef BinaryField::GetCFData()
{
return Data;
}
//---------------------------------------------------------------------------
size_t BinaryField::GetDataSize(void)
{
if (!Data) return 2;
return CFDataGetLength(Data) + 2;
}
//---------------------------------------------------------------------------
int BinaryField::Compare(Field *Entry)
{
if (!Entry) return -1;
size_t compare_length;
const uint8_t *compare_data = ((BinaryField*)Entry)->GetData(&compare_length);
size_t size;
const uint8_t *data = GetData(&size);
return memcmp(data, compare_data, min(compare_length, size));
}
//---------------------------------------------------------------------------
bool BinaryField::ApplyFilter(Field *FilterData, int op)
{
size_t l, s;
const uint8_t *p = ((BinaryField *)FilterData)->GetData(&l);
const uint8_t *d = GetData(&s);
if (!p)
p = (const uint8_t *)"";
if (!d)
d = (const uint8_t *)"";
bool r;
switch (op)
{
case FILTER_EQUALS:
if (l != s)
r = false;
else
r = !memcmp(d, p, min(s, l));
break;
case FILTER_CONTAINS:
if (l > s)
r = FALSE;
else
r = !!memmem(d, p, s, l);
break;
case FILTER_ABOVE:
r = (memcmp(d, p, min(s, l)) > 0);
break;
case FILTER_BELOW:
r = (memcmp(d, p, min(s, l)) < 0);
break;
case FILTER_BELOWOREQUAL:
r = (memcmp(d, p, min(s, l)) <= 0);
break;
case FILTER_ABOVEOREQUAL:
r = (memcmp(d, p, min(s, l)) >= 0);
break;
case FILTER_ISEMPTY:
r = (s == 0);
break;
case FILTER_ISNOTEMPTY:
r = (s != 0);
break;
default:
r = true;
break;
}
return r;
}

38
Src/nde/osx/BinaryField.h Normal file
View file

@ -0,0 +1,38 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
BinaryField Class Prototypes
--------------------------------------------------------------------------- */
#ifndef __BINARYFIELD_H
#define __BINARYFIELD_H
#include "Field.h"
#include <bfc/platform/types.h>
class BinaryField : public Field
{
protected:
virtual void ReadTypedData(const uint8_t *, size_t len);
virtual void WriteTypedData(uint8_t *, size_t len);
virtual size_t GetDataSize(void);
virtual int Compare(Field *Entry);
virtual bool ApplyFilter(Field *Data, int flags);
void InitField(void);
CFDataRef Data;
public:
~BinaryField();
BinaryField(const uint8_t *Data, int len);
BinaryField();
const uint8_t *GetData(size_t *len);
void SetData(const uint8_t *Data, size_t len);
CFDataRef GetCFData();
};
#endif

160
Src/nde/osx/ColumnField.cpp Normal file
View file

@ -0,0 +1,160 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
ColumnField Class
Mac OS X implementation
Field data layout:
[1 byte] Field Type
[1 byte] Unused (maybe convert to 'searchable')
[1 byte] Name Length
[Name Length bytes] Name (UTF-8)
--------------------------------------------------------------------------- */
#include "../nde.h"
//---------------------------------------------------------------------------
ColumnField::ColumnField(unsigned char FieldID, CFStringRef FieldName, unsigned char FieldType, Table *parentTable)
{
InitField();
Type = FIELD_COLUMN;
MyType = FieldType;
Name = (CFStringRef)CFRetain(FieldName);
ID = FieldID;
}
//---------------------------------------------------------------------------
void ColumnField::InitField(void)
{
searchable = false;
MyType = FIELD_UNKNOWN;
Type = FIELD_COLUMN;
Name = NULL;
ID = 0;
}
//---------------------------------------------------------------------------
ColumnField::ColumnField()
{
InitField();
}
//---------------------------------------------------------------------------
ColumnField::~ColumnField()
{
if (Name)
CFRelease(Name);
}
void ColumnField::SetSearchable(bool val)
{
searchable=val;
}
bool ColumnField::IsSearchableField() const
{
return searchable;
}
//---------------------------------------------------------------------------
void ColumnField::ReadTypedData(const uint8_t *data, size_t len)
{
unsigned char c;
int pos=0;
CHECK_CHAR(len);
MyType = GET_CHAR(); pos++;
CHECK_CHAR(len);
pos++;
CHECK_CHAR(len);
c = GET_CHAR(); pos++;
if (c)
{
CHECK_BIN(len, c);
if (Name)
CFRelease(Name);
Name = CFStringCreateWithBytes(kCFAllocatorDefault, data+pos, c, kCFStringEncodingUTF8, false);
}
}
//---------------------------------------------------------------------------
void ColumnField::WriteTypedData(uint8_t *data, size_t len)
{
int pos = 0;
CHECK_CHAR(len);
PUT_CHAR(MyType); pos++;
CHECK_CHAR(len);
PUT_CHAR(0/*(char)indexUnique*/);
pos++;
if (Name)
{
CFIndex lengthRequired=0;
CFStringGetBytes(Name, CFRangeMake(0, CFStringGetLength(Name)), kCFStringEncodingUTF8, 0, false, NULL, 0, &lengthRequired);
CHECK_BIN(len, lengthRequired+1);
PUT_CHAR(lengthRequired); pos++;
CFStringGetBytes(Name, CFRangeMake(0, CFStringGetLength(Name)), kCFStringEncodingUTF8, 0, false, data+pos, lengthRequired, 0);
}
else
{
PUT_CHAR(0);
}
}
//---------------------------------------------------------------------------
unsigned char ColumnField::GetDataType(void)
{
return MyType;
}
//---------------------------------------------------------------------------
void ColumnField::SetDataType(unsigned char type)
{
if ((MyType == FIELD_INTEGER || MyType == FIELD_BOOLEAN || MyType == FIELD_DATETIME || MyType == FIELD_LENGTH) &&
(type == FIELD_INTEGER || type == FIELD_BOOLEAN || type == FIELD_DATETIME || type == FIELD_LENGTH)) {
MyType = type;
}
// going from string to filename or filename to string is OK
if ((MyType == FIELD_FILENAME && type == FIELD_STRING)
|| (MyType == FIELD_STRING && type == FIELD_FILENAME))
{
MyType = type;
}
}
//---------------------------------------------------------------------------
CFStringRef ColumnField::GetFieldName(void)
{
return Name;
}
//---------------------------------------------------------------------------
size_t ColumnField::GetDataSize(void)
{
if (Name)
{
CFIndex lengthRequired=0;
CFStringGetBytes(Name, CFRangeMake(0, CFStringGetLength(Name)), kCFStringEncodingUTF8, 0, false, NULL, 0, &lengthRequired);
return lengthRequired+3;
}
else
return 3;
}
//---------------------------------------------------------------------------
int ColumnField::Compare(Field * /*Entry*/)
{
return 0;
}

49
Src/nde/osx/ColumnField.h Normal file
View file

@ -0,0 +1,49 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
ColumnField Class Prototypes
Mac OS X implementation
--------------------------------------------------------------------------- */
#ifndef __COLUMNFIELD_H
#define __COLUMNFIELD_H
#include "Field.h"
#include "LinkedList.h"
#include "Table.h"
#include "Scanner.h"
class ColumnField : public Field
{
public:
ColumnField(unsigned char FieldID, CFStringRef FieldName, unsigned char FieldType, Table *parentTable);
ColumnField();
~ColumnField();
/* Field implementation */
virtual void ReadTypedData(const uint8_t *, size_t len);
virtual void WriteTypedData(uint8_t *, size_t len);
virtual size_t GetDataSize(void);
virtual int Compare(Field *Entry);
/* ColumnField methods */
void InitField(void);
void SetDataType(unsigned char type);
bool IsSearchableField() const;
void SetSearchable(bool val);
unsigned char GetDataType(void);
CFStringRef GetFieldName(void);
protected:
bool searchable;
CFStringRef Name;
unsigned char MyType;
};
#endif

View file

@ -0,0 +1,45 @@
#include "FilenameField.h"
#include "nde.h"
/*
Mac OS X implementation of FilenameField
only the equals operator will be case-sensitive. substring search, ends, starts, etc. will be case-insensitive,
to make things like "filename ends .mp3" easier
TODO: it'd be massive overhead, but it'd be more correct to check if the file system is actually case sensitive (for the path being searched)
*/
//---------------------------------------------------------------------------
FilenameField::FilenameField(CFStringRef Str) : StringField(Str)
{
Type = FIELD_FILENAME;
}
//---------------------------------------------------------------------------
FilenameField::FilenameField()
{
Type = FIELD_FILENAME;
}
//---------------------------------------------------------------------------
int FilenameField::Compare(Field *Entry)
{
if (!Entry) return -1;
if (Entry->GetType() != GetType()) return 0;
CFStringRef compareString = ((StringField*)Entry)->GetString();
if (!String && !compareString) return 0;
if (!String && compareString) return 1;
if (!compareString) return -1;
return CFStringCompare(String, compareString, 0);
}
Field *FilenameField::Clone(Table *pTable)
{
FilenameField *clone = new FilenameField(String);
clone->Pos = FIELD_CLONE;
clone->ID = ID;
clone->MaxSizeOnDisk = GetDataSize();
return clone;
}

View file

@ -0,0 +1,23 @@
#ifndef NDE_FILENAMEFIELD_H
#define NDE_FILENAMEFIELD_H
/*
Mostly the same as StringField
but this implements OS-dependent string comparisons that make sense for the file system
*/
#include "nde.h"
#include "NDEString.h"
class FilenameField : public StringField
{
protected:
virtual int Compare(Field *Entry);
virtual Field *Clone(Table *pTable);
public:
FilenameField(CFStringRef Str);
FilenameField();
};
#endif

126
Src/nde/osx/IndexField.cpp Normal file
View file

@ -0,0 +1,126 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
IndexField Class
--------------------------------------------------------------------------- */
#include "nde.h"
//---------------------------------------------------------------------------
IndexField::IndexField(unsigned char id, int Pos, int type, CFStringRef FieldName)
{
InitField();
Type = FIELD_INDEX;
Name = (CFStringRef)CFRetain(FieldName);
ID = id;
Position = Pos;
DataType = type;
}
//---------------------------------------------------------------------------
void IndexField::InitField(void)
{
index = 0;
Type = FIELD_INDEX;
Name = NULL;
ID = 0;
Position = -1;
DataType = FIELD_UNKNOWN;
}
//---------------------------------------------------------------------------
IndexField::IndexField()
{
InitField();
}
//---------------------------------------------------------------------------
IndexField::~IndexField()
{
if (Name)
CFRelease(Name);
delete index;
}
//---------------------------------------------------------------------------
void IndexField::ReadTypedData(const uint8_t *data, size_t len)
{
unsigned char c;
int pos=0;
CHECK_INT(len);
Position = GET_INT(); pos += 4;
CHECK_INT(len);
DataType = GET_INT(); pos += 4;
CHECK_CHAR(len);
c = GET_CHAR(); pos++;
if (c)
{
CHECK_BIN(len, c);
if (Name)
CFRelease(Name);
Name = CFStringCreateWithBytes(kCFAllocatorDefault, data+pos, c, kCFStringEncodingUTF8, false);
}
}
//---------------------------------------------------------------------------
void IndexField::WriteTypedData(uint8_t *data, size_t len)
{
int pos=0;
CHECK_INT(len);
PUT_INT(Position); pos += 4;
CHECK_INT(len);
PUT_INT(DataType); pos += 4;
CHECK_CHAR(len);
if (Name)
{
CFIndex lengthRequired=0;
CFStringGetBytes(Name, CFRangeMake(0, CFStringGetLength(Name)), kCFStringEncodingUTF8, 0, false, NULL, 0, &lengthRequired);
CHECK_BIN(len, lengthRequired+1);
PUT_CHAR(lengthRequired); pos++;
CFStringGetBytes(Name, CFRangeMake(0, CFStringGetLength(Name)), kCFStringEncodingUTF8, 0, false, data+pos, lengthRequired, 0);
}
}
//---------------------------------------------------------------------------
CFStringRef IndexField::GetIndexName(void)
{
return Name;
}
//---------------------------------------------------------------------------
size_t IndexField::GetDataSize(void)
{
if (Name)
{
CFIndex lengthRequired=0;
CFStringGetBytes(Name, CFRangeMake(0, CFStringGetLength(Name)), kCFStringEncodingUTF8, 0, false, NULL, 0, &lengthRequired);
return lengthRequired+9;
}
else
return 9;
}
//---------------------------------------------------------------------------
int IndexField::Compare(Field * /*Entry*/)
{
return 0;
}
//---------------------------------------------------------------------------
int IndexField::TranslateToIndex(int Id, IndexField *toindex)
{
if (index && toindex && toindex->index)
return index->TranslateIndex(Id, toindex->index);
return -1;
}

37
Src/nde/osx/IndexField.h Normal file
View file

@ -0,0 +1,37 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
IndexField Class Prototypes
--------------------------------------------------------------------------- */
#ifndef __INDEXFIELD_H
#define __INDEXFIELD_H
class IndexField : public Field
{
public:
IndexField(unsigned char id, int Pos, int type, CFStringRef FieldName);
IndexField();
~IndexField();
virtual void ReadTypedData(const uint8_t *, size_t len);
virtual void WriteTypedData(uint8_t *, size_t len);
virtual size_t GetDataSize(void);
virtual int Compare(Field *Entry);
void InitField(void);
CFStringRef GetIndexName(void);
int TranslateToIndex(int Id, IndexField *index);
Index *index; // TODO: make protected
protected:
int Position;
int DataType;
CFStringRef Name;
};
#endif

170
Src/nde/osx/IndexRecord.cpp Normal file
View file

@ -0,0 +1,170 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
IndexRecord Class
--------------------------------------------------------------------------- */
#include "nde.h"
#include <stdio.h>
IndexRecord::IndexRecord(int RecordPos, int insertionPoint, VFILE *TableHandle, Table *ParentTable)
{
InsertionPoint = insertionPoint;
if (RecordPos != 0)
{
int n=0;
uint32_t ThisPos = RecordPos;
while (ThisPos)
{
if (n >= 128)
break;
Vfseek(TableHandle, ThisPos, SEEK_SET);
Field Entry (ThisPos);
Field *TypedEntry = Entry.ReadField(ParentTable, ThisPos, &ThisPos);
if (!TypedEntry) break; // some db error?
AddField(TypedEntry);
// ThisPos = TypedEntry->GetNextFieldPos();
n++;
}
}
}
void IndexRecord::BuildCollaboration()
{
for (FieldList::iterator itr=Fields.begin();itr!=Fields.end();itr++)
{
IndexField *p = (IndexField *)*itr;
if (p->next)
p->index->Colaborate((IndexField *)p->next);
else
p->index->Colaborate((IndexField *)*Fields.begin());
}
}
bool IndexRecord::NeedFix()
{
for (FieldList::iterator itr=Fields.begin();itr!=Fields.end();itr++)
{
IndexField *p = (IndexField *)*itr;
if (p->index->NeedFix())
return true;
}
return false;
}
#ifdef _WIN32
IndexField *IndexRecord::GetIndexByName(const wchar_t *name)
{
for (FieldList::iterator itr=Fields.begin();itr!=Fields.end();itr++)
{
IndexField *p = (IndexField *)*itr;
if (!_wcsicmp(p->GetIndexName(), name))
return p;
}
return NULL;
}
#else
IndexField *IndexRecord::GetIndexByName(CFStringRef name)
{
for (FieldList::iterator itr=Fields.begin();itr!=Fields.end();itr++)
{
IndexField *p = (IndexField *)*itr;
if (CFStringCompare(p->GetIndexName(), name, kCFCompareCaseInsensitive) == kCFCompareEqualTo)
return p;
}
return NULL;
}
#endif
bool IndexRecord::CheckIndexing(int v)
{
int i = v;
for (FieldList::iterator itr=Fields.begin();itr!=Fields.end();itr++)
{
IndexField *p = (IndexField *)*itr;
v = p->index->GetCooperative(v);
}
return v == i;
}
void IndexRecord::SetModified(BOOL modifiedVal)
{
for (FieldList::iterator itr=Fields.begin();itr!=Fields.end();itr++)
{
IndexField *p = (IndexField *)*itr;
p->index->Modified = modifiedVal;
}
}
Field *RecordBase::GetField(unsigned char ID)
{
for (FieldList::iterator itr=Fields.begin();itr!=Fields.end();itr++)
{
IndexField *p = (IndexField *)*itr;
if (p->GetFieldId() == ID)
return p;
}
return NULL;
}
void RecordBase::AddField(Field *field)
{
if (!field) return;
if (GetField(field->ID))
return;
Fields.push_back(field);
}
int IndexRecord::WriteFields(Table *ParentTable)
{
Field *previous = 0;
for (FieldList::iterator itr=Fields.begin();itr!=Fields.end();itr++)
{
IndexField *p = (IndexField *)*itr;
p->WriteField(ParentTable, previous, (Field *)p->next);
previous = p;
}
return WriteIndex(ParentTable);
}
int IndexRecord::WriteIndex(Table *ParentTable)
{
int P=0;
if (!Fields.empty())
P=(*Fields.begin())->GetFieldPos();
return ParentTable->index->Update(INDEX_RECORD_NUM, P, this, FALSE);
}
void RecordBase::RemoveField(Field *field)
{
if (!field)
return;
Fields.erase(field);
delete field;
}
void IndexRecord::WalkFields(FieldsWalker callback, void *context)
{
if (callback)
{
for (FieldList::iterator itr=Fields.begin();itr!=Fields.end();itr++)
{
if (!callback(this, *itr, context))
break;
}
}
}

19
Src/nde/osx/IndexRecord.h Normal file
View file

@ -0,0 +1,19 @@
#pragma once
#include <stdio.h>
#include "Record.h"
#include "../nu/PtrDeque2.h"
class IndexRecord : public RecordBase
{
public:
IndexRecord(int RecordPos, int insertionPoint, VFILE *FileHandle,Table *p);
void BuildCollaboration();
bool NeedFix();
IndexField *GetIndexByName(const wchar_t *name);
int GetColumnCount() { return Fields.size() - 1; }
bool CheckIndexing(int v);
int WriteFields(Table *ParentTable);
int WriteIndex(Table *ParentTable);
typedef bool (*FieldsWalker)(IndexRecord *record, Field *entry, void *context);
void WalkFields(FieldsWalker callback, void *context);
};

1018
Src/nde/osx/IntegerField.cpp Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,93 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
IntegerField Class Prototypes
--------------------------------------------------------------------------- */
#ifndef __INTEGERFIELD_H
#define __INTEGERFIELD_H
#include <bfc/platform/types.h>
class TimeParse {
public:
int is_relative; // ago/after/before used
int absolute_datetime; // if not is_relative, this is the date/time, otherwise it's the resulting date/time if the query was ran now
int absolute_hasdate; // if not, use only the time portion of absolute_datetime, the rest is now
int absolute_hastime; // if not, use only the date portion of absolute_datetime, the rest is now
int relative_year; // -1 = this year
int relative_month; // -1 = this month
int relative_day; // -1 = this day, -2 = this week
int relative_hour; // -1 = this hour
int relative_min; // -1 = this minute
int relative_sec; // -1 = this second
int relative_kwday; // not used(-1), 0 to 6 for sunday to saturday, yesterday(7), today(8), tomorrow(9)
int offset_value; // timeago/offsetby numerical edit field
int offset_what; // not used(-1) years(0), months(1), weeks(2), days(3), hours(4), minutes(5), seconds(6)
int offset_whence; // not used(-1), after(0), ago/before(1)
int offset_used; // if 1, 'time ago' / 'offset by' should be checked
};
class IntegerField : public Field
{
protected:
virtual void ReadTypedData(const uint8_t *, size_t len);
virtual void WriteTypedData(uint8_t *, size_t len);
virtual size_t GetDataSize(void);
virtual int Compare(Field *Entry);
virtual bool ApplyFilter(Field *Data, int op);
void InitField(void);
int Value;
enum {
WHAT_YEARS,
WHAT_MONTHS,
WHAT_WEEKS,
WHAT_DAYS,
WHAT_HOURS,
WHAT_MINUTES,
WHAT_SECONDS,
};
enum {
FROM_BARE,
FROM_AGO,
FROM_SINCE,
};
public:
~IntegerField();
IntegerField(int);
IntegerField();
int GetValue(void);
void SetValue(int);
int ApplyConversion(const char *format, TimeParse *tp=NULL);
static int LookupToken(CFStringRef t);
};
class DateTimeField : public IntegerField {
public:
DateTimeField();
DateTimeField(int Val);
virtual ~DateTimeField();
};
class LengthField : public IntegerField {
public:
LengthField();
LengthField(int Val);
virtual ~LengthField();
};
#endif

936
Src/nde/osx/Query.cpp Normal file
View file

@ -0,0 +1,936 @@
#include "nde.h"
#include "NDEString.h"
#include "Query.h"
//---------------------------------------------------------------------------
BOOL Scanner::Query(const char *query)
{
if (!query) return FALSE;
if (last_query) CFRelease(last_query);
last_query = CFStringCreateWithBytes(NULL, (const uint8_t *)query, strlen(query), kCFStringEncodingUTF32, false);
RemoveFilters();
in_query_parser = 1;
BOOL r = Query_Parse(query);
if (r == FALSE)
{
if (!disable_date_resolution) RemoveFilters();
last_query_failed = TRUE;
}
in_query_parser = 0;
Query_CleanUp();
return r & CheckFilters();
}
CFStringRef Scanner::GetLastQuery()
{
return last_query;
}
typedef struct
{
CFStringRef token;
int tid;
} tokenstruct;
tokenstruct Tokens[] = // Feel free to add more...
{
{CFSTR("AND"), TOKEN_AND },
{CFSTR("OR"), TOKEN_OR },
{CFSTR("HAS"), TOKEN_CONTAINS },
{CFSTR("NOTHAS"),TOKEN_NOTCONTAINS},
{CFSTR("BEGINS"), TOKEN_BEGINS },
{CFSTR("ENDS"), TOKEN_ENDS },
{CFSTR("ISEMPTY"), TOKEN_ISEMPTY},
{CFSTR("ISNOTEMPTY"),TOKEN_ISNOTEMPTY},
{CFSTR("LIKE"), TOKEN_LIKE},
{CFSTR("BEGINSLIKE"), TOKEN_BEGINSLIKE},
};
typedef struct
{
int Op;
int Level;
} OpLevel;
static int Query_ParseLength(CFStringRef str)
{
int x;
CFArrayRef array = CFStringCreateArrayBySeparatingStrings(NULL, str, CFSTR(":"));
if (array)
{
CFIndex count = CFArrayGetCount(array);
if (count == 2)
{
CFStringRef t1 = (CFStringRef)CFArrayGetValueAtIndex(array, 0);
CFStringRef t2 = (CFStringRef)CFArrayGetValueAtIndex(array, 1);
x = CFStringGetIntValue(t1) * 60 + CFStringGetIntValue(t2);
CFRelease(array);
return x;
}
if (count == 3)
{
CFStringRef t1 = (CFStringRef)CFArrayGetValueAtIndex(array, 0);
CFStringRef t2 = (CFStringRef)CFArrayGetValueAtIndex(array, 1);
CFStringRef t3 = (CFStringRef)CFArrayGetValueAtIndex(array, 2);
x = CFStringGetIntValue(t1) * 60 * 60 + CFStringGetIntValue(t2) * 60 + CFStringGetIntValue(t3);
CFRelease(array);
return x;
}
CFRelease(array);
}
return CFStringGetIntValue(str);;
}
/*
our state machine
&, |
----------<-------------------------<----------------------<-----------
| |
v ID (Col) =, >, <... ID / Data / [f] ) |
---->(0) ----->-----> (1) ------>-----> (2) ------>------> (3) ------>-----> (4) <--
| |^ \isempty------------->------------/ |^ | |
| !( || ||---- | ) |
--<-- ---------<---------------------------<-------------<-| | -->--
&, | v [f] |
-->--
*/
//---------------------------------------------------------------------------
BOOL Scanner::Query_Parse(const char *query)
{
const char *p = query; // pointer on next token to read
size_t size;
int state = 0;
int pcount = 0;
VListEntry<OpLevel> *entry;
if (pstack.GetNElements() > 0)
Query_CleanUp();
while (1)
{
p = Query_EatSpace(p);
int t = Query_GetNextToken(p, &size, &token);
if (t == TOKEN_UNKNOWN)
{
Query_SyntaxError((int)(p-query));
return FALSE;
}
if (t == TOKEN_EOQ)
break;
switch (state)
{
case 0:
switch (t)
{
case TOKEN_PAROPEN:
state = 0;
// check too many parenthesis open
if (pcount == 255)
{
Query_SyntaxError((int)(p-query)); // should not be _syntax_ error
return FALSE;
}
// up one level
pcount++;
break;
case TOKEN_NOT:
// push not in this level
OpLevel o;
o.Op = FILTER_NOT;
o.Level = pcount;
entry = new VListEntry<OpLevel>;
entry->SetVal(o);
pstack.AddEntry(entry, TRUE);
state = 0;
break;
case TOKEN_IDENTIFIER:
state = 1;
// create filter column
if (AddFilterByName(token, NULL, FILTER_NONE) == ADDFILTER_FAILED)
{
Query_SyntaxError((int)(p-query));
return FALSE;
}
break;
default:
Query_SyntaxError((int)(p-query));
return FALSE;
}
break;
case 1:
switch (t)
{
case TOKEN_EQUAL:
{
state = 2;
// set filter op
Filter *f = GetLastFilter();
f->SetOp(FILTER_EQUALS);
break;
}
case TOKEN_ABOVE:
{
state = 2;
// set filter op
Filter *f = GetLastFilter();
f->SetOp(FILTER_ABOVE);
break;
}
case TOKEN_BELOW:
{
state = 2;
// set filter op
Filter *f = GetLastFilter();
f->SetOp(FILTER_BELOW);
break;
}
case TOKEN_CONTAINS:
{
state = 2;
// set filter op
Filter *f = GetLastFilter();
f->SetOp(FILTER_CONTAINS);
break;
}
case TOKEN_NOTCONTAINS:
{
state = 2;
// set filter op
Filter *f = GetLastFilter();
f->SetOp(FILTER_NOTCONTAINS);
break;
}
case TOKEN_AOREQUAL:
{
state = 2;
// set filter op
Filter *f = GetLastFilter();
f->SetOp(FILTER_ABOVEOREQUAL);
break;
}
case TOKEN_BOREQUAL:
{
state = 2;
// set filter op
Filter *f = GetLastFilter();
f->SetOp(FILTER_BELOWOREQUAL);
break;
}
case TOKEN_NOTEQUAL:
{
state = 2;
// set filter op
Filter *f = GetLastFilter();
f->SetOp(FILTER_NOTEQUALS);
break;
}
case TOKEN_BEGINS:
{
state = 2;
Filter *f = GetLastFilter();
f->SetOp(FILTER_BEGINS);
}
break;
case TOKEN_ENDS:
{
state = 2;
Filter *f = GetLastFilter();
f->SetOp(FILTER_ENDS);
}
break;
case TOKEN_LIKE:
{
state = 2;
// set filter op
Filter *f = GetLastFilter();
f->SetOp(FILTER_LIKE);
break;
}
case TOKEN_BEGINSLIKE:
{
state = 2;
// set filter op
Filter *f = GetLastFilter();
f->SetOp(FILTER_BEGINSLIKE);
break;
}
case TOKEN_ISNOTEMPTY:
case TOKEN_ISEMPTY:
{
state = 3;
Filter *f = GetLastFilter();
f->SetOp(t==TOKEN_ISEMPTY ? FILTER_ISEMPTY : FILTER_ISNOTEMPTY);
// pop all operators in this level beginning by the last inserted
entry = (VListEntry<OpLevel> *)pstack.GetFoot();
while (entry)
{
if (entry->GetVal().Level == pcount)
{
AddFilterOp(entry->GetVal().Op);
VListEntry<OpLevel> *_entry = (VListEntry<OpLevel> *)entry->GetPrevious();
pstack.RemoveEntry(entry);
entry = _entry;
}
else
break;
}
}
break;
default:
Query_SyntaxError((int)(p-query));
return FALSE;
}
break;
case 2:
if (t == TOKEN_SQBRACKETOPEN)
{
state = 3;
const char *s = strchr(p, ']');
if (!s)
{
Query_SyntaxError((int)(p-query));
return FALSE;
}
p = Query_EatSpace(p);
if (*p == '[') p++;
CFStringRef format = CFStringCreateWithBytes(NULL, (const uint8_t *)p, (s-p), kCFStringEncodingUTF32, false);
Filter *f = GetLastFilter();
int id = f->GetId();
ColumnField *c = GetColumnById(id);
int tt = c ? c->GetDataType() : -1;
if (disable_date_resolution || !c || (tt != FIELD_INTEGER && tt != FIELD_DATETIME && tt != FIELD_LENGTH && tt != FIELD_BOOLEAN))
{
if (disable_date_resolution)
{
StringField *field = (StringField *)f->Data();
if (!field)
{
// format was used without a value, assume value is 0
f->SetData(new StringField(CFSTR("")));
entry = (VListEntry<OpLevel> *)pstack.GetFoot();
while (entry)
{
if (entry->GetVal().Level == pcount)
{
AddFilterOp(entry->GetVal().Op);
VListEntry<OpLevel> *_entry = (VListEntry<OpLevel> *)entry->GetPrevious();
pstack.RemoveEntry(entry);
entry = _entry;
}
else
break;
}
field = (StringField*)f->Data();
}
field->SetNDEString(format);
if (format) CFRelease(format);
p = s+1;
continue;
}
if (format) CFRelease(format);
Query_SyntaxError((int)(p-query));
return FALSE;
}
IntegerField *field = (IntegerField *)f->Data();
if (!field)
{
// format was used without a value, assume value is 0
f->SetData(new IntegerField(0));
entry = (VListEntry<OpLevel> *)pstack.GetFoot();
while (entry)
{
if (entry->GetVal().Level == pcount)
{
AddFilterOp(entry->GetVal().Op);
VListEntry<OpLevel> *_entry = (VListEntry<OpLevel> *)entry->GetPrevious();
pstack.RemoveEntry(entry);
entry = _entry;
}
else
break;
}
field = (IntegerField *)f->Data();
}
// TODO: make sure this is safe (that p and s havn't been iterated)
char *temp_format = (char *)malloc((s-p+1));
strncpy(temp_format, p, s-p);
temp_format[s-p] = 0;
int r = field->ApplyConversion(temp_format);
free(temp_format);
ndestring_release(format);
if (!r)
{
Query_SyntaxError((int)(p-query));
return FALSE;
}
p = s+1;
continue;
}
// switch (t) {
// case TOKEN_IDENTIFIER:
else // JF> we make this relaxed, so anything is valid as a value
{
state = 3;
// set filter data
Filter *f = GetLastFilter();
int id = f->GetId();
ColumnField *c = GetColumnById(id);
switch (c ? c->GetDataType() : -1)
{
case FIELD_DATETIME:
if (disable_date_resolution)
goto field_string_override;
case FIELD_LENGTH:
{
int i;
IntegerField *i_f = new IntegerField();
i = Query_ParseLength(token);
i_f->SetValue(i);
f->SetData(i_f);
}
break;
case FIELD_BOOLEAN:
case FIELD_INTEGER:
{
int i;
IntegerField *i_f = new IntegerField();
i = CFStringGetIntValue(token);
i_f->SetValue(i);
f->SetData(i_f);
}
break;
case FIELD_INT64:
{
int64_t i;
Int64Field *i_f = new Int64Field();
#ifdef _WIN32
i = _wtoi64(token); // todo: Replace with own conversion and error checking
#else
i = CFStringGetIntValue(token); // TODO!!! 64bit integer here ... maybe use CFNumberFormatterCreateNumberFromString but it's a lot of overhead
#endif
i_f->SetValue(i);
f->SetData(i_f);
}
break;
case FIELD_FILENAME:
{
FilenameField *s_f = new FilenameField();
s_f->SetNDEString(token);
f->SetData(s_f);
}
break;
case FIELD_STRING:
field_string_override:
{
StringField *s_f = new StringField();
s_f->SetNDEString(token);
f->SetData(s_f);
}
break;
default:
Query_SyntaxError((int)(p-query));
return FALSE;
break;
}
// pop all operators in this level beginning by the last inserted
entry = (VListEntry<OpLevel> *)pstack.GetFoot();
while (entry)
{
if (entry->GetVal().Level == pcount)
{
AddFilterOp(entry->GetVal().Op);
VListEntry<OpLevel> *_entry = (VListEntry<OpLevel> *)entry->GetPrevious();
pstack.RemoveEntry(entry);
entry = _entry;
}
else
break;
}
break;
}
// default:
// Query_SyntaxError(p-query);
// return FALSE;
// }
break;
case 3:
switch (t)
{
case TOKEN_SQBRACKETOPEN:
{
const char *s = strchr(p, ']');
if (!s)
{
Query_SyntaxError((int)(p-query));
return FALSE;
}
p = Query_EatSpace(p);
if (*p == '[') p++;
CFStringRef format = CFStringCreateWithBytes(NULL, (const uint8_t *)p, (s-p), kCFStringEncodingUTF32, false);
Filter *f = GetLastFilter();
int id = f->GetId();
ColumnField *c = GetColumnById(id);
int tt = c ? c->GetDataType() : -1;
if (disable_date_resolution || !c || (tt != FIELD_INTEGER && tt != FIELD_DATETIME && tt != FIELD_LENGTH && tt != FIELD_BOOLEAN))
{
if (disable_date_resolution)
{
StringField *field = (StringField *)f->Data();
if (!field)
{
// format was used without a value, assume value is 0
f->SetData(new StringField(CFSTR("")));
entry = (VListEntry<OpLevel> *)pstack.GetFoot();
while (entry)
{
if (entry->GetVal().Level == pcount)
{
AddFilterOp(entry->GetVal().Op);
VListEntry<OpLevel> *_entry = (VListEntry<OpLevel> *)entry->GetPrevious();
pstack.RemoveEntry(entry);
entry = _entry;
}
else
break;
}
field = (StringField *)f->Data();
}
field->SetNDEString(format);
if (format) CFRelease(format);
p = s+1;
continue;
}
if (format) CFRelease(format);
Query_SyntaxError((int)(p-query));
return FALSE;
}
IntegerField *field = (IntegerField *)f->Data();
if (!field)
{
// format was used without a value, assume value is 0
f->SetData(new IntegerField(0));
entry = (VListEntry<OpLevel> *)pstack.GetFoot();
while (entry)
{
if (entry->GetVal().Level == pcount)
{
AddFilterOp(entry->GetVal().Op);
VListEntry<OpLevel> *_entry = (VListEntry<OpLevel> *)entry->GetPrevious();
pstack.RemoveEntry(entry);
entry = _entry;
}
else
break;
}
field = (IntegerField *)f->Data();
}
// TODO: make sure this is safe (that p and s havn't been iterated)
char *temp_format = (char *)malloc((s-p+1));
strncpy(temp_format, p, s-p);
temp_format[s-p] = 0;
int r = field->ApplyConversion(temp_format);
free(temp_format);
ndestring_release(format);
if (!r)
{
Query_SyntaxError((int)(p-query));
return FALSE;
}
p = s+1;
continue;
}
break;
case TOKEN_PARCLOSE:
state = 4;
// check parenthesis count
if (pcount == 0)
{
Query_SyntaxError((int)(p-query));
return FALSE;
}
// down one level
pcount--;
// pop all operators in this level, beginning by the last inserted
while (entry)
{
if (entry->GetVal().Level == pcount)
{
AddFilterOp(entry->GetVal().Op);
VListEntry<OpLevel> *_entry = (VListEntry<OpLevel> *)entry->GetPrevious();
pstack.RemoveEntry(entry);
entry = _entry;
}
else
break;
}
break;
case TOKEN_AND:
{
state = 0;
// push and
OpLevel o;
o.Op = FILTER_AND;
o.Level = pcount;
entry = new VListEntry<OpLevel>;
entry->SetVal(o);
pstack.AddEntry(entry, TRUE);
break;
}
case TOKEN_OR:
{
state = 0;
// push or
OpLevel o;
o.Op = FILTER_OR;
o.Level = pcount;
entry = new VListEntry<OpLevel>;
entry->SetVal(o);
pstack.AddEntry(entry, TRUE);
break;
}
default:
Query_SyntaxError((int)(p-query));
return FALSE;
}
break;
case 4:
switch (t)
{
case TOKEN_AND:
{
state = 0;
// push and
OpLevel o;
o.Op = FILTER_AND;
o.Level = pcount;
entry = new VListEntry<OpLevel>;
entry->SetVal(o);
pstack.AddEntry(entry, TRUE);
break;
}
case TOKEN_OR:
{
state = 0;
// push or
OpLevel o;
o.Op = FILTER_OR;
o.Level = pcount;
entry = new VListEntry<OpLevel>;
entry->SetVal(o);
pstack.AddEntry(entry, TRUE);
break;
}
case TOKEN_PARCLOSE:
state = 4;
// check parenthesis count
if (pcount == 0)
{
Query_SyntaxError((int)(p-query));
return FALSE;
}
// down one level
pcount--;
// pop all operators in this level, beginning by the last inserted
while (entry)
{
if (entry->GetVal().Level == pcount)
{
AddFilterOp(entry->GetVal().Op);
VListEntry<OpLevel> *_entry = (VListEntry<OpLevel> *)entry->GetPrevious();
pstack.RemoveEntry(entry);
entry = _entry;
}
else
break;
}
break;
default:
Query_SyntaxError((int)(p-query));
return FALSE;
}
break;
default:
// Ahem... :/
break;
}
p += size;
}
if (pcount > 0)
{
Query_SyntaxError((int)(p-query));
return FALSE;
}
return TRUE;
}
//---------------------------------------------------------------------------
void Scanner::Query_SyntaxError(int c)
{
}
//---------------------------------------------------------------------------
void Scanner::Query_CleanUp()
{
while (pstack.GetNElements() > 0)
{
VListEntry<int> *e;
e = (VListEntry<int> *)pstack.GetHead();
pstack.RemoveEntry(e);
}
}
//---------------------------------------------------------------------------
const char *Scanner::Query_EatSpace(const char *p)
{
while (*p && *p == ' ') p++;
return p;
}
//---------------------------------------------------------------------------
const char *Scanner::Query_ProbeNonAlphaNum(const char *p)
{
int inquote=0;
while (*p && (!Query_isControlChar(*p) || (inquote)))
{
if (*p == '\"')
{
if (!inquote)
inquote = 1;
else
return p+1;
}
p++;
}
return p;
}
//---------------------------------------------------------------------------
int Scanner::Query_isControlChar(char p)
{
switch (p)
{
case '&':
case '|':
case '!':
case '(':
case '[':
case ')':
case ']':
case '>':
case '<':
case '=':
case ',':
case ' ':
return TRUE;
}
return FALSE;
}
//---------------------------------------------------------------------------
char *Scanner::Query_ProbeAlphaNum(char *p)
{
while (*p && Query_isControlChar(*p)) p++;
return p;
}
//---------------------------------------------------------------------------
char *Scanner::Query_ProbeSpace(char *p)
{
while (*p && *p != ' ') p++;
return p;
}
//---------------------------------------------------------------------------
int Scanner::Query_LookupToken(CFStringRef t)
{
for (int i=0;i<sizeof(Tokens)/sizeof(tokenstruct);i++)
{
if (CFStringCompare(Tokens[i].token, t, kCFCompareCaseInsensitive) == kCFCompareEqualTo)
return Tokens[i].tid;
}
return TOKEN_IDENTIFIER;
}
//---------------------------------------------------------------------------
int Scanner::Query_GetNextToken(const char *p, size_t *size, CFStringRef *_token, int tokentable)
{
int t = TOKEN_EOQ;
const char *startptr = p;
if (!*p) return TOKEN_EOQ;
p = Query_EatSpace(p);
const char *e = Query_ProbeNonAlphaNum(p);
if (e != p) // We have a word
{
if (*_token) CFRelease(*_token);
// check for a quoted string
if (*p == '\"' && e != p+1 && e[-1] == '\"')
{
CFStringRef inner_string = CFStringCreateWithBytes(kCFAllocatorDefault, (const UInt8 *)(p+1), (e-p-2), kCFStringEncodingUTF8, false);
// escape it (ugh)
CFStringRef escaped_string = CFURLCreateStringByReplacingPercentEscapes(NULL, inner_string, CFSTR(""));
if (escaped_string)
{
*_token = escaped_string;
CFRelease(inner_string);
}
else
{
*_token = inner_string;
}
}
else
{
*_token = CFStringCreateWithBytes(kCFAllocatorDefault, (const UInt8 *)p, (e-p), kCFStringEncodingUTF8, false);
}
switch (tokentable)
{
case -1:
t = TOKEN_IDENTIFIER;
break;
case 0:
t = Query_LookupToken(*_token);
break;
case 1:
t = IntegerField::LookupToken(*_token);
}
p = e;
}
else // We have a symbol
{
switch (*p)
{
case '&':
if (*(p+1) == '&') p++;
t = TOKEN_AND;
break;
case '|':
if (*(p+1) == '|') p++;
t = TOKEN_OR;
break;
case '!':
if (*(p+1) == '=')
{
p++;
t = TOKEN_NOTEQUAL;
break;
}
t = TOKEN_NOT;
break;
case '(':
t = TOKEN_PAROPEN;
break;
case ')':
t = TOKEN_PARCLOSE;
break;
case '[':
t = TOKEN_SQBRACKETOPEN;
break;
case ']':
t = TOKEN_SQBRACKETCLOSE;
break;
case ',':
t = TOKEN_COMMA;
break;
case '>':
if (*(p+1) == '=')
{
p++;
t = TOKEN_AOREQUAL;
break;
}
if (*(p+1) == '<')
{
p++;
t = TOKEN_NOTEQUAL;
break;
}
t = TOKEN_ABOVE;
break;
case '<':
if (*(p+1) == '=')
{
p++;
t = TOKEN_BOREQUAL;
break;
}
if (*(p+1) == '>')
{
p++;
t = TOKEN_NOTEQUAL;
break;
}
t = TOKEN_BELOW;
break;
case '=':
if (*(p+1) == '>')
{
p++;
t = TOKEN_AOREQUAL;
break;
}
if (*(p+1) == '<')
{
p++;
t = TOKEN_BOREQUAL;
break;
}
if (*(p+1) == '!')
{
p++;
t = TOKEN_NOTEQUAL;
break;
}
if (*(p+1) == '=') p++;
t = TOKEN_EQUAL;
break;
default:
t = TOKEN_UNKNOWN;
break;
}
p++;
}
*size = (int)(p - startptr);
return t;
}

27
Src/nde/osx/Query.h Normal file
View file

@ -0,0 +1,27 @@
#pragma once
#define TOKEN_UNKNOWN -1 // BLAAAAA!!!!!!!!
#define TOKEN_EOQ 0 // End of Query
#define TOKEN_IDENTIFIER 1 // Column name or data to match against
#define TOKEN_EQUAL 2 // =, ==, IS
#define TOKEN_NOTEQUAL 3 // !=, =!, <>, ><
#define TOKEN_BELOW 4 // <
#define TOKEN_ABOVE 5 // >
#define TOKEN_BOREQUAL 6 // <=, =<
#define TOKEN_AOREQUAL 7 // >=, =>
#define TOKEN_NOT 8 // !, NOT
#define TOKEN_AND 9 // &, &&, AND
#define TOKEN_OR 10 // |, ||, OR
#define TOKEN_PAROPEN 11 // (
#define TOKEN_PARCLOSE 12 // )
#define TOKEN_CONTAINS 13 // HAS
#define TOKEN_BEGINS 14 // string starts with...
#define TOKEN_ENDS 15 // string ends with...
#define TOKEN_LIKE 16 // string is nearly (excluding "the " and whitespace etc)
#define TOKEN_ISEMPTY 17 // field does not exists
#define TOKEN_SQBRACKETOPEN 18 // [
#define TOKEN_SQBRACKETCLOSE 19 // ]
#define TOKEN_COMMA 20 // ,
#define TOKEN_NOTCONTAINS 21 // NOTHAS
#define TOKEN_ISNOTEMPTY 22 // field does not exists
#define TOKEN_BEGINSLIKE 23 // string is nearly starts with (excluding "the " and whitespace etc)

138
Src/nde/osx/Record.cpp Normal file
View file

@ -0,0 +1,138 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
Record Class
--------------------------------------------------------------------------- */
//#include "record.h"
#include "nde.h"
#include <stdio.h>
void RecordBase::Retain()
{
ref_count++;
}
void RecordBase::Release()
{
if (--ref_count == 0)
delete this;
}
RecordBase::RecordBase()
{
ref_count = 1;
InsertionPoint = 0;
}
//---------------------------------------------------------------------------
Record::Record(int RecordPos, int insertionPoint, VFILE *TableHandle, Table *ParentTable)
{
InsertionPoint = insertionPoint;
Record *columns = ParentTable->GetColumns();
int max=columns ? columns->Fields.size() : 128;
int n=0;
if (RecordPos != 0)
{
uint32_t ThisPos = RecordPos;
while (ThisPos)
{
if (n >= max)
break;
Vfseek(TableHandle, ThisPos, SEEK_SET);
Field Entry (ThisPos);
Field *TypedEntry = Entry.ReadField(ParentTable, ThisPos, &ThisPos);
if (!TypedEntry) break; // some db error?
AddField(TypedEntry);
n++;
}
}
}
//---------------------------------------------------------------------------
RecordBase::~RecordBase()
{
Fields.deleteAll();
}
#ifdef _WIN32
ColumnField *Record::GetColumnByName(const wchar_t *name)
{
for (FieldList::iterator itr=Fields.begin();itr!=Fields.end();itr++)
{
ColumnField *p = (ColumnField *)*itr;
if (!_wcsicmp(p->GetFieldName(), name))
return p;
}
return NULL;
}
#elif defined(__APPLE__)
ColumnField *Record::GetColumnByName(CFStringRef name)
{
for (FieldList::iterator itr=Fields.begin();itr!=Fields.end();itr++)
{
ColumnField *p = (ColumnField *)*itr;
if (CFStringCompare(p->GetFieldName(), name, kCFCompareCaseInsensitive) == kCFCompareEqualTo)
return p;
}
return NULL;
}
#endif
//---------------------------------------------------------------------------
int Record::WriteFields(Table *ParentTable, int RecordIndex)
{
Field *previous = 0;
for (FieldList::iterator itr=Fields.begin();itr!=Fields.end();itr++)
{
Field *p = *itr;
p->WriteField(ParentTable, previous, (Field *)p->next);
previous = p;
}
return WriteIndex(ParentTable, RecordIndex);
}
//---------------------------------------------------------------------------
int Record::WriteIndex(Table *ParentTable, int RecordIndex)
{
int P=0;
if (RecordIndex == NEW_RECORD)
RecordIndex = ParentTable->index->Insert(InsertionPoint);
if (!Fields.empty())
{
Field *f = *Fields.begin();
P=f->GetFieldPos();
}
return ParentTable->index->Update(RecordIndex, P, this, FALSE);
}
//---------------------------------------------------------------------------
void Record::Delete(Table *ParentTable, int RecordIndex)
{
ParentTable->index->Delete(RecordIndex, ParentTable->index->Get(RecordIndex), this);
}
void Record::WalkFields(FieldsWalker callback, void *context)
{
if (callback)
{
for (FieldList::iterator itr=Fields.begin();itr!=Fields.end();itr++)
{
if (!callback(this, *itr, context))
break;
}
}
}

50
Src/nde/osx/Record.h Normal file
View file

@ -0,0 +1,50 @@
#pragma once
#include "field.h"
#include "Vfs.h"
#include <stdio.h>
#include "../nu/PtrMap.h"
#ifdef __APPLE__
#include <CoreFoundation/CoreFoundation.h>
#endif
class ColumnField;
class RecordBase
{
public:
RecordBase();
virtual ~RecordBase();
Field *GetField(unsigned char ID);
void Retain();
void Release();
void RemoveField(Field *field);
void AddField(Field *field);
protected:
void Undelete(void);
int InsertionPoint; // TODO: benski> might be able to pass this into WriteFields/WriteIndex
int ref_count;
typedef nu::PtrDeque2<Field> FieldList;
FieldList Fields;
};
class Record : public RecordBase
{
public:
Record(int RecordPos, int insertionPoint, VFILE *FileHandle,Table *p);
bool InCache() { return ref_count > 1; }
#ifdef __APPLE__
ColumnField *GetColumnByName(CFStringRef name);
#else
ColumnField *GetColumnByName(const wchar_t *name);
#endif
int WriteFields(Table *ParentTable, int RecordIndex);
int WriteIndex(Table *ParentTable, int RecordIndex);
void Delete(Table *ParentTable, int RecordIndex);
typedef bool (*FieldsWalker)(Record *record, Field *entry, void *context);
NDE_API void WalkFields(FieldsWalker callback, void *context);
};

1283
Src/nde/osx/Scanner.cpp Normal file

File diff suppressed because it is too large Load diff

210
Src/nde/osx/Scanner.h Normal file
View file

@ -0,0 +1,210 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
Scanner Class Prototypes
--------------------------------------------------------------------------- */
#ifndef __SCANNER_H
#define __SCANNER_H
#include "record.h"
#include "Table.h"
#include "index.h"
#include "../nu/Vector.h"
#include "../nu/ValueSet.h"
#ifdef __APPLE__
#include <CoreFoundation/CoreFoundation.h>
#endif
class Table;
class Index;
#pragma warning( disable: 4251 )
class Scanner;
class Record;
class Scanner : public LinkedListEntry
{
public:
Record *GetRecord(int Idx);
Scanner(Table *parentTable);
void IndexModified(void);
Index *GetIndex() { return index; }
Index *index; // TODO: make protected
protected:
~Scanner();
Table *pTable;
BOOL iModified;
typedef Vector<StringField *> SearchStrings;
SearchStrings search_strings;
typedef ValueSet<unsigned char> SearchFields;
SearchFields search_fields;
bool search_any;
void GetCurrentRecord(void);
bool MatchFilters(void);
bool MatchSearches();
bool MatchSearch(const SearchFields &fields, StringField *search_field);
//BOOL MatchJoins(void);
int CheckFilters(void);
void CacheLastLocate(int Id, int From, Field *field, Index *i, int j);
#ifdef _WIN32
static int Query_LookupToken(const wchar_t *token);
#else
static int Query_LookupToken(CFStringRef token);
#endif
void Query_CleanUp(void);
void Query_SyntaxError(int c);
public:
#ifdef _WIN32
static int Query_GetNextToken(const wchar_t *p, int *size, wchar_t **token, int tokentable=0);
static const wchar_t *Query_EatSpace(const wchar_t *p);
static wchar_t *Query_ProbeSpace(wchar_t *p);
static const wchar_t *Query_ProbeNonAlphaNum(const wchar_t *p);
static wchar_t *Query_ProbeAlphaNum(wchar_t *p);
static int Query_isControlChar(wchar_t p);
BOOL Query(const wchar_t *query);
BOOL Query_Parse(const wchar_t *query);
#else
static int Query_GetNextToken(const char *p, size_t *size, CFStringRef *token, int tokentable=0);
static const char *Query_EatSpace(const char *p);
static char *Query_ProbeSpace(char *p);
static const char *Query_ProbeNonAlphaNum(const char *p);
static char *Query_ProbeAlphaNum(char *p);
static int Query_isControlChar(char p);
BOOL Query(const char *query);
BOOL Query_Parse(const char *query);
#endif
#ifdef _WIN32
const wchar_t *GetLastQuery();
#elif defined(__APPLE__)
CFStringRef GetLastQuery();
#endif
public://fucko: protected
//String token;
LinkedList pstack;
#ifdef _WIN32
wchar_t *token;
#else
CFStringRef token;
#endif
#ifdef _WIN32
wchar_t *last_query;
#elif defined(__APPLE__)
CFStringRef last_query;
#endif
int last_query_failed;
protected:
Record *CurrentRecord;
int CurrentRecordIdx;
LinkedList FilterList;
Index *lastLocateIndex;
int lastLocateIdx;
Field *lastLocateFieldClone;
int lastLocateFrom;
int lastLocateId;
BOOL Edition;
int ResultPtr;
BOOL FiltersOK;
public:
bool MatchFilter(Filter *filter);
typedef bool (*FilterWalker)(Scanner *scanner, Filter *filter, void *context);
void WalkFilters(FilterWalker walker, void *context);
#ifdef _WIN32
ColumnField *GetColumnByName(const wchar_t *FieldName);
#else
ColumnField *GetColumnByName(CFStringRef FieldName);
#endif
ColumnField *GetColumnById(unsigned char id);
#ifdef _WIN32
Field *NewFieldByName(const wchar_t *fieldName, unsigned char Perm);
#else
Field *NewFieldByName(CFStringRef fieldName, unsigned char Perm);
#endif
Field *NewFieldById(unsigned char Id, unsigned char Perm);
void DeleteField(Field *field);
#ifdef _WIN32
void DeleteFieldByName(const wchar_t *name);
#else
void DeleteFieldByName(CFStringRef name);
#endif
void DeleteFieldById(unsigned char Id);
void Cancel(void);
void Insert(void);
void Edit(void);
void Post(void);
void Delete(void);
#ifdef _WIN32
Field *GetFieldByName(const wchar_t *FieldName);
#else
Field *GetFieldByName(CFStringRef FieldName);
#endif
Field *GetFieldById(unsigned char Id);
void First(int *killswitch=0);
void Last(int *killswitch=0);
int Next(int *killswitch=0);
int Previous(int *killswitch=0);
BOOL Eof(void);
BOOL Bof(void);
void New(void);
int GetRecordsCount(void);
void GetRecordById(int Id, BOOL checkFilters=TRUE);
int GetRecordId(void);
void Sync(void);
#ifdef _WIN32
BOOL LocateByName(const wchar_t *column, int From, Field *field, int *nskip=NULL);
#else
BOOL LocateByName(CFStringRef column, int From, Field *field, int *nskip=NULL);
#endif
BOOL LocateById(int Id, int From, Field *field, int *nskip=NULL);
BOOL LocateByIdEx(int Id, int From, Field *field, int *nskip, int comp_mode);
// Filters
#ifdef _WIN32
int AddFilterByName(const wchar_t *name, Field *Data, unsigned char Op);
#else
int AddFilterByName(CFStringRef name, Field *Data, unsigned char Op);
#endif
int AddFilterById(unsigned char Id, Field *Data, unsigned char Op);
int AddFilterOp(unsigned char Op);
void RemoveFilters(void);
Filter *GetLastFilter(void);
#ifdef _WIN32
BOOL SetWorkingIndexByName(const wchar_t *desc);
#else
BOOL SetWorkingIndexByName(CFStringRef desc);
#endif
BOOL SetWorkingIndexById(unsigned char Id);
#ifdef _WIN32
void Search(const wchar_t *search_string);
#endif
BOOL HasIndexChanged(void) { return iModified; }
void ClearDirtyBit(void);
float FragmentationLevel(void);
Table *GetTable();
int in_query_parser;
int disable_date_resolution;
};
#endif

297
Src/nde/osx/StringField.cpp Normal file
View file

@ -0,0 +1,297 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
StringField Class
Mac OS X (CFStringRef) implementation
--------------------------------------------------------------------------- */
#include "../nde.h"
#include "StringField.h"
//---------------------------------------------------------------------------
StringField::StringField(CFStringRef Str)
{
InitField();
Type = FIELD_STRING;
if (Str)
{
SetNDEString(Str);
}
}
//---------------------------------------------------------------------------
void StringField::InitField(void)
{
Type = FIELD_STRING;
String=0;
}
//---------------------------------------------------------------------------
StringField::StringField()
{
InitField();
}
//---------------------------------------------------------------------------
StringField::~StringField()
{
if (String)
CFRelease(String);
}
//---------------------------------------------------------------------------
void StringField::ReadTypedData(const uint8_t *data, size_t len)
{
unsigned short c;
CHECK_SHORT(len);
c = (unsigned short)(data[0]|(data[1]<<8));
data+=2;
if (c)
{
bool unicode=false;
if (c >= 2 // enough room for BOM
&& (c % 2) == 0) // can't be unicode if it's not an even multiple of 2
{
wchar_t BOM=0;
memcpy(&BOM, data, 2);
if (BOM == 0xFEFF || BOM == 0xFFFE)
{
unicode=true;
}
}
CHECK_BIN(len, c);
if (unicode)
{
if (String)
CFRelease(String);
String = CFStringCreateWithBytes(kCFAllocatorDefault, data, c, kCFStringEncodingUTF16, true);
}
else
{
if (String)
CFRelease(String);
String = CFStringCreateWithBytes(kCFAllocatorDefault, data, c, kCFStringEncodingWindowsLatin1, false);
}
}
}
//---------------------------------------------------------------------------
void StringField::WriteTypedData(uint8_t *data, size_t len)
{
int pos=0;
CHECK_SHORT(len);
if (String)
{
CFIndex lengthRequired=0;
CFStringGetBytes(String, CFRangeMake(0, CFStringGetLength(String)), kCFStringEncodingUTF16, 0, true, NULL, 0, &lengthRequired);
CHECK_BIN(len, lengthRequired+2);
PUT_SHORT(lengthRequired); pos+=2;
CFStringGetBytes(String, CFRangeMake(0, CFStringGetLength(String)), kCFStringEncodingUTF16, 0, true, data+pos, lengthRequired, 0);
}
else
{
PUT_SHORT(0);
}
}
CFStringRef StringField::GetString()
{
return String;
}
void StringField::SetNDEString(CFStringRef Str)
{
if (!Str)
return;
CFStringRef old = String;
String = (CFStringRef)CFRetain(Str);
CFRelease(old);
}
//---------------------------------------------------------------------------
size_t StringField::GetDataSize(void)
{
if (String)
{
CFIndex lengthRequired=0;
CFStringGetBytes(String, CFRangeMake(0, CFStringGetLength(String)), kCFStringEncodingUTF16, 0, true, NULL, 0, &lengthRequired);
return lengthRequired+2;
}
else
return 2;
}
//---------------------------------------------------------------------------
int StringField::Compare(Field *Entry)
{
if (!Entry) return -1;
if (Entry->GetType() != GetType()) return 0;
CFStringRef compareString = ((StringField*)Entry)->GetString();
if (!String && !compareString) return 0;
if (!String && compareString) return 1;
if (!compareString) return -1;
return CFStringCompare(String, compareString, kCFCompareCaseInsensitive|kCFCompareNonliteral|kCFCompareDiacriticInsensitive);
}
//---------------------------------------------------------------------------
int StringField::Starts(Field *Entry)
{
if (!Entry) return -1;
if (Entry->GetType() != GetType()) return 0;
CFStringRef compareString = ((StringField*)Entry)->GetString();
if (!String || !compareString) return 0;
CFRange findRange = CFStringFind(String, compareString, kCFCompareCaseInsensitive|kCFCompareNonliteral|kCFCompareAnchored|kCFCompareDiacriticInsensitive);
if (findRange.location == kCFNotFound)
return 0;
return findRange.location == 0;
}
//---------------------------------------------------------------------------
int StringField::Contains(Field *Entry)
{
if (!Entry) return -1;
if (Entry->GetType() != GetType()) return 0;
CFStringRef compareString = ((StringField*)Entry)->GetString();
if (!String || !compareString) return 0;
CFRange findRange = CFStringFind(String, compareString, kCFCompareCaseInsensitive|kCFCompareNonliteral|kCFCompareDiacriticInsensitive);
return findRange.location != kCFNotFound;
}
Field *StringField::Clone(Table *pTable)
{
StringField *clone = new StringField(String);
clone->Pos = FIELD_CLONE;
clone->ID = ID;
clone->MaxSizeOnDisk = GetDataSize();
return clone;
}
//---------------------------------------------------------------------------
bool StringField::ApplyFilter(Field *Data, int op)
{
if (op == FILTER_ISEMPTY || op == FILTER_ISNOTEMPTY)
{
bool r = (op == FILTER_ISEMPTY);
if (!String)
return r;
if (CFStringGetLength(String) == 0)
return r;
return !r;
}
//
bool r;
StringField *compField = (StringField *)Data;
switch (op)
{
case FILTER_EQUALS:
r = !Compare(Data);
break;
case FILTER_NOTEQUALS:
r = !!Compare(Data);
break;
case FILTER_CONTAINS:
r = !!Contains(Data);
break;
case FILTER_NOTCONTAINS:
r = !Contains(Data);
break;
case FILTER_ABOVE:
r = (bool)(Compare(Data) > 0);
break;
case FILTER_ABOVEOREQUAL:
r = (bool)(Compare(compField) >= 0);
break;
case FILTER_BELOW:
r = (bool)(Compare(compField) < 0);
break;
case FILTER_BELOWOREQUAL:
r = (bool)(Compare(compField) <= 0);
break;
case FILTER_BEGINS:
r = !!Starts(compField);
break;
case FILTER_ENDS:
{
CFStringRef compareString = ((StringField*)Data)->GetString();
if (!String || !compareString) return 0;
CFRange findRange = CFStringFind(String, compareString, kCFCompareCaseInsensitive|kCFCompareNonliteral|kCFCompareAnchored|kCFCompareBackwards);
if (findRange.location == kCFNotFound)
r=0;
else
r = findRange.location != 0;
}
break;
case FILTER_LIKE:
/* TODO
if (compField->optimized_the)
p = compField->optimized_the;
else
{
SKIP_THE_AND_WHITESPACEW(p);
compField->optimized_the = p;
}
if (optimized_the)
d = optimized_the;
else
{
SKIP_THE_AND_WHITESPACEW(d);
optimized_the=d;
}
r = (bool)(nde_wcsicmp(d, p) == 0);
*/
r = !!Compare(compField);
break;
case FILTER_BEGINSLIKE:
/*
if (compField->optimized_the)
p = compField->optimized_the;
else
{
SKIP_THE_AND_WHITESPACEW(p);
compField->optimized_the = p;
}
if (optimized_the)
d = optimized_the;
else
{
SKIP_THE_AND_WHITESPACEW(d);
optimized_the=d;
}
r = (bool)(nde_wcsnicmp(d, p, wcslen(p)) == 0);
*/
r = !!Starts(compField);
break;
default:
r = true;
break;
}
return r;
}

50
Src/nde/osx/StringField.h Normal file
View file

@ -0,0 +1,50 @@
/*
---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
---------------------------------------------------------------------------
*/
/*
---------------------------------------------------------------------------
StringField Class Prototypes
---------------------------------------------------------------------------
*/
#ifndef __STRINGFIELD_H
#define __STRINGFIELD_H
#include <CoreFoundation/CFString.h>
class StringField : public Field
{
public:
StringField();
~StringField();
StringField(CFStringRef Str);
CFStringRef GetString(); // CFRetain this if you need to keep it for a while
void SetNDEString(CFStringRef str);
protected:
virtual void ReadTypedData(const uint8_t *, size_t len);
virtual void WriteTypedData(uint8_t *, size_t len);
virtual size_t GetDataSize(void);
virtual int Compare(Field *Entry);
virtual int Starts(Field *Entry);
virtual int Contains(Field *Entry);
virtual bool ApplyFilter(Field *Data, int op);
virtual Field *Clone(Table *pTable);
void InitField(void);
CFStringRef String;
};
#endif

659
Src/nde/osx/Table.cpp Normal file
View file

@ -0,0 +1,659 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
Table Class
Apple Mac OS X implementation
--------------------------------------------------------------------------- */
#include "../nde.h"
#include <stdio.h>
#include <string.h>
#include "../CRC.H"
const char *tSign="NDETABLE";
//---------------------------------------------------------------------------
Table::Table(const char *TableName, const char *Idx, BOOL Create, Database *_db, BOOL _Cached)
: columns_cached(false), use_row_cache(false), Scanner(this)
{
Handle = 0;
memset(column_ids, FIELD_UNKNOWN, 255);
Cached = _Cached;
db = _db;
AutoCreate = Create;
Name = strdup(TableName);
IdxName = strdup(Idx);
Init();
}
//---------------------------------------------------------------------------
void Table::Init()
{
numErrors = 0;
Scanners = new LinkedList();
// benski> cut: Handle=NULL;
IdxHandle=NULL;
FieldsRecord=NULL;
IndexList=NULL;
GLocateUpToDate = FALSE;
}
//---------------------------------------------------------------------------
Table::~Table()
{
Reset();
if (Handle) // Reset doesn't completely destroy Handle
Vfdestroy(Handle);
Handle = 0;
free(Name);
free(IdxName);
}
//---------------------------------------------------------------------------
void Table::Reset()
{
if (IndexList) IndexList->Release();
IndexList=0;
if (FieldsRecord) FieldsRecord->Release();
FieldsRecord=0;
delete Scanners;
Scanners=0;
if (Handle)
Vfclose(Handle); // close (but don't destroy) to keep mutex open.
if (IdxHandle)
Vfdestroy(IdxHandle);
IdxHandle = 0;
for (RowCache::iterator itr=rowCache.begin();itr!=rowCache.end();itr++)
{
if (itr->second)
itr->second->Release();
}
rowCache.clear();
memset(column_ids, FIELD_UNKNOWN, 255);
columns_cached=false;
}
struct IndexNewWalkerContext
{
IndexNewWalkerContext(Table *_table)
{
N = -1;
table = _table;
}
int N;
Table *table;
};
bool Table::IndexNewWalker(IndexRecord *record, Field *entry, void *context_in)
{
IndexNewWalkerContext *context = (IndexNewWalkerContext *)context_in;
IndexField *p = (IndexField *)entry;
p->index = new Index(context->table->IdxHandle, p->ID, context->N++, p->Type, FALSE, 0, context->table);
return true;
}
//---------------------------------------------------------------------------
BOOL Table::Open(void)
{
BOOL Valid;
int justcreated = 0;
if (!Handle)
Handle = Vfnew(Name, "r+b", Cached);
if (!Handle) return FALSE;
if (!Vflock(Handle))
{
Vfdestroy(Handle);
Handle = 0;
return FALSE;
}
Handle = Vfopen(Handle, Name, "r+b", Cached);
IdxHandle = Vfopen(0, IdxName, "r+b", TRUE);
Valid = (Handle && IdxHandle);
// unlock
if (Valid || !AutoCreate)
{
//if (Handle)
//Vfunlock(Handle);
}
else
{
if (Handle)
{
Vfclose(Handle);
if (IdxHandle)
Vfdestroy(IdxHandle);
IdxHandle = 0;
}
else
{
if (IdxHandle)
Vfdestroy(IdxHandle);
IdxHandle = 0;
Handle = Vfnew(Name, "w+b", Cached);
if (!Vflock(Handle))
{
Vfdestroy(Handle);
return FALSE;
}
}
Handle = Vfopen(Handle, Name, "w+b", Cached);
IdxHandle = Vfopen(0, IdxName, "w+b", TRUE);
Valid = (Handle && IdxHandle);
if (Valid)
{
Vfwrite(__TABLE_SIGNATURE__, strlen(__TABLE_SIGNATURE__), Handle);
Vfwrite(__INDEX_SIGNATURE__, strlen(__TABLE_SIGNATURE__), IdxHandle);
// TODO bensk> change if NUM_SPECIAL_RECORDS ever increases
int v=NUM_SPECIAL_RECORDS;//strlen(__TABLE_SIGNATURE__);
Vfwrite(&v, sizeof(v), IdxHandle);
// v = 0; fwrite(&v, sizeof(v), 1, IdxHandle);
v = -1; Vfwrite(&v, sizeof(v), IdxHandle); // write ID
v = 0;
for (int i=0;i<NUM_SPECIAL_RECORDS;i++)
{
Vfwrite(&v, sizeof(v), IdxHandle);
Vfwrite(&v, sizeof(v), IdxHandle);
}
Sync();
justcreated = 1;
}
}
if (!Valid)
{
if (Handle) Vfdestroy(Handle);
if (IdxHandle) Vfdestroy(IdxHandle);
Handle = NULL;
IdxHandle = NULL;
}
else
{
int Ptr;
char test1[9]={0,};
char test2[9]={0,};
Vfseek(Handle, 0, SEEK_SET);
Vfread(test1, strlen(__TABLE_SIGNATURE__), Handle);
Vfseek(IdxHandle, 0, SEEK_SET);
Vfread(test2, strlen(__INDEX_SIGNATURE__), IdxHandle);
test1[8]=0;
test2[8]=0;
if (strcmp(test1, __TABLE_SIGNATURE__) || strcmp(test2, __INDEX_SIGNATURE__))
{
if (Handle) Vfdestroy(Handle);
Handle = 0;
if (IdxHandle) Vfdestroy(IdxHandle);
IdxHandle = 0;
return FALSE;
}
// Load default index
IndexField *field;
field = new IndexField(PRIMARY_INDEX, -1, -1, CFSTR("None"));
field->index = new Index(IdxHandle, PRIMARY_INDEX, -1, -1, FALSE, 0, this);
// Get indexes
Ptr = field->index->Get(INDEX_RECORD_NUM);
IndexList = new IndexRecord(Ptr, INDEX_RECORD_NUM, Handle, this);
if (!IndexList)
{
delete field;
if (Handle) Vfdestroy(Handle);
Handle = 0;
if (IdxHandle) Vfdestroy(IdxHandle);
IdxHandle = 0;
return FALSE;
}
// Init them
IndexNewWalkerContext newContext(this);
IndexList->WalkFields(IndexNewWalker, &newContext);
// Add default in case its not there (if it is it won't be added by addfield)
IndexList->AddField(field);
// Get the default index (whether loaded or preloaded)
Scanner::index = ((IndexField*)IndexList->GetField(PRIMARY_INDEX))->index;
// If it's different from preloaded, delete preloaded
if (field->index != Scanner::index)
{
delete field;
field=0;
}
// Set up colaboration
IndexList->BuildCollaboration();
// Get columns
Ptr = Scanner::index->Get(FIELDS_RECORD_NUM);
FieldsRecord = new Record(Ptr, FIELDS_RECORD_NUM, Handle, this);
if (!FieldsRecord)
{
IndexList->Release();
IndexList=0;
if (Handle) Vfdestroy(Handle);
Handle = 0;
if (IdxHandle) Vfdestroy(IdxHandle);
IdxHandle = 0;
return FALSE;
}
// update the column cache
FieldsRecord->WalkFields(BuildColumnCache, this);
columns_cached=true;
}
#if 0 // TODO
if (Valid && !justcreated)
{
if (IndexList->NeedFix())
Compact();
}
#endif
if (Valid) First();
if (Handle)
Vfunlock(Handle);
return Valid;
}
//---------------------------------------------------------------------------
void Table::Close(void)
{
int v=0;
if (Handle && IndexList && Vflock(Handle, 0))
{
IndexList->WalkFields(IndexWriteWalker, 0);
}
delete Scanners;
Scanners = NULL;
Vsync(Handle);
if (IdxHandle)
{
Vfdestroy(IdxHandle);
IdxHandle = NULL;
v |= 2;
}
if (Handle)
{
Vfdestroy(Handle);
Handle = NULL;
v |= 1;
}
if (v != 3)
return;
}
bool Table::IndexWriteWalker(IndexRecord *record, Field *entry, void *context)
{
IndexField *field = (IndexField *)entry;
field->index->WriteIndex();
return true;
}
//---------------------------------------------------------------------------
void Table::Sync(void)
{
if (!Vflock(Handle))
return;
if (IndexList)
IndexList->WalkFields(IndexWriteWalker, 0);
int err=0;
if (!err && Handle) err|=Vsync(Handle);
if (!err && IdxHandle) err|=Vsync(IdxHandle);
Vfunlock(Handle);
}
//---------------------------------------------------------------------------
ColumnField *Table::NewColumn(unsigned char FieldID, CFStringRef FieldName, unsigned char FieldType, BOOL indexUnique)
{
columns_cached=false; // if they start writing new columns, kill the columns cache until they PostColumns()
ColumnField *f = GetColumnById(FieldID);
if (f) {
int t = f->GetDataType();
if (t != FieldType) {
if (CompatibleFields(t, FieldType))
{
f->SetDataType(FieldType);
goto aok;
}
}
return NULL;
}
aok:
if (GetColumnByName(FieldName))
return NULL;
ColumnField *field = new ColumnField(FieldID, FieldName, FieldType, this);
column_ids[FieldID]=FieldType;
FieldsRecord->AddField(field);
return field;
}
void Table::SetFieldSearchableById(unsigned char field_id, bool searchable)
{
ColumnField *column = GetColumnById(field_id);
if (column)
column->SetSearchable(searchable);
if (searchable)
{
search_fields.insert(field_id);
}
else
{
search_fields.erase(field_id);
}
}
//---------------------------------------------------------------------------
bool Table::BuildColumnCache(Record *record, Field *entry, void *context)
{
Table *table = (Table *)context;
ColumnField *column = (ColumnField *)entry;
unsigned char field_id=column->GetFieldId();
table->column_ids[field_id] = column->GetDataType();
if (column->IsSearchableField())
{
table->search_fields.insert(field_id);
}
else
{
table->search_fields.erase(field_id);
}
return true;
}
//---------------------------------------------------------------------------
void Table::PostColumns(void)
{
FieldsRecord->WriteFields(this, FIELDS_RECORD_NUM);
memset(column_ids, FIELD_UNKNOWN, 255);
FieldsRecord->WalkFields(BuildColumnCache, this);
columns_cached=true;
}
unsigned char Table::GetColumnType(unsigned char Id)
{
if (columns_cached)
{
return column_ids[Id];
}
else
{
return GetColumnById(Id)->GetDataType();
}
}
//---------------------------------------------------------------------------
IndexField *Table::GetIndexByName(CFStringRef name)
{
if (!IndexList)
return NULL;
return IndexList->GetIndexByName(name);
}
//---------------------------------------------------------------------------
IndexField *Table::GetIndexById(unsigned char Id)
{
if (!IndexList)
return NULL;
return (IndexField *)IndexList->GetField(Id);
}
//---------------------------------------------------------------------------
void Table::AddIndexByName(CFStringRef name, CFStringRef desc)
{
ColumnField *header = GetColumnByName(name);
if (header)
{
unsigned char Idx = header->ID;
AddIndexById(Idx, desc);
}
}
//---------------------------------------------------------------------------
void Table::AddIndexById(unsigned char Id, CFStringRef desc)
{
if (GetIndexById(Id)) return;
ColumnField *col = GetColumnById(Id);
if (!col)
return;
IndexField *newindex = new IndexField(Id, IndexList->GetColumnCount(), col->GetDataType(), desc);
newindex->index = new Index(IdxHandle, Id, IndexList->GetColumnCount(), col->GetDataType(), TRUE, Scanner::index->NEntries, this);
IndexList->AddField(newindex);
IndexField *previous = (IndexField *)newindex->prev;
previous->index->Colaborate(newindex);
IndexField *primary_index = (IndexField *)IndexList->GetField(PRIMARY_INDEX);
newindex->index->Colaborate(primary_index);
previous->index->Propagate();
IndexList->WriteFields(this);
}
//---------------------------------------------------------------------------
BOOL Table::CheckIndexing(void)
{
if (IndexList->GetColumnCount() == 0) return TRUE;
for (int i=0;i<Scanner::index->NEntries;i++)
{
if (!IndexList->CheckIndexing(i))
return FALSE;
}
return TRUE;
}
struct IndexWalkerThunkContext
{
void *context;
Table *_this;
Table::IndexWalker callback;
};
bool Table::IndexWalkerThunk(IndexRecord *record, Field *entry, void *context_in)
{
IndexWalkerThunkContext *context = (IndexWalkerThunkContext *)context_in;
return context->callback(context->_this, (IndexField *)entry, context->context);
}
//---------------------------------------------------------------------------
void Table::WalkIndices(IndexWalker callback, void *context)
{
if (IndexList && callback)
{
IndexWalkerThunkContext walkerContext = { context, this, callback };
IndexList->WalkFields(IndexWalkerThunk, &walkerContext);
}
}
//---------------------------------------------------------------------------
void Table::DropIndex(IndexField *Ptr)
{
if (!Ptr || Ptr->Type != FIELD_INDEX) return;
if (Scanner::index == Ptr->index)
{
Scanner::index = ((IndexField*)IndexList->GetField(PRIMARY_INDEX))->index;
IndexList->BuildCollaboration();
}
IndexList->RemoveField(Ptr);
if (Scanner::index->SecIndex == Ptr)
Scanner::index->SecIndex = 0;
IndexList->SetModified(TRUE);
IndexList->WriteFields(this);
}
//---------------------------------------------------------------------------
void Table::DropIndexByName(CFStringRef desc)
{
IndexField *indx = GetIndexByName(desc);
if (CFStringCompare(desc, CFSTR("None"), kCFCompareCaseInsensitive) == kCFCompareEqualTo)
return;
if (indx)
DropIndex(indx);
}
//---------------------------------------------------------------------------
void Table::DropIndexById(unsigned char Id)
{
if (!IndexList)
return;
if (Id == (unsigned char)PRIMARY_INDEX) return;
IndexField *indx=(IndexField *)IndexList->GetField(Id);
if (indx)
DropIndex(indx);
}
//---------------------------------------------------------------------------
BOOL Table::LocateByIdEx(int Id, int From, Field *field, int comp_mode)
{
return Scanner::LocateByIdEx(Id, From, field, NULL, comp_mode);
}
//---------------------------------------------------------------------------
Record *Table::GetColumns(void)
{
if (!FieldsRecord)
return NULL;
return FieldsRecord;
}
//---------------------------------------------------------------------------
Scanner *Table::NewScanner()
{
Scanner *s = new Scanner(this);
/*if (Scanners->GetNElements() > 0)*/
s->index = Scanner::index;
Scanners->AddEntry(s, TRUE);
return s;
}
//---------------------------------------------------------------------------
Scanner *Table::GetDefaultScanner(void)
{
return this;
}
//---------------------------------------------------------------------------
void Table::DeleteScanner(Scanner *scan)
{
if (!scan) return;
Scanners->RemoveEntry(scan);
}
//---------------------------------------------------------------------------
void Table::IndexModified(void)
{
Scanner *s = (Scanner *)Scanners->GetHead();
while (s)
{
s->IndexModified();
s = (Scanner *)s->GetNext();
}
}
//---------------------------------------------------------------------------
void Table::SetGlobalLocateUpToDate(BOOL is) {
GLocateUpToDate = is;
}
ColumnField *Table::GetColumnById(unsigned char Idx)
{
if (!FieldsRecord)
return NULL;
return (ColumnField *)FieldsRecord->GetField(Idx);
}
ColumnField *Table::GetColumnByName(CFStringRef FieldName)
{
return FieldsRecord->GetColumnByName(FieldName);
}
void Table::RowCache_Delete(int position)
{
if (use_row_cache)
{
RowCache::iterator found = rowCache.find(position);
if (found != rowCache.end())
{
if (found->second)
found->second->Release();
rowCache.erase(found);
}
}
}
void Table::RowCache_Remove(int position)
{
if (use_row_cache)
{
Record *&row = rowCache[position];
if (row)
{
row->Release();
}
row = 0;
}
}
void Table::RowCache_Add(Record *record, int position)
{
if (use_row_cache)
{
record->Retain();
Record *&row = rowCache[position];
if (row)
{
row->Release();
}
row = record;
}
}
Record *Table::RowCache_Get(int position)
{
if (!use_row_cache)
return 0;
Record *row = rowCache[position];
if (row)
row->Retain();
return row;
}
void Table::EnableRowCache()
{
use_row_cache=true;
}

165
Src/nde/osx/Table.h Normal file
View file

@ -0,0 +1,165 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
Table Class Prototypes
Apple Mac OS X implementation
--------------------------------------------------------------------------- */
#ifndef __TABLE_H
#define __TABLE_H
#include <stdio.h>
#include "Scanner.h"
#include <map>
#include "IndexRecord.h"
class Table : private Scanner
{
public:
// TODO: move these back to protected
VFILE *Handle;
using Scanner::index;
bool use_row_cache;
BOOL GLocateUpToDate;
private:
void Init();
void Reset();
private:
LinkedList *Scanners;
protected:
char *Name; // TODO: CFStringRef
char *IdxName; // TODO: CFStringRef
VFILE *IdxHandle;
BOOL AutoCreate;
Record *FieldsRecord;
IndexRecord *IndexList;
Database *db;
BOOL Cached;
int numErrors;
using Scanner::Edition;
bool columns_cached;
unsigned char column_ids[256];
typedef std::map<int, Record*> RowCache;
RowCache rowCache;
// Tables
static bool Compact_ColumnWalk(Record *record, Field *entry, void *context_in);
static bool Compact_ColumnWalk2(Record *record, Field *entry, void *context_in);
static bool Compact_IndexWalk(Table *table, IndexField *entry, void *context);
static bool IndexWriteWalker(IndexRecord *record, Field *entry, void *context);
static bool IndexWalkerThunk(IndexRecord *record, Field *entry, void *context);
static bool IndexNewWalker(IndexRecord *record, Field *entry, void *context);
static bool BuildColumnCache(Record *record, Field *entry, void *context);
public:
typedef bool (*IndexWalker)(Table *table, IndexField *entry, void *context);
Table(const char *TableName, const char *IdxName, BOOL Create, Database *db, BOOL Cached);
~Table();
BOOL Open(void);
void Close(void);
// Columns
ColumnField *NewColumn(unsigned char Id, CFStringRef name, unsigned char type, BOOL indexUniques);
void DeleteColumn(ColumnField *field); // todo
void DeleteColumnByName(const wchar_t *name); // todo
void DeleteColumnById(unsigned char Id); // todo
void PostColumns(void);
NDE_API Record *GetColumns(void);
ColumnField *GetColumnByName(CFStringRef FieldName);
ColumnField *GetColumnById(unsigned char Idx);
unsigned char GetColumnType(unsigned char Id);
// Fields
using Scanner::NewFieldByName;
using Scanner::NewFieldById;
using Scanner::GetFieldByName;
using Scanner::GetFieldById;
using Scanner::DeleteField;
using Scanner::DeleteFieldByName;
using Scanner::DeleteFieldById;
// Records
using Scanner::First;
using Scanner::Last;
using Scanner::Next;
using Scanner::Previous;
using Scanner::Eof;
using Scanner::Bof;
using Scanner::New;
using Scanner::Insert;
using Scanner::Edit;
using Scanner::Cancel;
using Scanner::Post;
using Scanner::Delete;
using Scanner::GetRecordsCount;
using Scanner::GetRecordById;
using Scanner::GetRecordId;
void Sync(void);
using Scanner::LocateByName;
using Scanner::LocateById;
BOOL LocateByIdEx(int Id, int From, Field *field, int comp_mode);
// Indexes
void AddIndexByName(CFStringRef FieldName, CFStringRef KeyName);
void AddIndexById(unsigned char Id, CFStringRef KeyName);
void WalkIndices(IndexWalker callback, void *context);
IndexField *GetIndexByName(CFStringRef name);
IndexField *GetIndexById(unsigned char Id);
using Scanner::SetWorkingIndexByName;
using Scanner::SetWorkingIndexById;
NDE_API BOOL CheckIndexing(void);
void DropIndexByName(CFStringRef desc);
void DropIndexById(unsigned char Id);
void DropIndex(IndexField *Ptr);
void IndexModified(void);
// Filters
using Scanner::AddFilterByName;
using Scanner::AddFilterById;
using Scanner::AddFilterOp;
using Scanner::RemoveFilters;
// Scanners
Scanner *NewScanner();
Scanner *GetDefaultScanner(void);
void DeleteScanner(Scanner *scan);
// Misc
using Scanner::FragmentationLevel;
void Compact(int *progress = NULL);
void SetGlobalLocateUpToDate(BOOL is);
// Row Cache
void RowCache_Delete(int position);
void RowCache_Remove(int position);
void RowCache_Add(Record *record, int position);
Record *RowCache_Get(int position);
NDE_API void EnableRowCache();
// Searching
void SetFieldSearchableById(unsigned char field_id, bool searchable);
int HasErrors()
{
return numErrors > 0;
}
int NumErrors()
{
return numErrors;
}
void IncErrorCount()
{
numErrors++;
}
};
#endif

542
Src/nde/osx/Vfs.cpp Normal file
View file

@ -0,0 +1,542 @@
/* ---------------------------------------------------------------------------
Nullsoft Database Engine
--------------------
codename: Near Death Experience
--------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
Virtual File System
--------------------------------------------------------------------------- */
#include "nde.h"
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "Vfs.h"
#ifndef EOF
#define EOF -1
#endif
#include "../nu/strsafe.h"
/* the FILE (fopen/fwrite/etc) implementation for Mac and Linux */
VFILE *Vfnew(const char *fl, const char *mode, BOOL Cached)
{
if (!fl) return NULL;
VFILE *f = (VFILE *)malloc(sizeof(VFILE));
if (!f)
return NULL;
memset(f, 0, sizeof(VFILE));
#ifdef NDE_ALLOW_NONCACHED
f->cached = Cached;
#else
f->cached = TRUE;
#endif
if (!strchr(mode, '+'))
{
if (strchr(mode, 'r'))
f->mode = VFS_READ | VFS_MUSTEXIST;
if (strchr(mode, 'w'))
f->mode = VFS_WRITE | VFS_CREATE | VFS_NEWCONTENT;
if (strchr(mode, 'a'))
f->mode = VFS_WRITE | VFS_CREATE | VFS_SEEKEOF;
}
else
{
if (strstr(mode, "r+"))
f->mode = VFS_WRITE | VFS_MUSTEXIST;
if (strstr(mode, "w+"))
f->mode = VFS_WRITE | VFS_CREATE | VFS_NEWCONTENT;
if (strstr(mode, "a+"))
f->mode = VFS_WRITE | VFS_CREATE | VFS_SEEKEOF;
}
if (f->mode == 0 || ((f->mode & VFS_READ) && (f->mode & VFS_WRITE)))
{
free(f);
return NULL;
}
snprintf(f->lockname, sizeof(f->lockname), "%s.lock", fl);
return f;
}
//----------------------------------------------------------------------------
VFILE *Vfopen(VFILE *f, const char *fl, const char *mode, BOOL Cached)
{
if (!f)
{
f = Vfnew(fl, mode, Cached);
if (!f)
return 0;
}
if (!f && !fl) return NULL;
#ifdef NDE_ALLOW_NONCACHED
if (!f->cached)
{
f->rfile = fopen(fl, mode);
if (f->rfile)
f->filename = _strdup(fl);
}
else
{
free(f);
return NULL;
}
return f;
}
#endif
if (f->mode & VFS_MUSTEXIST)
{
if (access(fl, 0) != 0)
{
free(f);
return NULL;
}
}
if (!(f->mode & VFS_NEWCONTENT))
{
FILE *pf;
pf = fopen(fl, "rb");
if (!pf)
{
f->data = (unsigned char *)calloc(VFILE_INC, 1);
if (f->data == NULL)
{
free(f);
return NULL;
}
f->filesize = 0;
f->maxsize = VFILE_INC;
}
else
{
fseek(pf, 0, SEEK_END);
f->filesize = ftell(pf);
fseek(pf, 0, SEEK_SET);
f->data = (unsigned char *)calloc(f->filesize, 1);
if (f->data == NULL)
{
free(f);
return NULL;
}
f->maxsize = f->filesize;
fread(f->data, f->filesize, 1, pf);
fclose(pf);
}
}
if (f->mode & VFS_SEEKEOF)
f->ptr = f->filesize;
f->filename = strdup(fl);
return f;
}
//----------------------------------------------------------------------------
void Vfclose(VFILE *f)
{
if (!f) return;
#ifdef NDE_ALLOW_NONCACHED
if (!f->cached)
{
free(f->filename);
if (f->rfile)
fclose(f->rfile);
f->rfile=0;
// free(f);
return;
}
#endif
if (!(f->mode & VFS_WRITE))
{
free(f->filename);
free(f->data);
//free(f);
return;
}
Vsync(f);
while (f->locks)
Vfunlock(f, 1);
free(f->filename);
free(f->data);
//free(f);
}
//----------------------------------------------------------------------------
size_t Vfread(void *ptr, size_t size, VFILE *f)
{
if (!ptr || !f) return 0;
#ifdef NDE_ALLOW_NONCACHED
if (!f->cached)
{
return fread(ptr, 1, size, f->rfile);
}
#endif
size_t s = size;
if (!s) return 0;
if (s + f->ptr > f->filesize)
{
//FUCKO: remove this
if (!(f->ptr < f->filesize))
{
// if (!f->flushtable) // this would be ideal, if we could figure out f->flushtable
// f->flushtable=MessageBox(g_hwnd,"DB read failed, DB may be corrupted.\r\n\r\n"
// "Hit Retry to continue, or Cancel to clear the DB and start over","Winamp Library Error",MB_RETRYCANCEL) == IDCANCEL; //fucko
//MessageBox(g_hwnd,"DB read failed, DB may be corrupted. If this error persists, remove all files from the library.",
// "Winamp Library Error",MB_OK);
return 0;
}
s = f->filesize - f->ptr;
}
memcpy(ptr, f->data+f->ptr, s);
f->ptr += s;
return (s/size);
}
//----------------------------------------------------------------------------
void Vfwrite(const void *ptr, size_t size, VFILE *f)
{
if (!ptr || !f) return;
#ifdef NDE_ALLOW_NONCACHED
if (!f->cached)
{
fwrite(ptr, size*n, f->rfile);
return;
}
#endif
f->dirty=1;
if (size + f->ptr > f->maxsize)
{
// grow f->data,f->maxsize to be (size + f->ptr + VFILE_INC-1)&~(VFILE_INC-1)
// instead of calling Vgrow again which gets kinda slow
size_t newsize=(size + f->ptr + VFILE_INC-1)&~(VFILE_INC-1);
f->data=(unsigned char *)realloc(f->data,newsize);
if (f->data == NULL) return;
memset(f->data+f->maxsize,0,newsize-f->maxsize);
f->maxsize=newsize;
}
memcpy(f->data + f->ptr, ptr, size);
f->ptr += size;
if (f->ptr > f->filesize)
f->filesize = f->ptr;
}
//----------------------------------------------------------------------------
void Vgrow(VFILE *f)
{
if (!f) return;
#ifdef NDE_ALLOW_NONCACHED
if (!f->cached) return;
#endif
f->data = (unsigned char *)realloc(f->data, f->maxsize + VFILE_INC);
f->maxsize += VFILE_INC;
}
//----------------------------------------------------------------------------
void Vfputs(char *str, VFILE *f)
{
if (!f) return;
#ifdef NDE_ALLOW_NONCACHED
if (!f->cached)
{
fputs(str, f->rfile);
return;
}
#endif
Vfwrite(str, strlen(str), f);
}
//----------------------------------------------------------------------------
void Vfputc(char c, VFILE *f)
{
if (!f) return;
#ifdef NDE_ALLOW_NONCACHED
if (!f->cached)
{
fputc(c, f->rfile);
return;
}
#endif
Vfwrite(&c, 1, f);
}
/* benski> unused:
// not mac compliant
//----------------------------------------------------------------------------
char *Vfgets(char *dest, int n, VFILE *f) {
if (!f) return NULL;
#ifdef NDE_ALLOW_NONCACHED
if (!f->cached)
{
#ifdef NDE_NOWIN32FILEIO
return fgets(dest, n, f->rfile);
#else
#error port me!
#endif
}
#endif
unsigned char c=0;
char *p;
int l=0;
p = dest;
while (l < n && !Vfeof(f)) {
c = f->data[f->ptr];
f->ptr++;
*p = c;
p++;
l++;
if (c == '\n') {
if (!Vfeof(f) && f->data[f->ptr] == '\r') {
f->ptr++;
}
break;
}
}
*p=0;
return dest;
}
*/
/* benski> unused:
//----------------------------------------------------------------------------
char Vfgetc(VFILE *f) {
if (!f) return EOF;
#ifdef NDE_ALLOW_NONCACHED
if (!f->cached)
#ifdef NDE_NOWIN32FILEIO
return fgetc(f->rfile);
#else
#error port me#
#endif
#endif
if (!Vfeof(f))
return f->data[f->ptr++];
return EOF;
}
*/
//----------------------------------------------------------------------------
unsigned long Vftell(VFILE *f)
{
if (!f) return (unsigned)-1;
#ifdef NDE_ALLOW_NONCACHED
if (!f->cached)
{
return ftell(f->rfile);
}
#endif
return f->ptr;
}
//----------------------------------------------------------------------------
void Vfseek(VFILE *f, long i, int whence)
{
if (!f) return;
#ifdef NDE_ALLOW_NONCACHED
if (!f->cached)
{
fseek(f->rfile, i, whence);
return;
}
#endif
switch (whence)
{
case SEEK_SET:
f->ptr = i;
break;
case SEEK_CUR:
f->ptr += i;
break;
case SEEK_END:
f->ptr = f->filesize+i;
break;
}
}
//----------------------------------------------------------------------------
int Vfeof(VFILE *f)
{
if (!f) return -1;
#ifdef NDE_ALLOW_NONCACHED
if (!f->cached)
{
return feof(f->rfile);
}
#endif
return (f->ptr >= f->filesize);
}
//----------------------------------------------------------------------------
int Vsync(VFILE *f)
{
if (!f) return 0;
if (!f->dirty) return 0;
if (f->mode & VFS_WRITE)
{
#ifdef NDE_ALLOW_NONCACHED
if (!f->cached)
{
int p=ftell(f->rfile);
fclose(f->rfile);
f->rfile = fopen(f->filename, "r+b");
if (!f->rfile)
return 1;
fseek(f->rfile, p, SEEK_SET);
return 0;
}
#endif
char newfn[1024], oldfn[1024];
DWORD mypid=getpid();
snprintf(newfn,sizeof(newfn), "%s.n3w%08X",f->filename,mypid);
snprintf(oldfn,sizeof(oldfn), "%s.o1d%08X",f->filename,mypid);
unlink(newfn);
unlink(oldfn);
tryagain:
FILE *pf = fopen(newfn, "wb");
if (!pf || fwrite(f->data, f->filesize, 1, pf) != 1)
{
if (pf) fclose(pf);
printf("Error flushing DB to disk (is your drive full?)\n\nHit (R)etry to try again (recommended), or (C)ancel to abort (NOT recommended, and may leave the DB in an unuseable state)");
fflush(stdout);
char c;
while (1)
{
scanf("%c", &c);
// clear_stdin();
c = toupper(c);
if (c == 'R') goto tryagain;
else if (c == 'C') break;
}
unlink(newfn);
return 1;
}
fclose(pf);
rename(f->filename,oldfn); // save old file
int rv=0;
tryagain2:
if (rename(newfn,f->filename))
{
printf("Error updating DB file on disk. This should never really happen\n\nHit (R)etry to try again (recommended), or (C)ancel to abort (NOT recommended, and may leave the DB in an unuseable state)");
fflush(stdout);
char c;
while (1)
{
scanf("%c", &c);
// clear_stdin();
c = toupper(c);
if (c == 'R') goto tryagain2;
else if (c == 'C') break;
}
rename(oldfn,f->filename); // restore old file
rv=1;
}
// clean up our temp files
unlink(oldfn);
unlink(newfn);
//free(newfn);
//free(oldfn);
if (rv == 0)
f->dirty=0;
return rv;
}
f->dirty=0;
return 0;
}
void Vfdestroy(VFILE *f)
{
// benski> TODO:
if (f)
{
Vfclose(f);
while (f->locks)
Vfunlock(f, 1);
// TODO if (f->mutex) CloseHandle(f->mutex);
free(f);
}
}
// benski> TODO implement these with fopen
// returns 0 on failure
int Vflock(VFILE *fl, BOOL is_sync)
{
#ifndef NO_TABLE_WIN32_LOCKING
if (!fl) return 0;
if (!is_sync && fl->cached)
return 1;
if (fl->locks++ == 0)
{
int retry_cnt=0;
FILE *fFile;
do
{
fFile = fopen(fl->lockname, "wb");
if (fFile == 0) Sleep(100);
}
while (fFile == 0 && retry_cnt++ < 100); // try for 10 seconds
if (fFile == INVALID_HANDLE_VALUE) return 0; // db already locked, fail gracefully
fl->lockFile = fFile;
}
#endif
return 1;
}
void Vfunlock(VFILE *fl, BOOL is_sync)
{
#ifndef NO_TABLE_WIN32_LOCKING
if (!is_sync && fl->cached)
return;
if (--fl->locks == 0)
{
if (fl && fl->lockFile && fl->lockFile != INVALID_HANDLE_VALUE)
{
fclose(fl->lockFile);
unlink(fl->lockname);
}
}
#endif
}

66
Src/nde/osx/Vfs.h Normal file
View file

@ -0,0 +1,66 @@
#ifndef __NDE_VFS_H
#define __NDE_VFS_H
#include <bfc/platform/types.h>
#include <stdio.h>
//#define NDE_ALLOW_NONCACHED
/*
#ifdef NDE_ALLOW_NONCACHED
#ifndef NDE_NOWIN32FILEIO
#error NDE_ALLOW_NONCACHED at least for now requires NDE_NOWIN32FILEIO
#endif
#endif
*/
#define VFILE_INC 65536
#define VFS_READ 1
#define VFS_WRITE 2
#define VFS_SEEKEOF 4
#define VFS_CREATE 8
#define VFS_NEWCONTENT 16
#define VFS_MUSTEXIST 32
typedef struct {
uint8_t *data;
unsigned long ptr;
unsigned long filesize;
unsigned long maxsize;
char *filename;
char mode;
BOOL cached;
int dirty;
#ifdef NDE_ALLOW_NONCACHED
FILE *rfile;
#endif
FILE *lockFile;
char lockname[1024];
int locks;
} VFILE;
#ifdef __cplusplus
extern "C" {
#endif
VFILE *Vfnew(const char *fl, const char *mode, BOOL Cached);
VFILE *Vfopen(VFILE *f, const char *fl, const char *mode, BOOL Cached);
size_t Vfread(void *ptr, size_t size, VFILE *buf);
void Vfseek(VFILE *fl, long i, int whence);
unsigned long Vftell(VFILE *fl);
void Vfclose(VFILE *fl);
void Vfdestroy(VFILE *fl); // benski> TODO:
void Vfwrite(const void *ptr, size_t size, VFILE *f);
int Vfeof(VFILE *fl);
int Vsync(VFILE *fl); // 1 on error updating
int Vflock(VFILE *fl, BOOL is_sync=TRUE); // returns 0 on failure
void Vfunlock(VFILE *fl, BOOL is_sync=TRUE);
#ifdef __cplusplus
}
#endif
#endif

640
Src/nde/osx/nde_c.cpp Normal file
View file

@ -0,0 +1,640 @@
#include "nde_c.h"
#include "nde.h"
#ifdef _WIN32
#include "../nu/AutoCharFn.h"
#include "../nu/AutoWide.h"
#endif
/* Database */
#ifdef _WIN32
nde_database_t NDE_CreateDatabase(HINSTANCE hInstance)
{
return (nde_database_t)new Database(hInstance);
}
#else
nde_database_t NDE_CreateDatabase()
{
return (nde_database_t)new Database();
}
#endif
void NDE_DestroyDatabase(nde_database_t db)
{
delete (Database *)db;
}
#ifdef _WIN32
nde_table_t NDE_Database_OpenTable(nde_database_t db, const wchar_t *filename, const wchar_t *indexname, int create, int cache)
{
Database *database = (Database *)db;
if (database && filename)
return (nde_table_t)database->OpenTable(filename, indexname, (BOOL)create, (BOOL)cache);
else
return 0;
}
#else
nde_table_t NDE_Database_OpenTable(nde_database_t db, const char *filename, const char *indexname, int create, int cache)
{
Database *database = (Database *)db;
if (database && filename)
return (nde_table_t)database->OpenTable(filename, indexname, (BOOL)create, (BOOL)cache);
else
return 0;
}
#endif
void NDE_Database_CloseTable(nde_database_t db, nde_table_t t)
{
Database *database = (Database *)db;
Table *table = (Table *)t;
if (database && table)
{
database->CloseTable(table);
}
}
/* Table */
#ifdef _WIN32
nde_field_t NDE_Table_NewColumn(nde_table_t t, unsigned char id, const char *name, unsigned char type)
{
Table *table = (Table *)t;
if (table)
return (nde_field_t)table->NewColumn(id, AutoWide(name), type, FALSE);
else
return 0;
}
#else
nde_field_t NDE_Table_NewColumn(nde_table_t t, unsigned char id, CFStringRef name, unsigned char type)
{
Table *table = (Table *)t;
if (table)
return (nde_field_t)table->NewColumn(id, name, type, FALSE);
else
return 0;
}
#endif
void NDE_Table_PostColumns(nde_table_t t)
{
Table *table = (Table *)t;
if (table)
table->PostColumns();
}
#ifdef _WIN32
void NDE_Table_AddIndexByID(nde_table_t t, unsigned char id, const char *name)
{
Table *table = (Table *)t;
if (table)
table->AddIndexById(id, AutoWide(name));
}
#else
void NDE_Table_AddIndexByID(nde_table_t t, unsigned char id, CFStringRef name)
{
Table *table = (Table *)t;
if (table)
table->AddIndexById(id, name);
}
#endif
nde_scanner_t NDE_Table_CreateScanner(nde_table_t t)
{
Table *table = (Table *)t;
if (table)
return (nde_scanner_t)table->NewScanner();
else
return 0;
}
void NDE_Table_DestroyScanner(nde_table_t t, nde_scanner_t s)
{
Table *table = (Table *)t;
Scanner *scanner = (Scanner *)s;
if (table && scanner)
table->DeleteScanner(scanner);
}
void NDE_Table_Sync(nde_table_t t)
{
Table *table = (Table *)t;
if (table)
table->Sync();
}
#ifdef _WIN32
void NDE_Table_Compact(nde_table_t t, int *progress)
{
Table *table = (Table *)t;
if (table)
table->Compact(progress);
}
#endif
int NDE_Table_GetRecordsCount(nde_table_t t)
{
Table *table = (Table *)t;
if (table)
return table->GetRecordsCount();
else
return 0;
}
nde_field_t NDE_Table_GetColumnByID(nde_table_t t, unsigned char id)
{
Table *table = (Table *)t;
if (table)
return (nde_field_t)table->GetColumnById(id);
else
return 0;
}
#ifdef _WIN32
nde_field_t NDE_Table_GetColumnByName(nde_table_t t, const char *name)
{
Table *table = (Table *)t;
if (table && name)
return (nde_field_t)table->GetColumnByName(AutoWide(name));
else
return 0;
}
#else
nde_field_t NDE_Table_GetColumnByName(nde_table_t t, CFStringRef name)
{
Table *table = (Table *)t;
if (table && name)
return (nde_field_t)table->GetColumnByName(name);
else
return 0;
}
#endif
void NDE_Table_SetColumnSearchableByID(nde_table_t t, unsigned char id, int searchable)
{
Table *table = (Table *)t;
if (table)
table->SetFieldSearchableById(id, !!searchable);
}
/* Scanner */
#ifdef _WIN32
int NDE_Scanner_Query(nde_scanner_t s, const wchar_t *query)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
return scanner->Query(query);
else
return 0;
}
void NDE_Scanner_Search(nde_scanner_t s, const wchar_t *search_term)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
scanner->Search(search_term);
}
const wchar_t *NDE_Scanner_GetLastQuery(nde_scanner_t s)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
return scanner->GetLastQuery();
else
return 0;
}
#elif defined(__APPLE__)
int NDE_Scanner_Query(nde_scanner_t s, const char *query)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
return scanner->Query(query);
else
return 0;
}
CFStringRef NDE_Scanner_GetLastQuery(nde_scanner_t s)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
return scanner->GetLastQuery();
else
return 0;
}
#endif
int NDE_Scanner_GetRecordsCount(nde_scanner_t s)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
return scanner->GetRecordsCount();
else
return 0;
}
void NDE_Scanner_New(nde_scanner_t s)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
scanner->New();
}
void NDE_Scanner_Post(nde_scanner_t s)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
scanner->Post();
}
void NDE_Scanner_First(nde_scanner_t s, int *killswitch)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
scanner->First(killswitch);
}
void NDE_Scanner_Delete(nde_scanner_t s)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
scanner->Delete();
}
void NDE_Scanner_Edit(nde_scanner_t s)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
scanner->Edit();
}
int NDE_Scanner_EOF(nde_scanner_t s)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
return scanner->Eof();
else
return 1;
}
int NDE_Scanner_BOF(nde_scanner_t s)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
return scanner->Bof();
else
return 1;
}
nde_field_t NDE_Scanner_NewFieldByID(nde_scanner_t s, unsigned char id)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
return (nde_field_t)scanner->NewFieldById(id, PERM_READWRITE);
else
return 0;
}
#ifdef _WIN32
nde_field_t NDE_Scanner_NewFieldByName(nde_scanner_t s, const char *name)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
return (nde_field_t)scanner->NewFieldByName(AutoWide(name), PERM_READWRITE);
else
return 0;
}
#else
nde_field_t NDE_Scanner_NewFieldByName(nde_scanner_t s, CFStringRef name)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
return (nde_field_t)scanner->NewFieldByName(name, PERM_READWRITE);
else
return 0;
}
#endif
nde_field_t NDE_Scanner_GetFieldByID(nde_scanner_t s, unsigned char id)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
return (nde_field_t)scanner->GetFieldById(id);
else
return 0;
}
#ifdef _WIN32
nde_field_t NDE_Scanner_GetFieldByName(nde_scanner_t s, const char *name)
{
Scanner *scanner = (Scanner *)s;
if (scanner && name)
return (nde_field_t)scanner->GetFieldByName(AutoWide(name));
else
return 0;
}
#else
nde_field_t NDE_Scanner_GetFieldByName(nde_scanner_t s, CFStringRef name)
{
Scanner *scanner = (Scanner *)s;
if (scanner && name)
return (nde_field_t)scanner->GetFieldByName(name);
else
return 0;
}
#endif
void NDE_Scanner_AddFilterByID(nde_scanner_t s, unsigned char id, nde_field_t f, unsigned char filter_operation)
{
Scanner *scanner = (Scanner *)s;
Field *field = (Field *)f;
if (scanner && field)
scanner->AddFilterById(id, field, filter_operation);
}
int NDE_Scanner_LocateInteger(nde_scanner_t s, unsigned char id, int from, int value, int *nskip, int compare_mode)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
{
IntegerField field(value);
return scanner->LocateByIdEx(id, from, &field, nskip, compare_mode);
}
else
return 0;
}
#ifdef _WIN32
int NDE_Scanner_LocateString(nde_scanner_t s, unsigned char id, int from, const wchar_t *value, int *nskip, int compare_mode)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
{
StringField field(value);
return scanner->LocateByIdEx(id, from, &field, nskip, compare_mode);
}
else
return 0;
}
int NDE_Scanner_LocateNDEString(nde_scanner_t s, unsigned char id, int from, wchar_t *value, int *nskip, int compare_mode)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
{
StringField field(value, STRING_IS_NDESTRING);
return scanner->LocateByIdEx(id, from, &field, nskip, compare_mode);
}
else
return 0;
}
#endif
#ifdef _WIN32
int NDE_Scanner_LocateFilename(nde_scanner_t s, unsigned char id, int from, const wchar_t *value, int *nskip, int compare_mode)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
{
FilenameField field(value);
return scanner->LocateByIdEx(id, from, &field, nskip, compare_mode);
}
else
return 0;
}
int NDE_Scanner_LocateNDEFilename(nde_scanner_t s, unsigned char id, int from, wchar_t *value, int *nskip, int compare_mode)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
{
FilenameField field(value, STRING_IS_NDESTRING);
return scanner->LocateByIdEx(id, from, &field, nskip, compare_mode);
}
else
return 0;
}
#endif
int NDE_Scanner_LocateField(nde_scanner_t s, unsigned char id, int from, nde_field_t f, int *nskip, int compare_mode)
{
Scanner *scanner = (Scanner *)s;
Field *field = (Field *)f;
if (scanner && field)
{
return scanner->LocateByIdEx(id, from, field, nskip, compare_mode);
}
else
return 0;
}
void NDE_Scanner_DeleteField(nde_scanner_t s, nde_field_t f)
{
Scanner *scanner = (Scanner *)s;
Field *field = (Field *)f;
if (scanner && field)
{
scanner->DeleteField(field);
}
}
void NDE_Scanner_RemoveFilters(nde_scanner_t s)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
scanner->RemoveFilters();
}
int NDE_Scanner_Next(nde_scanner_t s, int *killswitch)
{
Scanner *scanner = (Scanner *)s;
if (scanner)
return scanner->Next(killswitch);
else
return 0;
}
/* Filter functions */
unsigned char NDE_Filter_GetID(nde_filter_t f)
{
Filter *filter = (Filter *)f;
if (filter)
return filter->GetId();
else
return FILTERS_INVALID; // right value but I'm not sure if it's the best constant name to use
}
NDE_API unsigned char NDE_Filter_GetOp(nde_filter_t f)
{
Filter *filter = (Filter *)f;
if (filter)
return filter->GetOp();
else
return FILTERS_INVALID; // right value but I'm not sure if it's the best constant name to use
}
NDE_API nde_field_t NDE_Filter_GetData(nde_filter_t f)
{
Filter *filter = (Filter *)f;
if (filter)
return (nde_field_t)filter->Data();
else
return 0;
}
/* Field functions */
unsigned char NDE_Field_GetType(nde_field_t f)
{
Field *field = (Field *)f;
if (field)
return field->GetType();
else
return FIELD_UNKNOWN;
}
unsigned char NDE_Field_GetID(nde_field_t f)
{
Field *field = (Field *)f;
if (field)
return field->GetFieldId();
else
return FIELD_UNKNOWN;
}
/* StringField functions */
#ifdef _WIN32
void NDE_StringField_SetNDEString(nde_field_t f, wchar_t *nde_string)
{
StringField *field = (StringField *)(Field *)f;
if (field)
field->SetNDEString(nde_string);
}
wchar_t *NDE_StringField_GetString(nde_field_t f)
{
StringField *field = (StringField *)(Field *)f;
if (field)
return field->GetStringW();
else
return 0;
}
#ifdef _WIN32
void NDE_StringField_SetString(nde_field_t f, const wchar_t *str)
{
StringField *field = (StringField *)(Field *)f;
if (field)
field->SetStringW(str);
}
#endif
#elif defined(__APPLE__)
void NDE_StringField_SetString(nde_field_t f, CFStringRef nde_string)
{
StringField *field = (StringField *)(Field *)f;
if (field)
field->SetNDEString(nde_string);
}
CFStringRef NDE_StringField_GetString(nde_field_t f)
{
StringField *field = (StringField *)(Field *)f;
if (field)
return field->GetString();
else
return 0;
}
#endif
/* IntegerField functions */
void NDE_IntegerField_SetValue(nde_field_t f, int value)
{
IntegerField *field = (IntegerField *)(Field *)f;
if (field)
field->SetValue(value);
}
int NDE_IntegerField_GetValue(nde_field_t f)
{
IntegerField *field = (IntegerField *)(Field *)f;
if (field)
return field->GetValue();
else
return 0;
}
nde_field_t NDE_IntegerField_Create(int value)
{
return (nde_field_t)new IntegerField(value);
}
/* BinaryField */
void *NDE_BinaryField_GetData(nde_field_t f, size_t *length)
{
BinaryField *field = (BinaryField *)(Field *)f;
if (field)
return (void *)field->GetData(length);
else
return 0;
}
#ifdef __APPLE__
CFDataRef NDE_BinaryField_GetCFData(nde_field_t f)
{
BinaryField *field = (BinaryField *)(Field *)f;
if (field)
return field->GetCFData();
else
return 0;
}
#endif
void NDE_BinaryField_SetData(nde_field_t f, const void *data, size_t length)
{
BinaryField *field = (BinaryField *)(Field *)f;
if (field)
field->SetData((const uint8_t *)data, length);
}
/* Int128Field */
void NDE_Int128Field_SetValue(nde_field_t f, const void *value)
{
Int128Field *field = (Int128Field *)(Field *)f;
if (field && value)
field->SetValue(value);
}
/* ColumnField */
#ifdef _WIN32
const wchar_t *NDE_ColumnField_GetFieldName(nde_field_t f)
{
ColumnField *field = (ColumnField *)(Field *)f;
if (field)
return field->GetFieldName();
else
return 0;
}
#else
CFStringRef NDE_ColumnField_GetFieldName(nde_field_t f)
{
ColumnField *field = (ColumnField *)(Field *)f;
if (field)
return field->GetFieldName();
else
return 0;
}
#endif
unsigned char NDE_ColumnField_GetDataType(nde_field_t f)
{
ColumnField *field = (ColumnField *)(Field *)f;
if (field)
return field->GetDataType();
else
return FIELD_UNKNOWN;
}
#ifdef _WIN32
__time64_t NDE_Time_ApplyConversion(__time64_t value, const wchar_t *str, class TimeParse *tp)
{
IntegerField f(value);
f.ApplyConversion(str, tp);
return f.GetValue();
}
#endif

246
Src/nde/osx/nde_c.h Normal file
View file

@ -0,0 +1,246 @@
#pragma once
/* C style API.
We'll eventually deprecate the C++ API as it presents a lot of linking challenges
*/
#include "nde_defines.h"
#ifdef _WIN32
#include "NDEString.h"
#include <bfc/platform/types.h>
#endif
#ifdef __APPLE__
#include <CoreFoundation/CoreFoundation.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __APPLE__
typedef time_t __time64_t; // TODO: find a way to do native 64bit time values
#endif
typedef struct nde_database_struct_t { } *nde_database_t;
typedef struct nde_table_struct_t { } *nde_table_t;
typedef struct nde_scanner_t_struct_t { } *nde_scanner_t;
typedef struct nde_field_t_struct_t { } *nde_field_t;
typedef struct nde_filter_struct_t { } *nde_filter_t;
/* Database functions */
// Windows API
#ifdef _WIN32
NDE_API void NDE_Init();
NDE_API void NDE_Quit();
#ifdef __cplusplus
NDE_API nde_database_t NDE_CreateDatabase(HINSTANCE hInstance=0);
#else
NDE_API nde_database_t NDE_CreateDatabase(HINSTANCE hInstance);
#endif
NDE_API void NDE_DestroyDatabase(nde_database_t db);
NDE_API nde_table_t NDE_Database_OpenTable(nde_database_t db, const wchar_t *filename, const wchar_t *filename_index, int create, int cache);
NDE_API void NDE_Database_CloseTable(nde_database_t db, nde_table_t table);
/* Table functions */
NDE_API nde_field_t NDE_Table_NewColumn(nde_table_t table, unsigned char id, const char *name, unsigned char type);
NDE_API void NDE_Table_PostColumns(nde_table_t table);
NDE_API void NDE_Table_AddIndexByID(nde_table_t table, unsigned char id, const char *name);
NDE_API nde_scanner_t NDE_Table_CreateScanner(nde_table_t table);
NDE_API void NDE_Table_DestroyScanner(nde_table_t table, nde_scanner_t scanner);
NDE_API void NDE_Table_Sync(nde_table_t table);
#ifdef __cplusplus
NDE_API void NDE_Table_Compact(nde_table_t table, int *progress=0);
#else
NDE_API void NDE_Table_Compact(nde_table_t table, int *progress);
#endif
NDE_API int NDE_Table_GetRecordsCount(nde_table_t table);
NDE_API nde_field_t NDE_Table_GetColumnByID(nde_table_t table, unsigned char id);
#ifdef _WIN32
NDE_API nde_field_t NDE_Table_GetColumnByName(nde_table_t table, const char *name);
#else
NDE_API nde_field_t NDE_Table_GetColumnByName(nde_table_t table, CFStringRef name);
#endif
NDE_API void NDE_Table_SetColumnSearchableByID(nde_table_t table, unsigned char id, int searchable);
/* Scanner functions */
NDE_API int NDE_Scanner_Query(nde_scanner_t scanner, const wchar_t *query);
NDE_API void NDE_Scanner_Search(nde_scanner_t scanner, const wchar_t *search_term);
NDE_API const wchar_t *NDE_Scanner_GetLastQuery(nde_scanner_t scanner);
NDE_API int NDE_Scanner_GetRecordsCount(nde_scanner_t scanner);
NDE_API void NDE_Scanner_New(nde_scanner_t scanner);
NDE_API void NDE_Scanner_Post(nde_scanner_t scanner);
#ifdef __cplusplus
NDE_API void NDE_Scanner_First(nde_scanner_t scanner, int *killswitch=0);
NDE_API int NDE_Scanner_Next(nde_scanner_t scanner, int *killswitch=0);
#else
NDE_API void NDE_Scanner_First(nde_scanner_t scanner, int *killswitch);
NDE_API int NDE_Scanner_Next(nde_scanner_t scanner, int *killswitch);
#endif
NDE_API void NDE_Scanner_Delete(nde_scanner_t scanner);
NDE_API void NDE_Scanner_Edit(nde_scanner_t scanner);
NDE_API int NDE_Scanner_EOF(nde_scanner_t scanner);
NDE_API int NDE_Scanner_BOF(nde_scanner_t scanner);
NDE_API nde_field_t NDE_Scanner_NewFieldByID(nde_scanner_t scanner, unsigned char id);
NDE_API nde_field_t NDE_Scanner_NewFieldByName(nde_scanner_t scanner, const char *name);
NDE_API nde_field_t NDE_Scanner_GetFieldByID(nde_scanner_t scanner, unsigned char id);
NDE_API nde_field_t NDE_Scanner_GetFieldByName(nde_scanner_t scanner, const char *name);
NDE_API void NDE_Scanner_AddFilterByID(nde_scanner_t scanner, unsigned char id, nde_field_t field, unsigned char filter_operation);
#ifdef __cplusplus
NDE_API int NDE_Scanner_LocateInteger(nde_scanner_t scanner, unsigned char id, int from, int value, int *nskip=0, int compare_mode=COMPARE_MODE_EXACT);
NDE_API int NDE_Scanner_LocateString(nde_scanner_t scanner, unsigned char id, int from, const wchar_t *value, int *nskip=0, int compare_mode=COMPARE_MODE_EXACT);
NDE_API int NDE_Scanner_LocateNDEString(nde_scanner_t scanner, unsigned char id, int from, wchar_t *value, int *nskip=0, int compare_mode=COMPARE_MODE_EXACT);
NDE_API int NDE_Scanner_LocateFilename(nde_scanner_t scanner, unsigned char id, int from, const wchar_t *value, int *nskip=0, int compare_mode=COMPARE_MODE_EXACT);
NDE_API int NDE_Scanner_LocateNDEFilename(nde_scanner_t scanner, unsigned char id, int from, wchar_t *value, int *nskip=0, int compare_mode=COMPARE_MODE_EXACT);
NDE_API int NDE_Scanner_LocateField(nde_scanner_t scanner, unsigned char id, int from, nde_field_t field, int *nskip=0, int compare_mode=COMPARE_MODE_EXACT);
#else
NDE_API int NDE_Scanner_LocateInteger(nde_scanner_t scanner, unsigned char id, int from, int value, int *nskip, int compare_mode);
NDE_API int NDE_Scanner_LocateString(nde_scanner_t scanner, unsigned char id, int from, const wchar_t *value, int *nskip, int compare_mode);
NDE_API int NDE_Scanner_LocateNDEString(nde_scanner_t scanner, unsigned char id, int from, wchar_t *value, int *nskip, int compare_mode);
NDE_API int NDE_Scanner_LocateFilename(nde_scanner_t scanner, unsigned char id, int from, const wchar_t *value, int *nskip, int compare_mode);
NDE_API int NDE_Scanner_LocateNDEFilename(nde_scanner_t scanner, unsigned char id, int from, wchar_t *value, int *nskip, int compare_mode);
NDE_API int NDE_Scanner_LocateField(nde_scanner_t scanner, unsigned char id, int from, nde_field_t field, int *nskip, int compare_mode);
#endif
NDE_API void NDE_Scanner_DeleteField(nde_scanner_t scanner, nde_field_t field);
NDE_API void NDE_Scanner_RemoveFilters(nde_scanner_t scanner);
/* Filter functions */
NDE_API unsigned char NDE_Filter_GetID(nde_filter_t filter);
NDE_API unsigned char NDE_Filter_GetOp(nde_filter_t filter);
NDE_API nde_field_t NDE_Filter_GetData(nde_filter_t filter);
/* Field functions */
NDE_API unsigned char NDE_Field_GetType(nde_field_t field);
NDE_API unsigned char NDE_Field_GetID(nde_field_t field);
/* String Field functions */
NDE_API wchar_t *NDE_StringField_GetString(nde_field_t field); /* returns non-const because it's an NDE string (reference counted, see ndestring.h) */
NDE_API void NDE_StringField_SetNDEString(nde_field_t field, wchar_t *nde_string);
NDE_API void NDE_StringField_SetString(nde_field_t field, const wchar_t *str);
/* IntegerField functions */
NDE_API void NDE_IntegerField_SetValue(nde_field_t field, int value);
NDE_API int NDE_IntegerField_GetValue(nde_field_t field);
NDE_API nde_field_t NDE_IntegerField_Create(int value); /* mainly used for NDE_Scanner_AddFilterByID */
/* BinaryField functions */
// on windows, the data pointer is optionally reference counted via ndestring (ndestring_retain if you plan on keeping it)
NDE_API void *NDE_BinaryField_GetData(nde_field_t field, size_t *length);
NDE_API void NDE_BinaryField_SetData(nde_field_t field, const void *data, size_t length);
/* Int128Field functions */
NDE_API void NDE_Int128Field_SetValue(nde_field_t field, const void *value);
/* ColumnField functions */
NDE_API const wchar_t *NDE_ColumnField_GetFieldName(nde_field_t field);
NDE_API unsigned char NDE_ColumnField_GetDataType(nde_field_t field);
NDE_API __time64_t NDE_Time_ApplyConversion(__time64_t value, const wchar_t *str, class TimeParse *tp);
#elif defined(__APPLE__) // Mac OS X API, uses CFStringRef for a lot of stuff
NDE_API void NDE_Init();
NDE_API void NDE_Quit();
NDE_API nde_database_t NDE_CreateDatabase();
NDE_API void NDE_DestroyDatabase(nde_database_t db);
NDE_API nde_table_t NDE_Database_OpenTable(nde_database_t db, const char *filename, const char *filename_index, int create, int cache);
NDE_API void NDE_Database_CloseTable(nde_database_t db, nde_table_t table);
/* Table functions */
NDE_API nde_field_t NDE_Table_NewColumn(nde_table_t table, unsigned char id, const char *name, unsigned char type);
NDE_API void NDE_Table_PostColumns(nde_table_t table);
NDE_API void NDE_Table_AddIndexByID(nde_table_t table, unsigned char id, const char *name);
NDE_API nde_scanner_t NDE_Table_CreateScanner(nde_table_t table);
NDE_API void NDE_Table_DestroyScanner(nde_table_t table, nde_scanner_t scanner);
NDE_API void NDE_Table_Sync(nde_table_t table);
#ifdef __cplusplus
NDE_API void NDE_Table_Compact(nde_table_t table, int *progress=0);
#else
NDE_API void NDE_Table_Compact(nde_table_t table, int *progress);
#endif
NDE_API int NDE_Table_GetRecordsCount(nde_table_t table);
NDE_API nde_field_t NDE_Table_GetColumnByID(nde_table_t table, unsigned char id);
#ifdef _WIN32
NDE_API nde_field_t NDE_Table_GetColumnByName(nde_table_t table, const char *name);
#else
NDE_API nde_field_t NDE_Table_GetColumnByName(nde_table_t table, CFStringRef name);
#endif
/* Scanner functions */
NDE_API int NDE_Scanner_Query(nde_scanner_t scanner, const wchar_t *query);
NDE_API CFStringRef NDE_Scanner_GetLastQuery(nde_scanner_t scanner);
NDE_API int NDE_Scanner_GetRecordsCount(nde_scanner_t scanner);
NDE_API void NDE_Scanner_New(nde_scanner_t scanner);
NDE_API void NDE_Scanner_Post(nde_scanner_t scanner);
#ifdef __cplusplus
NDE_API void NDE_Scanner_First(nde_scanner_t scanner, int *killswitch=0);
NDE_API int NDE_Scanner_Next(nde_scanner_t scanner, int *killswitch=0);
#else
NDE_API void NDE_Scanner_First(nde_scanner_t scanner, int *killswitch);
NDE_API int NDE_Scanner_Next(nde_scanner_t scanner, int *killswitch);
#endif
NDE_API void NDE_Scanner_Delete(nde_scanner_t scanner);
NDE_API void NDE_Scanner_Edit(nde_scanner_t scanner);
NDE_API int NDE_Scanner_EOF(nde_scanner_t scanner);
NDE_API int NDE_Scanner_BOF(nde_scanner_t scanner);
NDE_API nde_field_t NDE_Scanner_NewFieldByID(nde_scanner_t scanner, unsigned char id);
NDE_API nde_field_t NDE_Scanner_NewFieldByName(nde_scanner_t scanner, const char *name);
NDE_API nde_field_t NDE_Scanner_GetFieldByID(nde_scanner_t scanner, unsigned char id);
NDE_API nde_field_t NDE_Scanner_GetFieldByName(nde_scanner_t scanner, const char *name);
NDE_API void NDE_Scanner_AddFilterByID(nde_scanner_t scanner, unsigned char id, nde_field_t field, unsigned char filter_operation);
#ifdef __cplusplus
NDE_API int NDE_Scanner_LocateInteger(nde_scanner_t scanner, unsigned char id, int from, int value, int *nskip=0, int compare_mode=COMPARE_MODE_EXACT);
NDE_API int NDE_Scanner_LocateString(nde_scanner_t scanner, unsigned char id, int from, const wchar_t *value, int *nskip=0, int compare_mode=COMPARE_MODE_EXACT);
NDE_API int NDE_Scanner_LocateNDEString(nde_scanner_t scanner, unsigned char id, int from, wchar_t *value, int *nskip=0, int compare_mode=COMPARE_MODE_EXACT);
NDE_API int NDE_Scanner_LocateFilename(nde_scanner_t scanner, unsigned char id, int from, const wchar_t *value, int *nskip=0, int compare_mode=COMPARE_MODE_EXACT);
NDE_API int NDE_Scanner_LocateNDEFilename(nde_scanner_t scanner, unsigned char id, int from, wchar_t *value, int *nskip=0, int compare_mode=COMPARE_MODE_EXACT);
NDE_API int NDE_Scanner_LocateField(nde_scanner_t scanner, unsigned char id, int from, nde_field_t field, int *nskip=0, int compare_mode=COMPARE_MODE_EXACT);
#else
NDE_API int NDE_Scanner_LocateInteger(nde_scanner_t scanner, unsigned char id, int from, int value, int *nskip, int compare_mode);
NDE_API int NDE_Scanner_LocateString(nde_scanner_t scanner, unsigned char id, int from, const wchar_t *value, int *nskip, int compare_mode);
NDE_API int NDE_Scanner_LocateNDEString(nde_scanner_t scanner, unsigned char id, int from, wchar_t *value, int *nskip, int compare_mode);
NDE_API int NDE_Scanner_LocateFilename(nde_scanner_t scanner, unsigned char id, int from, const wchar_t *value, int *nskip, int compare_mode);
NDE_API int NDE_Scanner_LocateNDEFilename(nde_scanner_t scanner, unsigned char id, int from, wchar_t *value, int *nskip, int compare_mode);
NDE_API int NDE_Scanner_LocateField(nde_scanner_t scanner, unsigned char id, int from, nde_field_t field, int *nskip, int compare_mode);
#endif
NDE_API void NDE_Scanner_DeleteField(nde_scanner_t scanner, nde_field_t field);
NDE_API void NDE_Scanner_RemoveFilters(nde_scanner_t scanner);
/* Filter functions */
NDE_API unsigned char NDE_Filter_GetID(nde_filter_t filter);
NDE_API unsigned char NDE_Filter_GetOp(nde_filter_t filter);
NDE_API nde_field_t NDE_Filter_GetData(nde_filter_t filter);
/* Field functions */
NDE_API unsigned char NDE_Field_GetType(nde_field_t field);
NDE_API unsigned char NDE_Field_GetID(nde_field_t field);
/* String Field functions */
NDE_API CFStringRef NDE_StringField_GetString(nde_field_t field); /* returns non-const because it's an NDE string (reference counted, see ndestring.h) */
NDE_API void NDE_StringField_SetString(nde_field_t field, CFStringRef string);
/* IntegerField functions */
NDE_API void NDE_IntegerField_SetValue(nde_field_t field, int value);
NDE_API int NDE_IntegerField_GetValue(nde_field_t field);
NDE_API nde_field_t NDE_IntegerField_Create(int value); /* mainly used for NDE_Scanner_AddFilterByID */
/* BinaryField functions */
NDE_API void *NDE_BinaryField_GetData(nde_field_t field, size_t *length);
NDE_API CFDataRef NDE_BinaryField_GetCFData(nde_field_t field);
NDE_API void NDE_BinaryField_SetData(nde_field_t field, const void *data, size_t length);
/* Int128Field functions */
NDE_API void NDE_Int128Field_SetValue(nde_field_t field, const void *value);
/* ColumnField functions */
#ifdef _WIN32
NDE_API const char *NDE_ColumnField_GetFieldName(nde_field_t field);
#else
NDE_API CFStringRef NDE_ColumnField_GetFieldName(nde_field_t field);
#endif
NDE_API unsigned char NDE_ColumnField_GetDataType(nde_field_t field);
NDE_API __time64_t NDE_Time_ApplyConversion(__time64_t value, const wchar_t *str, class TimeParse *tp);
#endif
#ifdef __cplusplus
}
#endif

Some files were not shown because too many files have changed in this diff Show more