Logo Search packages:      
Sourcecode: ksh version File versions  Download package

vdexpand.c

/***********************************************************************
*                                                                      *
*               This software is part of the ast package               *
*          Copyright (c) 1995-2007 AT&T Intellectual Property          *
*                      and is licensed under the                       *
*                  Common Public License, Version 1.0                  *
*                    by AT&T Intellectual Property                     *
*                                                                      *
*                A copy of the License is available at                 *
*            http://www.opensource.org/licenses/cpl1.0.txt             *
*         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
*                                                                      *
*              Information and Software Systems Research               *
*                            AT&T Research                             *
*                           Florham Park NJ                            *
*                                                                      *
*                   Phong Vo <kpv@research.att.com>                    *
*                                                                      *
***********************************************************************/
#include    "vdelhdr.h"


/*    Expand a squeezed string
**
**    Written by Kiem-Phong Vo, kpv@research.att.com, 2/15/95
*/
typedef struct _table_s
{     uchar*            delta;            /* delta string               */
      uchar*            tar;        /* target data                */
      int         n_tar;
      K_UDECL(quick,recent,rhere);  /* address caches       */
} Table_t;

#if __STD_C
static int vdunfold(reg Table_t* tab)
#else
static int vdunfold(tab)
reg Table_t*      tab;
#endif
{
      reg int           size, copy;
      reg int           inst, k_type, n;
      reg uchar   *tar, *to, *fr;
      reg int           t, c_addr, n_tar;

      n_tar = tab->n_tar;
      tar = tab->tar;

      for(t = 0, c_addr = 0; t < n_tar; )
      {     inst = STRGETC(tab);
            k_type = K_GET(inst);

            if(!VD_ISCOPY(k_type))
            {     if(K_ISMERGE(k_type))   /* merge/add instruction      */
                        size = A_TGET(inst);
                  else if(A_ISHERE(inst)) /* locally coded ADD size     */
                        size = A_LGET(inst);
                  else              /* non-local ADD size         */
                  {     STRGETU(tab,size);
                        size = A_GET(size);
                  }
                  if((t+size) > n_tar)    /* out of sync    */
                        return -1;
                  c_addr += size;

                  /* copy data from the delta stream to target */
                  STRREAD(tab,tar+t,size);
                  t += size;

                  if(K_ISMERGE(k_type))
                  {     size = C_TGET(inst);
                        k_type -= K_MERGE;
                        goto do_copy;
                  }
            }
            else
            {     if(C_ISHERE(inst))      /* locally coded COPY size */
                        size = C_LGET(inst);
                  else
                  {     STRGETU(tab,size);
                        size = C_GET(size);
                  }
            do_copy:
                  if((t+size) > n_tar)    /* out of sync */
                        return -1;

                  if(k_type >= K_QUICK && k_type < (K_QUICK+K_QTYPE) )
                  {     copy = STRGETC(tab);
                        copy = tab->quick[copy + ((k_type-K_QUICK)<<VD_BITS)];
                  }
                  else
                  {     STRGETU(tab,copy);
                        if(k_type >= K_RECENT && k_type < (K_RECENT+K_RTYPE) )
                              copy += tab->recent[k_type - K_RECENT];
                        else if(k_type == K_HERE)
                              copy = c_addr - copy;
                        /* else k_type == K_SELF */
                  }
                  K_UPDATE(tab->quick,tab->recent,tab->rhere,copy);
                  c_addr += size;

                  if(copy >= t || (copy+size) > n_tar) /* out-of-sync */
                        return -1;

                  for(;;)     /* allow for copying overlapped data */
                  {     if((n = t-copy) > size)
                              n = size;
                        to = tar+t; fr = tar+copy;
                        MEMCPY(to,fr,n);
                        t += n;
                        if((size -= n) == 0)
                              break;
                  }
            }
      }

      return 0;
}

#if __STD_C
int vdexpand(Void_t* target, int size, Void_t* delta)
#else
int vdexpand(target, size, delta)
Void_t*     target;           /* target data    */
int   size;
Void_t*     delta;            /* delta data     */
#endif
{
      reg int     t;
      Table_t     tab;

      /* get true target size */
      tab.tar = (uchar*)target;
      tab.delta = (uchar*)delta;
      STRGETU(&tab,t);
      if(t > size)
            return -1;
      tab.n_tar = t;

      K_INIT(tab.quick,tab.recent,tab.rhere);
      if(vdunfold(&tab) < 0)
            return -1;

      return t;
}

Generated by  Doxygen 1.6.0   Back to index