Annotation of qemu/roms/ipxe/src/util/nrv2b.c, revision 1.1

1.1     ! root        1: /**************************************************************
        !             2:     Form adapted from lzhuf.c
        !             3:     written by Haruyasu Yoshizaki 11/20/1988
        !             4:     some minor changes 4/6/1989
        !             5:     comments translated by Haruhiko Okumura 4/7/1989
        !             6: 
        !             7:     minor beautifications and adjustments for compiling under Linux
        !             8:     by Markus Gutschke <[email protected]>
        !             9:                                                1997-01-27
        !            10: 
        !            11:     Modifications to allow use as a filter by Ken Yap
        !            12:     <[email protected]>.
        !            13: 
        !            14:                                                1997-07-01
        !            15: 
        !            16:     Small mod to cope with running on big-endian machines
        !            17:     by Jim Hague <[email protected])
        !            18:                                                1998-02-06
        !            19: 
        !            20:     Make compression statistics report shorter
        !            21:     by Ken Yap <[email protected]>.
        !            22:                                                2001-04-25
        !            23: 
        !            24:     Replaced algorithm with nrv2b from ucl the compression
        !            25:     library from upx.  That code is:
        !            26:     Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
        !            27:     And is distributed under the terms of the GPL.
        !            28:     The conversion was performed 
        !            29:     by Eric Biederman <[email protected]>.
        !            30:                                              20 August 2002
        !            31:                                                 
        !            32: **************************************************************/
        !            33: #define UCLPACK_COMPAT 0
        !            34: #define NDEBUG 1
        !            35: #include <stdio.h>
        !            36: #include <stdlib.h>
        !            37: #include <string.h>
        !            38: #include <ctype.h>
        !            39: #include <errno.h>
        !            40: #ifdef __FreeBSD__
        !            41: #include <inttypes.h>
        !            42: #else
        !            43: #include <stdint.h>
        !            44: #endif
        !            45: #include <limits.h>
        !            46: #include <assert.h>
        !            47: #if UCLPACK_COMPAT
        !            48: #include <netinet/in.h>
        !            49: #endif
        !            50: 
        !            51: #ifndef VERBOSE
        !            52: #define Fprintf(x)
        !            53: #define wterr     0
        !            54: #else
        !            55: #define Fprintf(x) fprintf x
        !            56: #endif
        !            57: 
        !            58: #ifndef MAIN
        !            59: extern
        !            60: #endif
        !            61: FILE  *infile, *outfile;
        !            62: 
        !            63: #if defined(ENCODE) || defined(DECODE)
        !            64: 
        !            65: #ifndef ENDIAN
        !            66: #define ENDIAN   0
        !            67: #endif
        !            68: #ifndef BITSIZE
        !            69: #define BITSIZE 32
        !            70: #endif
        !            71: 
        !            72: static __inline__ void Error(char *message)
        !            73: {
        !            74:        Fprintf((stderr, "\n%s\n", message));
        !            75:        exit(EXIT_FAILURE);
        !            76: }
        !            77: 
        !            78: /* These will be a complete waste of time on a lo-endian */
        !            79: /* system, but it only gets done once so WTF. */
        !            80: static unsigned long i86ul_to_host(unsigned long ul)
        !            81: {
        !            82:        unsigned long res = 0;
        !            83:        int i;
        !            84:        union
        !            85:        {
        !            86:                unsigned char c[4];
        !            87:                unsigned long ul;
        !            88:        } u;
        !            89: 
        !            90:        u.ul = ul;
        !            91:        for (i = 3; i >= 0; i--)
        !            92:                res = (res << 8) + u.c[i];
        !            93:        return res;
        !            94: }
        !            95: 
        !            96: static unsigned long host_to_i86ul(unsigned long ul)
        !            97: {
        !            98:        int i;
        !            99:        union
        !           100:        {
        !           101:                unsigned char c[4];
        !           102:                unsigned long ul;
        !           103:        } u;
        !           104: 
        !           105:        for (i = 0; i < 4; i++)
        !           106:        {
        !           107:                u.c[i] = ul & 0xff;
        !           108:                ul >>= 8;
        !           109:        }
        !           110:        return u.ul;
        !           111: }
        !           112: #endif
        !           113: 
        !           114: 
        !           115: 
        !           116: #if UCLPACK_COMPAT
        !           117: /* magic file header for compressed files */
        !           118: static const unsigned char magic[8] =
        !           119: { 0x00, 0xe9, 0x55, 0x43, 0x4c, 0xff, 0x01, 0x1a };
        !           120: 
        !           121: #endif
        !           122: 
        !           123: #ifdef ENCODE
        !           124: /********** NRV2B_99 compression **********/
        !           125: 
        !           126: /* Note by limiting the ring buffer I have limited the maximum
        !           127:  * offset to 64K.  Since etherboot rarely gets that big it
        !           128:  * is not a problem and it gives me a firm guarantee
        !           129:  * that I will never get a 3 byte string match that is encodes
        !           130:  * to more than 9/8 it's original size.
        !           131:  * That guaranteee is important to for the inplace decompressor.
        !           132:  * There are better ways to do this if a larger offset and buffer
        !           133:  * would give better compression.
        !           134:  */
        !           135: #define N       (65536ul)           /* size of ring buffer */
        !           136: #define THRESHOLD       1           /* lower limit for match length */
        !           137: #define F            2048           /* upper limit for match length */
        !           138: #define M2_MAX_OFFSET                 0xd00
        !           139: 
        !           140: /* note: to use default values pass -1, i.e. initialize
        !           141:  * this struct by a memset(x,0xff,sizeof(x)) */
        !           142: struct ucl_compress_config
        !           143: {
        !           144:        int bb_endian;
        !           145:        int bb_size;
        !           146:        unsigned int max_offset;
        !           147:        unsigned int max_match;
        !           148:        int s_level;
        !           149:        int h_level;
        !           150:        int p_level;
        !           151:        int c_flags;
        !           152:        unsigned int m_size;
        !           153: };
        !           154: 
        !           155: struct ucl_compress
        !           156: {
        !           157:        int init;
        !           158: 
        !           159:        unsigned int look;          /* bytes in lookahead buffer */
        !           160:        
        !           161:        unsigned int m_len;
        !           162:        unsigned int m_off;
        !           163:        
        !           164:        unsigned int last_m_len;
        !           165:        unsigned int last_m_off;
        !           166:        
        !           167:        const unsigned char *bp;
        !           168:        const unsigned char *ip;
        !           169:        const unsigned char *in;
        !           170:        const unsigned char *in_end;
        !           171:        unsigned char *out;
        !           172:        
        !           173:        uint64_t bb_b;
        !           174:        unsigned bb_k;
        !           175:        unsigned bb_c_endian;
        !           176:        unsigned bb_c_s;
        !           177:        unsigned bb_c_s8;
        !           178:        unsigned char *bb_p;
        !           179:        unsigned char *bb_op;
        !           180:        
        !           181:        struct ucl_compress_config conf;
        !           182:        unsigned int *result;
        !           183: 
        !           184:        unsigned int textsize;      /* text size counter */
        !           185:        unsigned int codesize;      /* code size counter */
        !           186:        unsigned int printcount; /* counter for reporting progress every 1K
        !           187:                                    bytes */
        !           188: 
        !           189:        
        !           190:        /* some stats */
        !           191:        unsigned long lit_bytes;
        !           192:        unsigned long match_bytes;
        !           193:        unsigned long rep_bytes;
        !           194:        unsigned long lazy;
        !           195: };
        !           196: 
        !           197: 
        !           198: 
        !           199: #define getbyte(c)  ((c).ip < (c).in_end ? *((c).ip)++ : (-1))
        !           200: 
        !           201: #define UCL_E_OK               0
        !           202: #define UCL_E_INVALID_ARGUMENT 1
        !           203: #define UCL_E_OUT_OF_MEMORY    2
        !           204: #define UCL_E_ERROR            3
        !           205: 
        !           206: /***********************************************************************
        !           207: //
        !           208: ************************************************************************/
        !           209: 
        !           210: #define SWD_HSIZE      16384
        !           211: #define SWD_MAX_CHAIN  2048
        !           212: #define SWD_BEST_OFF    1
        !           213: 
        !           214: #define HEAD3(b,p) \
        !           215:     (((0x9f5f*(((((uint32_t)b[p]<<5)^b[p+1])<<5)^b[p+2]))>>5) & (SWD_HSIZE-1))
        !           216: 
        !           217: #define HEAD2(b,p)      (b[p] ^ ((unsigned)b[p+1]<<8))
        !           218: #define NIL2              UINT_MAX
        !           219: 
        !           220: struct ucl_swd
        !           221: {
        !           222: /* public - "built-in" */
        !           223:        unsigned int n;
        !           224:        unsigned int f;
        !           225:        unsigned int threshold;
        !           226:        
        !           227: /* public - configuration */
        !           228:        unsigned int max_chain;
        !           229:        unsigned int nice_length;
        !           230:        int use_best_off;
        !           231:        unsigned int lazy_insert;
        !           232:        
        !           233: /* public - output */
        !           234:        unsigned int m_len;
        !           235:        unsigned int m_off;
        !           236:        unsigned int look;
        !           237:        int b_char;
        !           238: #if defined(SWD_BEST_OFF)
        !           239:        unsigned int best_off[ SWD_BEST_OFF ];
        !           240: #endif
        !           241:        
        !           242: /* semi public */
        !           243:        struct ucl_compress *c;
        !           244:        unsigned int m_pos;
        !           245: #if defined(SWD_BEST_OFF)
        !           246:        unsigned int best_pos[ SWD_BEST_OFF ];
        !           247: #endif
        !           248:        
        !           249: /* private */
        !           250:        const uint8_t *dict;
        !           251:        const uint8_t *dict_end;
        !           252:        unsigned int dict_len;
        !           253:        
        !           254: /* private */
        !           255:        unsigned int ip;                /* input pointer (lookahead) */
        !           256:        unsigned int bp;                /* buffer pointer */
        !           257:        unsigned int rp;                /* remove pointer */
        !           258:        unsigned int b_size;
        !           259:        
        !           260:        unsigned char *b_wrap;
        !           261:        
        !           262:        unsigned int node_count;
        !           263:        unsigned int first_rp;
        !           264: 
        !           265:        unsigned char b [ N + F + F ];
        !           266:        unsigned int head3 [ SWD_HSIZE ];
        !           267:        unsigned int succ3 [ N + F ];
        !           268:        unsigned int best3 [ N + F ];
        !           269:        unsigned int llen3 [ SWD_HSIZE ];
        !           270:        unsigned int head2 [ 65536U ];
        !           271: };
        !           272: 
        !           273: #define s_head3(s,key)        s->head3[key]
        !           274: 
        !           275: 
        !           276: #if !defined( NDEBUG)
        !           277: static void assert_match(const struct ucl_swd * swd, unsigned int m_len,
        !           278:        unsigned int m_off )
        !           279: 
        !           280: {
        !           281:        const struct ucl_compress *c = swd->c;
        !           282:        unsigned int d_off;
        !           283:        
        !           284:        assert(m_len >= 2);
        !           285:        if (m_off <= (unsigned int) (c->bp - c->in))
        !           286:        {
        !           287:                assert(c->bp - m_off + m_len < c->ip);
        !           288:                assert(memcmp(c->bp, c->bp - m_off, m_len) == 0);
        !           289:        }
        !           290:        else
        !           291:        {
        !           292:                assert(swd->dict != NULL);
        !           293:                d_off = m_off - (unsigned int) (c->bp - c->in);
        !           294:                assert(d_off <= swd->dict_len);
        !           295:                if (m_len > d_off)
        !           296:                {
        !           297:                        assert(memcmp(c->bp, swd->dict_end - d_off, d_off) ==
        !           298:                                0);
        !           299: 
        !           300:                        assert(c->in + m_len - d_off < c->ip);
        !           301:                        assert(memcmp(c->bp + d_off, c->in, m_len - d_off) ==
        !           302:                                0);
        !           303: 
        !           304:                }
        !           305:                else
        !           306:                {
        !           307:                        assert(memcmp(c->bp, swd->dict_end - d_off, m_len) ==
        !           308:                                0);
        !           309: 
        !           310:                }
        !           311:        }
        !           312: }
        !           313: #else
        !           314: #  define assert_match(a,b,c)   ((void)0)
        !           315: #endif
        !           316: 
        !           317: /***********************************************************************
        !           318: //
        !           319: ************************************************************************/
        !           320: 
        !           321: 
        !           322: static
        !           323: void swd_initdict(struct ucl_swd *s, const uint8_t *dict, unsigned int dict_len)
        !           324: 
        !           325: {
        !           326:        s->dict = s->dict_end = NULL;
        !           327:        s->dict_len = 0;
        !           328: 
        !           329:        if (!dict || dict_len <= 0)
        !           330:                return;
        !           331:        if (dict_len > s->n)
        !           332:        {
        !           333:                dict += dict_len - s->n;
        !           334:                dict_len = s->n;
        !           335:        }
        !           336: 
        !           337:        s->dict = dict;
        !           338:        s->dict_len = dict_len;
        !           339:        s->dict_end = dict + dict_len;
        !           340:        memcpy(s->b,dict,dict_len);
        !           341:        s->ip = dict_len;
        !           342: }
        !           343: 
        !           344: 
        !           345: static
        !           346: void swd_insertdict(struct ucl_swd *s, unsigned int node, unsigned int len)
        !           347: {
        !           348:        unsigned int key;
        !           349: 
        !           350:        s->node_count = s->n - len;
        !           351:        s->first_rp = node;
        !           352: 
        !           353:        while (len-- > 0)
        !           354:        {
        !           355:                key = HEAD3(s->b,node);
        !           356:                s->succ3[node] = s_head3(s,key);
        !           357:                s->head3[key] = (unsigned int)(node);
        !           358:                s->best3[node] = (unsigned int)(s->f + 1);
        !           359:                s->llen3[key]++;
        !           360:                assert(s->llen3[key] <= s->n);
        !           361: 
        !           362:                key = HEAD2(s->b,node);
        !           363:                s->head2[key] = (unsigned int)(node);
        !           364: 
        !           365:                node++;
        !           366:        }
        !           367: }
        !           368: 
        !           369: /***********************************************************************
        !           370: //
        !           371: ************************************************************************/
        !           372: 
        !           373: 
        !           374: static
        !           375: int swd_init(struct ucl_swd *s, const uint8_t *dict, unsigned int dict_len)
        !           376: {
        !           377:        unsigned int i = 0;
        !           378:        int c = 0;
        !           379: 
        !           380:        if (s->n == 0)
        !           381:                s->n = N;
        !           382:        if (s->f == 0)
        !           383:                s->f = F;
        !           384:        s->threshold = THRESHOLD;
        !           385:        if (s->n > N || s->f > F)
        !           386:                return UCL_E_INVALID_ARGUMENT;
        !           387: 
        !           388:        /* defaults */
        !           389:        s->max_chain = SWD_MAX_CHAIN;
        !           390:        s->nice_length = s->f;
        !           391:        s->use_best_off = 0;
        !           392:        s->lazy_insert = 0;
        !           393: 
        !           394:        s->b_size = s->n + s->f;
        !           395:        if (s->b_size + s->f >= UINT_MAX)
        !           396:                return UCL_E_ERROR;
        !           397:        s->b_wrap = s->b + s->b_size;
        !           398:        s->node_count = s->n;
        !           399: 
        !           400:        memset(s->llen3, 0, sizeof(s->llen3[0]) * SWD_HSIZE);
        !           401:        for (i = 0; i < 65536U; i++)
        !           402:                s->head2[i] = NIL2;
        !           403: 
        !           404:        s->ip = 0;
        !           405:        swd_initdict(s,dict,dict_len);
        !           406:        s->bp = s->ip;
        !           407:        s->first_rp = s->ip;
        !           408: 
        !           409:        assert(s->ip + s->f <= s->b_size);
        !           410: 
        !           411:        s->look = (unsigned int) (s->c->in_end - s->c->ip);
        !           412:        if (s->look > 0)
        !           413:        {
        !           414:                if (s->look > s->f)
        !           415:                        s->look = s->f;
        !           416:                memcpy(&s->b[s->ip],s->c->ip,s->look);
        !           417:                s->c->ip += s->look;
        !           418:                s->ip += s->look;
        !           419:        }
        !           420:        if (s->ip == s->b_size)
        !           421:                s->ip = 0;
        !           422: 
        !           423:        if (s->look >= 2 && s->dict_len > 0)
        !           424:                swd_insertdict(s,0,s->dict_len);
        !           425: 
        !           426:        s->rp = s->first_rp;
        !           427:        if (s->rp >= s->node_count)
        !           428:                s->rp -= s->node_count;
        !           429:        else
        !           430:                s->rp += s->b_size - s->node_count;
        !           431: 
        !           432:        /* unused i */
        !           433:        /* unused c */
        !           434:        return UCL_E_OK;
        !           435: }
        !           436: 
        !           437: 
        !           438: static
        !           439: void swd_exit(struct ucl_swd *s)
        !           440: {
        !           441:        /* unused s */
        !           442: 
        !           443: }
        !           444: 
        !           445: #define swd_pos2off(s,pos) \
        !           446:        (s->bp > (pos) ? s->bp - (pos) : s->b_size - ((pos) - s->bp))
        !           447: 
        !           448: /***********************************************************************
        !           449: //
        !           450: ************************************************************************/
        !           451: 
        !           452: static __inline__
        !           453: void swd_getbyte(struct ucl_swd *s)
        !           454: {
        !           455:        int c;
        !           456: 
        !           457:        if ((c = getbyte(*(s->c))) < 0)
        !           458:        {
        !           459:                if (s->look > 0)
        !           460:                        --s->look;
        !           461:        }
        !           462:        else
        !           463:        {
        !           464:                s->b[s->ip] = (uint8_t)(c);
        !           465:                if (s->ip < s->f)
        !           466:                        s->b_wrap[s->ip] = (uint8_t)(c);
        !           467:        }
        !           468:        if (++s->ip == s->b_size)
        !           469:                s->ip = 0;
        !           470:        if (++s->bp == s->b_size)
        !           471:                s->bp = 0;
        !           472:        if (++s->rp == s->b_size)
        !           473:                s->rp = 0;
        !           474: }
        !           475: /***********************************************************************
        !           476: // remove node from lists
        !           477: ************************************************************************/
        !           478: 
        !           479: static __inline__
        !           480: void swd_remove_node(struct ucl_swd *s, unsigned int node)
        !           481: {
        !           482:        if (s->node_count == 0)
        !           483:        {
        !           484:                unsigned int key;
        !           485:                
        !           486: #ifdef UCL_DEBUG
        !           487:                if (s->first_rp != UINT_MAX)
        !           488:                {
        !           489:                        if (node != s->first_rp)
        !           490:                                printf("Remove %5d: %5d %5d %5d %5d %6d %6d\n",
        !           491: 
        !           492:                                        node, s->rp, s->ip, s->bp, s->first_rp,
        !           493:                                        s->ip - node, s->ip - s->bp);
        !           494:                        assert(node == s->first_rp);
        !           495:                        s->first_rp = UINT_MAX;
        !           496:                }
        !           497: #endif
        !           498:                
        !           499:                key = HEAD3(s->b,node);
        !           500:                assert(s->llen3[key] > 0);
        !           501:                --s->llen3[key];
        !           502:                
        !           503:                key = HEAD2(s->b,node);
        !           504:                assert(s->head2[key] != NIL2);
        !           505:                if ((unsigned int) s->head2[key] == node)
        !           506:                        s->head2[key] = NIL2;
        !           507:        }
        !           508:        else
        !           509:                --s->node_count;
        !           510: }
        !           511: 
        !           512: 
        !           513: /***********************************************************************
        !           514: //
        !           515: ************************************************************************/
        !           516: 
        !           517: 
        !           518: static
        !           519: void swd_accept(struct ucl_swd *s, unsigned int n)
        !           520: {
        !           521:        assert(n <= s->look);
        !           522: 
        !           523:        if (n > 0) do
        !           524:        {
        !           525:                unsigned int key;
        !           526: 
        !           527:                swd_remove_node(s,s->rp);
        !           528: 
        !           529:                /* add bp into HEAD3 */
        !           530:                key = HEAD3(s->b,s->bp);
        !           531:                s->succ3[s->bp] = s_head3(s,key);
        !           532:                s->head3[key] = (unsigned int)(s->bp);
        !           533:                s->best3[s->bp] = (unsigned int)(s->f + 1);
        !           534:                s->llen3[key]++;
        !           535:                assert(s->llen3[key] <= s->n);
        !           536: 
        !           537:                /* add bp into HEAD2 */
        !           538:                key = HEAD2(s->b,s->bp);
        !           539:                s->head2[key] = (unsigned int)(s->bp);
        !           540: 
        !           541:                swd_getbyte(s);
        !           542:        } while (--n > 0);
        !           543: }
        !           544: 
        !           545: /***********************************************************************
        !           546: //
        !           547: ************************************************************************/
        !           548: 
        !           549: static
        !           550: void swd_search(struct ucl_swd *s, unsigned int node, unsigned int cnt)
        !           551: {
        !           552:        const unsigned char *p1;
        !           553:        const unsigned char *p2;
        !           554:        const unsigned char *px;
        !           555: 
        !           556:        unsigned int m_len = s->m_len;
        !           557:        const unsigned char * b  = s->b;
        !           558:        const unsigned char * bp = s->b + s->bp;
        !           559:        const unsigned char * bx = s->b + s->bp + s->look;
        !           560:        unsigned char scan_end1;
        !           561:        
        !           562:        assert(s->m_len > 0);
        !           563:        
        !           564:        scan_end1 = bp[m_len - 1];
        !           565:        for ( ; cnt-- > 0; node = s->succ3[node])
        !           566:        {
        !           567:                p1 = bp;
        !           568:                p2 = b + node;
        !           569:                px = bx;
        !           570:                
        !           571:                assert(m_len < s->look);
        !           572:                
        !           573:                if (
        !           574:                        p2[m_len - 1] == scan_end1 &&
        !           575:                        p2[m_len] == p1[m_len] &&
        !           576:                        p2[0] == p1[0] &&
        !           577:                        p2[1] == p1[1])
        !           578:                {
        !           579:                        unsigned int i;
        !           580:                        assert(memcmp(bp,&b[node],3) == 0);
        !           581:                        
        !           582:                        p1 += 2; p2 += 2;
        !           583:                        do {} while (++p1 < px && *p1 == *++p2);
        !           584:                        i = p1 - bp;
        !           585:                        
        !           586: #ifdef UCL_DEBUG
        !           587:                        if (memcmp(bp,&b[node],i) != 0)
        !           588:                                printf("%5ld %5ld %02x%02x %02x%02x\n",
        !           589:                                        (long)s->bp, (long) node,
        !           590:                                        bp[0], bp[1], b[node], b[node+1]);
        !           591: #endif
        !           592:                        assert(memcmp(bp,&b[node],i) == 0);
        !           593:                        
        !           594: #if defined(SWD_BEST_OFF)
        !           595:                        if (i < SWD_BEST_OFF)
        !           596:                        {
        !           597:                                if (s->best_pos[i] == 0)
        !           598:                                        s->best_pos[i] = node + 1;
        !           599:                        }
        !           600: #endif
        !           601:                        if (i > m_len)
        !           602:                        {
        !           603:                                s->m_len = m_len = i;
        !           604:                                s->m_pos = node;
        !           605:                                if (m_len == s->look)
        !           606:                                        return;
        !           607:                                if (m_len >= s->nice_length)
        !           608:                                        return;
        !           609:                                if (m_len > (unsigned int) s->best3[node])
        !           610:                                        return;
        !           611:                                scan_end1 = bp[m_len - 1];
        !           612:                        }
        !           613:                }
        !           614:        }
        !           615: }
        !           616: 
        !           617: static int swd_search2(struct ucl_swd *s)
        !           618: {
        !           619:        unsigned int key;
        !           620:        
        !           621:        assert(s->look >= 2);
        !           622:        assert(s->m_len > 0);
        !           623:        
        !           624:        key = s->head2[ HEAD2(s->b,s->bp) ];
        !           625:        if (key == NIL2)
        !           626:                return 0;
        !           627: #ifdef UCL_DEBUG
        !           628:        if (memcmp(&s->b[s->bp],&s->b[key],2) != 0)
        !           629:                printf("%5ld %5ld %02x%02x %02x%02x\n", (long)s->bp, (long)key,
        !           630:                        s->b[s->bp], s->b[s->bp+1], s->b[key], s->b[key+1]);
        !           631: #endif
        !           632:        assert(memcmp(&s->b[s->bp],&s->b[key],2) == 0);
        !           633: #if defined(SWD_BEST_OFF)
        !           634:        if (s->best_pos[2] == 0)
        !           635:                s->best_pos[2] = key + 1;
        !           636: #endif
        !           637:        
        !           638:        if (s->m_len < 2)
        !           639:        {
        !           640:                s->m_len = 2;
        !           641:                s->m_pos = key;
        !           642:        }
        !           643:        return 1;
        !           644: }
        !           645: 
        !           646: /***********************************************************************
        !           647: //
        !           648: ************************************************************************/
        !           649: 
        !           650: static
        !           651: void swd_findbest(struct ucl_swd *s)
        !           652: {
        !           653:        unsigned int key;
        !           654:        unsigned int cnt, node;
        !           655:        unsigned int len;
        !           656: 
        !           657:        assert(s->m_len > 0);
        !           658: 
        !           659:        /* get current head, add bp into HEAD3 */
        !           660:        key = HEAD3(s->b,s->bp);
        !           661:        node = s->succ3[s->bp] = s_head3(s,key);
        !           662:        cnt = s->llen3[key]++;
        !           663:        assert(s->llen3[key] <= s->n + s->f);
        !           664:        if (cnt > s->max_chain && s->max_chain > 0)
        !           665:                cnt = s->max_chain;
        !           666:        s->head3[key] = (unsigned int)(s->bp);
        !           667: 
        !           668:        s->b_char = s->b[s->bp];
        !           669:        len = s->m_len;
        !           670:        if (s->m_len >= s->look)
        !           671:        {
        !           672:                if (s->look == 0)
        !           673:                        s->b_char = -1;
        !           674:                s->m_off = 0;
        !           675:                s->best3[s->bp] = (unsigned int)(s->f + 1);
        !           676:        }
        !           677:        else
        !           678:        {
        !           679:                if (swd_search2(s))
        !           680:                        if (s->look >= 3)
        !           681:                                swd_search(s,node,cnt);
        !           682:                if (s->m_len > len)
        !           683:                        s->m_off = swd_pos2off(s,s->m_pos);
        !           684:                s->best3[s->bp] = (unsigned int)(s->m_len);
        !           685: 
        !           686: #if defined(SWD_BEST_OFF)
        !           687:                if (s->use_best_off)
        !           688:                {
        !           689:                        int i;
        !           690:                        for (i = 2; i < SWD_BEST_OFF; i++)
        !           691:                                if (s->best_pos[i] > 0)
        !           692:                                        s->best_off[i] =
        !           693:                                                swd_pos2off(s,s->best_pos[i]-1);
        !           694: 
        !           695:                                else
        !           696:                                        s->best_off[i] = 0;
        !           697:                }
        !           698: #endif
        !           699:        }
        !           700: 
        !           701:        swd_remove_node(s,s->rp);
        !           702: 
        !           703:        /* add bp into HEAD2 */
        !           704:        key = HEAD2(s->b,s->bp);
        !           705:        s->head2[key] = (unsigned int)(s->bp);
        !           706: }
        !           707: 
        !           708: 
        !           709: /***********************************************************************
        !           710: //
        !           711: ************************************************************************/
        !           712: 
        !           713: static int
        !           714: init_match ( struct ucl_compress *c, struct ucl_swd *s,
        !           715:        const uint8_t *dict, unsigned int dict_len,
        !           716:        uint32_t flags )
        !           717: {
        !           718:        int r;
        !           719:        
        !           720:        assert(!c->init);
        !           721:        c->init = 1;
        !           722:        
        !           723:        s->c = c;
        !           724:        
        !           725:        c->last_m_len = c->last_m_off = 0;
        !           726:        
        !           727:        c->textsize = c->codesize = c->printcount = 0;
        !           728:        c->lit_bytes = c->match_bytes = c->rep_bytes = 0;
        !           729:        c->lazy = 0;
        !           730:        
        !           731:        r = swd_init(s,dict,dict_len);
        !           732:        if (r != UCL_E_OK)
        !           733:        {
        !           734:                swd_exit(s);
        !           735:                return r;
        !           736:        }
        !           737:        
        !           738:        s->use_best_off = (flags & 1) ? 1 : 0;
        !           739:        return UCL_E_OK;
        !           740: }
        !           741: 
        !           742: static int
        !           743: find_match ( struct ucl_compress *c, struct ucl_swd *s,
        !           744:        unsigned int this_len, unsigned int skip )
        !           745: {
        !           746:        assert(c->init);
        !           747:        
        !           748:        if (skip > 0)
        !           749:        {
        !           750:                assert(this_len >= skip);
        !           751:                swd_accept(s, this_len - skip);
        !           752:                c->textsize += this_len - skip + 1;
        !           753:        }
        !           754:        else
        !           755:        {
        !           756:                assert(this_len <= 1);
        !           757:                c->textsize += this_len - skip;
        !           758:        }
        !           759:        
        !           760:        s->m_len = THRESHOLD;
        !           761: #ifdef SWD_BEST_OFF
        !           762:        if (s->use_best_off)
        !           763:                memset(s->best_pos,0,sizeof(s->best_pos));
        !           764: #endif
        !           765:        swd_findbest(s);
        !           766:        c->m_len = s->m_len;
        !           767:        c->m_off = s->m_off;
        !           768:        
        !           769:        swd_getbyte(s);
        !           770:        
        !           771:        if (s->b_char < 0)
        !           772:        {
        !           773:                c->look = 0;
        !           774:                c->m_len = 0;
        !           775:                swd_exit(s);
        !           776:        }
        !           777:        else
        !           778:        {
        !           779:                c->look = s->look + 1;
        !           780:        }
        !           781:        c->bp = c->ip - c->look;
        !           782:        
        !           783: #if 0
        !           784:        /* brute force match search */
        !           785:        if (c->m_len > THRESHOLD && c->m_len + 1 <= c->look)
        !           786:        {
        !           787:                const uint8_t *ip = c->bp;
        !           788:                const uint8_t *m  = c->bp - c->m_off;
        !           789:                const uint8_t *in = c->in;
        !           790:                
        !           791:                if (ip - in > N)
        !           792:                        in = ip - N;
        !           793:                for (;;)
        !           794:                {
        !           795:                        while (*in != *ip)
        !           796:                                in++;
        !           797:                        if (in == ip)
        !           798:                                break;
        !           799:                        if (in != m)
        !           800:                                if (memcmp(in,ip,c->m_len+1) == 0)
        !           801:                                        printf("%p %p %p %5d\n",in,ip,m,c->m_len);
        !           802: 
        !           803:                        in++;
        !           804:                }
        !           805:        }
        !           806: #endif
        !           807:        
        !           808:        return UCL_E_OK;
        !           809: }
        !           810: 
        !           811: 
        !           812: static int bbConfig(struct ucl_compress *c, int endian, int bitsize)
        !           813: {
        !           814:        if (endian != -1)
        !           815:        {
        !           816:                if (endian != 0)
        !           817:                        return UCL_E_ERROR;
        !           818:                c->bb_c_endian = endian;
        !           819:        }
        !           820:        if (bitsize != -1)
        !           821:        {
        !           822:                if (bitsize != 8 && bitsize != 16 && bitsize != 32 && bitsize != 64)
        !           823:                        return UCL_E_ERROR;
        !           824:                c->bb_c_s = bitsize;
        !           825:                c->bb_c_s8 = bitsize / 8;
        !           826:        }
        !           827:        c->bb_b = 0; c->bb_k = 0;
        !           828:        c->bb_p = NULL;
        !           829:        c->bb_op = NULL;
        !           830:        return UCL_E_OK;
        !           831: }
        !           832: 
        !           833: static void bbWriteBits(struct ucl_compress *c)
        !           834: {
        !           835:        uint8_t *p = c->bb_p;
        !           836:        uint64_t b = c->bb_b;
        !           837: 
        !           838:        p[0] = (uint8_t)(b >>  0);
        !           839:        if (c->bb_c_s >= 16)
        !           840:        {
        !           841:                p[1] = (uint8_t)(b >>  8);
        !           842:                if (c->bb_c_s >= 32)
        !           843:                {
        !           844:                        p[2] = (uint8_t)(b >> 16);
        !           845:                        p[3] = (uint8_t)(b >> 24);
        !           846:                        if (c->bb_c_s == 64)
        !           847:                        {
        !           848:                                p[4] = (uint8_t)(b >> 32);
        !           849:                                p[5] = (uint8_t)(b >> 40);
        !           850:                                p[6] = (uint8_t)(b >> 48);
        !           851:                                p[7] = (uint8_t)(b >> 56);
        !           852:                        }
        !           853:                }
        !           854:        }
        !           855: }
        !           856: 
        !           857: 
        !           858: static void bbPutBit(struct ucl_compress *c, unsigned bit)
        !           859: {
        !           860:        assert(bit == 0 || bit == 1);
        !           861:        assert(c->bb_k <= c->bb_c_s);
        !           862: 
        !           863:        if (c->bb_k < c->bb_c_s)
        !           864:        {
        !           865:                if (c->bb_k == 0)
        !           866:                {
        !           867:                        assert(c->bb_p == NULL);
        !           868:                        c->bb_p = c->bb_op;
        !           869:                        c->bb_op += c->bb_c_s8;
        !           870:                }
        !           871:                assert(c->bb_p != NULL);
        !           872:                assert(c->bb_p + c->bb_c_s8 <= c->bb_op);
        !           873: 
        !           874:                c->bb_b = (c->bb_b << 1) + bit;
        !           875:                c->bb_k++;
        !           876:        }
        !           877:        else
        !           878:        {
        !           879:                assert(c->bb_p != NULL);
        !           880:                assert(c->bb_p + c->bb_c_s8 <= c->bb_op);
        !           881: 
        !           882:                bbWriteBits(c);
        !           883:                c->bb_p = c->bb_op;
        !           884:                c->bb_op += c->bb_c_s8;
        !           885:                c->bb_b = bit;
        !           886:                c->bb_k = 1;
        !           887:        }
        !           888: }
        !           889: 
        !           890: 
        !           891: static void bbPutByte(struct ucl_compress *c, unsigned b)
        !           892: {
        !           893:        /**printf("putbyte %p %p %x  (%d)\n", op, bb_p, x, bb_k);*/
        !           894:        assert(c->bb_p == NULL || c->bb_p + c->bb_c_s8 <= c->bb_op);
        !           895:        *c->bb_op++ = (uint8_t)(b);
        !           896: }
        !           897: 
        !           898: static void bbFlushBits(struct ucl_compress *c, unsigned filler_bit)
        !           899: {
        !           900:        if (c->bb_k > 0)
        !           901:        {
        !           902:                assert(c->bb_k <= c->bb_c_s);
        !           903:                while (c->bb_k != c->bb_c_s)
        !           904:                        bbPutBit(c, filler_bit);
        !           905:                bbWriteBits(c);
        !           906:                c->bb_k = 0;
        !           907:        }
        !           908:        c->bb_p = NULL;
        !           909: }
        !           910: 
        !           911: 
        !           912: 
        !           913: /***********************************************************************
        !           914: //
        !           915: ************************************************************************/
        !           916: 
        !           917: 
        !           918: static void code_prefix_ss11(struct ucl_compress *c, uint32_t i)
        !           919: {
        !           920:        if (i >= 2)
        !           921:        {
        !           922:                uint32_t t = 4;
        !           923:                i += 2;
        !           924:                do {
        !           925:                        t <<= 1;
        !           926:                } while (i >= t);
        !           927:                t >>= 1;
        !           928:                do {
        !           929:                        t >>= 1;
        !           930:                        bbPutBit(c, (i & t) ? 1 : 0);
        !           931:                        bbPutBit(c, 0);
        !           932:                } while (t > 2);
        !           933:        }
        !           934:        bbPutBit(c, (unsigned)i & 1);
        !           935:        bbPutBit(c, 1);
        !           936: }
        !           937: 
        !           938: static void
        !           939: code_match(struct ucl_compress *c, unsigned int m_len, const unsigned int m_off)
        !           940: 
        !           941: {
        !           942:        while (m_len > c->conf.max_match)
        !           943:        {
        !           944:                code_match(c, c->conf.max_match - 3, m_off);
        !           945:                m_len -= c->conf.max_match - 3;
        !           946:        }
        !           947:        
        !           948:        c->match_bytes += m_len;
        !           949:        if (m_len > c->result[3])
        !           950:                c->result[3] = m_len;
        !           951:        if (m_off > c->result[1])
        !           952:                c->result[1] = m_off;
        !           953: 
        !           954:        bbPutBit(c, 0);
        !           955: 
        !           956:        if (m_off == c->last_m_off)
        !           957:        {
        !           958:                bbPutBit(c, 0);
        !           959:                bbPutBit(c, 1);
        !           960:        }
        !           961:        else
        !           962:        {
        !           963:                code_prefix_ss11(c, 1 + ((m_off - 1) >> 8));
        !           964:                bbPutByte(c, (unsigned)m_off - 1);
        !           965:        }
        !           966:        m_len = m_len - 1 - (m_off > M2_MAX_OFFSET);
        !           967:        if (m_len >= 4)
        !           968:        {
        !           969:                bbPutBit(c,0);
        !           970:                bbPutBit(c,0);
        !           971:                code_prefix_ss11(c, m_len - 4);
        !           972:        }
        !           973:        else
        !           974:        {
        !           975:                bbPutBit(c, m_len > 1);
        !           976:                bbPutBit(c, (unsigned)m_len & 1);
        !           977:        }
        !           978: 
        !           979:        c->last_m_off = m_off;
        !           980: }
        !           981: 
        !           982: static void
        !           983: code_run(struct ucl_compress *c, const uint8_t *ii, unsigned int lit)
        !           984: {
        !           985:        if (lit == 0)
        !           986:                return;
        !           987:        c->lit_bytes += lit;
        !           988:        if (lit > c->result[5])
        !           989:                c->result[5] = lit;
        !           990:        do {
        !           991:                bbPutBit(c, 1);
        !           992:                bbPutByte(c, *ii++);
        !           993:        } while (--lit > 0);
        !           994: }
        !           995: 
        !           996: /***********************************************************************
        !           997: //
        !           998: ************************************************************************/
        !           999: 
        !          1000: static int
        !          1001: len_of_coded_match(struct ucl_compress *c, unsigned int m_len, unsigned int
        !          1002:        m_off)
        !          1003: 
        !          1004: {
        !          1005:        int b;
        !          1006:        if (m_len < 2 || (m_len == 2 && (m_off > M2_MAX_OFFSET))
        !          1007:                || m_off > c->conf.max_offset)
        !          1008:                return -1;
        !          1009:        assert(m_off > 0);
        !          1010:        
        !          1011:        m_len = m_len - 2 - (m_off > M2_MAX_OFFSET);
        !          1012:        
        !          1013:        if (m_off == c->last_m_off)
        !          1014:                b = 1 + 2;
        !          1015:        else
        !          1016:        {
        !          1017:                b = 1 + 10;
        !          1018:                m_off = (m_off - 1) >> 8;
        !          1019:                while (m_off > 0)
        !          1020:                {
        !          1021:                        b += 2;
        !          1022:                        m_off >>= 1;
        !          1023:                }
        !          1024:        }
        !          1025: 
        !          1026:        b += 2;
        !          1027:        if (m_len < 3)
        !          1028:                return b;
        !          1029:        m_len -= 3;
        !          1030: 
        !          1031:        do {
        !          1032:                b += 2;
        !          1033:                m_len >>= 1;
        !          1034:        } while (m_len > 0);
        !          1035: 
        !          1036:        return b;
        !          1037: }
        !          1038: 
        !          1039: int ucl_nrv2b_99_compress(
        !          1040:        const uint8_t *in, unsigned long in_len,
        !          1041:        uint8_t *out, unsigned long *out_len,
        !          1042:        unsigned int *result)
        !          1043: {
        !          1044:        const uint8_t *ii;
        !          1045:        unsigned int lit;
        !          1046:        unsigned int m_len, m_off;
        !          1047:        struct ucl_compress c_buffer;
        !          1048:        struct ucl_compress * const c = &c_buffer;
        !          1049:        struct ucl_swd *swd;
        !          1050:        unsigned int result_buffer[16];
        !          1051:        int r;
        !          1052: 
        !          1053: /* max compression */
        !          1054: #define SC_TRY_LAZY    2
        !          1055: #define SC_GOOD_LENGTH F
        !          1056: #define SC_MAX_LAZY    F
        !          1057: #define SC_NICE_LENGTH F
        !          1058: #define SC_MAX_CHAIN   4096
        !          1059: #define SC_FLAGS       1
        !          1060: #define SC_MAX_OFFSET  N
        !          1061:        
        !          1062:        memset(c, 0, sizeof(*c));
        !          1063:        c->ip = c->in = in;
        !          1064:        c->in_end = in + in_len;
        !          1065:        c->out = out;
        !          1066:        c->result = result ? result : result_buffer;
        !          1067:        memset(c->result, 0, 16*sizeof(*c->result));
        !          1068:        c->result[0] = c->result[2] = c->result[4] = UINT_MAX;
        !          1069:        result = NULL;
        !          1070:        memset(&c->conf, 0xff, sizeof(c->conf));
        !          1071:        r = bbConfig(c, ENDIAN, BITSIZE);
        !          1072:        if (r == 0)
        !          1073:                r = bbConfig(c, c->conf.bb_endian, c->conf.bb_size);
        !          1074:        if (r != 0)
        !          1075:                return UCL_E_INVALID_ARGUMENT;
        !          1076:        c->bb_op = out;
        !          1077:        
        !          1078:        ii = c->ip;             /* point to start of literal run */
        !          1079:        lit = 0;
        !          1080:        
        !          1081: 
        !          1082:        swd = (struct ucl_swd *) malloc(sizeof(*swd));
        !          1083:        if (!swd)
        !          1084:                return UCL_E_OUT_OF_MEMORY;
        !          1085: 
        !          1086:        swd->f = F;
        !          1087:        swd->n = N;
        !          1088:        if (in_len >= 256 && in_len < swd->n)
        !          1089:                swd->n = in_len;
        !          1090:        if (swd->f < 8 || swd->n < 256)
        !          1091:                return UCL_E_INVALID_ARGUMENT;
        !          1092: 
        !          1093:        r = init_match(c,swd,NULL,0, SC_FLAGS);
        !          1094:        if (r != UCL_E_OK)
        !          1095:        {
        !          1096:                free(swd);
        !          1097:                return r;
        !          1098:        }
        !          1099:        if (SC_MAX_CHAIN > 0)
        !          1100:                swd->max_chain = SC_MAX_CHAIN;
        !          1101:        if (SC_NICE_LENGTH > 0)
        !          1102:                swd->nice_length = SC_NICE_LENGTH;
        !          1103:        if (c->conf.max_match < swd->nice_length)
        !          1104:                swd->nice_length = c->conf.max_match;
        !          1105:        
        !          1106:        c->last_m_off = 1;
        !          1107:        r = find_match(c,swd,0,0);
        !          1108:        if (r != UCL_E_OK)
        !          1109:                return r;
        !          1110:        while (c->look > 0)
        !          1111:        {
        !          1112:                unsigned int ahead;
        !          1113:                unsigned int max_ahead;
        !          1114:                int l1, l2;
        !          1115:                
        !          1116:                c->codesize = c->bb_op - out;
        !          1117:                
        !          1118:                m_len = c->m_len;
        !          1119:                m_off = c->m_off;
        !          1120:                
        !          1121:                assert(c->bp == c->ip - c->look);
        !          1122:                assert(c->bp >= in);
        !          1123:                if (lit == 0)
        !          1124:                        ii = c->bp;
        !          1125:                assert(ii + lit == c->bp);
        !          1126:                assert(swd->b_char == *(c->bp));
        !          1127:                
        !          1128:                if (m_len < 2 || (m_len == 2 && (m_off > M2_MAX_OFFSET))
        !          1129:                        || m_off > c->conf.max_offset)
        !          1130:                {
        !          1131:                        /* a literal */
        !          1132:                        lit++;
        !          1133:                        swd->max_chain = SC_MAX_CHAIN;
        !          1134:                        r = find_match(c,swd,1,0);
        !          1135:                        assert(r == 0);
        !          1136:                        continue;
        !          1137:                }
        !          1138:                
        !          1139:                /* a match */
        !          1140:                assert_match(swd,m_len,m_off);
        !          1141:                
        !          1142:                /* shall we try a lazy match ? */
        !          1143:                ahead = 0;
        !          1144:                if (SC_TRY_LAZY <= 0 || m_len >= SC_MAX_LAZY || m_off ==
        !          1145:                        c->last_m_off)
        !          1146: 
        !          1147:                {
        !          1148:                        /* no */
        !          1149:                        l1 = 0;
        !          1150:                        max_ahead = 0;
        !          1151:                }
        !          1152:                else
        !          1153:                {
        !          1154:                        /* yes, try a lazy match */
        !          1155:                        l1 = len_of_coded_match(c,m_len,m_off);
        !          1156:                        assert(l1 > 0);
        !          1157:                        max_ahead = SC_TRY_LAZY;
        !          1158:                        if ((m_len - 1) < max_ahead) {
        !          1159:                                max_ahead = m_len -1;
        !          1160:                        }
        !          1161:                }
        !          1162:                
        !          1163:                while (ahead < max_ahead && c->look > m_len)
        !          1164:                {
        !          1165:                        if (m_len >= SC_GOOD_LENGTH)
        !          1166:                                swd->max_chain = SC_MAX_CHAIN >> 2;
        !          1167:                        else
        !          1168:                                swd->max_chain = SC_MAX_CHAIN;
        !          1169:                        r = find_match(c,swd,1,0);
        !          1170:                        ahead++;
        !          1171:                        
        !          1172:                        assert(r == 0);
        !          1173:                        assert(c->look > 0);
        !          1174:                        assert(ii + lit + ahead == c->bp);
        !          1175:                        
        !          1176:                        if (c->m_len < 2)
        !          1177:                                continue;
        !          1178:                        l2 = len_of_coded_match(c,c->m_len,c->m_off);
        !          1179:                        if (l2 < 0)
        !          1180:                                continue;
        !          1181:                        if (l1 + (int)(ahead + c->m_len - m_len) * 5 > l2 +
        !          1182:                                (int)(ahead) * 9)
        !          1183:                        {
        !          1184:                                c->lazy++;
        !          1185:                                assert_match(swd,c->m_len,c->m_off);
        !          1186:                                lit += ahead;
        !          1187:                                assert(ii + lit == c->bp);
        !          1188:                                goto lazy_match_done;
        !          1189:                        }
        !          1190:                }
        !          1191:                
        !          1192:                assert(ii + lit + ahead == c->bp);
        !          1193:                
        !          1194:                /* 1 - code run */
        !          1195:                code_run(c,ii,lit);
        !          1196:                lit = 0;
        !          1197:                
        !          1198:                /* 2 - code match */
        !          1199:                code_match(c,m_len,m_off);
        !          1200:                swd->max_chain = SC_MAX_CHAIN;
        !          1201:                r = find_match(c,swd,m_len,1+ahead);
        !          1202:                assert(r == 0);
        !          1203:                
        !          1204:        lazy_match_done: ;
        !          1205:        }
        !          1206:        
        !          1207:        /* store final run */
        !          1208:        code_run(c,ii,lit);
        !          1209:        
        !          1210:        /* EOF */
        !          1211:        bbPutBit(c, 0);
        !          1212:        code_prefix_ss11(c, 0x1000000U);
        !          1213:        bbPutByte(c, 0xff);
        !          1214: 
        !          1215:        bbFlushBits(c, 0);
        !          1216:        
        !          1217:        assert(c->textsize == in_len);
        !          1218:        c->codesize = c->bb_op - out;
        !          1219:        *out_len = c->bb_op - out;
        !          1220:        
        !          1221: #if 0
        !          1222:        printf("%7ld %7ld -> %7ld   %7ld %7ld   %ld  (max: %d %d %d)\n",
        !          1223:                (long) c->textsize, (long) in_len, (long) c->codesize,
        !          1224:                c->match_bytes, c->lit_bytes,  c->lazy,
        !          1225:                c->result[1], c->result[3], c->result[5]);
        !          1226: #endif
        !          1227:        assert(c->lit_bytes + c->match_bytes == in_len);
        !          1228:        
        !          1229:        swd_exit(swd);
        !          1230:        free(swd);
        !          1231: 
        !          1232:        return UCL_E_OK;
        !          1233: }
        !          1234: 
        !          1235: 
        !          1236: void Encode(void)  /* compression */
        !          1237: {
        !          1238:        uint8_t *in, *out;
        !          1239:        unsigned long in_len, out_len;
        !          1240:        uint32_t tw;
        !          1241:        int r;
        !          1242:        fseek(infile, 0, SEEK_END);
        !          1243:        in_len = ftell(infile);
        !          1244: #ifdef VERBOSE
        !          1245:        if ((signed long)in_len < 0)
        !          1246:                Fprintf((stderr, "Errno: %d", errno));
        !          1247: #endif
        !          1248: #if UCLPACK_COMPAT
        !          1249:        {
        !          1250:                uint8_t byte;
        !          1251:                if (fwrite(magic, sizeof(magic), 1, outfile) != 1)
        !          1252:                        Error("Can't write.");
        !          1253:                tw = htonl(0); /* flags */
        !          1254:                if (fwrite(&tw, sizeof(tw), 1, outfile) != 1)
        !          1255:                        Error("Can't write.");
        !          1256:                byte = 0x2b;            /* method */
        !          1257:                if (fwrite(&byte, sizeof(byte), 1, outfile) != 1)
        !          1258:                        Error("Can't write.");
        !          1259:                byte = 10;              /* level */
        !          1260:                if (fwrite(&byte, sizeof(byte), 1, outfile) != 1)
        !          1261:                        Error("Can't write.");
        !          1262:                tw = htonl(256*1024);           /* block_size */
        !          1263:                if (fwrite(&tw, sizeof(tw), 1, outfile) != 1)
        !          1264:                        Error("Can't write.");
        !          1265:                tw = htonl(in_len);
        !          1266:                if (fwrite(&tw, sizeof(tw), 1, outfile) != 1)
        !          1267:                        Error("Can't write.");  /* output size of text */
        !          1268:        }
        !          1269: #else
        !          1270:        tw = host_to_i86ul(in_len);
        !          1271:        if (fwrite(&tw, sizeof(tw), 1, outfile) != 1)
        !          1272:                Error("Can't write.");  /* output size of text */
        !          1273: #endif 
        !          1274:        if (in_len == 0)
        !          1275:                return;
        !          1276:        rewind(infile);
        !          1277: 
        !          1278:        in = malloc(in_len);
        !          1279:        out_len = in_len + (in_len/8) + 256;
        !          1280:        out = malloc(out_len);
        !          1281:        if (!in || !out) {
        !          1282:                Error("Can't malloc");
        !          1283:        }
        !          1284:        if (fread(in, in_len, 1, infile) != 1) {
        !          1285:                Error("Can't read");
        !          1286:        }
        !          1287:        r = ucl_nrv2b_99_compress(in, in_len, out, &out_len, 0 );
        !          1288:        if (r != UCL_E_OK)
        !          1289:                Error("Compression failure\n");
        !          1290: #if UCLPACK_COMPAT
        !          1291:        tw = htonl(out_len);
        !          1292:        if (fwrite(&tw, sizeof(tw), 1, outfile) != 1)
        !          1293:                Error("Can't write.");  /* file size of text */
        !          1294: 
        !          1295: #endif
        !          1296:        if (fwrite(out, out_len, 1, outfile) != 1) {
        !          1297:                Error("Write error\n");
        !          1298:        }
        !          1299: #if UCLPACK_COMPAT
        !          1300:        tw = htonl(0); /* EOF marker */
        !          1301:        if (fwrite(&tw, sizeof(tw), 1, outfile) != 1)
        !          1302:                Error("Can't write.");
        !          1303: 
        !          1304: #endif
        !          1305: 
        !          1306: #ifdef LONG_REPORT
        !          1307:        Fprintf((stdout, "input size    %ld bytes\n", in_len));
        !          1308:        Fprintf((stdout, "output size   %ld bytes\n", out_len));
        !          1309:        Fprintf((stdout, "input/output  %.3f\n", (double)in_len / out_len));
        !          1310: #else
        !          1311:        Fprintf((stdout, "input/output = %ld/%ld = %.3f\n", in_len, out_len,
        !          1312:                (double)in_len / out_len));
        !          1313: #endif
        !          1314:        
        !          1315: }
        !          1316: 
        !          1317: #endif
        !          1318: 
        !          1319: #ifdef DECODE
        !          1320: 
        !          1321: #define GETBIT_8(bb, src, ilen) \
        !          1322:     (((bb = bb & 0x7f ? bb*2 : ((unsigned)src[ilen++]*2+1)) >> 8) & 1)
        !          1323: 
        !          1324: #define GETBIT_LE16(bb, src, ilen) \
        !          1325:     (bb*=2,bb&0xffff ? (bb>>16)&1 : (ilen+=2,((bb=(src[ilen-2]+src[ilen-1]*256u)*2+1)>>16)&1))
        !          1326: 
        !          1327: #define GETBIT_LE32(bb, src, ilen) \
        !          1328:     (bc > 0 ? ((bb>>--bc)&1) : (bc=31,\
        !          1329:     bb=*(const uint32_t *)((src)+ilen),ilen+=4,(bb>>31)&1))
        !          1330: 
        !          1331: #define GETBIT_LE64(bb, src, ilen) \
        !          1332:     (bc > 0 ? ((bb>>--bc)&1) : (bc=63, \
        !          1333:     bb=*(const uint64_t *)((src)+ilen),ilen+=8,(bb>>63)&1))
        !          1334: 
        !          1335: #if ENDIAN == 0 && BITSIZE == 8
        !          1336: #define GETBIT(bb, src, ilen) GETBIT_8(bb, src, ilen)
        !          1337: #endif
        !          1338: #if ENDIAN == 0 && BITSIZE == 16
        !          1339: #define GETBIT(bb, src, ilen) GETBIT_LE16(bb, src, ilen)
        !          1340: #endif
        !          1341: #if ENDIAN == 0 && BITSIZE == 32
        !          1342: #define GETBIT(bb, src, ilen) GETBIT_LE32(bb, src, ilen)
        !          1343: #endif
        !          1344: #if ENDIAN == 0 && BITSIZE == 64
        !          1345: #define GETBIT(bb, src, ilen) GETBIT_LE64(bb, src, ilen)
        !          1346: #endif
        !          1347: #ifndef GETBIT
        !          1348: #error "Bad Combination of ENDIAN and BITSIZE values specified"
        !          1349: #endif
        !          1350: 
        !          1351: #undef SAFE
        !          1352: 
        !          1353: #ifdef SAFE
        !          1354: #define FAIL(x,r)   if (x) { Error(r); }
        !          1355: #else
        !          1356: #define FAIL(x,r)
        !          1357: #endif
        !          1358: 
        !          1359: void Decode(void)  /* recover */
        !          1360: {
        !          1361:        uint32_t tw;
        !          1362:        uint8_t *src, *dst;
        !          1363:        unsigned long max_src_len, src_len, dst_len;
        !          1364:        unsigned long ilen = 0, olen = 0, last_m_off =  1;
        !          1365: #if BITSIZE <= 32
        !          1366:        uint32_t bb = 0;
        !          1367: #elif BITSIZE == 64
        !          1368:        uint64_t bb = 0;
        !          1369: #endif
        !          1370:        unsigned bc = 0;
        !          1371: #if UCLPACK_COMPAT
        !          1372:        if (fseek(infile, sizeof(magic) + sizeof(tw) + 1 + 1 + sizeof(tw),
        !          1373:                SEEK_SET) != 0)
        !          1374: 
        !          1375:                Error("Seek Error");
        !          1376:        if (fread(&tw, sizeof(tw), 1, infile) < 1)
        !          1377:                Error("Can't read"); /* read size of text */
        !          1378:        dst_len = ntohl(tw);
        !          1379:        if (fread(&tw, sizeof(tw), 1, infile) < 1)
        !          1380:                Error("Can't read"); /* read size of file */
        !          1381:        max_src_len = ntohl(tw);
        !          1382: #else
        !          1383:        if (fread(&tw, sizeof(tw), 1, infile) < 1)
        !          1384:                Error("Can't read"); /* read size of text */
        !          1385:        dst_len = i86ul_to_host(tw);
        !          1386:        max_src_len = dst_len + (dst_len/8) + 256;
        !          1387: #endif
        !          1388:        if (dst_len == 0)
        !          1389:                return;
        !          1390:        dst = malloc(dst_len);
        !          1391:        if (!dst)
        !          1392:                Error("Can't malloc");
        !          1393:        src = malloc(max_src_len);
        !          1394:        if (!src)
        !          1395:                Error("Can't malloc");
        !          1396:        src_len = fread(src, 1, max_src_len, infile);
        !          1397:        if (src_len <= 0) 
        !          1398:                Error("Can't read");
        !          1399: 
        !          1400:        for(;;) {
        !          1401:                unsigned int m_off, m_len;
        !          1402:                while(GETBIT(bb, src, ilen)) {
        !          1403:                        FAIL(ilen >= src_len, "input overrun");
        !          1404:                        FAIL(olen >= dst_len, "output  overrun");
        !          1405:                        dst[olen++] = src[ilen++];
        !          1406:                }
        !          1407:                m_off = 1;
        !          1408:                do {
        !          1409:                        m_off = m_off*2 + GETBIT(bb, src, ilen);
        !          1410:                        FAIL(ilen >= src_len, "input overrun");
        !          1411:                        FAIL(m_off > 0xffffffU +3, "lookbehind overrun");
        !          1412:                } while (!GETBIT(bb, src, ilen));
        !          1413:                if (m_off == 2)
        !          1414:                {
        !          1415:                        m_off = last_m_off;
        !          1416:                }
        !          1417:                else
        !          1418:                {
        !          1419:                        FAIL(ilen >= src_len, "input overrun");
        !          1420:                        m_off = (m_off - 3)*256 + src[ilen++];
        !          1421:                        if (m_off == 0xffffffffU)
        !          1422:                                break;
        !          1423:                        last_m_off = ++m_off;
        !          1424:                }
        !          1425:                m_len = GETBIT(bb, src, ilen);
        !          1426:                m_len = m_len*2 + GETBIT(bb, src, ilen);
        !          1427:                if (m_len == 0) 
        !          1428:                {
        !          1429:                        m_len++;
        !          1430:                        do {
        !          1431:                                m_len = m_len*2 + GETBIT(bb, src, ilen);
        !          1432:                                FAIL(ilen >= src_len, "input overrun");
        !          1433:                                FAIL(m_len >= dst_len, "output overrun");
        !          1434:                        } while(!GETBIT(bb, src, ilen));
        !          1435:                        m_len += 2;
        !          1436:                }
        !          1437:                m_len += (m_off > 0xd00);
        !          1438:                FAIL(olen + m_len > dst_len, "output overrun");
        !          1439:                FAIL(m_off > olen, "lookbeind overrun");
        !          1440:                {
        !          1441:                        const uint8_t *m_pos;
        !          1442:                        m_pos = dst + olen - m_off;
        !          1443:                        dst[olen++] = *m_pos++;
        !          1444:                        do {
        !          1445:                                dst[olen++] = *m_pos++;
        !          1446:                        } while(--m_len > 0);
        !          1447:                }
        !          1448:        }
        !          1449:        FAIL(ilen < src_len, "input not consumed");
        !          1450:        FAIL(ilen > src_len, "input overrun");
        !          1451:        assert(ilen == src_len);
        !          1452:        Fprintf((stderr, "%12ld\n", olen));
        !          1453:        if (dst_len != olen) {
        !          1454:                fprintf(stderr, "length != expected length\n");
        !          1455:        }
        !          1456:        if (fwrite(dst, olen, 1, outfile) != 1)
        !          1457:                Error("Write error\n");
        !          1458:        free(src);
        !          1459:        free(dst);
        !          1460: }
        !          1461: #endif
        !          1462: 
        !          1463: #ifdef MAIN
        !          1464: int main(int argc, char *argv[])
        !          1465: {
        !          1466:        char  *s;
        !          1467:        FILE  *f;
        !          1468:        int    c;
        !          1469:        
        !          1470:        if (argc == 2) {
        !          1471:                outfile = stdout;
        !          1472:                if ((f = tmpfile()) == NULL) {
        !          1473:                        perror("tmpfile");
        !          1474:                        return EXIT_FAILURE;
        !          1475:                }
        !          1476:                while ((c = getchar()) != EOF)
        !          1477:                        fputc(c, f);
        !          1478:                rewind(infile = f);
        !          1479:        }
        !          1480:        else if (argc != 4) {
        !          1481:                Fprintf((stderr, "'nrv2b e file1 file2' encodes file1 into file2.\n"
        !          1482:                        "'nrv2b d file2 file1' decodes file2 into file1.\n"));
        !          1483:                return EXIT_FAILURE;
        !          1484:        }
        !          1485:        if (argc == 4) {
        !          1486:                if ((s = argv[1], s[1] || strpbrk(s, "DEde") == NULL)
        !          1487:                        || (s = argv[2], (infile  = fopen(s, "rb")) == NULL)
        !          1488:                        || (s = argv[3], (outfile = fopen(s, "wb")) == NULL)) {
        !          1489:                        Fprintf((stderr, "??? %s\n", s));
        !          1490:                        return EXIT_FAILURE;
        !          1491:                }
        !          1492:        }
        !          1493:        if (toupper(*argv[1]) == 'E')
        !          1494:                Encode();
        !          1495:        else
        !          1496:                Decode();
        !          1497:        fclose(infile);
        !          1498:        fclose(outfile);
        !          1499:        return EXIT_SUCCESS;
        !          1500: }
        !          1501: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.