Skip to content

Commit f905efc

Browse files
committed
Add a RAII-class for sqlite managed memory
Added a detail namnespace containing a new class for managing memory allocated with the function sqllite3_alloc(). The new class is: - Default constructible (creates a null buffer) - Copy constructible and copy assignable (copies the memory buffer size and contents into a new memory buffer) - Move constructible and move assignable.
1 parent c7fed9e commit f905efc

File tree

2 files changed

+142
-8
lines changed

2 files changed

+142
-8
lines changed

CppSQLite3.cpp

Lines changed: 97 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include "CppSQLite3.h"
99
#include <cstdlib>
10+
#include <utility>
1011

1112

1213
// Named constant for passing to CppSQLite3Exception when passing it a string
@@ -22,6 +23,94 @@ int sqlite3_decode_binary(const unsigned char *in, unsigned char *out);
2223

2324
////////////////////////////////////////////////////////////////////////////////
2425

26+
namespace detail
27+
{
28+
29+
SQLite3Memory::SQLite3Memory() :
30+
mnBufferLen(0),
31+
mpBuf(nullptr)
32+
{
33+
}
34+
35+
SQLite3Memory::SQLite3Memory(int nBufferLen) :
36+
mnBufferLen(nBufferLen),
37+
mpBuf(sqlite3_malloc(nBufferLen))
38+
{
39+
if (!mpBuf && mnBufferLen>0)
40+
{
41+
throw CppSQLite3Exception(CPPSQLITE_ERROR,
42+
"Cannot allocate memory",
43+
DONT_DELETE_MSG);
44+
}
45+
}
46+
47+
SQLite3Memory::SQLite3Memory(const char* szFormat, va_list list) :
48+
mnBufferLen(0),
49+
mpBuf(sqlite3_vmprintf(szFormat, list))
50+
{
51+
if (!mpBuf)
52+
{
53+
throw CppSQLite3Exception(CPPSQLITE_ERROR,
54+
"Cannot allocate memory",
55+
DONT_DELETE_MSG);
56+
}
57+
mnBufferLen = std::strlen(static_cast<char const*>(mpBuf))+1;
58+
}
59+
60+
SQLite3Memory::~SQLite3Memory()
61+
{
62+
clear();
63+
}
64+
65+
SQLite3Memory::SQLite3Memory(SQLite3Memory const& other) :
66+
mnBufferLen(other.mnBufferLen),
67+
mpBuf(sqlite3_malloc(other.mnBufferLen))
68+
{
69+
if (!mpBuf && mnBufferLen>0)
70+
{
71+
throw CppSQLite3Exception(CPPSQLITE_ERROR,
72+
"Cannot allocate memory",
73+
DONT_DELETE_MSG);
74+
}
75+
std::memcpy(mpBuf, other.mpBuf, mnBufferLen);
76+
}
77+
78+
SQLite3Memory& SQLite3Memory::operator=(SQLite3Memory const& lhs)
79+
{
80+
SQLite3Memory tmp(lhs);
81+
swap(tmp);
82+
return *this;
83+
}
84+
85+
SQLite3Memory::SQLite3Memory(SQLite3Memory&& other) :
86+
mnBufferLen(other.mnBufferLen),
87+
mpBuf(other.mpBuf)
88+
{
89+
other.mnBufferLen = 0;
90+
other.mpBuf = nullptr;
91+
}
92+
93+
SQLite3Memory& SQLite3Memory::operator=(SQLite3Memory&& lhs)
94+
{
95+
swap(lhs);
96+
return *this;
97+
}
98+
99+
void SQLite3Memory::swap(SQLite3Memory& other)
100+
{
101+
std::swap(mnBufferLen, other.mnBufferLen);
102+
std::swap(mpBuf, other.mpBuf);
103+
}
104+
105+
void SQLite3Memory::clear()
106+
{
107+
sqlite3_free(mpBuf);
108+
mpBuf = nullptr;
109+
mnBufferLen = 0;
110+
}
111+
112+
}
113+
25114
////////////////////////////////////////////////////////////////////////////////
26115

27116
CppSQLite3Exception::CppSQLite3Exception(const int nErrCode,
@@ -40,7 +129,7 @@ CppSQLite3Exception::CppSQLite3Exception(const int nErrCode,
40129
}
41130
}
42131

