0

So far my program passes all but 2 of check50 server2:

:( Requesting cat.jpg returns 200, image/jpeg, and correct image

:( Requesting two files in a row (cat.html then cat.jpg) succeeds

I think they result from the same problem: loading jpg file.

I have gone through some question replies on this website and found out fgetc() can not successfully deal with binary file, such as jpg. So I changed to fread, still does not work.

As far as I know, by using char* buffer, some 0x00 from jpg file make false ends to the string. So I try to imitate how we "fread" jpg in pset 4. I think in pset 4 the program "typedef uint8_t BYTE", so that the 0x00 wouldn't be any problem.

However this time, the program has already set "typedef char BYTE;", so I can not just put " uint8_t* buffer" to store the address in content, which apparently takes only char.

Please, I'd be grateful for advice!

Here is my load function:

/**
 * Loads a file into memory dynamically allocated on heap.
 * Stores address thereof in *content and length thereof in *length.
 */
bool load(FILE* file, BYTE** content, size_t* length)
{
    if (file == NULL)
    {
        return false;
    }

    char* buffer = malloc(1);
    *length = 0;

    while (fread(&buffer[*length], 1, 1, file) == 1)
    {
        *length = *length + 1;
        buffer = realloc(buffer, *length + 1);
    }

    buffer = realloc(buffer, *length);
    *content = &buffer[0];

    return true;
}
0

1 Answer 1

2

This looks great! It was a long journey, it will be worth it.

Review the lookup function and make sure it adheres to this requirement from the spec:

image/jpeg (not image/jpg) for any file whose path ends in .jpg (or any capitalization thereof),

To clarify the fgetc issue:

Something like this for (c = fgetc(file); c != EOF; c = fgetc(file)) will work as long as c is declared as an integer. If it is declared as a char or a BYTE, the fgetc will detect a "false EOF".

From man fgetc:

fgetc() reads the next character from stream and returns it as an unsigned char cast to an int,

For an ascii text file each c will be in integer range 0 - 127. Not so with image files. The fgetc for loop is detecting a "false EOF". Some byte in the image files is being cast to the int -1. EOF is defined (in stdio.h) as -1. The loop ends prematurely. If you cast c as an int (instead of char or BYTE), it should work.

6
  • I made it! all check50 passed! I still have some questions though: (1) I wrote fgetc version and fread version, both works with both BYTE* buffer and char* buffer. However, I want to know which is the correct way to code? (2) Whether I put BYTE* buffer or char* buffer it's still an array of "char" type data. After fgetc() or fread() reads the first by of jpg file 0xff, which is 255 and about to to store it to buffer, how come the "8-bit number is not cast to a char and therefore causing problems?
    – user13479
    Commented Oct 9, 2016 at 10:41
  • Personally, I like fread(buffer,1,512,file) to read 512 bytes at a time. I cannot pass judgement on "the correct way to code". I know that all questions in this forum where poster used an fgetc into a char type (like the for loop in the answer above), there were problems with image data. I found that this article explained it well. The problem (with fgetc) is not how the buffer is declared, it is how one uses the result of fgetc. Commented Oct 9, 2016 at 11:14
  • I mean, even using fread, it gets datas like 0x00, which is a number in 8-bits. When storing it into char* buffer, is it not cast into char??? Also, I just noticed that in interpret(), it write char* content; while in transfer(), it writes BYTE* content. Why the difference?
    – user13479
    Commented Oct 9, 2016 at 12:09
  • One difference with fread and fgetc is that fread does no casting, but fgetc does. And it is specifically that casting that will provoke "false EOF". As long as you don't try to use that char* or BYTE* data as char, program will gladly store the 8bits that it reads. I cannot speak for the program author. I would posit that since interpret works on php files, and php files (and query arguments) are ascii text, it is sure to be char* data. transfer will operate on text or image files, so declaring content as a BYTE* indicates that distinction (even though they are the same "under the hood"). Commented Oct 9, 2016 at 15:39
  • I guess there is still so much to lean... May I ask why does the program typedef char BYTE at the beginning, if the program can still work with char* buffer or char* content? What is the point of typedef char BYTE ??
    – user13479
    Commented Oct 9, 2016 at 23:59

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .