Skip to content

Instantly share code, notes, and snippets.

@oxbambooxo
Last active March 30, 2017 13:52
Show Gist options
  • Save oxbambooxo/a63e71d81ad45cd254e99d5c3e168cd9 to your computer and use it in GitHub Desktop.
Save oxbambooxo/a63e71d81ad45cd254e99d5c3e168cd9 to your computer and use it in GitHub Desktop.
"cat" in libuv without global variables
#include <stdlib.h>
#include <unistd.h>
#include <uv.h>
typedef struct req_bundle_s {
uv_loop_t *loop;
uv_fs_t *read_req;
uv_fs_t *writ_req;
unsigned int read_fd;
unsigned int writ_fd;
char *buf;
unsigned int buf_len;
} req_bundle_t;
req_bundle_t *malloc_req_bundle(uv_loop_t *loop, unsigned int read_fd, unsigned int writ_fd) {
req_bundle_t *req_bundle = (req_bundle_t *) malloc(sizeof(req_bundle_t));
req_bundle->loop = loop;
req_bundle->read_req = (uv_fs_t *) malloc(sizeof(uv_fs_t));
req_bundle->read_req->data = req_bundle;
req_bundle->writ_req = NULL;
req_bundle->read_fd = read_fd;
req_bundle->writ_fd = writ_fd;
req_bundle->buf = (char *) malloc(4096);
req_bundle->buf_len = 4096;
return req_bundle;
}
void free_req_bundle(req_bundle_t *req_bundle) {
free(req_bundle->buf);
uv_fs_req_cleanup(req_bundle->read_req);
free(req_bundle->read_req);
if (req_bundle->writ_req) {
uv_fs_req_cleanup(req_bundle->writ_req);
free(req_bundle->writ_req);
}
close(req_bundle->read_fd);
free(req_bundle);
}
void on_read(uv_fs_t *read_req);
void on_write(uv_fs_t *write_req);
void on_read(uv_fs_t *read_req) {
if (read_req->result < 0) {
fprintf(stderr, "Read error: %s\n", uv_strerror((int) read_req->result));
free_req_bundle((req_bundle_t *) read_req->data);
return;
}
else if (read_req->result == 0) {
uv_fs_t close_req;
req_bundle_t *req_bundle = (req_bundle_t *) read_req->data;
int result = uv_fs_close(req_bundle->loop, &close_req, (uv_file) req_bundle->read_fd, NULL);
if (result == -1) {
fprintf(stderr, "Error at closing file: %s.\n", uv_strerror(result));
}
uv_fs_req_cleanup(&close_req);
free_req_bundle(req_bundle);
}
else if (read_req->result > 0) {
req_bundle_t *req_bundle = (req_bundle_t *) read_req->data;
if (!req_bundle->writ_req) {
req_bundle->writ_req = (uv_fs_t *) malloc(sizeof(uv_fs_t));
req_bundle->writ_req->data = req_bundle;
}
/* read_req->result is real data buf len */
uv_buf_t iov = uv_buf_init(req_bundle->buf, (unsigned int) read_req->result);
uv_fs_write(req_bundle->loop, req_bundle->writ_req, req_bundle->writ_fd, &iov, 1, -1, on_write);
}
}
void on_write(uv_fs_t *write_req) {
if (write_req->result < 0) {
fprintf(stderr, "Write error!");
free_req_bundle((req_bundle_t *) write_req->data);
return;
}
else {
req_bundle_t *req_bundle = (req_bundle_t *) write_req->data;
uv_buf_t iov = uv_buf_init(req_bundle->buf, req_bundle->buf_len);
uv_fs_read(req_bundle->loop, req_bundle->read_req, req_bundle->read_fd, &iov, 1, -1, on_read);
}
}
void uv_read_file(uv_loop_t *loop, const char *path, unsigned int destination_fd) {
uv_fs_t open_req;
int result = uv_fs_open(loop, &open_req, path, O_RDONLY, 0, NULL);
if (result >= 0) {
req_bundle_t *req_bundle = malloc_req_bundle(loop, (unsigned int) result, destination_fd);
uv_buf_t iov = uv_buf_init(req_bundle->buf, req_bundle->buf_len);
uv_fs_read(loop, req_bundle->read_req, (uv_file) result, &iov, 1, -1, on_read);
} else {
fprintf(stderr, "error opening file: %s\n", uv_strerror(result));
}
uv_fs_req_cleanup(&open_req);
}
int main(int argc, char *argv[]) {
uv_loop_t *loop = uv_default_loop();
if (argc > 1) {
for (int n = 1; n < argc; n++) {
/* output multi file but asynchronous make reader confused, to little avail. */
uv_read_file(loop, argv[n], 1);
}
} else {
printf("error before run: not file exists\n");
return 1;
}
uv_run(loop, UV_RUN_DEFAULT);
uv_loop_close(loop);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment