This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Strange Behavior


Greetings,

While writing a generic C++ algoririthm for base64 encoding, I came
across
some very strange behavior.  If you take the following program
(admittedly
verbose for debugging purposes) and test it on some data, say the logo
image
from www.google.com, you may notice (depending on your platform) that
the
byte at offset 0230 (octal) is either read in with an incorrect value or
is
skipped entirely.

	template < class InputItor, class OutputItor >
	OutputItor
	encode (InputItor first, InputItor last,
	        OutputItor out) {
	
	  static const char s [] =
	      "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
	      "abcdefghijklmnopqrstuvwxyz"
	      "0123456789+/";
	
	  while (first != last) {
	    unsigned char uc0 = *first++;
	    int i0 = (uc0>>2) & 0x3f;
	    char c0 = s [i0];
	    *out++ = c0;
	
	    unsigned char uc1 = (first == last? 0: *first++);
	    int i1 = ((uc0<<4) + (uc1>>4)) & 0x3f;
	    char c1 = s [i1];
	    *out++ = c1;
	
	    bool eof = (first == last);
	    unsigned char uc2 = (eof? 0: *first++);
	    int i2 = ((uc1<<2) + (uc2>>6)) & 0x3f;
	    char c2 = (eof? '=': s [i2]);
	    *out++ = c2;
	
	    int i3 = uc2 & 0x3f;
	    char c3 = (first == last? '=': s [i3]);
	    *out++ = c3;
	  }
	
	  return out;
	}
	
	#include <algorithm>
	#include <fstream>
	#include <iterator>
	#include <iostream>
	#include <string>
	using namespace std;
	
	extern int
	main () {
	  ifstream in ("logo.gif", ios_base::binary);
	
	  istream_iterator< char > first (in);
	  istream_iterator< char > last;
	  string s;
	  encode (first, last, back_inserter (s));
	
	  cout << s;
	
	  return 0;
	}

You can boil the while loop down to it's basic read operations and still
see the same results.

	  while (first != last) {
	    unsigned char uc0 = *first++;
	    unsigned char uc1 = (first == last? 0: *first++);
	    unsigned char uc2 = (first == last? 0: *first++);
        }

Just for sake of sanity, I wrote a quick version of the algorithm in C.
Naturally, this program behaves as it should.

	#include <stdio.h>
	#include <stdlib.h>
	
	extern int
	main (int argc, char* argv []) {
	
	  FILE* in = fopen ("logo.gif", "rb");
	  if (in == NULL) {
	    perror (argv[0]);
	    exit (EXIT_FAILURE);
	  }
	
	  const char s [] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
	                    "abcdefghijklmnopqrstuvwxyz"
	                    "0123456789+/";
	
	  while (!feof (in)) {
	    unsigned char uc0 = fgetc (in);
	    int i0 = (uc0>>2) & 0x3f;
	    char c0 = s [i0];
	    putc (c0, stdout);
	
	    unsigned char uc1 = (feof (in)? 0: fgetc (in));
	    int i1 = ((uc0<<4) + (uc1>>4)) & 0x3f;
	    char c1 = s [i1];
	    putc (c1, stdout);
	
	    int eof = feof (in);
	    unsigned char uc2 = (eof? 0: fgetc (in));
	    int i2 = ((uc1<<2) + (uc2>>6)) & 0x3f;
	    char c2 = (eof? '=': s [i2]);
	    putc (c2, stdout);
	
	    int i3 = uc2 & 0x3f;
	    char c3 = (feof (in)? '=': s [i3]);
	    putc (c3, stdout);
	  }
	
	  fclose (in);
	
	  return 0;
	}

If anyone can shed some light on the strange behavior in the C++
program,
I would appreciate it very much.

Thanks,
Eric.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]