01e6765e3dd584c582211061427c9218fc683ae4
   1/*
   2 *  LibXDiff by Davide Libenzi ( File Differential Library )
   3 *  Copyright (C) 2003  Davide Libenzi
   4 *
   5 *  This library is free software; you can redistribute it and/or
   6 *  modify it under the terms of the GNU Lesser General Public
   7 *  License as published by the Free Software Foundation; either
   8 *  version 2.1 of the License, or (at your option) any later version.
   9 *
  10 *  This library is distributed in the hope that it will be useful,
  11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13 *  Lesser General Public License for more details.
  14 *
  15 *  You should have received a copy of the GNU Lesser General Public
  16 *  License along with this library; if not, write to the Free Software
  17 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18 *
  19 *  Davide Libenzi <davidel@xmailserver.org>
  20 *
  21 */
  22
  23#include "xinclude.h"
  24
  25
  26
  27#define XDL_GUESS_NLINES 256
  28
  29
  30
  31
  32int xdl_emit_diffrec(char const *rec, long size, char const *pre, long psize,
  33                     xdemitcb_t *ecb) {
  34        mmbuffer_t mb[2];
  35
  36        mb[0].ptr = (char *) pre;
  37        mb[0].size = psize;
  38        mb[1].ptr = (char *) rec;
  39        mb[1].size = size;
  40
  41        if (ecb->outf(ecb->priv, mb, 2) < 0) {
  42
  43                return -1;
  44        }
  45
  46        return 0;
  47}
  48
  49void *xdl_mmfile_first(mmfile_t *mmf, long *size)
  50{
  51        *size = mmf->size;
  52        return mmf->ptr;
  53}
  54
  55
  56void *xdl_mmfile_next(mmfile_t *mmf, long *size)
  57{
  58        return NULL;
  59}
  60
  61
  62long xdl_mmfile_size(mmfile_t *mmf)
  63{
  64        return mmf->size;
  65}
  66
  67
  68int xdl_cha_init(chastore_t *cha, long isize, long icount) {
  69
  70        cha->head = cha->tail = NULL;
  71        cha->isize = isize;
  72        cha->nsize = icount * isize;
  73        cha->ancur = cha->sncur = NULL;
  74        cha->scurr = 0;
  75
  76        return 0;
  77}
  78
  79
  80void xdl_cha_free(chastore_t *cha) {
  81        chanode_t *cur, *tmp;
  82
  83        for (cur = cha->head; (tmp = cur) != NULL;) {
  84                cur = cur->next;
  85                xdl_free(tmp);
  86        }
  87}
  88
  89
  90void *xdl_cha_alloc(chastore_t *cha) {
  91        chanode_t *ancur;
  92        void *data;
  93
  94        if (!(ancur = cha->ancur) || ancur->icurr == cha->nsize) {
  95                if (!(ancur = (chanode_t *) xdl_malloc(sizeof(chanode_t) + cha->nsize))) {
  96
  97                        return NULL;
  98                }
  99                ancur->icurr = 0;
 100                ancur->next = NULL;
 101                if (cha->tail)
 102                        cha->tail->next = ancur;
 103                if (!cha->head)
 104                        cha->head = ancur;
 105                cha->tail = ancur;
 106                cha->ancur = ancur;
 107        }
 108
 109        data = (char *) ancur + sizeof(chanode_t) + ancur->icurr;
 110        ancur->icurr += cha->isize;
 111
 112        return data;
 113}
 114
 115
 116void *xdl_cha_first(chastore_t *cha) {
 117        chanode_t *sncur;
 118
 119        if (!(cha->sncur = sncur = cha->head))
 120                return NULL;
 121
 122        cha->scurr = 0;
 123
 124        return (char *) sncur + sizeof(chanode_t) + cha->scurr;
 125}
 126
 127
 128void *xdl_cha_next(chastore_t *cha) {
 129        chanode_t *sncur;
 130
 131        if (!(sncur = cha->sncur))
 132                return NULL;
 133        cha->scurr += cha->isize;
 134        if (cha->scurr == sncur->icurr) {
 135                if (!(sncur = cha->sncur = sncur->next))
 136                        return NULL;
 137                cha->scurr = 0;
 138        }
 139
 140        return (char *) sncur + sizeof(chanode_t) + cha->scurr;
 141}
 142
 143
 144long xdl_guess_lines(mmfile_t *mf) {
 145        long nl = 0, size, tsize = 0;
 146        char const *data, *cur, *top;
 147
 148        if ((cur = data = xdl_mmfile_first(mf, &size)) != NULL) {
 149                for (top = data + size; nl < XDL_GUESS_NLINES;) {
 150                        if (cur >= top) {
 151                                tsize += (long) (cur - data);
 152                                if (!(cur = data = xdl_mmfile_next(mf, &size)))
 153                                        break;
 154                                top = data + size;
 155                        }
 156                        nl++;
 157                        if (!(cur = memchr(cur, '\n', top - cur)))
 158                                cur = top;
 159                        else
 160                                cur++;
 161                }
 162                tsize += (long) (cur - data);
 163        }
 164
 165        if (nl && tsize)
 166                nl = xdl_mmfile_size(mf) / (tsize / nl);
 167
 168        return nl + 1;
 169}
 170
 171
 172unsigned long xdl_hash_record(char const **data, char const *top) {
 173        unsigned long ha = 5381;
 174        char const *ptr = *data;
 175
 176        for (; ptr < top && *ptr != '\n'; ptr++) {
 177                ha += (ha << 5);
 178                ha ^= (unsigned long) *ptr;
 179        }
 180        *data = ptr < top ? ptr + 1: ptr;
 181
 182        return ha;
 183}
 184
 185
 186unsigned int xdl_hashbits(unsigned int size) {
 187        unsigned int val = 1, bits = 0;
 188
 189        for (; val < size && bits < CHAR_BIT * sizeof(unsigned int); val <<= 1, bits++);
 190        return bits ? bits: 1;
 191}
 192
 193
 194int xdl_num_out(char *out, long val) {
 195        char *ptr, *str = out;
 196        char buf[32];
 197
 198        ptr = buf + sizeof(buf) - 1;
 199        *ptr = '\0';
 200        if (val < 0) {
 201                *--ptr = '-';
 202                val = -val;
 203        }
 204        for (; val && ptr > buf; val /= 10)
 205                *--ptr = "0123456789"[val % 10];
 206        if (*ptr)
 207                for (; *ptr; ptr++, str++)
 208                        *str = *ptr;
 209        else
 210                *str++ = '0';
 211        *str = '\0';
 212
 213        return str - out;
 214}
 215
 216
 217long xdl_atol(char const *str, char const **next) {
 218        long val, base;
 219        char const *top;
 220
 221        for (top = str; XDL_ISDIGIT(*top); top++);
 222        if (next)
 223                *next = top;
 224        for (val = 0, base = 1, top--; top >= str; top--, base *= 10)
 225                val += base * (long)(*top - '0');
 226        return val;
 227}
 228
 229
 230int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2, xdemitcb_t *ecb) {
 231        int nb = 0;
 232        mmbuffer_t mb;
 233        char buf[128];
 234
 235        memcpy(buf, "@@ -", 4);
 236        nb += 4;
 237
 238        nb += xdl_num_out(buf + nb, c1 ? s1: 0);
 239
 240        memcpy(buf + nb, ",", 1);
 241        nb += 1;
 242
 243        nb += xdl_num_out(buf + nb, c1);
 244
 245        memcpy(buf + nb, " +", 2);
 246        nb += 2;
 247
 248        nb += xdl_num_out(buf + nb, c2 ? s2: 0);
 249
 250        memcpy(buf + nb, ",", 1);
 251        nb += 1;
 252
 253        nb += xdl_num_out(buf + nb, c2);
 254
 255        memcpy(buf + nb, " @@\n", 4);
 256        nb += 4;
 257
 258        mb.ptr = buf;
 259        mb.size = nb;
 260        if (ecb->outf(ecb->priv, &mb, 1) < 0)
 261                return -1;
 262
 263        return 0;
 264}
 265