pelib
2.0.0
|
00001 /* 00002 * fifo.c 00003 * 00004 * Created on: 26 Jan 2012 00005 * Copyright 2012 Nicolas Melot 00006 * 00007 * This file is part of pelib. 00008 * 00009 * pelib is free software: you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation, either version 3 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * pelib is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with pelib. If not, see <http://www.gnu.org/licenses/>. 00021 * 00022 */ 00023 00024 #include <string.h> 00025 #include <stdlib.h> 00026 #include <stdio.h> 00027 #include <stddef.h> 00028 00029 #ifndef CFIFO_T 00030 #error Using generic fifo without a type 00031 #endif 00032 00033 // Aliases for static functions 00034 #define state(elem) PELIB_CONCAT_3(cfifo_, elem, _state) 00035 #define is_in_content(elem) PELIB_CONCAT_2(is_in_content_, elem) 00036 #define continuous_read_length(elem) PELIB_CONCAT_2(continuous_read_length_, elem) 00037 static size_t continuous_read_length(CFIFO_T)(cfifo_t(CFIFO_T) *fifo); 00038 #define continuous_write_length(elem) PELIB_CONCAT_2(continuous_write_length_, elem) 00039 static size_t continuous_write_length(CFIFO_T)(cfifo_t(CFIFO_T) *fifo); 00040 00041 #define CFIFO_EMPTY "[]" 00042 #define CFIFO_SEPARATOR ":" 00043 #define CFIFO_BEGIN "[" 00044 #define CFIFO_END "]" 00045 00046 #ifdef debug 00047 #undef debug 00048 #undef debug_addr 00049 #undef debug_int 00050 #undef debug_size_t 00051 #endif 00052 00053 #if 10 00054 #define debug(var) printf("[%s:%s:%d] %s = \"%s\"\n", __FILE__, __FUNCTION__, __LINE__, #var, var); fflush(NULL) 00055 #define debug_addr(var) printf("[%s:%s:%d] %s = \"%p\"\n", __FILE__, __FUNCTION__, __LINE__, #var, var); fflush(NULL) 00056 #define debug_int(var) printf("[%s:%s:%d] %s = \"%d\"\n", __FILE__, __FUNCTION__, __LINE__, #var, var); fflush(NULL) 00057 #define debug_size_t(var) printf("[%s:%s:%d] %s = \"%zu\"\n", __FILE__, __FUNCTION__, __LINE__, #var, (size_t)(var)); fflush(NULL) 00058 #else 00059 #define debug(var) 00060 #define debug_addr(var) 00061 #define debug_int(var) 00062 #define debug_size_t(var) 00063 #endif 00064 00065 enum state 00066 { 00067 NORMAL, REVERSE, EMPTY, FULL 00068 }; 00069 typedef enum state state_t; 00070 00071 int 00072 pelib_alloc_buffer(cfifo_t(CFIFO_T))(cfifo_t(CFIFO_T)* cfifo, size_t capacity) 00073 { 00074 cfifo->buffer = (CFIFO_T*)malloc(sizeof(CFIFO_T) * capacity); 00075 cfifo->capacity = capacity; 00076 00077 return 1; 00078 } 00079 00080 cfifo_t(CFIFO_T)* 00081 pelib_alloc_struct(cfifo_t(CFIFO_T))() 00082 { 00083 cfifo_t(CFIFO_T) *fifo; 00084 fifo = (cfifo_t(CFIFO_T)*)malloc(sizeof(cfifo_t(CFIFO_T))); 00085 00086 return fifo; 00087 } 00088 00089 cfifo_t(CFIFO_T)* 00090 pelib_alloc_collection(cfifo_t(CFIFO_T))(size_t size) 00091 { 00092 cfifo_t(CFIFO_T) *fifo; 00093 fifo = pelib_alloc_struct(cfifo_t(CFIFO_T))(); 00094 if(fifo != NULL) 00095 { 00096 if(pelib_alloc_buffer(cfifo_t(CFIFO_T))(fifo, size) == 0) 00097 { 00098 pelib_free_struct(cfifo_t(CFIFO_T))(fifo); 00099 return NULL; 00100 } 00101 } 00102 00103 00104 return fifo; 00105 } 00106 00107 int 00108 pelib_init(cfifo_t(CFIFO_T))(cfifo_t(CFIFO_T)* fifo) 00109 { 00110 fifo->last_op = PELIB_CFIFO_POP; 00111 fifo->read = 0; 00112 fifo->write = 0; 00113 00114 return 1; 00115 } 00116 00117 int 00118 pelib_free(cfifo_t(CFIFO_T))(cfifo_t(CFIFO_T)* fifo) 00119 { 00120 pelib_free_buffer(cfifo_t(CFIFO_T))(fifo); 00121 return pelib_free_struct(cfifo_t(CFIFO_T))(fifo); 00122 } 00123 00124 int 00125 pelib_free_struct(cfifo_t(CFIFO_T))(cfifo_t(CFIFO_T)* fifo) 00126 { 00127 free((void*)fifo->buffer); 00128 00129 return 1; 00130 } 00131 00132 int 00133 pelib_free_buffer(cfifo_t(CFIFO_T))(cfifo_t(CFIFO_T)* fifo) 00134 { 00135 free(fifo); 00136 return 1; 00137 } 00138 00139 FILE* 00140 pelib_printf(cfifo_t(CFIFO_T))(FILE* stream, cfifo_t(CFIFO_T) fifo) 00141 { 00142 char* str; 00143 str = pelib_string(cfifo_t(CFIFO_T))(fifo); 00144 printf("%s\n", str); 00145 free(str); 00146 00147 return stream; 00148 } 00149 00150 FILE* 00151 pelib_printf_detail(cfifo_t(CFIFO_T))(FILE* stream, cfifo_t(CFIFO_T) fifo, int level) 00152 { 00153 char* str; 00154 str = pelib_string_detail(cfifo_t(CFIFO_T))(fifo, level); 00155 printf("%s\n", str); 00156 free(str); 00157 00158 return stream; 00159 } 00160 00161 static state_t 00162 state(CFIFO_T)(cfifo_t(CFIFO_T) *cfifo) 00163 { 00164 /* 00165 debug_size_t((size_t)cfifo->read); 00166 debug_size_t((size_t)cfifo->write); 00167 debug_size_t((size_t)cfifo->last_op); 00168 */ 00169 if (cfifo->read == cfifo->write) 00170 { 00171 if (cfifo->last_op == PELIB_CFIFO_POP) 00172 { 00173 return EMPTY; 00174 } 00175 else if (cfifo->last_op == PELIB_CFIFO_PUSH) 00176 { 00177 return FULL; 00178 } 00179 else 00180 { 00181 fprintf(stdout, "[ERROR:%s:%s:%i] Illegal state at fifo %p\n", __FILE__, __FUNCTION__, __LINE__, cfifo); 00182 return EMPTY; 00183 } 00184 } 00185 else if (cfifo->read < cfifo->write) 00186 { 00187 return NORMAL; 00188 } 00189 else 00190 { 00191 return REVERSE; 00192 } 00193 } 00194 00195 // returns 1 if index is in data area 00196 // returns 3 if index is in position of read index 00197 // returns 7 if index is in both read and write position, and in data area (fifo full) 00198 // returns -7 if index is in both read and write position not in data area (fifo empty) 00199 // returns -1 if index is not in data area 00200 // returns -5 if index is in position of write index but not in data area 00201 // ERRORS: 00202 // returns -2 if index is in position of read index but not read, but is not in data area 00203 // returns 5 if index is in position of write index but not read, but still is in data area 00204 // returns 6 if in both read and write indexes but cannot determine if in data area or not 00205 // returns 0 in case of other errors 00213 static int 00214 is_in_content(CFIFO_T)(cfifo_t(CFIFO_T) *fifo, size_t index) 00215 { 00216 int res; 00217 size_t read; 00218 state_t state; 00219 00220 read = fifo->read; 00221 state = state(CFIFO_T)(fifo); 00222 00223 res = 1; 00224 res += index == read ? 2 : 0; 00225 res += index == fifo->write ? 4 : 0; 00226 00227 switch (state) 00228 { 00229 case NORMAL: 00230 if (index < read || index >= fifo->write) 00231 { 00232 res = -1 * res; 00233 } 00234 break; 00235 case REVERSE: 00236 if (index >= fifo->write && index < read) 00237 { 00238 res = -1 * res; 00239 } 00240 break; 00241 case EMPTY: 00242 res = -1 * res; 00243 break; 00244 case FULL: 00245 // Do nothing 00246 break; 00247 default: 00248 fprintf(stderr, "[ERROR:%s:%s:%i] Illegal cfifo state", __FILE__, __FUNCTION__, __LINE__); 00249 return 0; 00250 break; 00251 } 00252 00253 return res; 00254 } 00255 00256 char* 00257 pelib_string(cfifo_t(CFIFO_T))(cfifo_t(CFIFO_T) fifo) 00258 { 00259 return pelib_string_detail(cfifo_t(CFIFO_T))(fifo, 0); 00260 } 00261 00262 char* 00263 pelib_string_detail(cfifo_t(CFIFO_T))(cfifo_t(CFIFO_T) fifo, int level) 00264 { 00265 char *str, *elem; 00266 unsigned int i; 00267 int status; 00268 00269 str = (char*)malloc(sizeof(char) * ((PELIB_FIFO_ELEM_MAX_CHAR + 1) * fifo.capacity) 00270 + 4); 00271 00272 sprintf(str, "["); 00273 for (i = 0; i < fifo.capacity; i++) 00274 { 00275 status = is_in_content(CFIFO_T)(&fifo, i); 00276 if (abs(status) & 2) 00277 { 00278 sprintf(str, "%s>", str); 00279 } 00280 if (abs(status) & 4) 00281 { 00282 sprintf(str, "%s>", str); 00283 } 00284 if(status > 0) 00285 { 00286 elem = pelib_string_detail(CFIFO_T)(fifo.buffer[i], level); 00287 sprintf(str, "%s%s", str, elem); 00288 free(elem); 00289 } 00290 else 00291 { 00292 sprintf(str, "%s.", str); 00293 } 00294 if (i < fifo.capacity - 1) 00295 { 00296 sprintf(str, "%s:", str); 00297 } 00298 } 00299 sprintf(str, "%s]", str); 00300 00301 return str; 00302 } 00303 00304 int 00305 pelib_cfifo_push(CFIFO_T)(cfifo_t(CFIFO_T)* fifo, CFIFO_T elem) 00306 { 00307 if (fifo->capacity > 0 && 00308 state(CFIFO_T)(fifo) != FULL) 00309 { 00310 memcpy((void*)&(fifo->buffer[fifo->write]), &elem, sizeof(CFIFO_T)); 00311 00312 fifo->write = (fifo->write + 1) % fifo->capacity; 00313 fifo->last_op = PELIB_CFIFO_PUSH; 00314 00315 return 1; 00316 } 00317 else 00318 { 00319 return 0; 00320 } 00321 } 00322 00323 size_t 00324 pelib_cfifo_fill(CFIFO_T)(cfifo_t(CFIFO_T)* fifo, size_t num) 00325 { 00326 size_t length = pelib_cfifo_capacity(CFIFO_T)(fifo) - pelib_cfifo_length(CFIFO_T)(fifo); 00327 num = length < num ? length : num; 00328 00329 fifo->write = (fifo->write + num) % fifo->capacity; 00330 00331 if(num > 0) 00332 { 00333 fifo->last_op = PELIB_CFIFO_PUSH; 00334 } 00335 00336 return num; 00337 } 00338 00339 CFIFO_T* 00340 pelib_cfifo_peekaddr(CFIFO_T)(cfifo_t(CFIFO_T)* fifo, size_t offset, size_t *num, CFIFO_T **addr) 00341 { 00342 if ((fifo->capacity > 0 && offset < pelib_cfifo_length(CFIFO_T)(fifo) && state(CFIFO_T)(fifo) != EMPTY)) 00343 { 00344 size_t avail = continuous_read_length(CFIFO_T)(fifo); 00345 if(num != NULL) 00346 { 00347 *num = avail; 00348 } 00349 if(addr != NULL) 00350 { 00351 if((fifo->read + offset + avail) % fifo->capacity != fifo->write) 00352 { 00353 *addr = (CFIFO_T*)&(fifo->buffer[(fifo->read + offset + avail) % fifo->capacity]); 00354 } 00355 else 00356 { 00357 *addr = NULL; 00358 } 00359 } 00360 00361 /* 00362 debug_size_t(fifo->read); 00363 debug_size_t(offset); 00364 debug_size_t(fifo->read + offset); 00365 debug_size_t((fifo->read + offset) % fifo->capacity); 00366 debug_size_t(fifo->buffer); 00367 debug_size_t(&(fifo->buffer[(fifo->read + offset) % fifo->capacity])); 00368 */ 00369 return (CFIFO_T*)&(fifo->buffer[(fifo->read + offset) % fifo->capacity]); 00370 } 00371 else 00372 { 00373 if(num != NULL) 00374 { 00375 *num = 0; 00376 } 00377 return NULL; 00378 } 00379 } 00380 00381 CFIFO_T* 00382 pelib_cfifo_writeaddr(CFIFO_T)(cfifo_t(CFIFO_T)* fifo, size_t *num, CFIFO_T **addr) 00383 { 00384 if ((fifo->capacity - pelib_cfifo_length(CFIFO_T)(fifo) > 0) || 1) 00385 { 00386 size_t avail = continuous_write_length(CFIFO_T)(fifo); 00387 if(num != NULL) 00388 { 00389 *num = avail; 00390 } 00391 if(addr != NULL) 00392 { 00393 if((fifo->write + avail) % fifo->capacity != fifo->read) 00394 { 00395 *addr = (CFIFO_T*)&(fifo->buffer[(fifo->write + avail) % fifo->capacity]); 00396 } 00397 else 00398 { 00399 *addr = NULL; 00400 } 00401 } 00402 00403 return (CFIFO_T*)&(fifo->buffer[fifo->write]); 00404 } 00405 else 00406 { 00407 return NULL; 00408 } 00409 } 00410 00411 CFIFO_T 00412 pelib_cfifo_pop(CFIFO_T)(cfifo_t(CFIFO_T)* fifo) 00413 { 00414 CFIFO_T *ptr, res; 00415 00416 ptr = pelib_cfifo_peekaddr(CFIFO_T)(fifo, 0, NULL, NULL); 00417 if (ptr != NULL) 00418 { 00419 fifo->read = (fifo->read + 1) % fifo->capacity; 00420 fifo->last_op = PELIB_CFIFO_POP; 00421 00422 res = *ptr; 00423 00424 return res; 00425 } 00426 else 00427 { 00428 CFIFO_T def; 00429 pelib_init(CFIFO_T)(&def); 00430 return def; 00431 } 00432 } 00433 00434 size_t 00435 pelib_cfifo_discard(CFIFO_T)(cfifo_t(CFIFO_T) *fifo, size_t num) 00436 { 00437 int length = pelib_cfifo_length(CFIFO_T)(fifo); 00438 num = num < (size_t) length ? num : (size_t)length; 00439 00440 fifo->read = (fifo->read + num) % fifo->capacity; 00441 00442 if(num > 0) 00443 { 00444 fifo->last_op = PELIB_CFIFO_POP; 00445 } 00446 00447 return num; 00448 } 00449 00450 CFIFO_T 00451 pelib_cfifo_peek(CFIFO_T)(cfifo_t(CFIFO_T)* cfifo, size_t offset) 00452 { 00453 CFIFO_T *ptr, res; 00454 ptr = pelib_cfifo_peekaddr(CFIFO_T)(cfifo, offset, NULL, NULL); 00455 if (ptr != NULL) 00456 { 00457 res = *ptr; 00458 return res; 00459 } 00460 else 00461 { 00462 CFIFO_T def; 00463 pelib_init(CFIFO_T)(&def); 00464 return def; 00465 } 00466 } 00467 00468 int 00469 pelib_cfifo_is_full(CFIFO_T)(cfifo_t(CFIFO_T)* cfifo) 00470 { 00471 return state(CFIFO_T)(cfifo) == FULL; 00472 } 00473 00474 int 00475 pelib_cfifo_is_empty(CFIFO_T)(cfifo_t(CFIFO_T)* cfifo) 00476 { 00477 return state(CFIFO_T)(cfifo) == EMPTY; 00478 } 00479 00480 size_t 00481 pelib_cfifo_pushmem(CFIFO_T)(cfifo_t(CFIFO_T) *fifo, CFIFO_T* mem, size_t num) 00482 { 00483 size_t left, length, pushed; 00484 switch(state(CFIFO_T)(fifo)) 00485 { 00486 case EMPTY: 00487 case NORMAL: 00488 left = fifo->capacity - fifo->write; 00489 length = left < num ? left : num; 00490 00491 memcpy((void*)&fifo->buffer[fifo->write], mem, length * sizeof(CFIFO_T)); 00492 00493 // Record amount of elements pushed 00494 pushed = length; 00495 // Update fifo's write pointer 00496 fifo->write = (fifo->write + length) % fifo->capacity; 00497 00498 if(pushed > 0) 00499 { 00500 fifo->last_op = PELIB_CFIFO_PUSH; 00501 } 00502 00503 // If left was not enough to accomodate the memory buffer to write 00504 if(left < num) 00505 { 00506 // Now we are in the reverse mode, just call the function again 00507 pushed += pelib_cfifo_pushmem(CFIFO_T)(fifo, mem + length, num - length); 00508 } 00509 00510 return pushed; 00511 break; 00512 00513 case FULL: 00514 case REVERSE: 00515 // Copy from write to read 00516 left = fifo->read - fifo->write; 00517 length = left < num ? left : num; 00518 memcpy((void*)&(fifo->buffer[fifo->write]), mem, length * sizeof(CFIFO_T)); 00519 00520 fifo->write += length; 00521 pushed = length; 00522 00523 if(pushed > 0) 00524 { 00525 fifo->last_op = PELIB_CFIFO_PUSH; 00526 } 00527 00528 return pushed; 00529 break; 00530 00531 default: 00532 return 0; 00533 break; 00534 } 00535 } 00536 00537 size_t 00538 pelib_cfifo_popmem(CFIFO_T)(cfifo_t(CFIFO_T) *fifo, CFIFO_T* mem, size_t num) 00539 { 00540 size_t i; 00541 size_t left, length, popped; 00542 volatile int* ptr; 00543 size_t intlength; 00544 00545 switch(state(CFIFO_T)(fifo)) 00546 { 00547 case FULL: 00548 case REVERSE: 00549 // Copy from write to end of buffer 00550 left = fifo->capacity - fifo->read; 00551 length = left < num ? left : num; 00552 00553 memcpy(mem, (void*)&(fifo->buffer[fifo->read]), length * sizeof(CFIFO_T)); 00554 00555 intlength = (length * sizeof(CFIFO_T)) / sizeof(int) ; 00556 ptr = (volatile int*) (&fifo->buffer[fifo->read]); 00557 00558 // Record amount of elements pushed 00559 popped = length; 00560 00561 // Update fifo's write pointer 00562 fifo->read = (fifo->read + length) % fifo->capacity; 00563 00564 if(popped > 0) 00565 { 00566 fifo->last_op = PELIB_CFIFO_POP; 00567 } 00568 00569 // If left was not enough to accomodate the memory buffer to write 00570 if(left < num) 00571 { 00572 // Now we are in the reverse mode, just call the function again 00573 popped += pelib_cfifo_popmem(CFIFO_T)(fifo, mem + length, num - length); 00574 } 00575 00576 return popped; 00577 break; 00578 00579 case EMPTY: 00580 case NORMAL: 00581 // Copy from write to read 00582 left = fifo->write - fifo->read; 00583 length = left < num ? left : num; 00584 memcpy(mem, (void*)&(fifo->buffer[fifo->read]), length * sizeof(CFIFO_T)); 00585 00586 intlength = (length * sizeof(CFIFO_T)) / sizeof(int) ; 00587 00588 ptr = (volatile int*) (&fifo->buffer[fifo->read]); 00589 fifo->read += length; 00590 popped = length; 00591 00592 if(popped > 0) 00593 { 00594 fifo->last_op = PELIB_CFIFO_POP; 00595 } 00596 00597 return popped; 00598 break; 00599 00600 default: 00601 return 0; 00602 break; 00603 } 00604 } 00605 00606 size_t 00607 pelib_cfifo_peekmem(CFIFO_T)(cfifo_t(CFIFO_T)* fifo, CFIFO_T* mem, size_t num, size_t offset) 00608 { 00609 size_t left, length; 00610 cfifo_t(CFIFO_T) copy = *fifo; 00611 copy.read = (copy.read + offset) % copy.capacity; 00612 00613 switch(state(CFIFO_T)(©)) 00614 { 00615 case FULL: 00616 case REVERSE: 00617 // Copy from write to end of buffer 00618 left = copy.capacity - copy.read; 00619 length = left < num ? left : num; 00620 00621 memcpy(mem, (void*)&(copy.buffer[copy.read]), length * sizeof(CFIFO_T)); 00622 00623 // If left was not enough to accomodate the memory buffer to write 00624 if((left) < num && left > 0) 00625 { 00626 // Now we are in the reverse mode, just call the function again 00627 length += pelib_cfifo_peekmem(CFIFO_T)(©, mem + length, num - length, length); 00628 } 00629 00630 return length; 00631 break; 00632 00633 case EMPTY: 00634 case NORMAL: 00635 // Copy from write to read 00636 left = copy.write - copy.read; 00637 length = left < num ? left : num; 00638 00639 memcpy(mem, (void*)&(copy.buffer[copy.read]), length * sizeof(CFIFO_T)); 00640 00641 return length; 00642 break; 00643 00644 default: 00645 return 0; 00646 break; 00647 } 00648 } 00649 00650 static 00651 size_t 00652 continuous_read_length(CFIFO_T)(cfifo_t(CFIFO_T)* fifo) 00653 { 00654 switch(state(CFIFO_T)(fifo)) 00655 { 00656 case FULL: 00657 case REVERSE: 00658 return fifo->capacity - fifo->read; 00659 break; 00660 00661 case EMPTY: 00662 return 0; 00663 break; 00664 case NORMAL: 00665 return fifo->write - fifo->read; 00666 break; 00667 00668 default: 00669 return -1; 00670 break; 00671 } 00672 } 00673 00674 static 00675 size_t 00676 continuous_write_length(CFIFO_T)(cfifo_t(CFIFO_T)* fifo) 00677 { 00678 switch(state(CFIFO_T)(fifo)) 00679 { 00680 case FULL: 00681 return 0; 00682 break; 00683 case REVERSE: 00684 return fifo->read - fifo->write; 00685 break; 00686 00687 case EMPTY: 00688 case NORMAL: 00689 return fifo->capacity - fifo->write; 00690 break; 00691 00692 default: 00693 return -1; 00694 break; 00695 } 00696 } 00697 00698 size_t 00699 pelib_cfifo_popfifo(CFIFO_T)(cfifo_t(CFIFO_T)* src, cfifo_t(CFIFO_T)* tgt, size_t num) 00700 { 00701 size_t requested = num; 00702 00703 while(num > 0 && !pelib_cfifo_is_empty(CFIFO_T)(src) && !pelib_cfifo_is_full(CFIFO_T)(tgt)) 00704 { 00705 size_t readl = continuous_read_length(CFIFO_T)(src); 00706 volatile size_t writel = continuous_write_length(CFIFO_T)(tgt); 00707 size_t length = readl < writel ? readl : writel; 00708 length = num < length ? num : length; 00709 memcpy((void*)&(tgt->buffer[tgt->write]), (void*)&(src->buffer[src->read]), length * sizeof(CFIFO_T)); 00710 num -= length; 00711 pelib_cfifo_discard(CFIFO_T)(src, length); 00712 pelib_cfifo_fill(CFIFO_T)(tgt, length); 00713 } 00714 00715 return requested - num; 00716 } 00717 00718 size_t 00719 pelib_cfifo_length(CFIFO_T)(cfifo_t(CFIFO_T) *cfifo) 00720 { 00721 switch(state(CFIFO_T)(cfifo)) 00722 { 00723 case EMPTY: 00724 return 0; 00725 break; 00726 case NORMAL: 00727 return cfifo->write - cfifo->read; 00728 break; 00729 case REVERSE: 00730 return cfifo->capacity - (cfifo->read - cfifo->write); 00731 break; 00732 case FULL: 00733 return cfifo->capacity; 00734 break; 00735 } 00736 00737 return 0; 00738 } 00739 00740 CFIFO_T 00741 pelib_cfifo_last(CFIFO_T)(cfifo_t(CFIFO_T) *cfifo) 00742 { 00743 size_t length = pelib_cfifo_length(CFIFO_T)(cfifo); 00744 00745 if(pelib_cfifo_length(CFIFO_T)(cfifo) <= 0) 00746 { 00747 CFIFO_T def; 00748 pelib_init(CFIFO_T)(&def); 00749 return def; 00750 } 00751 else 00752 { 00753 CFIFO_T* ptr = pelib_cfifo_peekaddr(CFIFO_T)(cfifo, length - 1, NULL, NULL); 00754 return *ptr; 00755 } 00756 } 00757 00758 size_t 00759 pelib_cfifo_capacity(CFIFO_T)(cfifo_t(CFIFO_T)* cfifo) 00760 { 00761 return cfifo->capacity; 00762 } 00763