2

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.

4

3 回答 3

2

您可以创建自己的包装函数,fread()archive_read_data()具有相同的原型。这些包装器中的每一个都将只包含一行代码,以调用底层read()函数,并根据需要重新排列参数。

然后根据上下文使用函数指针来区分两个包装器。

于 2012-04-10T20:42:41.607 回答
1

如果分析校验和的代码是相同的,你可以把它变成一个函数——也就是花括号里面的部分。在我看来,如果它们调用相同的函数,那么拥有两个独立的循环并不是那么糟糕。它们可以被视为一个薄包装。

于 2012-04-10T20:48:27.553 回答
0

这两个函数实际上只需要 3 个参数:

  • 指向数据源的指针
  • 指向数据缓冲区的指针
  • 要读取的字节数

您可以编写一个包装函数,fread为其赋予与以下相同的签名archive_read_data(反之亦然):

ssize_t my_fread(FILE *fp, char *buf, int len) {
  return fread(buf, 1, len, fp);
}
于 2012-04-10T20:43:57.597 回答