Last active
March 30, 2017 13:52
-
-
Save oxbambooxo/a63e71d81ad45cd254e99d5c3e168cd9 to your computer and use it in GitHub Desktop.
"cat" in libuv without global variables
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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