From 1cb00589065fd05b8d7cf0030eed84c488e9634d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20Ankarstr=C3=B6m?= Date: Tue, 16 Aug 2022 13:42:11 +0200 Subject: Avoid serialization. A great benefit of this is that the program doesn't need to COPY the data from the file view to the struct. --- c/data.cpp | 33 ++++++++------------------------- c/data.h | 32 ++++++++++++++++++-------------- c/test.cpp | 57 ++++++++++++++------------------------------------------- 3 files changed, 40 insertions(+), 82 deletions(-) (limited to 'c') diff --git a/c/data.cpp b/c/data.cpp index 1a78ef2..fe348e7 100644 --- a/c/data.cpp +++ b/c/data.cpp @@ -18,7 +18,7 @@ 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) +FileView::FileView(const wchar_t* const filename, const size_t cb) { hf = CreateFile(filename, GENERIC_READ|GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); @@ -39,12 +39,12 @@ DatView::DatView(const wchar_t* const filename, const size_t cb) if (!hm) throw Win32Error{}; - view = MapViewOfFile(hm, FILE_MAP_ALL_ACCESS, 0, 0, 0); + view = reinterpret_cast(MapViewOfFile(hm, FILE_MAP_ALL_ACCESS, 0, 0, 0)); if (!view) throw Win32Error{}; } -DatView::~DatView() +FileView::~FileView() { FlushViewOfFile(view, 0); UnmapViewOfFile(view); @@ -52,31 +52,14 @@ DatView::~DatView() CloseHandle(hf); } -unsigned char* Serialize(const ElvData& e, unsigned char* buf) +void Write(unsigned char* buf, const ElvData& e) { - unsigned char version = 'a'; - buf = ValToBuf(version, buf); - buf = ValToBuf(e.rating, buf); - buf = ValToBuf(e.bWatched, buf); - buf = ValToBuf(e.bTVOriginal, buf); - buf = ValToBuf(e.sRating, buf); - buf = ValToBuf(e.siEp, buf); - buf = ValToBuf(e.title, buf); - return buf; + memcpy(buf, reinterpret_cast(&e), sizeof(e)); } -unsigned char* Unserialize(ElvData& e, unsigned char* buf) +ElvData* Read(unsigned char* const buf) { - unsigned char version; - buf = BufToVal(buf, version); - if (version != 'a') + if (buf[0] != 'a') return nullptr; - - buf = BufToVal(buf, e.rating); - buf = BufToVal(buf, e.bWatched); - buf = BufToVal(buf, e.bTVOriginal); - buf = BufToVal(buf, e.sRating); - buf = BufToVal(buf, e.siEp); - buf = BufToVal(buf, e.title); - return buf; + return reinterpret_cast(buf); } diff --git a/c/data.h b/c/data.h index 91e34d9..4e25251 100644 --- a/c/data.h +++ b/c/data.h @@ -5,14 +5,18 @@ #include "util.h" #include "wcharptr.h" +/* ElvData and DlvData are written as-is to disk; note the careful + * alignment. */ + struct ElvData { - int rating = 0; - bool bWatched = false; - bool bTVOriginal = false; - wchar_t sRating[3] = {0}; - wchar_t siEp[5] = {0}; - wchar_t title[128] = {0}; + unsigned char version = 'a'; /* 0-1 */ + unsigned char rating = 0; /* 1-2 */ + unsigned char bWatched = 0; /* 2-3 */ + unsigned char bTVOriginal = 0; /* 3-4 */ + wchar_t sRating[4] = {0}; /* 4-12 */ + wchar_t siEp[6] = {0}; /* 12-24 */ + wchar_t title[128] = {0}; /* 24-280 */ }; struct DlvData @@ -24,19 +28,19 @@ struct DlvData wchar_t wiki[128] = {0}; }; -struct DatView +struct FileView { - DatView(const wchar_t* filename, size_t cb); - ~DatView(); + FileView(const wchar_t* filename, size_t cb); + ~FileView(); + inline operator unsigned char*() { return view; } HANDLE hf; HANDLE hm; - void* view; + unsigned char* 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); +void Write(unsigned char* buf, const ElvData& e); +ElvData* Read(unsigned char* buf); inline int FromWeb(const int iEp, ElvData& e, DlvData& d) noexcept { @@ -57,7 +61,7 @@ inline bool FromProlog(const int iEp, ElvData& e) noexcept else return false; - if (Pl("episode_data","episode_rating",iEp,&e.rating)) + if (Pl("episode_data","episode_rating",iEp,reinterpret_cast(&e.rating))) Swprintf(e.sRating, L"%d", e.rating); if (Pl("episode_data","tv_original",iEp)) diff --git a/c/test.cpp b/c/test.cpp index fb5d44d..abb03b3 100644 --- a/c/test.cpp +++ b/c/test.cpp @@ -47,59 +47,31 @@ TESTS FAIL("date is not correct"); } - TEST(Serialization) - { - ElvData e1; - FromProlog(6, e1); - - unsigned char buf[CB_SERIALIZE_ELVDATA]; - Serialize(e1, buf); - - ElvData e2; - if (!Unserialize(e2, buf)) - 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"); - } - - TEST(SerializationPlusIO) + TEST(IO) { ElvData e1; FromProlog(6, e1); { - DatView dv{L"tmp.dat", CB_SERIALIZE_ELVDATA}; - Serialize(e1, static_cast(dv.view)); + FileView fv{L"tmp.dat", sizeof(e1)}; + Write(fv, e1); } { - DatView dv{L"tmp.dat", CB_SERIALIZE_ELVDATA}; - - ElvData e2; - if (!Unserialize(e2, static_cast(dv.view))) - FAIL("invalid serialization version"); - if (e1.rating != e2.rating) - FAIL("rating is different"); - if (e1.bWatched != e2.bWatched) + FileView fv{L"tmp.dat", sizeof(e1)}; + ElvData* e2 = Read(fv); + if (e1.rating != e2->rating) + FAIL("rating is different (%d/%d)", e1.rating, e2->rating); + if (e1.bWatched != e2->bWatched) FAIL("bWatched is different"); - if (e1.bTVOriginal != e2.bTVOriginal) + if (e1.bTVOriginal != e2->bTVOriginal) FAIL("bTVOriginal is different"); - if (wcscmp(e1.sRating, e2.sRating) != 0) + if (wcscmp(e1.sRating, e2->sRating) != 0) FAIL("sRating is different"); - if (wcscmp(e1.siEp, e2.siEp) != 0) + if (wcscmp(e1.siEp, e2->siEp) != 0) FAIL("siEp is different"); - if (wcscmp(e1.title, e2.title) != 0) + if (wcscmp(e1.title, e2->title) != 0) FAIL("title is different"); } - DeleteFile(L"tmp.dat"); + //DeleteFile(L"tmp.dat"); } }; @@ -109,8 +81,7 @@ int RunTests() StrcpyWithSmallerDestination{}, //EpisodeDataFromWeb{}, EpisodeDataFromProlog{}, - Serialization{}, - SerializationPlusIO{}, + IO{}, }; printf("Results (%llu tests):\n", sizeof(tests)/sizeof(*tests)); -- cgit v1.2.3