aboutsummaryrefslogtreecommitdiff
path: root/c
diff options
context:
space:
mode:
authorJohn Ankarström <john@ankarstrom.se>2022-08-16 13:42:11 +0200
committerJohn Ankarström <john@ankarstrom.se>2022-08-16 13:42:11 +0200
commit1cb00589065fd05b8d7cf0030eed84c488e9634d (patch)
treef6054ff80e8c87d8a4b7a53dbfced30f05dd6dd2 /c
parent5095c2e2ba9aadf468514804fb3a872d10fdc17d (diff)
downloadEpisodeBrowser-1cb00589065fd05b8d7cf0030eed84c488e9634d.tar.gz
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.
Diffstat (limited to 'c')
-rw-r--r--c/data.cpp33
-rw-r--r--c/data.h32
-rw-r--r--c/test.cpp57
3 files changed, 40 insertions, 82 deletions
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<unsigned char*>(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<const unsigned char*>(&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<ElvData*>(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<int*>(&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<unsigned char*>(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<unsigned char*>(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));