Skip to content

Instantly share code, notes, and snippets.

@jeremyheiler
Last active December 23, 2015 02:09
Show Gist options
  • Save jeremyheiler/6564874 to your computer and use it in GitHub Desktop.
Save jeremyheiler/6564874 to your computer and use it in GitHub Desktop.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define BUFFER_SIZE 5
struct reqdata
{
char *data;
size_t len;
size_t pos;
};
static size_t swrite(char *ptr, size_t size, size_t nmemb,
struct reqdata *stream)
{
if (!stream) return 0;
size_t cpylen = size * nmemb;
size_t newlen = stream->len + cpylen + sizeof(char);
char *data = realloc(stream->data, newlen);
if (!data) return 0;
memcpy(data + stream->len, ptr, cpylen);
data[stream->len + cpylen] = '\0';
stream->data = data;
stream->len += cpylen;
return cpylen;
}
static size_t sread(char *ptr, size_t size, size_t nmemb,
struct reqdata *stream)
{
if (!stream) return 0;
size_t maxlen = size * nmemb;
size_t curlen = stream->len - stream->pos;
size_t cpylen = curlen < maxlen ? curlen : maxlen;
memcpy(ptr, stream->data + stream->pos, cpylen);
stream->pos += cpylen;
return cpylen;
}
int main(int argc, char **argv)
{
char *s1 = "abcdefg"; //"foofoofoofoofoofoofoo";
struct reqdata *data1 = malloc(sizeof(struct reqdata));
data1->data = malloc(sizeof(char));;
data1->data[0] = '\0';
data1->len = 0;
swrite(s1, sizeof(char), BUFFER_SIZE, data1);
swrite(s1 + BUFFER_SIZE, sizeof(char), BUFFER_SIZE, data1);
printf("Result: %s\n", data1->data);
free(data1->data);
free(data1);
struct reqdata *data2 = malloc(sizeof(struct reqdata));
data2->data = s1;
data2->len = strlen(s1);
data2->pos = 0;
char *s3 = malloc(sizeof(char) * (BUFFER_SIZE + 1));
size_t read;
read = sread(s3, sizeof(char), BUFFER_SIZE, data2);
s3[read] = '\0';
printf("Result: %s\n", s3);
read = sread(s3, sizeof(char), BUFFER_SIZE, data2);
s3[read] = '\0';
printf("Result: %s\n", s3);
free(s3);
free(data2);
return 0;
}
@jeremyheiler
Copy link
Author

@jeremy-w

i lined up the bullets.

  • i think the biggest things i did wrong are: i used 8 spaces instead of 1 tab, struct open paren is on a new line, and i didn't put the function's return type on its own line.
  • that's good to know. in this case i am restricted by libcurl requiring size_t.
  • makes sense to me.
  • after knowing this, i reread the (bsd) manual and it doesn't seem to be explicit. it just says the data is "unchanged" which (now obviously) means not free'd.
  • in this case, swrite and sread are intended to be callbacks for libcurl. if libcurl expects void *, wouldn't using char * in the implementation narrow the type and be acceptable? (libcurl also allows you to provide the object being passed in.)
  • again, libcurl is dictating parameters here. i just copied the names, and they mention that they copied the names from fread and fwrite. i agree that they're not entirely clear, though.
  • hmm, for some reason i thought this would just take the size of a pointer, not the data type.
  • this is interesting. does this mean it only requires one call to free? even if data is realloc'd?
  • honestly, i don't know why i didn't use a const size_t here. i was probably just caught up in using #define.

thanks for taking the time to provide feedback!

@jeremyheiler
Copy link
Author

@kisom

i just want to comment in a few things real quick. you and jeremy have given me a lot of stuff to check out and comment further on. (and i really need to get some sleep!) style(9) looks pretty good. it seems like i follow most of it already. i know i am very lacking in error checking in this program. that's the next thing i plan on beefing up before i move this code into my larger project.

thanks so much. i really appreciate it!

@jeremy-w
Copy link

void* is a "I won't mess with it and have no idea what it is, so it has to be a pointer so I can at least hold it and pass it back sanely."

The OS X realloc manpage clearly derives from the FreeBSD version, and I guess it's more careful to point out that pitfall because it tripped them up enough to be worth adding their own alternative function that does what you want to do most of the time when the realloc fails.

GNU extensions are fine on OS X. Clang implements pretty much all of them, plus some of its own. At least they've finished implementing the simpler ones from a decade or two ago; some of the fancier ones regarding threading and such are unavailable. The big obnoxious one that's missing is __thread or whatever for transparent thread-local variables – it's only supported for ELF.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment