#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define BUFFSIZE 100
#define ALIGN (sizeof(unsigned long) - 1)
struct mem_pool_head {
struct mem_pool *head;
struct mem_pool *tail;
};
struct mem_pool {
struct mem_pool *next;
size_t item_size; /* item size */
size_t buff_size; /* data buffer size */
size_t dlen; /* data length */
size_t offset; /* pointer to next write position */
char data[0]; /* pointer to buffer address = BUFFSIZE */
};
static struct mem_pool_head head = { .head = NULL, .tail = NULL };
static struct mem_pool_head dhead = { .head = NULL, .tail = NULL };
static struct mem_pool * alloc_item(void)
{
struct mem_pool *item;
size_t size;
size = (sizeof(struct mem_pool) + BUFFSIZE + ALIGN) & ~ALIGN;
item = (struct mem_pool *) malloc(size);
if (item) {
memset(item, '\0', size);
item->dlen = 0;
item->offset = 0;
item->item_size = size;
item->buff_size = BUFFSIZE;
item->next = NULL;
}
return item;
}
static void item_enpool_tail(struct mem_pool_head *h, struct mem_pool *item)
{
(h->head) ? (h->tail = h->tail->next = item) : (h->head = h->tail = item);
}
static void init_mem_pool(struct mem_pool_head *h, int poollen)
{
struct mem_pool *item;
for (int i = 0; i < poollen; ++i) {
item = alloc_item();
if (item)
item_enpool_tail(&head, item);
}
}
static struct mem_pool * get_pool_head(struct mem_pool_head *pool)
{
return pool->head;
}
static void item_enqueue_data_tail(struct mem_pool_head *dhead, struct mem_pool_head *pool, struct mem_pool *item)
{
(dhead->head) ? (dhead->tail = dhead->tail->next = item) : (dhead->head = dhead->tail = item);
(pool->head = pool->head->next) ? (pool->tail = pool->tail) : (pool->tail = NULL);
}
static void handle_input(void)
{
size_t nread;
struct mem_pool *item;
for (;;) {
item = get_pool_head(&head);
if (item == NULL) {
printf("get_pool_head return NULL.\n");
break;
}
nread = read(STDIN_FILENO, item->data + item->offset, item->buff_size);
if (nread == -1) {
perror("read");
continue;
} else if (nread == 0) {
printf("receive EOF.\n");
break;
}
item->dlen += nread;
item->offset += nread;
item->buff_size -= nread;
if (item->buff_size == 0)
item_enqueue_data_tail(&dhead, &head, item);
}
}
static void output(struct mem_pool *item)
{
write(STDOUT_FILENO, item->data, item->dlen);
}
static void reinit_item(struct mem_pool *item)
{
memset(item, '\0', item->item_size);
item->buff_size = BUFFSIZE;
item->offset = 0;
item->dlen = 0;
item->next = NULL;
}
static void reset_dhead(struct mem_pool_head *dhead)
{
(dhead->head = dhead->head->next) ? (dhead->tail = dhead->tail) : (dhead->tail = NULL);
}
static void handle_output(void)
{
struct mem_pool *item;
while ((item = get_pool_head(&dhead)) != NULL) {
output(item);
reset_dhead(&dhead);
item_enpool_tail(&head, item); /* insert into buffer pool */
reinit_item(item);
}
}
int main(void)
{
init_mem_pool(&head, 100);
handle_input();
handle_output();
return 0;
}
|