aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Ankarström <john@ankarstrom.se>2022-08-16 04:37:48 +0200
committerJohn Ankarström <john@ankarstrom.se>2022-08-16 04:37:48 +0200
commit5095c2e2ba9aadf468514804fb3a872d10fdc17d (patch)
tree6683057496648797923ce686440c101510d9bc87
parentafd245c205e2787e54cb7e2fd34de617eeceed25 (diff)
downloadEpisodeBrowser-5095c2e2ba9aadf468514804fb3a872d10fdc17d.tar.gz
Implement preliminary IO.
It might be a good idea to eschew the structs and access the data directly from the view. Alternatively, the serialization functions might be rewritten to simply memcpy the structs, after either adding __attribute__((packed)) or ensuring consistent padding.
-rw-r--r--c/data.cpp36
-rw-r--r--c/data.h10
-rw-r--r--c/test.cpp31
3 files changed, 77 insertions, 0 deletions
diff --git a/c/data.cpp b/c/data.cpp
index e28378e..1a78ef2 100644
--- a/c/data.cpp
+++ b/c/data.cpp
@@ -1,6 +1,8 @@
#include <memory>
+#include <vector>
#include "data.h"
+#include "win.h"
template <typename T>
inline unsigned char* ValToBuf(const T& val, unsigned char* const buf)
@@ -16,6 +18,40 @@ inline unsigned char* BufToVal(unsigned char* const buf, T& val)
return buf+sizeof(val);
}
+DatView::DatView(const wchar_t* const filename, const size_t cb)
+{
+ hf = CreateFile(filename, GENERIC_READ|GENERIC_WRITE,
+ 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
+ if (hf == INVALID_HANDLE_VALUE) {
+ if (GetLastError() == ERROR_FILE_NOT_FOUND) {
+ hf = CreateFile(filename, GENERIC_READ|GENERIC_WRITE,
+ 0, nullptr, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, nullptr);
+ if (hf == INVALID_HANDLE_VALUE)
+ throw Win32Error{};
+ } else
+ throw Win32Error{};
+ }
+
+ LARGE_INTEGER cbMap;
+ cbMap.QuadPart = cb;
+ hm = CreateFileMapping(hf, nullptr, PAGE_READWRITE,
+ cbMap.HighPart, cbMap.LowPart, nullptr);
+ if (!hm)
+ throw Win32Error{};
+
+ view = MapViewOfFile(hm, FILE_MAP_ALL_ACCESS, 0, 0, 0);
+ if (!view)
+ throw Win32Error{};
+}
+
+DatView::~DatView()
+{
+ FlushViewOfFile(view, 0);
+ UnmapViewOfFile(view);
+ CloseHandle(hm);
+ CloseHandle(hf);
+}
+
unsigned char* Serialize(const ElvData& e, unsigned char* buf)
{
unsigned char version = 'a';
diff --git a/c/data.h b/c/data.h
index 797271d..91e34d9 100644
--- a/c/data.h
+++ b/c/data.h
@@ -24,6 +24,16 @@ struct DlvData
wchar_t wiki[128] = {0};
};
+struct DatView
+{
+ DatView(const wchar_t* filename, size_t cb);
+ ~DatView();
+ HANDLE hf;
+ HANDLE hm;
+ void* view;
+ /* TODO: Handle exceptions on read and write... */
+};
+
constexpr size_t CB_SERIALIZE_ELVDATA = 1+sizeof(ElvData);
unsigned char* Serialize(const ElvData& e, unsigned char* buf);
unsigned char* Unserialize(ElvData& e, unsigned char* buf);
diff --git a/c/test.cpp b/c/test.cpp
index 1fc7e3b..fb5d44d 100644
--- a/c/test.cpp
+++ b/c/test.cpp
@@ -71,6 +71,36 @@ TESTS
if (wcscmp(e1.title, e2.title) != 0)
FAIL("title is different");
}
+
+ TEST(SerializationPlusIO)
+ {
+ ElvData e1;
+ FromProlog(6, e1);
+ {
+ DatView dv{L"tmp.dat", CB_SERIALIZE_ELVDATA};
+ Serialize(e1, static_cast<unsigned char*>(dv.view));
+ }
+ {
+ DatView dv{L"tmp.dat", CB_SERIALIZE_ELVDATA};
+
+ ElvData e2;
+ if (!Unserialize(e2, static_cast<unsigned char*>(dv.view)))
+ FAIL("invalid serialization version");
+ if (e1.rating != e2.rating)
+ FAIL("rating is different");
+ if (e1.bWatched != e2.bWatched)
+ FAIL("bWatched is different");
+ if (e1.bTVOriginal != e2.bTVOriginal)
+ FAIL("bTVOriginal is different");
+ if (wcscmp(e1.sRating, e2.sRating) != 0)
+ FAIL("sRating is different");
+ if (wcscmp(e1.siEp, e2.siEp) != 0)
+ FAIL("siEp is different");
+ if (wcscmp(e1.title, e2.title) != 0)
+ FAIL("title is different");
+ }
+ DeleteFile(L"tmp.dat");
+ }
};
int RunTests()
@@ -80,6 +110,7 @@ int RunTests()
//EpisodeDataFromWeb{},
EpisodeDataFromProlog{},
Serialization{},
+ SerializationPlusIO{},
};
printf("Results (%llu tests):\n", sizeof(tests)/sizeof(*tests));