Newer
Older
ubixos / src / sys / misc / kernel_string_pool.c
/*
   "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;
}