In my current project I'm writing a C function to write a BMP-File. Internally, the function is split up into three parts: write header, write info header, write data.
In some of these functions I do need to allocate heap space with malloc
and actually write to disk with fwrite
. These functions are doomed to fail from time-to-time (malloc
can't find a big enough memory chunk to allocate and fwrite
could fail as well).
Now I'm unsure of how to handle failure situations reasonably. My current approach is to have a returned integer value indicate success.
uint8_t BMP32_write(FILE *output, BMP32_FILE *bmp32_file) {
uint8_t res = 0;
res |= BMP32_write_header(output, bmp32_file->bmph);
res |= BMP32_write_info_header(output, bmp32_file->bmpih);
res |= BMP32_write_rgbData(output, bmp32_file->bmpih->biWidth, bmp32_file->bmpih->biHeight, bmp32_file->rgbData);
return res;
}
static uint8_t BMP32_write_header(FILE *output, BMP32_HEADER *h) {
uint8_t res = 0;
res |= !fwrite(&h->bfType , sizeof(h->bfType) , 1, output);
res |= !fwrite(&h->bfSize , sizeof(h->bfSize) , 1, output);
res |= !fwrite(&h->bfReserved, sizeof(h->bfReserved), 1, output);
res |= !fwrite(&h->bfOffBits , sizeof(h->bfOffBits) , 1, output);
return res;
}
static uint8_t BMP32_write_info_header(FILE *output, BMP32_INFO_HEADER *ih) {
uint8_t res = 0;
res |= !fwrite(&ih->biSize , sizeof(ih->biSize) , 1, output);
res |= !fwrite(&ih->biWidth , sizeof(ih->biWidth) , 1, output);
res |= !fwrite(&ih->biHeight , sizeof(ih->biHeight) , 1, output);
res |= !fwrite(&ih->biPlanes , sizeof(ih->biPlanes) , 1, output);
res |= !fwrite(&ih->biBitCount , sizeof(ih->biBitCount) , 1, output);
res |= !fwrite(&ih->biCompression , sizeof(ih->biCompression) , 1, output);
res |= !fwrite(&ih->biImageSize , sizeof(ih->biImageSize) , 1, output);
res |= !fwrite(&ih->biXPelsPerMeter, sizeof(ih->biXPelsPerMeter), 1, output);
res |= !fwrite(&ih->biYPelsPerMeter, sizeof(ih->biYPelsPerMeter), 1, output);
res |= !fwrite(&ih->biClrUsed , sizeof(ih->biClrUsed) , 1, output);
res |= !fwrite(&ih->biClrImportant , sizeof(ih->biClrImportant) , 1, output);
return res;
}
static uint8_t BMP32_write_rgbData(FILE *output, uint32_t width, uint32_t height, RGB_POINT *rgbData) {
uint32_t i, currRow, currColumn, bytesPerRow;
uint8_t *rawDataRow, res;
bytesPerRow = widthToBytesPerRow(width);
rawDataRow = calloc(bytesPerRow, sizeof(uint8_t));
if (rawDataRow != NULL) {
for (currRow = height; currRow > 0; currRow--) {
for (currColumn = 0, i = 0; currColumn < width; currColumn++) {
rawDataRow[i++] = rgbData[width*(currRow-1) + currColumn].blue;
rawDataRow[i++] = rgbData[width*(currRow-1) + currColumn].green;
rawDataRow[i++] = rgbData[width*(currRow-1) + currColumn].red;
}
res |= !fwrite(rawDataRow, bytesPerRow, 1, output);
}
free(rawDataRow);
} else {
res = 1;
}
return res;
}
What is a common way to handle situations like this? What would you consider doing?