Files
cdesktop/cde/lib/DtSvc/DtUtil1/strtab.c
Patrick Georgi aced075a9f lib/DtSvc: Free memory more soundly
It _probably_ works to just pass free(ptr) another two arguments, but
compilers don't like this kind of sloppiness anymore.
The call site only expects this function to free the first value,
ignoring the other two, so model that in the local wrapper function.
2025-12-18 22:58:26 +01:00

311 lines
7.8 KiB
C

/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these libraries and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/* $XConsortium: strtab.c /main/4 1996/05/09 04:23:54 drk $ */
/*
routines to implement a string -> unique ptr table & access functions
suitable for use with shared memory
*/
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include "DtHash.h"
#include "DtShmDb.h"
typedef struct strtab {
unsigned int st_size; /* size in bytes */
unsigned int st_stroffset; /* offset (bytes) from this structure to contained strings */
unsigned int st_taboffset; /* offset (bytes) from this structure to table offset */
unsigned int st_count; /* number of elements in this string table */
} strtab_t;
typedef struct strtab_entry {
unsigned int key; /* offset into contained strings */
unsigned short first; /* offset in table to first string to hash to this spot */
unsigned short next; /* offset in table to next item to hash to this spot */
} strtab_entry_t;
typedef struct strlist {
DtHashTbl sl_hash; /* hash table to hold strings during definition */
DtHashTbl sl_bosons; /* reverse hash table for Nolan's lookup function */
unsigned int sl_charcount; /* count of current bytes of strings */
} strlist_t;
struct strtab_build {
unsigned int index; /* iteration */
unsigned char * strstart; /* start of strings */
strtab_entry_t * tabstart; /* start of table */
strtab_t * strtab; /* pointer to head */
};
#define NOT_AN_INDEX ((unsigned short) 0xffff)
static void inc_it (int * a, int * b, unsigned char * key);
static void build_it(int a, struct strtab_build * ptr, unsigned char * key);
#if !defined(__linux__)
extern char * strdup(const char *);
#endif
typedef int (*des_func)(void *);
/*
client routine
returns offset in string table where string is found,
else -1 if string is not found.
*/
const char * _DtShmBosonToString(DtShmStrtab strtab, int boson)
{
const char * s = (const char *) strtab + ((strtab_t *) strtab)->st_stroffset;
return(s+boson);
}
DtShmBoson _DtShmStringToBoson(DtShmStrtab strtab, const char * string)
{
unsigned int i,j;
unsigned const char * s;
strtab_entry_t * ptr = (strtab_entry_t *) ((unsigned char *) strtab +
((strtab_t *) strtab) -> st_taboffset);
/*
hash the input string
*/
i = 1;
j = 0;
s = (unsigned const char *) string;
while(*s!=0)
j += (*s++ << i++);
i = j % ((strtab_t *) strtab)->st_count;
/*
check bucket first pointer....
*/
if((i=(ptr+i)->first) == NOT_AN_INDEX)
return(-1);
/*
loop through other buckets on hash table, looking for
our string. Note that we reused s.
*/
s = (unsigned const char *) strtab + ((strtab_t *) strtab)->st_stroffset;
while(strcmp( (char *) (s + ptr[i].key), string))
if((i= ptr[i].next) == NOT_AN_INDEX)
return(-1);
return(ptr[i].key);
}
DtShmProtoStrtab
_DtShmProtoInitStrtab(int sizeguess)
{
strlist_t * ptr = (strlist_t *) malloc(sizeof(*ptr));
if(!ptr)
return(NULL);
if(!(ptr->sl_hash = _DtUtilMakeHash(sizeguess))) {
free(ptr);
return(NULL);
}
if(!(ptr->sl_bosons = _DtUtilMakeIHash(sizeguess))) {
(void)_DtUtilDestroyHash(ptr->sl_hash, NULL, NULL);
free(ptr);
return(NULL);
}
ptr->sl_charcount = 1;
return((DtShmProtoStrtab) ptr);
}
static int destroy_hashval(int *ptr, int *unused, unsigned char *unused2) {
free(ptr);
return 0;
}
int
_DtShmProtoDestroyStrtab(DtShmProtoStrtab strlist)
{
strlist_t * ptr = (strlist_t *) strlist;
_DtUtilDestroyHash(ptr->sl_hash, NULL, NULL);
_DtUtilDestroyHash(ptr->sl_bosons, destroy_hashval, NULL);
free(ptr);
return(0);
}
DtShmBoson
_DtShmProtoAddStrtab(DtShmProtoStrtab strlist, const char * string, int * isnew)
{
strlist_t * ptr = (strlist_t *) strlist;
intptr_t * bucket = (intptr_t *) _DtUtilGetHash(ptr->sl_hash, (const unsigned char *)string);
intptr_t ret = *bucket;
if(*bucket == 0) /* new */ {
unsigned char ** sptr;
*isnew = 1;
*bucket = ret = ptr->sl_charcount;
sptr = (unsigned char**)_DtUtilGetHash(ptr->sl_bosons, (const unsigned char *)ret);
*sptr = (unsigned char*)strdup(string);
ptr->sl_charcount += strlen(string) + 1;
}
else {
*isnew = 0;
}
return((DtShmBoson)ret);
}
const char *
_DtShmProtoLookUpStrtab (DtShmProtoStrtab prototab, DtShmBoson boson)
{
strlist_t * ptr = (strlist_t *) prototab;
unsigned char ** sptr;
sptr = (unsigned char **) _DtUtilFindHash(ptr->sl_bosons, (const unsigned char *) (intptr_t) boson);
return(sptr?((const char *)*sptr):NULL);
}
int
_DtShmProtoSizeStrtab(DtShmProtoStrtab strlist)
{
int foo[2];
int size;
strlist_t * ptr = (strlist_t * ) strlist;
foo[1] = foo[0] = 0;
_DtUtilOperateHash(ptr->sl_hash, inc_it, &foo);
size = sizeof(strtab_t) + (foo[0]) * sizeof(strtab_entry_t) + foo[0] + foo[1] + 3 ;
/* header */ /* table */ /* for string + terminator */ /* padding */
/*
fix size so that it is always a multiple of 4 for ease of programming
*/
size = (~3) & (size+3);
return(size);
}
DtShmStrtab
_DtShmProtoCopyStrtab(DtShmProtoStrtab in, void * destination)
{
strlist_t * strlist = (strlist_t *) in;
strtab_t * ptr = (strtab_t *) destination;
int foo[2];
int size;
struct strtab_build building;
foo[0] = foo[1] = 0;
_DtUtilOperateHash(strlist->sl_hash, inc_it, &foo);
size = sizeof(strtab_t) + (foo[0]) * sizeof(strtab_entry_t) + (foo[0] + foo[1] + 3) & ~3 ;
/* header */ /* table */ /* for string + terminator */
memset((char *) ptr, 255, size);
ptr-> st_size= size;
ptr-> st_stroffset = sizeof(*ptr);
ptr-> st_taboffset = sizeof(*ptr) + (foo[0] + foo[1] + 3) & ~3;
ptr-> st_count = foo[0]; /* patch alignment */
building.index = 0;
building.strstart = (unsigned char *) ptr + ptr->st_stroffset;
building.tabstart = (strtab_entry_t *) ((unsigned char *) ptr + ptr->st_taboffset);
building.strtab = ptr;
_DtUtilOperateHash(strlist->sl_hash, build_it, & building);
return((DtShmStrtab) destination);
}
static void build_it(int a, struct strtab_build * ptr, unsigned char * key)
{
unsigned int i,j;
unsigned char * s;
strtab_entry_t * e;
unsigned short * add_ptr;
strcpy((char *) ptr->strstart + a, (const char *)key);
i = 1;
j = 0;
s = key;
while(*s!=0)
j += (*s++ << i++);
i = j % ((strtab_t *) ptr->strtab)->st_count;
e = ptr->tabstart + ptr->index;
e -> key = a; /* save key value in our block */
e -> next = NOT_AN_INDEX;
e = ptr->tabstart + i;
if(e->first == NOT_AN_INDEX)
add_ptr = & e->first;
else {
e = ptr->tabstart + e->first;
while( e->next != NOT_AN_INDEX)
e = ptr->tabstart + e->next;
add_ptr = & e->next;
}
*add_ptr = ptr->index++;
}
/* ARGSUSED */
static void inc_it(int * a, int * b, unsigned char * key)
{
b[0]++;
b[1] += strlen((const char *)key) + 1;
}