1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-03-03 14:52:21 +02:00

Add Buffer object.

This commit is contained in:
David Steele 2017-12-22 19:56:01 -05:00
parent f89b027dec
commit c4b30af645
9 changed files with 269 additions and 1 deletions

View File

@ -76,6 +76,10 @@
<release-item>
<p>Improve <code>MemContext</code> module. Add temporary context blocks and refactor allocation arrays to include allocation size.</p>
</release-item>
<release-item>
<p>Add <code>Buffer</code> object.</p>
</release-item>
</release-development-list>
</release-core-list>

View File

@ -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 \

123
src/common/type/buffer.c Normal file
View File

@ -0,0 +1,123 @@
/***********************************************************************************************************************************
String Handler
***********************************************************************************************************************************/
#include <string.h>
#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();
}

22
src/common/type/buffer.h Normal file
View File

@ -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

View File

@ -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)
***********************************************************************************************************************************/

View File

@ -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);

View File

@ -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,

View File

@ -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");
}
}

View File

@ -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");