зеркало из https://github.com/mozilla/pjs.git
prototype serialized hash table
This commit is contained in:
Родитель
692516a02d
Коммит
041beb1bcd
|
@ -0,0 +1,219 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
* the License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
* Netscape Communications Corporation. All Rights Reserved.
|
||||
*/
|
||||
|
||||
#include "rdf.h"
|
||||
#include "rdfutil.h"
|
||||
#include "prtypes.h"
|
||||
#include "prmem.h"
|
||||
#include "nscore.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "plhash.h"
|
||||
#include "plstr.h"
|
||||
|
||||
typedef struct _SerializedHashTable {
|
||||
FILE* file;
|
||||
PLHashTable* table;
|
||||
char* buffer;
|
||||
size_t maxEntrySize;
|
||||
} SerializedHashTable;
|
||||
|
||||
typedef SerializedHashTable* SHT;
|
||||
|
||||
typedef struct _SHTEntry {
|
||||
void* value;
|
||||
size_t size;
|
||||
size_t offset;
|
||||
} SHTEntry;
|
||||
|
||||
typedef SHTEntry* SHTE;
|
||||
|
||||
void
|
||||
dumpHashItem (SHT table, char* key, size_t keyLen, void* value, size_t valueSize) {
|
||||
fprintf(table->file, "A %i\n%s\n%i\n", keyLen, key, valueSize);
|
||||
fwrite(value, 1, valueSize, table->file);
|
||||
fprintf(table->file, "\n");
|
||||
}
|
||||
|
||||
PRBool
|
||||
readNextItem(FILE *file, char** key, char** value, size_t *valueSize, PRBool *ignorep,
|
||||
int *offset) {
|
||||
char *xkey, *xvalue;
|
||||
int keySize;
|
||||
char ignoreChar;
|
||||
char tbuff[10];
|
||||
*offset = ftell(file);
|
||||
if (!fgets((char*)tbuff, 10, file)) return 0;
|
||||
if (tbuff[0] == 'X') return 0;
|
||||
sscanf(tbuff, "%c %i", &ignoreChar, &keySize);
|
||||
xkey = (char*) PR_Malloc(keySize + 1);
|
||||
if (!fgets(xkey, keySize+1, file)) return 0;
|
||||
fread(tbuff, 1, 1, file);
|
||||
memset(tbuff, '\0', 10);
|
||||
if (!fgets((char*)tbuff, 10, file)) return 0;
|
||||
sscanf(tbuff, "%i", valueSize);
|
||||
xvalue = (char*) PR_Malloc(*valueSize + 1);
|
||||
xvalue[*valueSize] = '\0';
|
||||
if (!fread(xvalue, *valueSize, 1, file)) return 0;
|
||||
fread(tbuff, 1, 1, file);
|
||||
if (ignoreChar == 'D') {
|
||||
PR_Free((void*)xvalue);
|
||||
PR_Free((void*)xkey);
|
||||
*ignorep = 1;
|
||||
return 1;
|
||||
} else {
|
||||
*ignorep = 0;
|
||||
*value = xvalue;
|
||||
*key = xkey;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PRIntn
|
||||
SHTFlusher(PLHashEntry *he, PRIntn index, void *arg) {
|
||||
SHT table = (SHT)arg;
|
||||
SHTE entry = (SHTE)he->value;
|
||||
char* key = (char*)he->key;
|
||||
char* v1 = (char*)entry->value;
|
||||
dumpHashItem(table, key, strlen(key), entry->value, entry->size);
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
FlushSHT (SHT table) {
|
||||
|
||||
table->buffer = (char*)PR_Malloc(table->maxEntrySize + 256);
|
||||
fseek(table->file, 0, SEEK_SET);
|
||||
PL_HashTableEnumerateEntries(table->table, SHTFlusher, table);
|
||||
fwrite("X", 1, 1, table->file);
|
||||
fflush(table->file);
|
||||
PR_Free(table->buffer);
|
||||
}
|
||||
|
||||
PLHashEntry*
|
||||
SHTAddInt (PLHashTable* table, size_t valueSize, void* value, char* key, int offset) {
|
||||
SHTE ve = (SHTE) PR_Malloc(sizeof(SHTEntry));
|
||||
ve->value = value;
|
||||
ve->size = valueSize;
|
||||
ve->offset = offset;
|
||||
return PL_HashTableAdd(table, key, ve);
|
||||
}
|
||||
|
||||
SHT
|
||||
MakeSerializedHash (FILE* file, PRUint32 numBuckets, PLHashFunction keyHash,
|
||||
PLHashComparator keyCompare, PLHashComparator valueCompare,
|
||||
const PLHashAllocOps *allocOps, void *allocPriv) {
|
||||
SHT table = (SHT)PR_Malloc(sizeof(SerializedHashTable));
|
||||
char* key;
|
||||
char* value;
|
||||
size_t valueSize;
|
||||
PRBool ignorep = 0;
|
||||
int offset;
|
||||
table->table = PL_NewHashTable(numBuckets, keyHash,
|
||||
keyCompare, valueCompare,
|
||||
allocOps, allocPriv);
|
||||
table->file = file;
|
||||
table->maxEntrySize = 1024;
|
||||
while (readNextItem(file, &key, &value, &valueSize, &ignorep, &offset)) {
|
||||
SHTAddInt(table->table, valueSize, value, key, offset);
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
void
|
||||
SHTAdd(SHT table, char *key, void *value, size_t valueSize) {
|
||||
fseek(table->file, 0, SEEK_END);
|
||||
SHTFlusher(SHTAddInt(table->table,valueSize, value, key, ftell(table->file)), 0, table);
|
||||
fflush(table->file);
|
||||
}
|
||||
|
||||
void
|
||||
SHTRemove(SHT table, char* key) {
|
||||
SHTE entry = (SHTE)PL_HashTableLookup(table->table, (void*) key);
|
||||
if (entry) {
|
||||
fseek(table->file, entry->offset, SEEK_SET);
|
||||
fwrite("D", 1, 1, table->file);
|
||||
fflush(table->file);
|
||||
PL_HashTableRemove(table->table, key);
|
||||
PR_Free(entry);
|
||||
}
|
||||
}
|
||||
|
||||
void*
|
||||
SHTLookup(SHT ht, const char *key) {
|
||||
SHTE entry = (SHTE)PL_HashTableLookup(ht->table, (void*) key);
|
||||
if (entry) {
|
||||
return entry->value;
|
||||
} else return 0;
|
||||
}
|
||||
|
||||
FILE*
|
||||
MakeOrOpenFile (char* name) {
|
||||
FILE* ans;
|
||||
ans = fopen(name, "r+");
|
||||
if (ans) return ans;
|
||||
ans = fopen(name, "w");
|
||||
fclose(ans);
|
||||
return fopen(name, "r+");
|
||||
}
|
||||
|
||||
void SHTtest () {
|
||||
FILE *f = MakeOrOpenFile("test");
|
||||
SHT table = MakeSerializedHash(f, 100, PL_HashString, PL_CompareStrings,
|
||||
PL_CompareValues, NULL, NULL);
|
||||
char buffer[1024];
|
||||
printf("\n>");
|
||||
while (fgets(buffer, 1023, stdin)) {
|
||||
if (strncmp(buffer, "x", 1) == 0) {
|
||||
FlushSHT(table);
|
||||
return;
|
||||
}
|
||||
if (strncmp(buffer, "a", 1) ==0) {
|
||||
char key[100], value[100];
|
||||
char *xkey, *xvalue;
|
||||
sscanf(buffer, "a %s %s", key, value);
|
||||
xkey = (char*)PR_Malloc(strlen(key)+1);
|
||||
xvalue = (char*)PR_Malloc(strlen(value)+1);
|
||||
memset(xkey, '\0', strlen(key)+1);
|
||||
memset(xvalue, '\0', strlen(value)+1);
|
||||
memcpy(xkey, key, strlen(key));
|
||||
memcpy(xvalue, value, strlen(value));
|
||||
SHTAdd(table, xkey, xvalue, strlen(xvalue));
|
||||
}
|
||||
if (strncmp(buffer, "q", 1) ==0) {
|
||||
char key[100];
|
||||
char* ans;
|
||||
sscanf(buffer, "q %s", key);
|
||||
ans = (char*)SHTLookup(table, (char*)key);
|
||||
printf("-> %s\n", (ans ? ans : "null"));
|
||||
}
|
||||
if (strncmp(buffer, "r", 1) == 0) {
|
||||
char key[100];
|
||||
sscanf(buffer, "r %s", key);
|
||||
SHTRemove(table, key);
|
||||
}
|
||||
printf("\n>");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
Загрузка…
Ссылка в новой задаче