You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
262 lines
7.4 KiB
262 lines
7.4 KiB
/* -*- mode: c; indent-tabs-mode: nil; -*- |
|
* $Id: util.c,v 1.3 2003/12/28 20:59:21 chrish Exp $ |
|
* |
|
* util -- Some simple utility routines so we don't need GLib |
|
* Copyright (c) 2002, Bill Janssen |
|
* |
|
* This program is free software; you can redistribute it and/or |
|
* modify it under the terms of the GNU General Public License |
|
* as published by the Free Software Foundation; either version 2 |
|
* of the License, or (at your option) any later version. |
|
* |
|
* This program is distributed in the hope that it will be useful, |
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
* GNU General Public License for more details. |
|
* |
|
* You should have received a copy of the GNU General Public License |
|
* along with this program; if not, write to the Free Software |
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
* |
|
*/ |
|
|
|
#if !defined(WIN32) |
|
#include <unistd.h> /* for lseek, etc. */ |
|
#else |
|
#include <io.h> |
|
#endif |
|
#include <stdlib.h> |
|
#include <sys/types.h> |
|
#include <stdarg.h> /* for _plkr_message */ |
|
#include <stdio.h> /* for stderr */ |
|
#include <sys/stat.h> /* for fstat() */ |
|
#include <string.h> /* for strndup() */ |
|
#include <errno.h> /* for errno */ |
|
#include <fcntl.h> /* for O_RDONLY */ |
|
#include <assert.h> /* for assert() */ |
|
|
|
#include <zlib.h> |
|
|
|
|
|
#include "unpluck.h" |
|
#include "unpluckint.h" |
|
|
|
/***********************************************************************/ |
|
/***********************************************************************/ |
|
/***** *****/ |
|
/***** Messages *****/ |
|
/***** *****/ |
|
/***********************************************************************/ |
|
/***********************************************************************/ |
|
|
|
static int ShowMessages = 0; |
|
|
|
void _plkr_message |
|
( |
|
const char* formatSpec, |
|
... |
|
) |
|
{ |
|
va_list ap; |
|
|
|
va_start (ap, formatSpec); |
|
|
|
if (ShowMessages) { |
|
(void) vfprintf (stderr, formatSpec, ap); |
|
fprintf (stderr, "\n"); |
|
} |
|
|
|
va_end (ap); |
|
} |
|
|
|
int plkr_ShowMessages |
|
( |
|
int val |
|
) |
|
{ |
|
int oldval = ShowMessages; |
|
|
|
ShowMessages = val; |
|
return oldval; |
|
} |
|
|
|
/***********************************************************************/ |
|
/***********************************************************************/ |
|
/***** *****/ |
|
/***** String Utilities *****/ |
|
/***** *****/ |
|
/***********************************************************************/ |
|
/***********************************************************************/ |
|
|
|
char* _plkr_strndup |
|
( |
|
char* str, |
|
int len |
|
) |
|
{ |
|
char* dup; |
|
|
|
dup = (char *) malloc (len + 1); |
|
strncpy (dup, str, len); |
|
dup[len] = 0; |
|
return dup; |
|
} |
|
|
|
/***********************************************************************/ |
|
/***********************************************************************/ |
|
/***** *****/ |
|
/***** Simple hash table maps string keys to void * values *****/ |
|
/***** *****/ |
|
/***********************************************************************/ |
|
/***********************************************************************/ |
|
|
|
typedef struct { |
|
char* he_key; |
|
void* he_data; |
|
} HashEntry; |
|
|
|
typedef struct { |
|
int hs_count; |
|
int hs_allocated; |
|
HashEntry* hs_entries; |
|
} HashTableSlot; |
|
|
|
struct HashTable { |
|
int ht_size; |
|
int ht_nPairs; |
|
HashTableSlot* ht_slots; |
|
}; |
|
|
|
#define HASH_INCREMENT_SIZE 5 |
|
|
|
#define hashtable_slot(ht,index) (&((ht)->ht_slots[index])) |
|
#define hashtable_hash_index(ht,key) (HashString((key), (ht)->ht_size)) |
|
#define hashtable_compare_keys(ht,key1,key2) (CompareStrings((key1),(key2))) |
|
|
|
static int CompareStrings |
|
( |
|
char* key1, |
|
char* key2 |
|
) |
|
{ |
|
return (strcmp (key1, key2) == 0); |
|
} |
|
|
|
static int HashString |
|
( |
|
char* str, |
|
int size |
|
) |
|
{ |
|
unsigned long crc; |
|
|
|
crc = crc32 (0L, NULL, 0); |
|
crc = crc32 (crc, (const Bytef*)str, strlen (str)); |
|
return (crc % size); |
|
} |
|
|
|
void* _plkr_FindInTable |
|
( |
|
HashTable* ht, |
|
char* key |
|
) |
|
{ |
|
HashTableSlot* slot; |
|
int count; |
|
|
|
if (ht == NULL) |
|
return (NULL); |
|
slot = hashtable_slot (ht, hashtable_hash_index (ht, key)); |
|
for (count = slot->hs_count; count > 0; count -= 1) |
|
if (hashtable_compare_keys |
|
(ht, key, slot->hs_entries[count - 1].he_key)) |
|
return (slot->hs_entries[count - 1].he_data); |
|
return (NULL); |
|
} |
|
|
|
void* _plkr_RemoveFromTable |
|
( |
|
HashTable* ht, |
|
char* key |
|
) |
|
{ |
|
HashTableSlot* slot; |
|
int count; |
|
|
|
if (ht == NULL) |
|
return (NULL); |
|
|
|
slot = hashtable_slot (ht, hashtable_hash_index (ht, key)); |
|
for (count = 0; count < slot->hs_count; count += 1) |
|
if (hashtable_compare_keys |
|
(ht, slot->hs_entries[count].he_key, key)) { |
|
void *data = slot->hs_entries[count].he_data; |
|
free (slot->hs_entries[count].he_key); |
|
if ((1 + (unsigned) count) < (unsigned) slot->hs_count) |
|
slot->hs_entries[count] = |
|
slot->hs_entries[slot->hs_count - 1]; |
|
--ht->ht_nPairs; |
|
if (--slot->hs_count <= 0) { |
|
free (slot->hs_entries); |
|
slot->hs_entries = NULL; |
|
slot->hs_allocated = 0; |
|
slot->hs_count = 0; |
|
} |
|
return (data); |
|
} |
|
return (NULL); |
|
} |
|
|
|
int _plkr_AddToTable |
|
( |
|
HashTable* ht, |
|
char* key, |
|
void* obj |
|
) |
|
{ |
|
HashTableSlot* slot; |
|
int count; |
|
|
|
if (ht == NULL) |
|
return (0); |
|
|
|
slot = hashtable_slot (ht, hashtable_hash_index (ht, key)); |
|
|
|
for (count = slot->hs_count; count > 0; count -= 1) |
|
if (hashtable_compare_keys |
|
(ht, key, slot->hs_entries[count - 1].he_key)) |
|
return (0); |
|
|
|
if (slot->hs_allocated == 0) { |
|
slot->hs_allocated = HASH_INCREMENT_SIZE; |
|
slot->hs_entries = |
|
(HashEntry *) malloc (sizeof (HashEntry) * slot->hs_allocated); |
|
slot->hs_count = 0; |
|
} |
|
else if (slot->hs_count >= slot->hs_allocated) |
|
slot->hs_entries = (HashEntry *) realloc (slot->hs_entries, |
|
(slot->hs_allocated += |
|
HASH_INCREMENT_SIZE) |
|
* sizeof (HashEntry)); |
|
slot->hs_entries[slot->hs_count].he_key = |
|
_plkr_strndup (key, strlen (key)); |
|
slot->hs_entries[slot->hs_count].he_data = obj; |
|
slot->hs_count += 1; |
|
ht->ht_nPairs += 1; |
|
return (1); |
|
} |
|
|
|
HashTable* _plkr_NewHashTable |
|
( |
|
int size |
|
) |
|
{ |
|
HashTable *newHash = (HashTable *) malloc (sizeof (HashTable)); |
|
|
|
newHash->ht_size = size; |
|
newHash->ht_nPairs = 0; |
|
newHash->ht_slots = |
|
(HashTableSlot *) malloc (sizeof (HashTableSlot) * size); |
|
memset ((void *) (newHash->ht_slots), 0, sizeof (HashTableSlot) * size); |
|
return (newHash); |
|
}
|
|
|