Re: [CODE] Introduction Snippet

From: Peter Ajamian (peter@pajamian.dhs.org)
Date: 11/15/00


I'm sorta re-hashing and replying back to the list on this one as I
prefer to have my correspondence go through the mailing list so that
others may comment and benefit.

> Peter Ajamian wrote:
> >
> > We'll get back to loading up the array later on.
> >
> > As far as loading and saving to file is concerned, you have several
> > options which have thier own benefits, or lack thereof...
> >
> > ASCII is less efficient in storage space and reading and writing, but it
> > is easier to work with.
> >
"Lewis, Jason" wrote:
>
> I am using ASCII PFILES, just to let ya know
>
Alrighty, then, ASCII it is.

> > In both forms you also have the choice of either saving data on all the
> > players or just for those players who are known.  Saving data only for
> > players who are known is more costly in terms of the amount of space per
> > entry (approx 32 times the space) but requires fewer entries.
> >
I'll go with saving data on all players as I tend to think that will be
more efficient in the end, if you want to do it the other way then by
all means do so.

> > You also have the choice of either using a separate file for each player
> > or saving all the data to one file.  Saving to a separate file makes for
> > faster loading and saving but is less efficient on disk space.  If you
> > are using ASCII pfiles then the choice is already made for you as ASCII
> > pfiles save in a separate file for each player anyways.

Okay, now to get down to business...

These functions should work with just about any ASCII pfile system.

Look through the following code extremely carefully, it contains a lot
of bit manipulation, pointer arithmetic, and other stuff which can be
very confusing.  I did not test it and it probably has some errors in it
so you'll have to at least partially understand it in order to fix the
errors.

Using these function you can cram 6 bits of data into one printable
ASCII
character using the digits 0-9, the letters A-Z and a-z and a subset of
the printable punctuation characters (only two are needed).  This will
allow us to pack three 32 bit longs (or unsigned longs, etc) into 16
characters...

/* Supporting Functions, note these RELY on a platform using the ASCII
character set */
int unpack_single_char(char c)
{
  if (c >= '.' && c <= '9')
    return c - '.';

  if (c >= 'A' && c <= 'Z')
    return c - 'A' + 12;

  if (c >= 'a' && c <= 'z')
    return c - 'a' + 38;

  /* mudlog(blah blah invalid character passed to unpack_single_char
blah blah); */

  /*
   * Set every bit except the first 6 including the sign bit.
   * This should serve as a signal which can be checked for
   * or safely ignored as 0.
   */
  return ~63;
}

char pack_single_char(int i)
{
#if 0
  /* Use this code if you want to send an error message to the mud */
  if (i &~63)
    mudlog(blah blah invalid number passed to pack_single_char blah
blah);
#endif

  i &= 63;

  if (i < 12)
    return i + '.';

  i -= 12;
  if (i < 26)
    return i + 'A';

  i -= 26;
  return i + 'a';
}

/* Works two bits at a time */
void unpack_to_ulong_array(char *line, unsigned long *array, long
length)
{
  long l;
  int i, j = 0, k;

  i = unpack_single_char(*line);
  for (l = 0; *line && *line != '\n' && l < length; l++) {
    for (k = 0; *line && *line != '\n' && k < 32; k+=2) {
      array[l] |= (i & 3) << k;
      i = i >> 2;

      j+=2;
      if (j >= 6) {
        j = 0;
        line++;
        i = unpack_single_char(*line);
      }
    }
  }
}

/* Again, two bits at a time, returns a pointer to a string which can be
written to the pfile. */
char *pack_from_ulong_array(unsigned long *array, long length)
{
  static char *line = NULL;
  static size_t linelen = 0;
  char *ptr;
  unsigned long u;
  long l;
  int i=0, j=0, k;

  /* Check the size of our buffer and increase it if necessary */
  if (linelen < (length*16 + 5) / 3) {
    linelen = top_idnum/6 + 2;
    if (line)
      RECREATE(line, char, linelen);
    else
      CREATE(line, char, linelen);
  }
  ptr = line;

  for (l = 0; l < length; l++) {
    u = array[l];
    for (k = 0; k < 32; k+=2) {
      i |= (u & 3) << j;
      u = u >> 2;

      j += 2;
      if (j >= 6) {
        j = 0;
        *ptr++ = pack_single_char(i);
        i = 0;
      }
    }
  }

  if (i)
    *ptr++ = pack_single_char(i);

  *ptr = 0;

  return line;
}


     +------------------------------------------------------------+
     | Ensure that you have read the CircleMUD Mailing List FAQ:  |
     |  http://qsilver.queensu.ca/~fletchra/Circle/list-faq.html  |
     +------------------------------------------------------------+



This archive was generated by hypermail 2b30 : 04/11/01 PDT