diff --git a/rdf/tests/sht.cpp b/rdf/tests/sht.cpp new file mode 100644 index 00000000000..f4be8f2a9ae --- /dev/null +++ b/rdf/tests/sht.cpp @@ -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>"); + } +} + + + + + +