Windows is a nightmare.
This commit is contained in:
parent
138bf8267b
commit
67d4a1ebce
86
Arena.cc
86
Arena.cc
|
@ -13,10 +13,8 @@
|
|||
|
||||
#define PROT_RW (PROT_WRITE|PROT_READ)
|
||||
#elif defined(__WIN64__) || defined(__WIN32__) || defined(WIN32)
|
||||
#include <Windows.h>
|
||||
#include <winbase.h>
|
||||
#include <fileapi.h>
|
||||
#include <strsafe.h>
|
||||
#include "WinHelpers.h"
|
||||
#pragma comment(lib, "advapi32.lib")
|
||||
#endif
|
||||
|
||||
#include <ios>
|
||||
|
@ -136,40 +134,6 @@ Arena::Create(const char *path, size_t fileSize)
|
|||
return this->Open(path);
|
||||
}
|
||||
#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
|
||||
Arena::Open(const char *path)
|
||||
{
|
||||
|
@ -189,20 +153,16 @@ Arena::Open(const char *path)
|
|||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
if (fHandle == INVALID_HANDLE_VALUE) {
|
||||
displayWinErr("CreateFileA");
|
||||
return -1;
|
||||
return Windows::DisplayWinError("CreateFileA", NULL);
|
||||
}
|
||||
|
||||
if (SetFilePointer(fHandle, 0, 0, FILE_BEGIN) != 0) {
|
||||
displayWinErr("SetFilePointer");
|
||||
CloseHandle(fHandle);
|
||||
return -1;
|
||||
return Windows::DisplayWinError("SetFilePointer", fHandle);
|
||||
}
|
||||
|
||||
if (GetFileSizeEx(fHandle, reinterpret_cast<PLARGE_INTEGER>(&fSize)) != TRUE) {
|
||||
displayWinErr("GetFileSizeEx");
|
||||
CloseHandle(fHandle);
|
||||
return -1;
|
||||
if (GetFileSizeEx(fHandle, reinterpret_cast<PLARGE_INTEGER>(&fSize)) !=
|
||||
TRUE) {
|
||||
return Windows::DisplayWinError("GetFileSizeEx", fHandle);
|
||||
}
|
||||
|
||||
this->SetAlloc(fSize);
|
||||
|
@ -217,10 +177,9 @@ Arena::Open(const char *path)
|
|||
&overlap) != TRUE) {
|
||||
auto errorCode = GetLastError();
|
||||
if (errorCode != ERROR_HANDLE_EOF) {
|
||||
displayWinErr("ReadFile");
|
||||
CloseHandle(fHandle);
|
||||
this->Destroy();
|
||||
return -1;
|
||||
|
||||
return Windows::DisplayWinError("ReadFile", fHandle);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -235,32 +194,15 @@ Arena::Open(const char *path)
|
|||
|
||||
|
||||
int
|
||||
Arena::Create(const char *path, size_t fileSize, DWORD mode)
|
||||
Arena::Create(const char *path, size_t fileSize)
|
||||
{
|
||||
HANDLE fHandle;
|
||||
|
||||
fHandle = CreateFileA(
|
||||
(LPSTR)path,
|
||||
GENERIC_READ|GENERIC_WRITE,
|
||||
mode,
|
||||
NULL,
|
||||
CREATE_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
if (fHandle == INVALID_HANDLE_VALUE) {
|
||||
displayWinErr("Create::CreateFileA");
|
||||
return -1;
|
||||
auto errorCode = Windows::CreateFixedSizeFile(path, fileSize);
|
||||
if (errorCode != 0) {
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
if (SetFileValidData(fHandle, fileSize) != fileSize) {
|
||||
displayWinErr("SetFileValidData");
|
||||
CloseHandle(fHandle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
CloseHandle(fHandle);
|
||||
return this->Open(path);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
bool
|
||||
|
|
2
Arena.h
2
Arena.h
|
@ -116,7 +116,7 @@ public:
|
|||
int Create(const char *path, size_t fileSize);
|
||||
#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
|
||||
/// Open reads a file into the arena; the file must already exist. On
|
||||
|
|
|
@ -26,7 +26,8 @@ set(HEADER_FILES
|
|||
Dictionary.h
|
||||
Exceptions.h
|
||||
Test.h
|
||||
TLV.h)
|
||||
TLV.h
|
||||
WinHelpers.h)
|
||||
|
||||
set(SOURCE_FILES
|
||||
Arena.cc
|
||||
|
@ -36,7 +37,8 @@ set(SOURCE_FILES
|
|||
Test.cc
|
||||
TLV.cc
|
||||
Commander.cpp
|
||||
Commander.h)
|
||||
Commander.h
|
||||
WinHelpers.cpp)
|
||||
|
||||
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 goodbyeCruelWorld("goodbye, cruel world");
|
||||
|
||||
std::cout << buffer << std::endl;
|
||||
std::cout << buffer << "\n";
|
||||
|
||||
buffer.Insert(1, (uint8_t *) "el", 2);
|
||||
buffer.Append('!');
|
||||
assert(buffer == helloWorld);
|
||||
|
||||
std::cout << buffer << std::endl;
|
||||
std::cout << buffer << "\n";
|
||||
|
||||
buffer.Remove(buffer.Length() - 1);
|
||||
std::cout << buffer << std::endl;
|
||||
std::cout << buffer << "\n";
|
||||
buffer.Remove(0, 5);
|
||||
std::cout << buffer << std::endl;
|
||||
std::cout << buffer << "\n";
|
||||
buffer.Insert(0, 'g');
|
||||
std::cout << buffer << std::endl;
|
||||
std::cout << buffer << "\n";
|
||||
buffer.Insert(1, (uint8_t *) "oodbye", 6);
|
||||
std::cout << buffer << std::endl;
|
||||
std::cout << buffer << "\n";
|
||||
assert(buffer == goodbyeWorld);
|
||||
buffer.Insert(9, (uint8_t *)"cruel ", 6);
|
||||
|
||||
std::cout << buffer << std::endl;
|
||||
std::cout << buffer << "\n";
|
||||
buffer.HexDump(std::cout);
|
||||
|
||||
buffer.Reclaim();
|
||||
buffer.Append("and now for something completely different...");
|
||||
|
||||
std::cout << buffer.Contents() << std::endl;
|
||||
std::cout << "Length: " << buffer.Length() << ", capacity " << buffer.Capacity() << std::endl;
|
||||
std::cout << buffer.Contents() << "\n";
|
||||
std::cout << "Length: " << buffer.Length() << ", capacity " << buffer.Capacity() << "\n";
|
||||
buffer.Resize(128);
|
||||
std::cout << "Length: " << buffer.Length() << ", capacity " << buffer.Capacity() << std::endl;
|
||||
std::cout << "Length: " << buffer.Length() << ", capacity " << buffer.Capacity() << "\n";
|
||||
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...");
|
||||
assert(buffer == buffer2);
|
||||
|
||||
buffer2.Remove(buffer2.Length()-3, 3);
|
||||
std::cout << buffer << std::endl;
|
||||
std::cout << buffer << "\n";
|
||||
assert(buffer != buffer2);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -26,7 +26,7 @@ testSetKV(Dictionary &pb, const char *k, uint8_t kl, const char *v,
|
|||
uint8_t vl)
|
||||
{
|
||||
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;
|
||||
std::cout << "\tSet complete\n";
|
||||
return ok;
|
||||
|
@ -42,7 +42,7 @@ main(int argc, const char *argv[])
|
|||
TLV::Record value;
|
||||
TLV::Record expect;
|
||||
|
||||
std::cout << "TESTPROG: " << argv[0] << std::endl;
|
||||
std::cout << "TESTPROG: " << argv[0] << "\n";
|
||||
|
||||
#if defined(__linux__)
|
||||
if (arena.Create(ARENA_FILE, ARENA_SIZE) == -1) {
|
||||
|
@ -53,7 +53,7 @@ main(int argc, const char *argv[])
|
|||
abort();
|
||||
}
|
||||
#endif
|
||||
std::cout << arena << std::endl;
|
||||
std::cout << arena << "\n";
|
||||
TLV::SetRecord(expect, DICTIONARY_TAG_VAL, TEST_KVSTRLEN3, TEST_KVSTR3);
|
||||
|
||||
Dictionary dict(arena);
|
||||
|
@ -73,17 +73,17 @@ main(int argc, const char *argv[])
|
|||
|
||||
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,
|
||||
TEST_KVSTRLEN6));
|
||||
std::cout << dict;
|
||||
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));
|
||||
std::cout << "\tcompare records" << std::endl;
|
||||
std::cout << "\tcompare records" << "\n";
|
||||
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,
|
||||
TEST_KVSTRLEN5));
|
||||
std::cout << dict;
|
||||
|
@ -92,7 +92,7 @@ main(int argc, const char *argv[])
|
|||
assert(dict.Lookup(TEST_KVSTR4, TEST_KVSTRLEN4, value));
|
||||
assert(cmpRecord(value, expect));
|
||||
|
||||
std::cout << "OK" <<std::endl;
|
||||
std::cout << "OK" <<"\n";
|
||||
|
||||
// Dump the generated arena for inspection later.
|
||||
#if defined(__linux__)
|
||||
|
|
30
tlvTest.cc
30
tlvTest.cc
|
@ -21,29 +21,29 @@ tlvTestSuite(Arena &backend)
|
|||
TLV::Record rec1, rec2, rec3, rec4;
|
||||
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(rec2, 2, TEST_STRLEN2, TEST_STR2);
|
||||
TLV::SetRecord(rec3, 1, TEST_STRLEN4, TEST_STR4);
|
||||
rec4.Tag = 1;
|
||||
|
||||
std::cout << "\twriting new rec1" << std::endl;
|
||||
std::cout << "\twriting new rec1" << "\n";
|
||||
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);
|
||||
std::cout << "\twriting new rec3" << std::endl;
|
||||
std::cout << "\twriting new rec3" << "\n";
|
||||
assert(TLV::WriteToMemory(backend, cursor, rec3) != nullptr);
|
||||
cursor = nullptr;
|
||||
|
||||
// the cursor should point at the next record,
|
||||
// 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);
|
||||
assert(cursor != nullptr);
|
||||
assert(cursor != backend.NewCursor());
|
||||
assert(cmpRecord(rec1, rec4));
|
||||
|
||||
std::cout << "\tFindTag 2" << std::endl;
|
||||
std::cout << "\tFindTag 2" << "\n";
|
||||
cursor = TLV::FindTag(backend, cursor, rec4);
|
||||
assert(cursor != nullptr);
|
||||
assert(cmpRecord(rec3, rec4));
|
||||
|
@ -62,20 +62,22 @@ tlvTestSuite(Arena &backend)
|
|||
bool
|
||||
runSuite(Arena &backend, const char *label)
|
||||
{
|
||||
std::cout << backend << std::endl;
|
||||
std::exception exc;
|
||||
|
||||
std::cout << backend << "\n";
|
||||
std::cout << "running test suite " << label << ": ";
|
||||
try {
|
||||
tlvTestSuite(backend);
|
||||
} catch (std::exception &exc){
|
||||
std::cout << "FAILED" << std::endl;
|
||||
std::cout << "FAILED: " << exc.what() << "\n";
|
||||
return false;
|
||||
}
|
||||
std::cout << "OK" << std::endl;
|
||||
std::cout << "OK" << "\n";
|
||||
|
||||
std::cout << "\tdestroying arena: ";
|
||||
backend.Destroy();
|
||||
|
||||
std::cout << "OK" << std::endl;
|
||||
std::cout << "OK" << "\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -88,7 +90,7 @@ main(int argc, const char *argv[])
|
|||
Arena arenaStatic;
|
||||
Arena arenaMem;
|
||||
|
||||
std::cout << "TESTPROG: " << argv[0] << std::endl;
|
||||
std::cout << "TESTPROG: " << argv[0] << "\n";
|
||||
|
||||
if (-1 == arenaStatic.SetStatic(arenaBuffer, ARENA_SIZE)) {
|
||||
abort();
|
||||
|
@ -98,8 +100,10 @@ main(int argc, const char *argv[])
|
|||
arenaStatic.Clear();
|
||||
|
||||
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();
|
||||
} else if (!runSuite(arenaFile, "arenaFile")) {
|
||||
abort();
|
||||
|
@ -112,6 +116,6 @@ main(int argc, const char *argv[])
|
|||
}
|
||||
arenaMem.Clear();
|
||||
|
||||
std::cout << "OK" << std::endl;
|
||||
std::cout << "OK" << "\n";
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue