user1071847
user1071847

Reputation: 709

C: code duplication example

I'm writing functions that take the checksum of two different things: one, a file; and two, an archive entry a la the BSD libarchive library. I borrowed the checksum code from GNU's coreutils.

My code for doing a checksum on a file reads from its source like this:

unsigned char buf[BUFLEN];
size_t bytes_read;
FILE *fp;
...
while ((bytes_read = fread (buf, 1, BUFLEN, fp)) > 0) { ... }

In my code for reading from an archive entry, the corresponding code looks like

struct archive *ar;
unsigned char buf[BUFLEN];
ssize_t bytes_read;
...
while ((bytes_read = archive_read_data(ar, buf, sizeof(buf))) > 0) { ... }

As it stands, I'll have to have two different functions here, even though most of the code is the same. I don't quite see how to do it by passing a function pointer, since fread and archive_read_data don't even have the same number of arguments. (I guess I could start by using read(2) instead of fread(3), but I'm not sure that's a productive way to proceed.)

Is there a nice method to avoid code duplication here? Aside from trying to do it with function pointers, I could do it by putting the identical code pieces in separate files, then #including'ing them, but that seems ugly.

In this particular example, the code for the functions isn't that long, so just going ahead and duplicating the code isn't that big a deal. I'm just wondering if an elegant solution exists.

Upvotes: 2

Views: 279

Answers (3)

Israel Unterman
Israel Unterman

Reputation: 13520

If the code analyzing the checksum is the same, you could make that into a function - that is the part inside the curly brace. In my opinion, it's not so bad having two separate loops, if they call the same function. They can be considered as a thin wrapper.

Upvotes: 1

Adam Liss
Adam Liss

Reputation: 48330

Both functions really only need 3 args:

  • pointer to the data source
  • pointer to the data buffer
  • number of bytes to read

You could write a wrapper function for fread to give it the same signature as archive_read_data (or vice-versa):

ssize_t my_fread(FILE *fp, char *buf, int len) {
  return fread(buf, 1, len, fp);
}

Upvotes: 0

Graham Borland
Graham Borland

Reputation: 60701

You can create your own wrapper functions for fread() and archive_read_data() which have identical prototypes. Each of these wrappers would contain just a single line of code, to call the underlying read() function, rearranging the parameters as needed.

Then use a function pointer to distinguish between your two wrappers depending on the context.

Upvotes: 2

Related Questions