Bayto Malin
Bayto Malin

Reputation: 23

How to create a similar function of fwrite

As you read in the title, I want to create a function like fwrite. But I can't seem to get a function similar to fwrite. I tried this:

int mini_fwrite(void *buffer, int size_element, int number_element, MYFILE *file) {
    if (file->ind_write == -1) {
        file->buffer_write = mini_calloc(IOBUFFER_SIZE, 1);
        file->ind_write = 0;
    }

    int i = 0;
    while (i < size_element * number_element) {
        ((char *)file->buffer_write)[file->ind_write] = ((char *)buffer)[i];
        file->ind_write++;
        i++;
        
        if (file->ind_write == IOBUFFER_SIZE) {
            if (write(file->fd, file->buffer_write, file->ind_write) == -1) {
                mini_perror("Error");
            }
            file->ind_write = 0;
        }
    }
    return i;
}

That's not what I want. I want writing, via a write, only be triggered when the buffer_write is full. Anyone have an idea ?

I started with a structure like this

typedef struct MYFILE {
    int fd;
    void *buffer_read;
    void *buffer_write;
    int ind_read;
    int ind_write;
} MYFILE;

and a function like fopen:

int IOBUFFER_SIZE = 2048;

MYFILE *mini_fopen(char *file, char mode)
{
    if (file == NULL)
        return NULL;

    MYFILE *fo;

    fo = (MYFILE *)mini_calloc(sizeof(MYFILE), 1);

    if (mode == 'r') fo->fd = open(file, O_RDONLY);
    else if (mode == 'w') fo->fd = open(file, O_WRONLY);
    else if (mode == 'b') fo->fd = open(file, O_RDWR);
    else if (mode == 'a') fo->fd = open(file, O_APPEND);
    else mini_perror("Error\n");

    if (fo->fd == -1) return NULL;
    fo->ind_read = -1;
    fo->ind_write = -1;
    fo->buffer_read = NULL;
    fo->buffer_write = NULL;

    return fo;
}

Upvotes: 1

Views: 101

Answers (1)

chqrlie
chqrlie

Reputation: 145277

I want writing, via a write, only be triggered when the buffer_write is full.

Your function does exactly that. It allocates the output buffer if not allocated already and copies bytes one at a time to it, writing the contents when file->ind_write has reached IOBUFFER_SIZE.

Yet there are some problems:

  • open(file, O_WRONLY) does not create the file if it does not already exist, you cannot create files with the current mini_fopen implementation.
  • the prototype for mini_fwrite should be:
    size_t mini_fwrite(const void *buffer,
                       size_t size_element,
                       size_t number_element,
                       MYFILE *file)
    
    and the return value is the number of elements successfully written.
  • buffer_read and buffer_write should have type unsigned char * to avoid the need for casts when accessing the buffer contents.
  • write(file->fd, file->buffer_write, file->ind_write) may returns the count of bytes successfully written. This count may be less than file->ind_write, especially if the call was interrupted by a signal. You should try again with the unwritten part of the buffer until everything is fully written or a return value of 0 or -1 is produced by the write system call.
  • writing the buffer could be moved to a different function called mini_fflush() which you would also call in mini_fclose().
  • you don't check for failure of mini_calloc to allocate memory.

Upvotes: 1

Related Questions