Logo Search packages:      
Sourcecode: sam2p version File versions

void RunLengthEncode::vi_write ( char const *  buf,
slen_t  len 
) [virtual]

vi_write() must be called with positive slen_t for normal writing, and vi_write(?,0); must be called to signal EOF. After that, it is prohibited to call vi_write() either way.

Implements Encoder.

Definition at line 601 of file encoder.cpp.

References saved, and GenBuffer::Writable::vi_write().

                                                         {
  unsigned j, umax;
  char b;
  if (len==0) { /* handle EOF */
    if (saved_rep!=0) {
      assert(saved_rep>=2);
      (saved+1)[-1]=257-saved_rep;
      (saved+1)[1]=(char)128; /* EOD */
      out.vi_write((saved+1)-1,3);
      // fprintf(stderr,"rd=%u\n",saved_rep);
    } else if (saved_c!=0) {
      (saved+1)[-1]=saved_c-1;
      (saved+1)[saved_c]=(char)128; /* EOD */
      out.vi_write((saved+1)-1, saved_c+2);
      // fprintf(stderr,"re=%u\n",saved_c);
    } else {
      (saved+1)[-1]=(char)128;
      out.vi_write((saved+1)-1, 1);
    }
    out.vi_write(0,0); /* propagate EOF */
    record_left=0; /* signal that no further data will be accepted */
    return;
  }
 again:
  assert(record_left>=1);
  assert(len>=1);
  /* Imp: locally cache vars saved* */
  j=0;
  if (saved_c==0) {
    saved_rep=0; saved_c=1; b=(saved+1)[0]=*buf++; len--;
    if (0==--record_left) goto put_norep;
    if (0==len) return;
    goto yes;
  }
  if (saved_c==1 && saved_rep==0) { yes:
    if (*buf++==(saved+1)[0]) {
      saved_rep=2; len--;
      if (0==--record_left) goto put_rep;
    } else {
      (saved+1)[1]=buf[-1]; saved_c=2; len--;
      if (0==--record_left) goto put_norep;
    }
    if (0==len) return;
  }
  assert(record_left>=1);
  assert(len>=1);
  assert((saved_rep==0 && saved_c>=2) || (saved_rep>=2 && saved_c==1));
  if (saved_rep!=0) { /* Try to increase the repeating sequence */
    assert(saved_rep>=2);
    assert(saved_c==1);
    assert(len>=1);
    b=(saved+1)[0];
    umax=len>128?128:len; if (umax>record_left) umax=record_left;
    /* fprintf(stderr,"um1=%u\n", umax); */
    if (umax>128-saved_rep) umax=128-saved_rep;
    assert(umax>=1);
    j=0; while (j!=umax && buf[j]==b) { j++; saved_rep++; }
    if (j!=len || saved_rep==128) {
     put_rep: /* Found a maximal repeat width */
      (saved+1)[-1]=257-saved_rep;
      out.vi_write((saved+1)-1,2);
      /* fprintf(stderr,"ra=%u\n",saved_rep); */
      if ((record_left-=j)==0) record_left=recordsize;
      buf+=j;
      saved_c=saved_rep=0;
      if (0==(len-=j)) return;
      goto again;
    } /* Current repeat width can be further increased */
  } else { /* Try to increase the non-repeating sequence */
    assert(saved_c>=2);
    if (buf[0]==(saved+1)[saved_c-1]) { /* this decision might be sub-optimal */
      saved_c--;
      /* Now: saved_c: non-repeat length, >=1 */
      (saved+1)[-1]=saved_c-1;
      out.vi_write((saved+1)-1, saved_c+1);
      /* fprintf(stderr,"rb=%u\n",saved_c); */
      // record_left++; /* because of saved_c--; but we would increase it later anyway */
      // buf+=saved_c;
      (saved+1)[0]=buf[0]; /* first matching char-pair data */
      saved_c=1; saved_rep=2; /* make the new block a >=2 repeat */
      record_left--; buf++;
      if (0==--len) return;
      goto again;
    }
    (saved+1)[saved_c++]=buf[0];
    //record_left--;
    //buf++;
    //len--;
    //if (saved_c==128) goto put_norep;
    //if (0==len) return;
    umax=len>128?128:len; if (umax>record_left) umax=record_left;
    if (umax>128-saved_c) umax=128-saved_c;
    /* fprintf(stderr,"um2=%u\n", umax); */
    assert(umax>=1);
    j=1; while (j!=umax && buf[j]!=buf[j-1]) (saved+1)[saved_c++]=buf[j++];
    if (j!=len || saved_c==128) {
     put_norep: /* Found a maximal non-repeat width */
      (saved+1)[-1]=saved_c-1;
      out.vi_write((saved+1)-1, saved_c+1);
      /* fprintf(stderr,"rc=%u\n",saved_c); */
      if ((record_left-=j)==0) record_left=recordsize;
      buf+=j;
      saved_c=saved_rep=0;
      if (0==(len-=j)) return;
      goto again;
    } /* Current non-repeat width can be further increased */
  }
  assert(j==len);
  record_left-=j;
  assert(saved_rep<128);
  assert(saved_c<128);
}


Generated by  Doxygen 1.6.0   Back to index