diff --git a/lib/Makefile.am b/lib/Makefile.am index 0fe52b4c..56f4df8c 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -31,9 +31,11 @@ DISTCLEANFILES = $(pkgconfig_DATA) lib_LTLIBRARIES = libspdylay.la -OBJECTS = spdylay_pq.c spdylay_map.c spdylay_queue.c +OBJECTS = spdylay_pq.c spdylay_map.c spdylay_queue.c \ + spdylay_buffer.c -HFILES = spdylay_pq.h spdylay_int.h spdylay_map.h spdylay_queue.h +HFILES = spdylay_pq.h spdylay_int.h spdylay_map.h spdylay_queue.h \ + spdylay_buffer.h libspdylay_la_SOURCES = $(HFILES) $(OBJECTS) libspdylay_la_LDFLAGS = -no-undefined \ diff --git a/lib/includes/spdylay/spdylay.h b/lib/includes/spdylay/spdylay.h index f2b50ede..cdc71302 100644 --- a/lib/includes/spdylay/spdylay.h +++ b/lib/includes/spdylay/spdylay.h @@ -30,6 +30,7 @@ extern "C" { #endif #include +#include enum spdylay_error { SPDYLAY_ERR_NOMEM = -500, diff --git a/lib/spdylay_buffer.c b/lib/spdylay_buffer.c new file mode 100644 index 00000000..b62c18c9 --- /dev/null +++ b/lib/spdylay_buffer.c @@ -0,0 +1,124 @@ +/* + * Spdylay - SPDY Library + * + * Copyright (c) 2012 Tatsuhiro Tsujikawa + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include "spdylay_buffer.h" + +#include +#include + +void spdylay_buffer_init(spdylay_buffer *buffer, size_t chunk_capacity) +{ + spdylay_queue_init(&buffer->q); + buffer->capacity = chunk_capacity; + buffer->len = 0; + /* + * Set last_offset to maximum so that first append adds new buffer + * buffer. + */ + buffer->last_offset = buffer->capacity; +} + +void spdylay_buffer_free(spdylay_buffer *buffer) +{ + while(!spdylay_queue_empty(&buffer->q)) { + free(spdylay_queue_front(&buffer->q)); + spdylay_queue_pop(&buffer->q); + } +} + +int spdylay_buffer_alloc(spdylay_buffer *buffer) +{ + int r; + uint8_t *buf = (uint8_t*)malloc(buffer->capacity); + if(buf == NULL) { + return SPDYLAY_ERR_NOMEM; + } + if((r = spdylay_queue_push(&buffer->q, buf)) != 0) { + free(buf); + return r; + } + buffer->len += buffer->capacity-buffer->last_offset; + buffer->last_offset = 0; + return 0; +} + +uint8_t* spdylay_buffer_get(spdylay_buffer *buffer) +{ + if(spdylay_queue_empty(&buffer->q)) { + return NULL; + } else { + return spdylay_queue_back(&buffer->q)+buffer->last_offset; + } +} + +size_t spdylay_buffer_avail(spdylay_buffer *buffer) +{ + return buffer->capacity-buffer->last_offset; +} + +void spdylay_buffer_advance(spdylay_buffer *buffer, size_t amount) +{ + buffer->last_offset += amount; + buffer->len += amount; + assert(buffer->last_offset <= buffer->capacity); +} + +size_t spdylay_buffer_length(spdylay_buffer *buffer) +{ + return buffer->len; +} + +size_t spdylay_buffer_front_length(spdylay_buffer *buffer) +{ + if(spdylay_queue_empty(&buffer->q)) { + return 0; + } else if(buffer->len >= buffer->capacity) { + return buffer->capacity; + } else { + return buffer->len; + } +} + +uint8_t* spdylay_buffer_front_data(spdylay_buffer *buffer) +{ + if(spdylay_queue_empty(&buffer->q)) { + return NULL; + } else { + return spdylay_queue_front(&buffer->q); + } +} + +void spdylay_buffer_pop(spdylay_buffer *buffer) +{ + if(!spdylay_queue_empty(&buffer->q)) { + if(buffer->len >= buffer->capacity) { + buffer->len -= buffer->capacity; + } else { + buffer->len = 0; + buffer->last_offset = buffer->capacity; + } + free(spdylay_queue_front(&buffer->q)); + spdylay_queue_pop(&buffer->q); + } +} diff --git a/lib/spdylay_buffer.h b/lib/spdylay_buffer.h new file mode 100644 index 00000000..30076797 --- /dev/null +++ b/lib/spdylay_buffer.h @@ -0,0 +1,78 @@ +/* + * Spdylay - SPDY Library + * + * Copyright (c) 2012 Tatsuhiro Tsujikawa + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef SPDYLAY_BUFFER_H +#define SPDYLAY_BUFFER_H + +#ifdef HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#include +#include "spdylay_queue.h" + +/* + * Fixed sized buffers backed by queue. + */ +typedef struct { + /* Capacity of each chunk buffer */ + size_t capacity; + /* Queue of chunk buffers */ + spdylay_queue q; + /* Total length of this buffer */ + size_t len; + /* Offset of last chunk buffer */ + size_t last_offset; +} spdylay_buffer; + +/* + * Initializes buffer with fixed chunk size chunk_capacity. + */ +void spdylay_buffer_init(spdylay_buffer *buffer, size_t chunk_capacity); +/* Releases allocated memory for buffer */ +void spdylay_buffer_free(spdylay_buffer *buffer); +/* Returns buffer pointer */ +uint8_t* spdylay_buffer_get(spdylay_buffer *buffer); +/* Returns available buffer length */ +size_t spdylay_buffer_avail(spdylay_buffer *buffer); +/* Advances buffer pointer by amount. This reduces available buffer + length. */ +void spdylay_buffer_advance(spdylay_buffer *buffer, size_t amount); +/* Allocate new chunk buffer. This will increase total length of + buffer (returned by spdylay_buffer_length) by capacity-last_offset. + It means untouched buffer is assumued to be written. */ +int spdylay_buffer_alloc(spdylay_buffer *buffer); + +/* Returns total length of buffer */ +size_t spdylay_buffer_length(spdylay_buffer *buffer); +/* Returns first chunk buffer length. If the chunk buffer is the last + one, last_offset will be returned. */ +size_t spdylay_buffer_front_length(spdylay_buffer *buffer); +/* Returns first chunk buffer pointer */ +uint8_t* spdylay_buffer_front_data(spdylay_buffer *buffer); +/* Pops first chunk buffer and decreases total length of buffer by the + size of poped chunk buffer. */ +void spdylay_buffer_pop(spdylay_buffer *buffer); + +#endif /* SPDYLAY_BUFFER_H */ diff --git a/tests/Makefile.am b/tests/Makefile.am index 34c2683d..b79bb5b0 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -25,9 +25,11 @@ if HAVE_CUNIT check_PROGRAMS = main -OBJECTS = main.c spdylay_pq_test.c spdylay_map_test.c spdylay_queue_test.c +OBJECTS = main.c spdylay_pq_test.c spdylay_map_test.c spdylay_queue_test.c \ + spdylay_buffer_test.c -HFILES = spdylay_pq_test.h spdylay_map_test.h spdylay_queue_test.h +HFILES = spdylay_pq_test.h spdylay_map_test.h spdylay_queue_test.h \ + spdylay_buffer_test.h main_SOURCES = $(HFILES) $(OBJECTS) diff --git a/tests/main.c b/tests/main.c index 8a36234e..50c12ced 100644 --- a/tests/main.c +++ b/tests/main.c @@ -29,6 +29,7 @@ #include "spdylay_pq_test.h" #include "spdylay_map_test.h" #include "spdylay_queue_test.h" +#include "spdylay_buffer_test.h" int init_suite1(void) { @@ -59,7 +60,8 @@ int main() /* add the tests to the suite */ if(!CU_add_test(pSuite, "pq", test_spdylay_pq) || !CU_add_test(pSuite, "map", test_spdylay_map) || - !CU_add_test(pSuite, "queue", test_spdylay_queue)) { + !CU_add_test(pSuite, "queue", test_spdylay_queue) || + !CU_add_test(pSuite, "buffer", test_spdylay_buffer)) { CU_cleanup_registry(); return CU_get_error(); } diff --git a/tests/spdylay_buffer_test.c b/tests/spdylay_buffer_test.c new file mode 100644 index 00000000..75c7c816 --- /dev/null +++ b/tests/spdylay_buffer_test.c @@ -0,0 +1,83 @@ +/* + * Spdylay - SPDY Library + * + * Copyright (c) 2012 Tatsuhiro Tsujikawa + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include "spdylay_buffer_test.h" + +#include + +#include + +#include "spdylay_buffer.h" + +void test_spdylay_buffer() +{ + spdylay_buffer buffer; + spdylay_buffer_init(&buffer, 8); + CU_ASSERT(0 == spdylay_buffer_length(&buffer)); + CU_ASSERT(0 == spdylay_buffer_avail(&buffer)); + CU_ASSERT(NULL == spdylay_buffer_get(&buffer)); + CU_ASSERT(0 == spdylay_buffer_alloc(&buffer)); + + CU_ASSERT(8 == spdylay_buffer_avail(&buffer)); + CU_ASSERT(NULL != spdylay_buffer_get(&buffer)); + memcpy(spdylay_buffer_get(&buffer), "012", 3); + spdylay_buffer_advance(&buffer, 3); + CU_ASSERT(3 == spdylay_buffer_length(&buffer)); + + CU_ASSERT(5 == spdylay_buffer_avail(&buffer)); + memcpy(spdylay_buffer_get(&buffer), "34567", 5); + spdylay_buffer_advance(&buffer, 5); + CU_ASSERT(8 == spdylay_buffer_length(&buffer)); + + CU_ASSERT(0 == spdylay_buffer_avail(&buffer)); + CU_ASSERT(0 == spdylay_buffer_alloc(&buffer)); + memcpy(spdylay_buffer_get(&buffer), "89ABCDE", 7); + spdylay_buffer_advance(&buffer, 7); + CU_ASSERT(15 == spdylay_buffer_length(&buffer)); + + CU_ASSERT(1 == spdylay_buffer_avail(&buffer)); + + CU_ASSERT(8 == spdylay_buffer_front_length(&buffer)); + CU_ASSERT(memcmp("01234567", spdylay_buffer_front_data(&buffer), 8) == 0); + spdylay_buffer_pop(&buffer); + + CU_ASSERT(7 == spdylay_buffer_length(&buffer)); + CU_ASSERT(memcmp("89ABCDE", spdylay_buffer_front_data(&buffer), 7) == 0); + spdylay_buffer_pop(&buffer); + + CU_ASSERT(0 == spdylay_buffer_length(&buffer)); + + CU_ASSERT(0 == spdylay_buffer_avail(&buffer)); + CU_ASSERT(NULL == spdylay_buffer_get(&buffer)); + + CU_ASSERT(0 == spdylay_buffer_alloc(&buffer)); + + CU_ASSERT(8 == spdylay_buffer_avail(&buffer)); + memcpy(spdylay_buffer_get(&buffer), "34567", 5); + spdylay_buffer_advance(&buffer, 5); + CU_ASSERT(5 == spdylay_buffer_length(&buffer)); + CU_ASSERT(memcmp("34567", spdylay_buffer_front_data(&buffer), 5) == 0); + + spdylay_buffer_free(&buffer); +} diff --git a/tests/spdylay_buffer_test.h b/tests/spdylay_buffer_test.h new file mode 100644 index 00000000..99ea4850 --- /dev/null +++ b/tests/spdylay_buffer_test.h @@ -0,0 +1,30 @@ +/* + * Spdylay - SPDY Library + * + * Copyright (c) 2012 Tatsuhiro Tsujikawa + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef SPDYLAY_BUFFER_TEST_H +#define SPDYLAY_BUFFER_TEST_H + +void test_spdylay_buffer(); + +#endif // SPDYLAY_BUFFER_TEST_H