/*
"kernel_string_pool.c"
created by: grayspace aka J. Leveille
for: UbixOS Project
date: May 11, 2002
purpose: to provide a mechanism for maintaining a pool of strings
for use by the kernel without unnecessary waste of memory
NOTEs:
- for now only ASCII is supported
- done quickly, pretty hacky
TODO:
- expand to support unicode
- use huffman encoding instead
$Id$
*/
#include "../../grayspace-misc/gsdefines.h"
#include "../../sys/include/misc/kernel_string_pool.h"
// returns pointer to character *after* substring read
static char * ReadSubString( char * p_dst, const BYTEg * p_substr )
{
char * p_retval;
char * p_curdst;
const char * p_cursubstr;
p_curdst = p_dst;
p_retval = p_dst + (*p_substr) + 1;
p_cursubstr = (const char *) (p_substr + 1);
do
{
*p_curdst = *p_cursubstr;
p_cursubstr++;
p_curdst++;
}
while( p_curdst < p_retval );
return p_retval;
}
// returns pointer to character *after* space appended after substring read
static char * ReadSubStringAppendSpace( char * p_dst, const BYTEg * p_substr )
{
char * p_retval;
p_retval = ReadSubString( p_dst, p_substr );
*p_retval = ' ';
p_retval++;
return p_retval;
}
// scans through all substrings until we arrive at the one we want
// returns pointer to the substring
static const BYTEg * FindSubString( const BYTEg * p_substrs,
DWORDg substr_idx )
{
DWORDg toskip;
const BYTEg * p_substr;
p_substr = p_substrs;
toskip = substr_idx;
while( toskip )
{
p_substr += (*p_substr);
toskip--;
}
return p_substr;
}
// p_substr_idx_o <- sub-string index
// returns next BYTE after substring index BYTEs
static const BYTEg * GetSubStringIndex( DWORDg * p_substr_idx_o,
const BYTEg * p_subidxbytes )
{
const BYTEg * p_idxbyte;
p_idxbyte = p_subidxbytes;
/*
'KRNWORD':
- [BYTE] 'key1'
- if key1 == [0,63]:
- key1 is the index of the 'sub-string' in the pool
- otherwise
- if key1 has bit 7 set
- [BYTE] 'key2'
- [BYTE] 'key3'
- the index of the 'sub-string' in the pool is:
(key1&0x7F) * 65536
+ key2 * 256
+ key3
- (index is in [16384,(2^23-1)]
- otherwise
- [BYTE] 'key2'
- the index of the 'sub-string' in the pool is:
(key1&0x3F) * 256
+ key2
- (index is in [64,16383])
*/
if( (*p_idxbyte) < 64 )
{
(*p_substr_idx_o) = (DWORDg) (*p_idxbyte);
return p_idxbyte + 1;
}
if( !( (*p_idxbyte) & (1<<7) ) )
{
(*p_substr_idx_o) = (DWORDg) (*p_idxbyte);
(*p_substr_idx_o) &= 0x7F;
p_idxbyte++;
(*p_substr_idx_o) <<= 8;
(*p_substr_idx_o) += (DWORDg) (*p_idxbyte);
return p_idxbyte + 1;
}
(*p_substr_idx_o) = (DWORDg) (*p_idxbyte);
(*p_substr_idx_o) &= 0x3F;
p_idxbyte++;
(*p_substr_idx_o) <<= 8;
(*p_substr_idx_o) += (DWORDg) (*p_idxbyte);
p_idxbyte++;
(*p_substr_idx_o) <<= 8;
(*p_substr_idx_o) += (DWORDg) (*p_idxbyte);
return p_idxbyte + 1;
}
// gets the substring indicated by 'id' from the pool 'p_ksp' into 'p_dst'
// - returns pointer to 'p_dst'
char * KSTR_POOL_GetString( KSTR_POOL * p_ksp, char * p_dst, DWORDg id )
{
DWORDg i;
DWORDg substr_idx;
char * p_curdst;
const BYTEg * p_substr;
const BYTEg * p_krnstr;
const BYTEg * p_over_krnstr;
// scan through *every* kernel string until we find the one we want
p_krnstr = p_ksp->p_krnstrs;
for( i = 0; i < id; i++ )
{
p_krnstr += (*p_krnstr);
}
// get end of kernel string
p_over_krnstr = (++p_krnstr) + (*p_krnstr);
while( 1 )
{
// find substring
p_krnstr = GetSubStringIndex( &substr_idx, p_krnstr );
p_substr = FindSubString( p_ksp->p_substrs, substr_idx );
if( p_krnstr < p_over_krnstr )
{
// append to destination and also append a space
p_curdst = ReadSubStringAppendSpace( p_curdst, p_substr );
continue;
}
// append to destination
p_curdst = ReadSubString( p_curdst, p_substr );
break;
}
return p_dst;
}