From c4b30af64598579f87b0556d974264a9248e5e82 Mon Sep 17 00:00:00 2001 From: David Steele Date: Fri, 22 Dec 2017 19:56:01 -0500 Subject: [PATCH] Add Buffer object. --- doc/xml/release.xml | 4 + src/Makefile | 2 + src/common/type/buffer.c | 123 +++++++++++++++++++ src/common/type/buffer.h | 22 ++++ src/common/type/string.c | 23 ++++ src/common/type/string.h | 3 + test/lib/pgBackRestTest/Common/DefineTest.pm | 10 ++ test/src/module/common/typeBufferTest.c | 74 +++++++++++ test/src/module/common/typeStringTest.c | 9 +- 9 files changed, 269 insertions(+), 1 deletion(-) create mode 100644 src/common/type/buffer.c create mode 100644 src/common/type/buffer.h create mode 100644 test/src/module/common/typeBufferTest.c diff --git a/doc/xml/release.xml b/doc/xml/release.xml index b8cfdf702..b9b22f119 100644 --- a/doc/xml/release.xml +++ b/doc/xml/release.xml @@ -76,6 +76,10 @@

Improve MemContext module. Add temporary context blocks and refactor allocation arrays to include allocation size.

+ + +

Add Buffer object.

+
diff --git a/src/Makefile b/src/Makefile index bf4ab4105..8a0ebdbaa 100644 --- a/src/Makefile +++ b/src/Makefile @@ -6,6 +6,7 @@ pgbackrest: \ common/error.o \ common/errorType.o \ common/memContext.o \ + common/type/buffer.o \ common/type/list.o \ common/type/string.o \ common/type/stringList.o \ @@ -18,6 +19,7 @@ pgbackrest: \ common/error.o \ common/errorType.o \ common/memContext.o \ + common/type/buffer.o \ common/type/list.o \ common/type/string.o \ common/type/stringList.o \ diff --git a/src/common/type/buffer.c b/src/common/type/buffer.c new file mode 100644 index 000000000..d3f3e1bfc --- /dev/null +++ b/src/common/type/buffer.c @@ -0,0 +1,123 @@ +/*********************************************************************************************************************************** +String Handler +***********************************************************************************************************************************/ +#include + +#include "common/memContext.h" +#include "common/type/buffer.h" + +/*********************************************************************************************************************************** +Contains information about the buffer +***********************************************************************************************************************************/ +struct Buffer +{ + MemContext *memContext; + size_t size; + unsigned char *buffer; +}; + +/*********************************************************************************************************************************** +Create a new buffer +***********************************************************************************************************************************/ +Buffer * +bufNew(size_t size) +{ + // Create object + Buffer *this = memNew(sizeof(Buffer)); + this->memContext = memContextCurrent(); + this->size = size; + + // Allocate buffer + if (size > 0) + this->buffer = memNewRaw(this->size); + + return this; +} + +/*********************************************************************************************************************************** +Create a new buffer from a string +***********************************************************************************************************************************/ +Buffer * +bufNewStr(const String *string) +{ + // Create object + Buffer *this = bufNew(strSize(string)); + + // Copy the data + memcpy(this->buffer, strPtr(string), this->size); + + return this; +} + +/*********************************************************************************************************************************** +Return buffer ptr +***********************************************************************************************************************************/ +unsigned char * +bufPtr(const Buffer *this) +{ + return this->buffer; +} + +/*********************************************************************************************************************************** +Resize the buffer +***********************************************************************************************************************************/ +Buffer * +bufResize(Buffer *this, size_t size) +{ + // If new size is zero then free memory if allocated + if (size == 0) + { + if (this->buffer != NULL) + { + MEM_CONTEXT_BEGIN(this->memContext) + { + memFree(this->buffer); + } + MEM_CONTEXT_END(); + } + + this->buffer = NULL; + this->size = 0; + } + // Else allocate or resize + else + { + MEM_CONTEXT_BEGIN(this->memContext) + { + if (this->buffer == NULL) + this->buffer = memNew(size); + else + this->buffer = memGrowRaw(this->buffer, size); + } + MEM_CONTEXT_END(); + + this->size = size; + } + + return this; +} + +/*********************************************************************************************************************************** +Return buffer size +***********************************************************************************************************************************/ +size_t +bufSize(const Buffer *this) +{ + return this->size; +} + +/*********************************************************************************************************************************** +Free the buffer +***********************************************************************************************************************************/ +void +bufFree(Buffer *this) +{ + MEM_CONTEXT_BEGIN(this->memContext) + { + if (this->buffer != NULL) + memFree(this->buffer); + + memFree(this); + } + MEM_CONTEXT_END(); +} diff --git a/src/common/type/buffer.h b/src/common/type/buffer.h new file mode 100644 index 000000000..b38846f12 --- /dev/null +++ b/src/common/type/buffer.h @@ -0,0 +1,22 @@ +/*********************************************************************************************************************************** +Buffer Handler +***********************************************************************************************************************************/ +#ifndef COMMON_TYPE_BUFFER_H +#define COMMON_TYPE_BUFFER_H + +/*********************************************************************************************************************************** +Buffer object +***********************************************************************************************************************************/ +typedef struct Buffer Buffer; + +/*********************************************************************************************************************************** +Functions +***********************************************************************************************************************************/ +Buffer *bufNew(size_t size); +Buffer *bufNewStr(const String *string); +Buffer *bufResize(Buffer *this, size_t size); +size_t bufSize(const Buffer *this); +unsigned char *bufPtr(const Buffer *this); +void bufFree(Buffer *this); + +#endif diff --git a/src/common/type/string.c b/src/common/type/string.c index 0c48fd0ff..fc51919ed 100644 --- a/src/common/type/string.c +++ b/src/common/type/string.c @@ -37,6 +37,29 @@ strNew(const char *string) return this; } +/*********************************************************************************************************************************** +Create a new string from a buffer + +If the buffer has a NULL character this may not work as expected. All the data will be copied but only the data before the NULL +character will be used as a string. +***********************************************************************************************************************************/ +String * +strNewBuf(const Buffer *buffer) +{ + // Create object + String *this = memNew(sizeof(String)); + this->memContext = memContextCurrent(); + this->size = bufSize(buffer); + + // Allocate and assign string + this->buffer = memNewRaw(this->size + 1); + memcpy(this->buffer, (char *)bufPtr(buffer), this->size); + this->buffer[this->size] = 0; + + // Return buffer + return this; +} + /*********************************************************************************************************************************** Create a new string from a format string with parameters (i.e. sprintf) ***********************************************************************************************************************************/ diff --git a/src/common/type/string.h b/src/common/type/string.h index 0af80afa9..849cad307 100644 --- a/src/common/type/string.h +++ b/src/common/type/string.h @@ -12,7 +12,10 @@ typedef struct String String; /*********************************************************************************************************************************** Functions ***********************************************************************************************************************************/ +#include "common/type/buffer.h" + String *strNew(const char *string); +String *strNewBuf(const Buffer *buffer); String *strNewFmt(const char *format, ...); String *strNewSzN(const char *string, size_t size); diff --git a/test/lib/pgBackRestTest/Common/DefineTest.pm b/test/lib/pgBackRestTest/Common/DefineTest.pm index 1781c0e43..dea59be60 100644 --- a/test/lib/pgBackRestTest/Common/DefineTest.pm +++ b/test/lib/pgBackRestTest/Common/DefineTest.pm @@ -161,6 +161,16 @@ my $oTestDef = 'common/type/stringList' => TESTDEF_COVERAGE_FULL, }, }, + { + &TESTDEF_NAME => 'type-buffer', + &TESTDEF_TOTAL => 2, + &TESTDEF_C => true, + + &TESTDEF_COVERAGE => + { + 'common/type/buffer' => TESTDEF_COVERAGE_FULL, + }, + }, { &TESTDEF_NAME => 'encode', &TESTDEF_TOTAL => 1, diff --git a/test/src/module/common/typeBufferTest.c b/test/src/module/common/typeBufferTest.c new file mode 100644 index 000000000..d2bbd3b6b --- /dev/null +++ b/test/src/module/common/typeBufferTest.c @@ -0,0 +1,74 @@ +/*********************************************************************************************************************************** +Test Buffers +***********************************************************************************************************************************/ + +/*********************************************************************************************************************************** +Test Run +***********************************************************************************************************************************/ +void testRun() +{ + // ***************************************************************************************************************************** + if (testBegin("bufNew(), bufNewStr(), bufSize(), bufPtr(), and bufFree()")) + { + Buffer *buffer = NULL; + + TEST_ASSIGN(buffer, bufNew(256), "new buffer"); + TEST_RESULT_PTR(bufPtr(buffer), buffer->buffer, "buffer pointer"); + TEST_RESULT_INT(bufSize(buffer), 256, "buffer size"); + + TEST_ASSIGN(buffer, bufNewStr(strNew("TEST-STR")), "new buffer from string"); + TEST_RESULT_BOOL(memcmp(bufPtr(buffer), "TEST-STR", 8) == 0, true, "check buffer"); + + TEST_RESULT_VOID(bufFree(buffer), "free buffer"); + } + + // ***************************************************************************************************************************** + if (testBegin("bufResize()")) + { + Buffer *buffer = NULL; + unsigned char *bufferPtr = NULL; + + TEST_ASSIGN(buffer, bufNew(0), "new zero buffer"); + TEST_RESULT_INT(bufSize(buffer), 0, "check size"); + TEST_RESULT_PTR(bufResize(buffer, 256), buffer, "resize buffer"); + TEST_RESULT_INT(bufSize(buffer), 256, "check size"); + + // Load data + TEST_ASSIGN(bufferPtr, bufPtr(buffer), "buffer pointer"); + + for (unsigned int bufferIdx = 0; bufferIdx < bufSize(buffer); bufferIdx++) + bufferPtr[bufferIdx] = bufferIdx; + + // Increase buffer size + TEST_ASSIGN(bufferPtr, bufPtr(bufResize(buffer, 512)), "increase buffer size"); + TEST_RESULT_INT(bufSize(buffer), 512, "check size"); + + // Test that no bytes have changed in the original data + unsigned int sameTotal = 0; + + for (unsigned int bufferIdx = 0; bufferIdx < 256; bufferIdx++) + if (bufferPtr[bufferIdx] == bufferIdx) + sameTotal++; + + TEST_RESULT_INT(sameTotal, 256, "original bytes match"); + + // Decrease buffer size + TEST_ASSIGN(bufferPtr, bufPtr(bufResize(buffer, 128)), "decrease buffer size"); + TEST_RESULT_INT(bufSize(buffer), 128, "check size"); + + // Test that no bytes have changed in the original data + sameTotal = 0; + + for (unsigned int bufferIdx = 0; bufferIdx < bufSize(buffer); bufferIdx++) + if (bufferPtr[bufferIdx] == bufferIdx) + sameTotal++; + + TEST_RESULT_INT(sameTotal, 128, "original bytes match"); + + // Resize to zero buffer + TEST_ASSIGN(bufferPtr, bufPtr(bufResize(buffer, 0)), "decrease to zero"); + TEST_RESULT_INT(bufSize(buffer), 0, "check size"); + TEST_ASSIGN(bufferPtr, bufPtr(bufResize(buffer, 0)), "decrease to zero again"); + TEST_RESULT_INT(bufSize(buffer), 0, "check size"); + } +} diff --git a/test/src/module/common/typeStringTest.c b/test/src/module/common/typeStringTest.c index e45112ed5..2ea21faa6 100644 --- a/test/src/module/common/typeStringTest.c +++ b/test/src/module/common/typeStringTest.c @@ -1,6 +1,7 @@ /*********************************************************************************************************************************** Test Strings ***********************************************************************************************************************************/ +#include "common/type/buffer.h" /*********************************************************************************************************************************** Test Run @@ -8,7 +9,7 @@ Test Run void testRun() { // ***************************************************************************************************************************** - if (testBegin("strNew(), strNewSzN(), and strFree()")) + if (testBegin("strNew(), strNewBuf(), strNewSzN(), and strFree()")) { String *string = strNew("static string"); TEST_RESULT_STR(strPtr(string), "static string", "new with static string"); @@ -21,6 +22,12 @@ void testRun() // ------------------------------------------------------------------------------------------------------------------------- TEST_RESULT_STR(strPtr(strNewSzN("testmorestring", 4)), "test", "new string with size limit"); + // ------------------------------------------------------------------------------------------------------------------------- + Buffer *buffer = bufNew(8); + memcpy(bufPtr(buffer), "12345678", 8); + + TEST_RESULT_STR(strPtr(strNewBuf(buffer)), "12345678", "new string from buffer"); + // ------------------------------------------------------------------------------------------------------------------------- string = strNewFmt("formatted %s %04d", "string", 1); TEST_RESULT_STR(strPtr(string), "formatted string 0001", "new with formatted string");