43-
132+
44133
CppSQLite3Exception::CppSQLite3Exception(const CppSQLite3Exception& e) :
45134
mnErrCode(e.mnErrCode)
46135
{
@@ -995,7 +1084,7 @@ void CppSQLite3Statement::bind(int nParam, const long long nValue)
9951084
{
9961085
checkVM();
9971086
int nRes = sqlite3_bind_int64(mpVM, nParam, nValue);
998-
1087+
9991088
if (nRes != SQLITE_OK)
10001089
{
10011090
throw CppSQLite3Exception(nRes,
@@ -1033,7 +1122,7 @@ void CppSQLite3Statement::bind(int nParam, const unsigned char* blobValue, int n
10331122
}
10341123
}
10351124

1036-
1125+
10371126
void CppSQLite3Statement::bindNull(int nParam)
10381127
{
10391128
checkVM();
@@ -1303,7 +1392,7 @@ sqlite3_stmt* CppSQLite3DB::compile(const char* szSQL)
13031392

13041393
////////////////////////////////////////////////////////////////////////////////
13051394
// SQLite encode.c reproduced here, containing implementation notes and source
1306-
// for sqlite3_encode_binary() and sqlite3_decode_binary()
1395+
// for sqlite3_encode_binary() and sqlite3_decode_binary()
13071396
////////////////////////////////////////////////////////////////////////////////
13081397

13091398
/*
@@ -1350,7 +1439,7 @@ sqlite3_stmt* CppSQLite3DB::compile(const char* szSQL)
13501439
** We would prefer to keep the size of the encoded string smaller than
13511440
** this.
13521441
**
1353-
** To minimize the encoding size, we first add a fixed offset value to each
1442+
** To minimize the encoding size, we first add a fixed offset value to each
13541443
** byte in the sequence. The addition is modulo 256. (That is to say, if
13551444
** the sum of the original character value and the offset exceeds 256, then
13561445
** the higher order bits are truncated.) The offset is chosen to minimize
@@ -1359,7 +1448,7 @@ sqlite3_stmt* CppSQLite3DB::compile(const char* szSQL)
13591448
** characters, the offset might be 0x01. Each of the 0x27 characters would
13601449
** then be converted into an 0x28 character which would not need to be
13611450
** escaped at all and so the 100 character input string would be converted
1362-
** into just 100 characters of output. Actually 101 characters of output -
1451+
** into just 100 characters of output. Actually 101 characters of output -
13631452
** we have to record the offset used as the first byte in the sequence so
13641453
** that the string can be decoded. Since the offset value is stored as
13651454
** part of the output string and the output string is not allowed to contain
@@ -1382,7 +1471,7 @@ sqlite3_stmt* CppSQLite3DB::compile(const char* szSQL)
13821471
**
13831472
** Decoding is obvious:
13841473
**
1385-
** (5) Copy encoded characters except the first into the decode
1474+
** (5) Copy encoded characters except the first into the decode
13861475
** buffer. Set the first encoded character aside for use as
13871476
** the offset in step 7 below.
13881477
**
@@ -1408,7 +1497,7 @@ sqlite3_stmt* CppSQLite3DB::compile(const char* szSQL)
14081497

14091498
/*
14101499
** Encode a binary buffer "in" of size n bytes so that it contains
1411-
** no instances of characters '\'' or '\000'. The output is
1500+
** no instances of characters '\'' or '\000'. The output is
14121501
** null-terminated and can be used as a string value in an INSERT
14131502
** or UPDATE statement. Use sqlite3_decode_binary() to convert the
14141503
** string back into its original binary.

CppSQLite3.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,51 @@
1414

1515
#define CPPSQLITE_ERROR 1000
1616

17+
namespace detail
18+
{
19+
/**
20+
* RAII class for managing memory allocated by sqlite
21+
*/
22+
class SQLite3Memory
23+
{
24+
public:
25+
26+
// Default constructor
27+
SQLite3Memory();
28+
// Constructor that allocates memory of a given size
29+
SQLite3Memory(int nBufferLen);
30+
// Constructor that formats a string with sqlite memory allocation
31+
SQLite3Memory(const char* szFormat, va_list list);
32+
// Destructor
33+
~SQLite3Memory();
34+
35+
// Copy constructor
36+
SQLite3Memory(SQLite3Memory const& other);
37+
// Copy assignment
38+
SQLite3Memory& operator=(SQLite3Memory const& lhs);
39+
40+
// Move constructor
41+
SQLite3Memory(SQLite3Memory&& other);
42+
// Move assignment
43+
SQLite3Memory& operator=(SQLite3Memory&& lhs);
44+
45+
// Swap operation
46+
void swap(SQLite3Memory& other);
47+
48+
int getLength() const { return mnBufferLen; }
49+
50+
void* getBuffer() const { return mpBuf; }
51+
52+
void clear();
53+
54+
private:
55+
56+
int mnBufferLen;
57+
void* mpBuf;
58+
};
59+
}
60+
61+
1762
class CppSQLite3Exception
1863
{
1964
public:

0 commit comments

Comments
 (0)