diff --git a/projects/openrct2.vcxproj b/projects/openrct2.vcxproj
index 13d1c0ff54..901c0793c3 100644
--- a/projects/openrct2.vcxproj
+++ b/projects/openrct2.vcxproj
@@ -208,6 +208,7 @@
+
diff --git a/src/audio/mixer.cpp b/src/audio/mixer.cpp
index 1edda91bc7..8df91e49c9 100644
--- a/src/audio/mixer.cpp
+++ b/src/audio/mixer.cpp
@@ -27,6 +27,7 @@ extern "C" {
}
#include "mixer.h"
#include
+#include "../core/Util.hpp"
Mixer gMixer;
@@ -434,10 +435,10 @@ Mixer::Mixer()
{
effectbuffer = 0;
volume = 1;
- for (int i = 0; i < countof(css1sources); i++) {
+ for (size_t i = 0; i < Util::CountOf(css1sources); i++) {
css1sources[i] = 0;
}
- for (int i = 0; i < countof(musicsources); i++) {
+ for (size_t i = 0; i < Util::CountOf(musicsources); i++) {
musicsources[i] = 0;
}
}
@@ -458,7 +459,7 @@ void Mixer::Init(const char* device)
format.channels = have.channels;
format.freq = have.freq;
const char* filename = get_file_path(PATH_ID_CSS1);
- for (int i = 0; i < countof(css1sources); i++) {
+ for (size_t i = 0; i < Util::CountOf(css1sources); i++) {
Source_Sample* source_sample = new Source_Sample;
if (source_sample->LoadCSS1(filename, i)) {
source_sample->Convert(format); // convert to audio output format, saves some cpu usage but requires a bit more memory, optional
@@ -481,13 +482,13 @@ void Mixer::Close()
}
Unlock();
SDL_CloseAudioDevice(deviceid);
- for (int i = 0; i < countof(css1sources); i++) {
+ for (size_t i = 0; i < Util::CountOf(css1sources); i++) {
if (css1sources[i] && css1sources[i] != &source_null) {
delete css1sources[i];
css1sources[i] = 0;
}
}
- for (int i = 0; i < countof(musicsources); i++) {
+ for (size_t i = 0; i < Util::CountOf(musicsources); i++) {
if (musicsources[i] && musicsources[i] != &source_null) {
delete musicsources[i];
musicsources[i] = 0;
@@ -530,9 +531,9 @@ void Mixer::Stop(Channel& channel)
Unlock();
}
-bool Mixer::LoadMusic(int pathId)
+bool Mixer::LoadMusic(size_t pathId)
{
- if (pathId >= countof(musicsources)) {
+ if (pathId >= Util::CountOf(musicsources)) {
return false;
}
if (!musicsources[pathId]) {
@@ -797,14 +798,14 @@ void Mixer_Init(const char* device)
gMixer.Init(device);
}
-void* Mixer_Play_Effect(int id, int loop, int volume, float pan, double rate, int deleteondone)
+void* Mixer_Play_Effect(size_t id, int loop, int volume, float pan, double rate, int deleteondone)
{
if (gOpenRCT2Headless) return 0;
if (!gConfigSound.sound) {
return 0;
}
- if (id >= countof(gMixer.css1sources)) {
+ if (id >= Util::CountOf(gMixer.css1sources)) {
return 0;
}
gMixer.Lock();
diff --git a/src/audio/mixer.h b/src/audio/mixer.h
index 4b2aeccbac..5d1e8a59b9 100644
--- a/src/audio/mixer.h
+++ b/src/audio/mixer.h
@@ -166,7 +166,7 @@ public:
void Unlock();
Channel* Play(Source& source, int loop, bool deleteondone, bool deletesourceondone);
void Stop(Channel& channel);
- bool LoadMusic(int pathid);
+ bool LoadMusic(size_t pathid);
void SetVolume(float volume);
Source* css1sources[SOUND_MAXID];
@@ -201,7 +201,7 @@ extern "C"
#endif
void Mixer_Init(const char* device);
-void* Mixer_Play_Effect(int id, int loop, int volume, float pan, double rate, int deleteondone);
+void* Mixer_Play_Effect(size_t id, int loop, int volume, float pan, double rate, int deleteondone);
void Mixer_Stop_Channel(void* channel);
void Mixer_Channel_Volume(void* channel, int volume);
void Mixer_Channel_Pan(void* channel, float pan);
diff --git a/src/core/Util.hpp b/src/core/Util.hpp
new file mode 100644
index 0000000000..4a8df1ce1c
--- /dev/null
+++ b/src/core/Util.hpp
@@ -0,0 +1,20 @@
+#ifndef _UTIL_HPP_
+#define _UTIL_HPP_
+
+#include
+
+/**
+ * Common utility functions.
+ */
+namespace Util {
+
+// Based on http://www.g-truc.net/post-0708.html
+template
+constexpr size_t CountOf(T const (&)[N]) noexcept
+{
+ return N;
+}
+
+} // namespace Util
+
+#endif // _UTIL_HPP_
diff --git a/src/network/network.cpp b/src/network/network.cpp
index 3f6f58ddf6..81d087295f 100644
--- a/src/network/network.cpp
+++ b/src/network/network.cpp
@@ -36,6 +36,7 @@ extern "C" {
#include
#include
#include
+#include "../core/Util.hpp"
extern "C" {
#include "../config.h"
#include "../game.h"
@@ -844,10 +845,10 @@ std::string Network::GenerateAdvertiseKey()
static char hexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
char key[17];
for (int i = 0; i < 16; i++) {
- int hexCharIndex = util_rand() % countof(hexChars);
+ int hexCharIndex = util_rand() % Util::CountOf(hexChars);
key[i] = hexChars[hexCharIndex];
}
- key[countof(key) - 1] = 0;
+ key[Util::CountOf(key) - 1] = 0;
return key;
}
diff --git a/src/platform/posix.c b/src/platform/posix.c
index c56b77ee78..e276911307 100644
--- a/src/platform/posix.c
+++ b/src/platform/posix.c
@@ -554,10 +554,10 @@ void platform_resolve_user_data_path()
char buffer[MAX_PATH];
buffer[0] = '\0';
log_verbose("buffer = '%s'", buffer);
-
+
const char *homedir = getpwuid(getuid())->pw_dir;
platform_posix_sub_user_data_path(buffer, homedir, separator);
-
+
log_verbose("OpenRCT2 user data directory = '%s'", buffer);
int len = strnlen(buffer, MAX_PATH);
wchar_t *w_buffer = regular_to_wchar(buffer);
diff --git a/src/rct2.h b/src/rct2.h
index ded705f7b5..fdf89ea8b6 100644
--- a/src/rct2.h
+++ b/src/rct2.h
@@ -81,7 +81,30 @@ typedef utf16* utf16string;
// Rounds an integer down to the given power of 2. y must be a power of 2.
#define floor2(x, y) ((x) & (~((y) - 1)))
-#define countof(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
+
+#ifndef __cplusplus
+// in C++ you should be using Util::CountOf
+#ifdef __GNUC__
+/**
+ * Force a compilation error if condition is true, but also produce a
+ * result (of value 0 and type size_t), so the expression can be used
+ * e.g. in a structure initializer (or where-ever else comma expressions
+ * aren't permitted).
+ */
+#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
+
+/* &a[0] degrades to a pointer: a different type from an array */
+#define __must_be_array(a) \
+ BUILD_BUG_ON_ZERO(__builtin_types_compatible_p(typeof(a), typeof(&a[0])))
+
+// based on http://lxr.free-electrons.com/source/include/linux/kernel.h#L54
+#define countof(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
+#elif defined (_MSC_VER)
+ #define countof(arr) _countof(arr)
+#else
+ #define countof(arr) (sizeof(arr) / sizeof((arr)[0]))
+#endif // __GNUC__
+#endif // __cplusplus
#ifndef _MSC_VER
// use similar struct packing as MSVC for our structs