Guest User

Untitled

a guest
Apr 26th, 2018
184
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.92 KB | None | 0 0
  1. tail -n
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <dqueue.h>
  7.  
  8. #define MAX_LEN 256
  9. #define MAX_LINES 32
  10. #define DEFAULT_TAIL 10
  11.  
  12. int getlinep(char *s, int lim);
  13.  
  14. int main(int argc, char *argv[])
  15. {
  16. char *line;
  17. char *temp;
  18. int tail_len = DEFAULT_TAIL;
  19. queue_t * queue = NULL;
  20. int elements;
  21. int len;
  22.  
  23. if(!(queue = queue_init(sizeof(char *)))) {
  24. fprintf(stderr, "Error %d: Could not initialise queue!n", MEM_ERROR);
  25. return MEM_ERROR;
  26. }
  27.  
  28. if(argc >= 2) {
  29. if(atoi(*(++argv))) {
  30. tail_len = -atoi(*argv);
  31. if(tail_len <= 0 || tail_len > MAX_LEN)
  32. tail_len = DEFAULT_TAIL;
  33. }
  34. }
  35.  
  36. for(elements = 0; elements < tail_len; elements++) {
  37. if(!(line = malloc(MAX_LEN))) {
  38. fprintf(stderr, "Error: Memory allocation failure!n");
  39. return MEM_ERROR;
  40. }
  41.  
  42. if(!getlinep(line, MAX_LEN)) {
  43. free(line);
  44.  
  45. if(elements == 0) {
  46. queue_destroy(&queue);
  47. return EXIT_SUCCESS;
  48. }
  49.  
  50. break;
  51. }
  52.  
  53. queue_push(&line, queue);
  54. }
  55.  
  56. if(elements == tail_len) {
  57. if(!(temp = malloc(MAX_LEN))) {
  58. fprintf(stderr, "Error: Memory allocation failure!n");
  59. return MEM_ERROR;
  60. }
  61. for(;;) {
  62. if(!(len = getlinep(temp, MAX_LEN))) {
  63. free(temp);
  64. break;
  65. }
  66.  
  67. queue_pop(&line, queue);
  68. memcpy(line, temp, len + 1);
  69. queue_push(&line, queue);
  70. }
  71. }
  72.  
  73. while(elements-- > 0) {
  74. queue_pop(&line, queue);
  75. printf("%s", line);
  76. free(line);
  77. }
  78.  
  79. queue_destroy(&queue);
  80.  
  81. return EXIT_SUCCESS;
  82. }
  83.  
  84. int getlinep(char *s, int lim)
  85. {
  86. int i;
  87.  
  88. for(i = 0; i < lim - 1 && (*s = getchar()) != EOF && *s != 'n'; i++, s++)
  89. ;
  90.  
  91. if(*s == 'n') {
  92. s++;
  93. i++;
  94. }
  95.  
  96. *s = '';
  97.  
  98. return i;
  99. }
  100.  
  101. #ifndef DQUEUE_H
  102. #define DQUEUE_H
  103.  
  104. #include <stdlib.h> /* Needed for size_t */
  105.  
  106. #define QUEUE_OK 0
  107. #define MEM_ERROR -1 /* Memory allocation error */
  108. #define SIZE_ERROR -2 /* Queue dimension error */
  109. #define INDEX_ERROR -3 /* No data at given index */
  110.  
  111. #define BLOCK_SIZE 1024
  112.  
  113. typedef struct queue_element_t
  114. {
  115. void * data; /* Contains the data stored at this node */
  116. void * next; /* Contains the pointer to the next element, or NULL if it's the tail node */
  117. } queue_element_t;
  118.  
  119. typedef struct
  120. {
  121. queue_element_t * head; /* Pointer to the head of the queue */
  122. queue_element_t * tail; /* Pointer to the tail of the queue */
  123. size_t size; /* The number of elements in the queue */
  124. size_t element_width; /* The size of each element in the queue */
  125. size_t tail_pos; /* The byte offset of the data being pushed into the queue (i.e. in the tail block) */
  126. size_t head_pos; /* The byte offset of the data being popped out of the queue (i.e. in the head block) */
  127. int status;
  128. } queue_t;
  129.  
  130. queue_t * queue_init(size_t element_size); /* Initialise the queue data structure */
  131. void queue_pop(void * const element, queue_t * queue); /* Pop an element from the front of the queue, deals with cleanup when the head node is empty */
  132. int queue_push(const void * const element, queue_t * queue); /* Push an element to the back of the queue, creates a new block when tail node is full */
  133. int queue_debug(const queue_t * const queue); /* Print information about the queue, returns the queue status if a valid queue pointer is given */
  134. void queue_destroy(queue_t * queue); /* Destroy the queue data structure and any associated nodes */
  135.  
  136. #endif
  137.  
  138. /*
  139. * Filename: dqueue.c
  140. * Author: Alexis Ferguson (highentropystring@gmail.com)
  141. * Date: 17/02/18
  142. * Licence: GNU GPL V3
  143. *
  144. * Library for a lightweight, generic, and dynamically allocated queue
  145. *
  146. * Return/exit codes:
  147. * QUEUE_OK - No error
  148. * SIZE_ERROR - Queue size error (invalid block size or number of elements)
  149. * MEM_ERROR - Memory allocation error
  150. * INDEX_ERROR - Couldn't pop data from the queue
  151. *
  152. * All functions returning pointers will return NULL on memory allocation faliure, else they will specify an error in queue->status for the user to handle
  153. *
  154. * Todo:
  155. * - Add secure versions of queue_destroy() and queue_pop() to overwrite memory blocks that are no longer in use
  156. *
  157. */
  158.  
  159. #include <dqueue.h>
  160. #include <stdio.h>
  161. #include <string.h>
  162.  
  163. queue_t * queue_init(size_t element_width)
  164. {
  165. queue_t * queue;
  166.  
  167. if(!(queue = malloc(sizeof(queue_t))))
  168. return NULL;
  169.  
  170. if(BLOCK_SIZE % element_width != 0 || (queue->element_width = element_width) <= 0) {
  171. queue->status = SIZE_ERROR;
  172. return queue;
  173. }
  174.  
  175. queue->tail_pos = 0;
  176. queue->head_pos = 0;
  177. queue->tail = NULL;
  178. queue->head = NULL;
  179. queue->size = 0;
  180. queue->status = QUEUE_OK;
  181.  
  182. return queue;
  183. }
  184.  
  185. void queue_destroy(queue_t * queue)
  186. {
  187. queue_element_t * temp;
  188.  
  189. if(queue == NULL)
  190. return;
  191.  
  192. while(queue->head) {
  193. free(queue->head->data);
  194. temp = queue->head->next;
  195. free(queue->head);
  196. queue->head = temp;
  197. }
  198.  
  199. queue->size = 0;
  200. queue->status = 0;
  201. queue->element_width = 0;
  202. queue->tail_pos = 0;
  203. queue->head_pos = 0;
  204. queue->tail = NULL;
  205.  
  206. free(queue);
  207. }
  208.  
  209. int queue_push(const void * const element, queue_t * queue)
  210. {
  211. queue_element_t * new_element;
  212.  
  213. if(queue->tail_pos == 0) {
  214. if(!(new_element = malloc(sizeof(queue_element_t)))) {
  215. queue->status = MEM_ERROR;
  216. return queue->status;
  217. }
  218.  
  219. if(!(new_element->data = malloc(BLOCK_SIZE))) {
  220. free(new_element);
  221. queue->status = MEM_ERROR;
  222. return queue->status;
  223. }
  224.  
  225. if(queue->head == NULL)
  226. queue->head = new_element;
  227. else
  228. queue->tail->next = new_element;
  229.  
  230. queue->tail = new_element;
  231. queue->tail->next = NULL;
  232. queue->size++;
  233. }
  234.  
  235. memcpy(queue->tail->data + queue->tail_pos, element, queue->element_width);
  236.  
  237. queue->tail_pos += queue->element_width;
  238.  
  239. if(queue->tail_pos >= BLOCK_SIZE)
  240. queue->tail_pos = 0;
  241.  
  242. return queue->status;
  243. }
  244.  
  245. void queue_pop(void * const element, queue_t * queue)
  246. {
  247. queue_element_t * temp;
  248.  
  249. if(queue->head == NULL || ((queue->head == queue->tail) && (queue->head_pos == queue->tail_pos))) {
  250. if(queue->tail_pos == 0) { /* Catch an error related to reseting the tail position and incrementing a block after a block has been filled */
  251. queue->tail_pos = BLOCK_SIZE;
  252. } else {
  253. queue->status = INDEX_ERROR;
  254. return;
  255. }
  256. }
  257.  
  258. memcpy(element, queue->head->data + queue->head_pos, queue->element_width);
  259.  
  260. queue->head_pos += queue->element_width;
  261.  
  262. if(queue->head_pos >= BLOCK_SIZE) {
  263. free(queue->head->data);
  264. temp = queue->head;
  265. queue->head = queue->head->next;
  266. free(temp);
  267.  
  268. queue->head_pos = 0;
  269. queue->size--;
  270. }
  271. }
  272.  
  273. int queue_debug(const queue_t * const queue)
  274. {
  275. if(queue == NULL) {
  276. printf("Error: Invalid queue pointer!n");
  277. return MEM_ERROR;
  278. }
  279.  
  280. if(queue->status == QUEUE_OK) {
  281. printf("Queue is %d blocks long with an element width of %d bytes with each block containing %d elementsnQueue head is at %p and the current element is %pn", (int)queue->size, (int)queue->element_width, BLOCK_SIZE / (int)queue->element_width, (void *)queue->head, (void *)queue->tail);
  282. } else if(queue->status == MEM_ERROR) {
  283. printf("Memory error in queue!n");
  284. } else if(queue->status == SIZE_ERROR) {
  285. printf("Size error in queue!n");
  286. } else if(queue->status == INDEX_ERROR) {
  287. printf("Index error in queue!n");
  288. }
  289.  
  290. return queue->status;
  291. }
  292.  
  293. #define BLOCK_SIZE (256 - sizeof(void *))
  294. typedef struct {
  295. void *next;
  296. char data[BLOCK_SIZE];
  297. } queue_element_t;
  298.  
  299. void * data;
  300.  
  301. void * * buffer;
  302.  
  303. typedef void* Data_Ptr;
  304.  
  305. typedef struct
  306. {
  307. Data_Ptr * buffer;
  308. void * next;
  309. } queue_element_t;
  310.  
  311. memcpy (queue->tail->data + queue->tail_pos, element, queue->element_width);
  312. queue->tail_pos += queue->element_width;
  313.  
  314. element = queue->head->buffer [queue->head_pos];
  315. queue->head_pos ++;
Add Comment
Please, Sign In to add comment