Re: [AD] compressing empty files

[ Thread Index | Date Index | More lists.liballeg.org/allegro-developers Archives ]


Please check (and confirm) this:

1. First this, which is straightforward (and was discovered after fixing the
   EOF problem):

   AL_INLINE(int, pack_getc, (PACKFILE *f),
   {
      f->buf_size--;
      if (f->buf_size > 0)
         return *(f->buf_pos++);
      else
         return _sort_out_getc(f);
   })

   We have one byte left in the buffer, none in the disk. So f->buf_size is 1.
   The f->buf_size becomes 0, and fails the check. We call the _sort_out_getc
   (which fills the pack buffer). But we lost the byte we had. So, I suggest
   either postdecrementing in the check or checking for greater or equal to 0.

2. Now, most file.c rely on pack_getc() returning EOF. However, that is not
   true (maybe a bug?). Check the pack_getc() again. The _sort_out_getc() is
   called (as well as in a few more places):

   int _sort_out_getc(PACKFILE *f)
   {
      if (f->buf_size == 0) {
         if (f->todo <= 0)
            f->flags |= PACKFILE_FLAG_EOF;
         return *(f->buf_pos++);
      }
      return refill_buffer(f);
   }

   If the packfile is completely empty (no bytes left in the buffer, no bytes
   left in the disk), it just sets the PACKFILE_FLAG_EOF flag on, but returns
   *(f->buf_pos++). What is inside there? As far as I checked, the buffer has
   not been filled with EOF. Check this at pack_fread():

      i = _sort_out_getc(f);
      if (i == EOF)

3. Finally, refill_buffer() ends this way:

      f->todo -= f->buf_size;
      f->buf_pos = f->buf;
      f->buf_size--;
      if (f->buf_size <= 0)
         if (f->todo <= 0)
            f->flags |= PACKFILE_FLAG_EOF;

      return *(f->buf_pos++);

   So, if both the buffer and the disk are empty, turns the PACKFILE_FLAG_EOF
   on, but still returns the following position, which might or mightn't be EOF.

This is the patch I suggest (merging all the patchs around):

--- cvs/allegro/src/file.c      Wed Mar  6 09:50:12 2002
+++ mod/allegro/src/file.c      Fri Jun 28 23:13:44 2002
@@ -2083,7 +2083,7 @@
    if (f->buf_size == 0) {
       if (f->todo <= 0)
 	 f->flags |= PACKFILE_FLAG_EOF;
-      return *(f->buf_pos++);
+         return (EOF);
    }
    return refill_buffer(f);
 }
@@ -2153,8 +2153,10 @@
    f->buf_pos = f->buf;
    f->buf_size--;
    if (f->buf_size <= 0)
-      if (f->todo <= 0)
+      if (f->todo <= 0) {
 	 f->flags |= PACKFILE_FLAG_EOF;
+         return (EOF);
+      }
 
    return *(f->buf_pos++);
 
--- cvs/allegro/include/allegro/inline/file.inl	Tue Nov  6 13:06:46 2001
+++ allegro/include/allegro/inline/file.inl	Fri Jun 28 22:40:38 2002
@@ -26,7 +26,7 @@
 AL_INLINE(int, pack_getc, (PACKFILE *f),
 {
    f->buf_size--;
-   if (f->buf_size > 0)
+   if (f->buf_size >= 0)
       return *(f->buf_pos++);
    else
       return _sort_out_getc(f);


I tested it under DJGPP, and worked (pack input packed; pack u packed output ->
output is equal to input, being it 0, 1 or 2 bytes, more test encouraged ;).

There seems to be a small recursion (pack_getc -> _sort_out_getc ->
refill_buffer -> pack_getc -> _sort_out_getc -> refill_buffer, which breaks the
recursion returning EOF). I think this behaviour is also done without this
patch. Maybe someone should look at that.

I am going out for a week, so I cannot test this under anything else, nor check
if there are more of this "turn the flag but not returning EOF" case. I am
taking the relevant files in the Palm, though (hmm... PalmAlleg? ;)


--
Roberto Alfonso (rpgrca@xxxxxxxxxx <> rpgrca@xxxxxxxxxx)
Rhynox, the Noble Rockfriend, Wild Battlerager of the Neidar Clan and
Proficient Blacksmith, rising hero, male dwarf (Genesis is the key)
ICQ: 44361979



Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/