Windows is a nightmare.
This commit is contained in:
parent
138bf8267b
commit
67d4a1ebce
144
Arena.cc
144
Arena.cc
|
@ -13,10 +13,8 @@
|
||||||
|
|
||||||
#define PROT_RW (PROT_WRITE|PROT_READ)
|
#define PROT_RW (PROT_WRITE|PROT_READ)
|
||||||
#elif defined(__WIN64__) || defined(__WIN32__) || defined(WIN32)
|
#elif defined(__WIN64__) || defined(__WIN32__) || defined(WIN32)
|
||||||
#include <Windows.h>
|
#include "WinHelpers.h"
|
||||||
#include <winbase.h>
|
#pragma comment(lib, "advapi32.lib")
|
||||||
#include <fileapi.h>
|
|
||||||
#include <strsafe.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <ios>
|
#include <ios>
|
||||||
|
@ -136,73 +134,35 @@ Arena::Create(const char *path, size_t fileSize)
|
||||||
return this->Open(path);
|
return this->Open(path);
|
||||||
}
|
}
|
||||||
#elif defined(__WIN64__) || defined(__WIN32__) || defined(WIN32)
|
#elif defined(__WIN64__) || defined(__WIN32__) || defined(WIN32)
|
||||||
static void
|
|
||||||
displayWinErr(LPTSTR lpszFunction)
|
|
||||||
{
|
|
||||||
// Retrieve the system error message for the last-error code
|
|
||||||
|
|
||||||
LPVOID lpMsgBuf;
|
|
||||||
LPVOID lpDisplayBuf;
|
|
||||||
DWORD dw = GetLastError();
|
|
||||||
|
|
||||||
FormatMessage(
|
|
||||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
|
||||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
|
||||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
||||||
NULL,
|
|
||||||
dw,
|
|
||||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
||||||
(LPTSTR) &lpMsgBuf,
|
|
||||||
0, NULL );
|
|
||||||
|
|
||||||
// Display the error message and exit the process
|
|
||||||
|
|
||||||
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
|
|
||||||
(lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR));
|
|
||||||
StringCchPrintf((LPTSTR)lpDisplayBuf,
|
|
||||||
LocalSize(lpDisplayBuf) / sizeof(TCHAR),
|
|
||||||
TEXT("%s failed with error %d: %s"),
|
|
||||||
lpszFunction, dw, lpMsgBuf);
|
|
||||||
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
|
|
||||||
|
|
||||||
LocalFree(lpMsgBuf);
|
|
||||||
LocalFree(lpDisplayBuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
Arena::Open(const char *path)
|
Arena::Open(const char *path)
|
||||||
{
|
{
|
||||||
HANDLE fHandle;
|
HANDLE fHandle;
|
||||||
DWORD fRead = 0;
|
DWORD fRead = 0;
|
||||||
size_t fSize;
|
size_t fSize;
|
||||||
size_t fRemaining;
|
size_t fRemaining;
|
||||||
auto *cursor = this->store;
|
auto *cursor = this->store;
|
||||||
OVERLAPPED overlap = {0};
|
OVERLAPPED overlap = {0};
|
||||||
|
|
||||||
fHandle = CreateFileA(
|
fHandle = CreateFileA(
|
||||||
(LPSTR)path,
|
(LPSTR) path,
|
||||||
GENERIC_READ,
|
GENERIC_READ,
|
||||||
(FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE),
|
(FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE),
|
||||||
NULL,
|
NULL,
|
||||||
OPEN_ALWAYS,
|
OPEN_ALWAYS,
|
||||||
FILE_ATTRIBUTE_NORMAL,
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
NULL);
|
NULL);
|
||||||
if (fHandle == INVALID_HANDLE_VALUE) {
|
if (fHandle == INVALID_HANDLE_VALUE) {
|
||||||
displayWinErr("CreateFileA");
|
return Windows::DisplayWinError("CreateFileA", NULL);
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SetFilePointer(fHandle, 0, 0, FILE_BEGIN) != 0) {
|
if (SetFilePointer(fHandle, 0, 0, FILE_BEGIN) != 0) {
|
||||||
displayWinErr("SetFilePointer");
|
return Windows::DisplayWinError("SetFilePointer", fHandle);
|
||||||
CloseHandle(fHandle);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetFileSizeEx(fHandle, reinterpret_cast<PLARGE_INTEGER>(&fSize)) != TRUE) {
|
if (GetFileSizeEx(fHandle, reinterpret_cast<PLARGE_INTEGER>(&fSize)) !=
|
||||||
displayWinErr("GetFileSizeEx");
|
TRUE) {
|
||||||
CloseHandle(fHandle);
|
return Windows::DisplayWinError("GetFileSizeEx", fHandle);
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this->SetAlloc(fSize);
|
this->SetAlloc(fSize);
|
||||||
|
@ -212,15 +172,14 @@ Arena::Open(const char *path)
|
||||||
fRemaining = fSize;
|
fRemaining = fSize;
|
||||||
while (fRemaining != 0) {
|
while (fRemaining != 0) {
|
||||||
overlap.Offset = (fSize - fRemaining);
|
overlap.Offset = (fSize - fRemaining);
|
||||||
if (ReadFile(fHandle, cursor, fSize-1,
|
if (ReadFile(fHandle, cursor, fSize - 1,
|
||||||
&fRead,
|
&fRead,
|
||||||
&overlap) != TRUE) {
|
&overlap) != TRUE) {
|
||||||
auto errorCode = GetLastError();
|
auto errorCode = GetLastError();
|
||||||
if (errorCode != ERROR_HANDLE_EOF) {
|
if (errorCode != ERROR_HANDLE_EOF) {
|
||||||
displayWinErr("ReadFile");
|
|
||||||
CloseHandle(fHandle);
|
|
||||||
this->Destroy();
|
this->Destroy();
|
||||||
return -1;
|
|
||||||
|
return Windows::DisplayWinError("ReadFile", fHandle);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -235,32 +194,15 @@ Arena::Open(const char *path)
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
Arena::Create(const char *path, size_t fileSize, DWORD mode)
|
Arena::Create(const char *path, size_t fileSize)
|
||||||
{
|
{
|
||||||
HANDLE fHandle;
|
auto errorCode = Windows::CreateFixedSizeFile(path, fileSize);
|
||||||
|
if (errorCode != 0) {
|
||||||
fHandle = CreateFileA(
|
return errorCode;
|
||||||
(LPSTR)path,
|
|
||||||
GENERIC_READ|GENERIC_WRITE,
|
|
||||||
mode,
|
|
||||||
NULL,
|
|
||||||
CREATE_ALWAYS,
|
|
||||||
FILE_ATTRIBUTE_NORMAL,
|
|
||||||
NULL);
|
|
||||||
if (fHandle == INVALID_HANDLE_VALUE) {
|
|
||||||
displayWinErr("Create::CreateFileA");
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SetFileValidData(fHandle, fileSize) != fileSize) {
|
|
||||||
displayWinErr("SetFileValidData");
|
|
||||||
CloseHandle(fHandle);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
CloseHandle(fHandle);
|
|
||||||
return this->Open(path);
|
return this->Open(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -308,18 +250,18 @@ Arena::Destroy()
|
||||||
delete this->store;
|
delete this->store;
|
||||||
break;
|
break;
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
case ArenaType::MemoryMapped:
|
case ArenaType::MemoryMapped:
|
||||||
if (munmap(this->store, this->size) == -1) {
|
if (munmap(this->store, this->size) == -1) {
|
||||||
abort();
|
abort();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (close(this->fd) == -1) {
|
if (close(this->fd) == -1) {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
this->fd = 0;
|
this->fd = 0;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
#if defined(NDEBUG)
|
#if defined(NDEBUG)
|
||||||
|
@ -342,7 +284,7 @@ operator<<(std::ostream &os, Arena &arena)
|
||||||
auto cursor = arena.NewCursor();
|
auto cursor = arena.NewCursor();
|
||||||
char cursorString[33] = {0};
|
char cursorString[33] = {0};
|
||||||
snprintf(cursorString, 32, "%#016llx",
|
snprintf(cursorString, 32, "%#016llx",
|
||||||
(long long unsigned int)cursor);
|
(long long unsigned int) cursor);
|
||||||
|
|
||||||
os << "Arena<";
|
os << "Arena<";
|
||||||
switch (arena.Type()) {
|
switch (arena.Type()) {
|
||||||
|
@ -356,9 +298,9 @@ operator<<(std::ostream &os, Arena &arena)
|
||||||
os << "allocated";
|
os << "allocated";
|
||||||
break;
|
break;
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
case ArenaType::MemoryMapped:
|
case ArenaType::MemoryMapped:
|
||||||
os << "mmap/file";
|
os << "mmap/file";
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
os << "unknown (this is a bug)";
|
os << "unknown (this is a bug)";
|
||||||
|
@ -384,7 +326,7 @@ Arena::Write(const char *path)
|
||||||
arenaFile = fopen(path, "w");
|
arenaFile = fopen(path, "w");
|
||||||
if (arenaFile == nullptr) {
|
if (arenaFile == nullptr) {
|
||||||
#else
|
#else
|
||||||
if (fopen_s(&arenaFile, path, "w") != 0) {
|
if (fopen_s(&arenaFile, path, "w") != 0) {
|
||||||
#endif
|
#endif
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -404,14 +346,14 @@ Arena::Write(const char *path)
|
||||||
uint8_t &
|
uint8_t &
|
||||||
Arena::operator[](size_t index)
|
Arena::operator[](size_t index)
|
||||||
{
|
{
|
||||||
if (index > this->size) {
|
if (index > this->size) {
|
||||||
#if defined(DESKTOP_BUILD) and !defined(KLIB_NO_ASSERT)
|
#if defined(DESKTOP_BUILD) and !defined(KLIB_NO_ASSERT)
|
||||||
throw std::range_error("index out of range");
|
throw std::range_error("index out of range");
|
||||||
#else
|
#else
|
||||||
abort();
|
abort();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
return this->store[index];
|
return this->store[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
2
Arena.h
2
Arena.h
|
@ -116,7 +116,7 @@ public:
|
||||||
int Create(const char *path, size_t fileSize);
|
int Create(const char *path, size_t fileSize);
|
||||||
#elif defined(__WIN64__) || defined(__WIN32__) || defined(WIN32)
|
#elif defined(__WIN64__) || defined(__WIN32__) || defined(WIN32)
|
||||||
|
|
||||||
int Create(const char *path, size_t fileSize, DWORD mode);
|
int Create(const char *path, size_t fileSize);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
/// Open reads a file into the arena; the file must already exist. On
|
/// Open reads a file into the arena; the file must already exist. On
|
||||||
|
|
|
@ -26,7 +26,8 @@ set(HEADER_FILES
|
||||||
Dictionary.h
|
Dictionary.h
|
||||||
Exceptions.h
|
Exceptions.h
|
||||||
Test.h
|
Test.h
|
||||||
TLV.h)
|
TLV.h
|
||||||
|
WinHelpers.h)
|
||||||
|
|
||||||
set(SOURCE_FILES
|
set(SOURCE_FILES
|
||||||
Arena.cc
|
Arena.cc
|
||||||
|
@ -36,7 +37,8 @@ set(SOURCE_FILES
|
||||||
Test.cc
|
Test.cc
|
||||||
TLV.cc
|
TLV.cc
|
||||||
Commander.cpp
|
Commander.cpp
|
||||||
Commander.h)
|
Commander.h
|
||||||
|
WinHelpers.cpp)
|
||||||
|
|
||||||
add_library(klib STATIC ${SOURCE_FILES} ${HEADER_FILES})
|
add_library(klib STATIC ${SOURCE_FILES} ${HEADER_FILES})
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,142 @@
|
||||||
|
//
|
||||||
|
// Created by kyle on 2023-10-10.
|
||||||
|
//
|
||||||
|
|
||||||
|
#if defined(__WIN64__) || defined(__WIN32__) || defined(WIN32)
|
||||||
|
|
||||||
|
#include "WinHelpers.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace klib {
|
||||||
|
namespace Windows {
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
DisplayWinError(LPTSTR lpszFunction, HANDLE handle)
|
||||||
|
{
|
||||||
|
// Retrieve the system error message for the last-error code
|
||||||
|
DWORD dw = GetLastError();
|
||||||
|
#ifndef NDEBUG
|
||||||
|
LPVOID lpMsgBuf;
|
||||||
|
LPVOID lpDisplayBuf;
|
||||||
|
|
||||||
|
FormatMessage(
|
||||||
|
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||||
|
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||||
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
|
NULL,
|
||||||
|
dw,
|
||||||
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
|
(LPTSTR) &lpMsgBuf,
|
||||||
|
0, NULL);
|
||||||
|
|
||||||
|
// Display the error message and exit the process
|
||||||
|
lpDisplayBuf = (LPVOID) LocalAlloc(LMEM_ZEROINIT,
|
||||||
|
(lstrlen((LPCTSTR) lpMsgBuf) +
|
||||||
|
lstrlen((LPCTSTR) lpszFunction) +
|
||||||
|
40) * sizeof(TCHAR));
|
||||||
|
StringCchPrintf((LPTSTR) lpDisplayBuf,
|
||||||
|
LocalSize(lpDisplayBuf) / sizeof(TCHAR),
|
||||||
|
TEXT("%s failed with error %d: %s"),
|
||||||
|
lpszFunction, dw, lpMsgBuf);
|
||||||
|
MessageBox(NULL, (LPCTSTR) lpDisplayBuf, TEXT("Error"), MB_OK);
|
||||||
|
|
||||||
|
LocalFree(lpMsgBuf);
|
||||||
|
LocalFree(lpDisplayBuf);
|
||||||
|
#endif
|
||||||
|
if ((handle != NULL) && (handle != INVALID_HANDLE_VALUE)) {
|
||||||
|
CloseHandle(handle);
|
||||||
|
}
|
||||||
|
return dw;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOL SetPrivilege(
|
||||||
|
HANDLE hToken, // access token handle
|
||||||
|
LPCTSTR lpszPrivilege, // name of privilege to enable/disable
|
||||||
|
BOOL bEnablePrivilege // to enable or disable privilege
|
||||||
|
)
|
||||||
|
{
|
||||||
|
TOKEN_PRIVILEGES tp;
|
||||||
|
LUID luid;
|
||||||
|
|
||||||
|
if (!LookupPrivilegeValue(
|
||||||
|
NULL, // lookup privilege on local system
|
||||||
|
lpszPrivilege, // privilege to lookup
|
||||||
|
&luid)) // receives LUID of privilege
|
||||||
|
{
|
||||||
|
printf("LookupPrivilegeValue error: %u\n", GetLastError());
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
tp.PrivilegeCount = 1;
|
||||||
|
tp.Privileges[0].Luid = luid;
|
||||||
|
if (bEnablePrivilege)
|
||||||
|
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||||
|
else
|
||||||
|
tp.Privileges[0].Attributes = 0;
|
||||||
|
|
||||||
|
// Enable the privilege or disable all privileges.
|
||||||
|
|
||||||
|
if (!AdjustTokenPrivileges(
|
||||||
|
hToken,
|
||||||
|
FALSE,
|
||||||
|
&tp,
|
||||||
|
sizeof(TOKEN_PRIVILEGES),
|
||||||
|
(PTOKEN_PRIVILEGES) NULL,
|
||||||
|
(PDWORD) NULL)) {
|
||||||
|
printf("AdjustTokenPrivileges error: %u\n", GetLastError());
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) {
|
||||||
|
printf("The token does not have the specified privilege. \n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HANDLE
|
||||||
|
CreateFileWindows(const char *path)
|
||||||
|
{
|
||||||
|
HANDLE fHandle;
|
||||||
|
|
||||||
|
return CreateFileA(
|
||||||
|
(LPSTR) path,
|
||||||
|
(GENERIC_READ | GENERIC_WRITE),
|
||||||
|
(FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE),
|
||||||
|
NULL,
|
||||||
|
CREATE_ALWAYS,
|
||||||
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
CreateFixedSizeFile(const char *path, size_t size)
|
||||||
|
{
|
||||||
|
_LARGE_INTEGER fileSize;
|
||||||
|
|
||||||
|
fileSize.QuadPart = size;
|
||||||
|
|
||||||
|
HANDLE fHandle = CreateFileWindows(path);
|
||||||
|
if (SetFilePointerEx(fHandle, fileSize, nullptr, FILE_BEGIN) != TRUE) {
|
||||||
|
return DisplayWinError("SetFilePointerEx", fHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SetEndOfFile(fHandle) != TRUE) {
|
||||||
|
return DisplayWinError("SetEndOfFile", fHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseHandle(fHandle);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace Windows
|
||||||
|
} // namespace klib
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,39 @@
|
||||||
|
//
|
||||||
|
// Created by kyle on 2023-10-10.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef KLIB_WINHELPERS_H
|
||||||
|
#define KLIB_WINHELPERS_H
|
||||||
|
|
||||||
|
#if defined(__WIN64__) || defined(__WIN32__) || defined(WIN32)
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <winbase.h>
|
||||||
|
#include <fileapi.h>
|
||||||
|
#include <strsafe.h>
|
||||||
|
|
||||||
|
namespace klib {
|
||||||
|
namespace Windows {
|
||||||
|
|
||||||
|
|
||||||
|
int DisplayWinError(LPTSTR lpszFunction, HANDLE handle);
|
||||||
|
|
||||||
|
BOOL SetPrivilege(
|
||||||
|
HANDLE hToken, // access token handle
|
||||||
|
LPCTSTR lpszPrivilege, // name of privilege to enable/disable
|
||||||
|
BOOL bEnablePrivilege // to enable or disable privilege
|
||||||
|
);
|
||||||
|
|
||||||
|
HANDLE CreateFileWindows(const char *path);
|
||||||
|
|
||||||
|
int CreateFixedSizeFile(const char *path, size_t size);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace Windows
|
||||||
|
} // namespace klib
|
||||||
|
|
||||||
|
#endif // Windows-only guards.
|
||||||
|
|
||||||
|
#endif //KLIB_WINHELPERS_H
|
|
@ -16,43 +16,43 @@ main(int argc, char *argv[])
|
||||||
Buffer goodbyeWorld("goodbye, world");
|
Buffer goodbyeWorld("goodbye, world");
|
||||||
Buffer goodbyeCruelWorld("goodbye, cruel world");
|
Buffer goodbyeCruelWorld("goodbye, cruel world");
|
||||||
|
|
||||||
std::cout << buffer << std::endl;
|
std::cout << buffer << "\n";
|
||||||
|
|
||||||
buffer.Insert(1, (uint8_t *) "el", 2);
|
buffer.Insert(1, (uint8_t *) "el", 2);
|
||||||
buffer.Append('!');
|
buffer.Append('!');
|
||||||
assert(buffer == helloWorld);
|
assert(buffer == helloWorld);
|
||||||
|
|
||||||
std::cout << buffer << std::endl;
|
std::cout << buffer << "\n";
|
||||||
|
|
||||||
buffer.Remove(buffer.Length() - 1);
|
buffer.Remove(buffer.Length() - 1);
|
||||||
std::cout << buffer << std::endl;
|
std::cout << buffer << "\n";
|
||||||
buffer.Remove(0, 5);
|
buffer.Remove(0, 5);
|
||||||
std::cout << buffer << std::endl;
|
std::cout << buffer << "\n";
|
||||||
buffer.Insert(0, 'g');
|
buffer.Insert(0, 'g');
|
||||||
std::cout << buffer << std::endl;
|
std::cout << buffer << "\n";
|
||||||
buffer.Insert(1, (uint8_t *) "oodbye", 6);
|
buffer.Insert(1, (uint8_t *) "oodbye", 6);
|
||||||
std::cout << buffer << std::endl;
|
std::cout << buffer << "\n";
|
||||||
assert(buffer == goodbyeWorld);
|
assert(buffer == goodbyeWorld);
|
||||||
buffer.Insert(9, (uint8_t *)"cruel ", 6);
|
buffer.Insert(9, (uint8_t *)"cruel ", 6);
|
||||||
|
|
||||||
std::cout << buffer << std::endl;
|
std::cout << buffer << "\n";
|
||||||
buffer.HexDump(std::cout);
|
buffer.HexDump(std::cout);
|
||||||
|
|
||||||
buffer.Reclaim();
|
buffer.Reclaim();
|
||||||
buffer.Append("and now for something completely different...");
|
buffer.Append("and now for something completely different...");
|
||||||
|
|
||||||
std::cout << buffer.Contents() << std::endl;
|
std::cout << buffer.Contents() << "\n";
|
||||||
std::cout << "Length: " << buffer.Length() << ", capacity " << buffer.Capacity() << std::endl;
|
std::cout << "Length: " << buffer.Length() << ", capacity " << buffer.Capacity() << "\n";
|
||||||
buffer.Resize(128);
|
buffer.Resize(128);
|
||||||
std::cout << "Length: " << buffer.Length() << ", capacity " << buffer.Capacity() << std::endl;
|
std::cout << "Length: " << buffer.Length() << ", capacity " << buffer.Capacity() << "\n";
|
||||||
buffer.Trim();
|
buffer.Trim();
|
||||||
std::cout << "Length: " << buffer.Length() << ", capacity " << buffer.Capacity() << std::endl;
|
std::cout << "Length: " << buffer.Length() << ", capacity " << buffer.Capacity() << "\n";
|
||||||
|
|
||||||
Buffer buffer2("and now for something completely different...");
|
Buffer buffer2("and now for something completely different...");
|
||||||
assert(buffer == buffer2);
|
assert(buffer == buffer2);
|
||||||
|
|
||||||
buffer2.Remove(buffer2.Length()-3, 3);
|
buffer2.Remove(buffer2.Length()-3, 3);
|
||||||
std::cout << buffer << std::endl;
|
std::cout << buffer << "\n";
|
||||||
assert(buffer != buffer2);
|
assert(buffer != buffer2);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -26,7 +26,7 @@ testSetKV(Dictionary &pb, const char *k, uint8_t kl, const char *v,
|
||||||
uint8_t vl)
|
uint8_t vl)
|
||||||
{
|
{
|
||||||
bool ok;
|
bool ok;
|
||||||
std::cout << "test Set " << k << "->" << v << std::endl;
|
std::cout << "test Set " << k << "->" << v << "\n";
|
||||||
ok = pb.Set(k, kl, v, vl) == 0;
|
ok = pb.Set(k, kl, v, vl) == 0;
|
||||||
std::cout << "\tSet complete\n";
|
std::cout << "\tSet complete\n";
|
||||||
return ok;
|
return ok;
|
||||||
|
@ -42,7 +42,7 @@ main(int argc, const char *argv[])
|
||||||
TLV::Record value;
|
TLV::Record value;
|
||||||
TLV::Record expect;
|
TLV::Record expect;
|
||||||
|
|
||||||
std::cout << "TESTPROG: " << argv[0] << std::endl;
|
std::cout << "TESTPROG: " << argv[0] << "\n";
|
||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
if (arena.Create(ARENA_FILE, ARENA_SIZE) == -1) {
|
if (arena.Create(ARENA_FILE, ARENA_SIZE) == -1) {
|
||||||
|
@ -53,7 +53,7 @@ main(int argc, const char *argv[])
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
std::cout << arena << std::endl;
|
std::cout << arena << "\n";
|
||||||
TLV::SetRecord(expect, DICTIONARY_TAG_VAL, TEST_KVSTRLEN3, TEST_KVSTR3);
|
TLV::SetRecord(expect, DICTIONARY_TAG_VAL, TEST_KVSTRLEN3, TEST_KVSTR3);
|
||||||
|
|
||||||
Dictionary dict(arena);
|
Dictionary dict(arena);
|
||||||
|
@ -73,17 +73,17 @@ main(int argc, const char *argv[])
|
||||||
|
|
||||||
assert(cmpRecord(value, expect));
|
assert(cmpRecord(value, expect));
|
||||||
|
|
||||||
std::cout << "test overwriting key" << std::endl;
|
std::cout << "test overwriting key" << "\n";
|
||||||
assert(testSetKV(dict, TEST_KVSTR2, TEST_KVSTRLEN2, TEST_KVSTR6,
|
assert(testSetKV(dict, TEST_KVSTR2, TEST_KVSTRLEN2, TEST_KVSTR6,
|
||||||
TEST_KVSTRLEN6));
|
TEST_KVSTRLEN6));
|
||||||
std::cout << dict;
|
std::cout << dict;
|
||||||
TLV::SetRecord(expect, DICTIONARY_TAG_VAL, TEST_KVSTRLEN6, TEST_KVSTR6);
|
TLV::SetRecord(expect, DICTIONARY_TAG_VAL, TEST_KVSTRLEN6, TEST_KVSTR6);
|
||||||
std::cout << "\tlookup" << std::endl;
|
std::cout << "\tlookup" << "\n";
|
||||||
assert(dict.Lookup(TEST_KVSTR2, TEST_KVSTRLEN2, value));
|
assert(dict.Lookup(TEST_KVSTR2, TEST_KVSTRLEN2, value));
|
||||||
std::cout << "\tcompare records" << std::endl;
|
std::cout << "\tcompare records" << "\n";
|
||||||
assert(cmpRecord(value, expect));
|
assert(cmpRecord(value, expect));
|
||||||
|
|
||||||
std::cout << "\tadd new key to dictionary" << std::endl;
|
std::cout << "\tadd new key to dictionary" << "\n";
|
||||||
assert(testSetKV(dict, TEST_KVSTR3, TEST_KVSTRLEN3, TEST_KVSTR5,
|
assert(testSetKV(dict, TEST_KVSTR3, TEST_KVSTRLEN3, TEST_KVSTR5,
|
||||||
TEST_KVSTRLEN5));
|
TEST_KVSTRLEN5));
|
||||||
std::cout << dict;
|
std::cout << dict;
|
||||||
|
@ -92,7 +92,7 @@ main(int argc, const char *argv[])
|
||||||
assert(dict.Lookup(TEST_KVSTR4, TEST_KVSTRLEN4, value));
|
assert(dict.Lookup(TEST_KVSTR4, TEST_KVSTRLEN4, value));
|
||||||
assert(cmpRecord(value, expect));
|
assert(cmpRecord(value, expect));
|
||||||
|
|
||||||
std::cout << "OK" <<std::endl;
|
std::cout << "OK" <<"\n";
|
||||||
|
|
||||||
// Dump the generated arena for inspection later.
|
// Dump the generated arena for inspection later.
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
|
|
30
tlvTest.cc
30
tlvTest.cc
|
@ -21,29 +21,29 @@ tlvTestSuite(Arena &backend)
|
||||||
TLV::Record rec1, rec2, rec3, rec4;
|
TLV::Record rec1, rec2, rec3, rec4;
|
||||||
uint8_t *cursor = nullptr;
|
uint8_t *cursor = nullptr;
|
||||||
|
|
||||||
std::cout << "\tSetting first three records." << std::endl;
|
std::cout << "\tSetting first three records." << "\n";
|
||||||
TLV::SetRecord(rec1, 1, TEST_STRLEN1, TEST_STR1);
|
TLV::SetRecord(rec1, 1, TEST_STRLEN1, TEST_STR1);
|
||||||
TLV::SetRecord(rec2, 2, TEST_STRLEN2, TEST_STR2);
|
TLV::SetRecord(rec2, 2, TEST_STRLEN2, TEST_STR2);
|
||||||
TLV::SetRecord(rec3, 1, TEST_STRLEN4, TEST_STR4);
|
TLV::SetRecord(rec3, 1, TEST_STRLEN4, TEST_STR4);
|
||||||
rec4.Tag = 1;
|
rec4.Tag = 1;
|
||||||
|
|
||||||
std::cout << "\twriting new rec1" << std::endl;
|
std::cout << "\twriting new rec1" << "\n";
|
||||||
assert(TLV::WriteToMemory(backend, cursor, rec1) != nullptr);
|
assert(TLV::WriteToMemory(backend, cursor, rec1) != nullptr);
|
||||||
std::cout << "\twriting new rec2" << std::endl;
|
std::cout << "\twriting new rec2" << "\n";
|
||||||
assert((cursor = TLV::WriteToMemory(backend, cursor, rec2)) != nullptr);
|
assert((cursor = TLV::WriteToMemory(backend, cursor, rec2)) != nullptr);
|
||||||
std::cout << "\twriting new rec3" << std::endl;
|
std::cout << "\twriting new rec3" << "\n";
|
||||||
assert(TLV::WriteToMemory(backend, cursor, rec3) != nullptr);
|
assert(TLV::WriteToMemory(backend, cursor, rec3) != nullptr);
|
||||||
cursor = nullptr;
|
cursor = nullptr;
|
||||||
|
|
||||||
// the cursor should point at the next record,
|
// the cursor should point at the next record,
|
||||||
// and rec4 should contain the same data as rec1.
|
// and rec4 should contain the same data as rec1.
|
||||||
std::cout << "\tFindTag 1" << std::endl;
|
std::cout << "\tFindTag 1" << "\n";
|
||||||
cursor = TLV::FindTag(backend, cursor, rec4);
|
cursor = TLV::FindTag(backend, cursor, rec4);
|
||||||
assert(cursor != nullptr);
|
assert(cursor != nullptr);
|
||||||
assert(cursor != backend.NewCursor());
|
assert(cursor != backend.NewCursor());
|
||||||
assert(cmpRecord(rec1, rec4));
|
assert(cmpRecord(rec1, rec4));
|
||||||
|
|
||||||
std::cout << "\tFindTag 2" << std::endl;
|
std::cout << "\tFindTag 2" << "\n";
|
||||||
cursor = TLV::FindTag(backend, cursor, rec4);
|
cursor = TLV::FindTag(backend, cursor, rec4);
|
||||||
assert(cursor != nullptr);
|
assert(cursor != nullptr);
|
||||||
assert(cmpRecord(rec3, rec4));
|
assert(cmpRecord(rec3, rec4));
|
||||||
|
@ -62,20 +62,22 @@ tlvTestSuite(Arena &backend)
|
||||||
bool
|
bool
|
||||||
runSuite(Arena &backend, const char *label)
|
runSuite(Arena &backend, const char *label)
|
||||||
{
|
{
|
||||||
std::cout << backend << std::endl;
|
std::exception exc;
|
||||||
|
|
||||||
|
std::cout << backend << "\n";
|
||||||
std::cout << "running test suite " << label << ": ";
|
std::cout << "running test suite " << label << ": ";
|
||||||
try {
|
try {
|
||||||
tlvTestSuite(backend);
|
tlvTestSuite(backend);
|
||||||
} catch (std::exception &exc){
|
} catch (std::exception &exc){
|
||||||
std::cout << "FAILED" << std::endl;
|
std::cout << "FAILED: " << exc.what() << "\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::cout << "OK" << std::endl;
|
std::cout << "OK" << "\n";
|
||||||
|
|
||||||
std::cout << "\tdestroying arena: ";
|
std::cout << "\tdestroying arena: ";
|
||||||
backend.Destroy();
|
backend.Destroy();
|
||||||
|
|
||||||
std::cout << "OK" << std::endl;
|
std::cout << "OK" << "\n";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +90,7 @@ main(int argc, const char *argv[])
|
||||||
Arena arenaStatic;
|
Arena arenaStatic;
|
||||||
Arena arenaMem;
|
Arena arenaMem;
|
||||||
|
|
||||||
std::cout << "TESTPROG: " << argv[0] << std::endl;
|
std::cout << "TESTPROG: " << argv[0] << "\n";
|
||||||
|
|
||||||
if (-1 == arenaStatic.SetStatic(arenaBuffer, ARENA_SIZE)) {
|
if (-1 == arenaStatic.SetStatic(arenaBuffer, ARENA_SIZE)) {
|
||||||
abort();
|
abort();
|
||||||
|
@ -98,8 +100,10 @@ main(int argc, const char *argv[])
|
||||||
arenaStatic.Clear();
|
arenaStatic.Clear();
|
||||||
|
|
||||||
Arena arenaFile;
|
Arena arenaFile;
|
||||||
|
auto status = arenaFile.Create(ARENA_FILE, ARENA_SIZE);
|
||||||
|
|
||||||
if (-1 == arenaFile.Create(ARENA_FILE, ARENA_SIZE)) {
|
if (status != 0) {
|
||||||
|
std::cerr << "Create failed with error " << status << "\n";
|
||||||
abort();
|
abort();
|
||||||
} else if (!runSuite(arenaFile, "arenaFile")) {
|
} else if (!runSuite(arenaFile, "arenaFile")) {
|
||||||
abort();
|
abort();
|
||||||
|
@ -112,6 +116,6 @@ main(int argc, const char *argv[])
|
||||||
}
|
}
|
||||||
arenaMem.Clear();
|
arenaMem.Clear();
|
||||||
|
|
||||||
std::cout << "OK" << std::endl;
|
std::cout << "OK" << "\n";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue