1 /*
2  * Portions of this file are copyright Rebirth contributors and licensed as
3  * described in COPYING.txt.
4  * Portions of this file are copyright Parallax Software and licensed
5  * according to the Parallax license below.
6  * See COPYING.txt for license details.
7  */
8 
9 #pragma once
10 
11 #ifdef __cplusplus
12 #include <algorithm>
13 #include <cctype>
14 #include <cstddef>
15 #include "dxxsconf.h"
16 #include <array>
17 
18 #define CALLSIGN_LEN                8       // so can use as filename (was: 12)
19 
20 struct callsign_t
21 {
22 	static const std::size_t array_length = CALLSIGN_LEN + 1;
23 	operator const void *() const = delete;
24 	using array_t = std::array<char, array_length>;
25 	typedef char elements_t[array_length];
26 	array_t a;
lower_predicatecallsign_t27 	static char lower_predicate(char c)
28 	{
29 		return std::tolower(static_cast<unsigned>(c));
30 	}
zero_terminatecallsign_t31 	callsign_t &zero_terminate(array_t::iterator i)
32 	{
33 		std::fill(i, end(a), 0);
34 		return *this;
35 	}
copycallsign_t36 	callsign_t &copy(const char *s, std::size_t N)
37 	{
38 		return zero_terminate(std::copy_n(s, std::min(a.size() - 1, N), begin(a)));
39 	}
copy_lowercallsign_t40 	callsign_t &copy_lower(const char *s, std::size_t N)
41 	{
42 		return zero_terminate(std::transform(s, std::next(s, std::min(a.size() - 1, N)), begin(a), lower_predicate));
43 	}
lowercallsign_t44 	void lower()
45 	{
46 		auto ba = begin(a);
47 		std::transform(ba, std::prev(end(a)), ba, lower_predicate);
48 		a.back() = 0;
49 	}
50 	[[nodiscard]]
buffercallsign_t51 	elements_t &buffer()
52 	{
53 		return *reinterpret_cast<elements_t *>(a.data());
54 	}
55 	template <std::size_t N>
56 		callsign_t &operator=(const char (&s)[N])
57 		{
58 			static_assert(N <= array_length, "string too long");
59 			return copy(s, N);
60 		}
61 	template <std::size_t N>
copy_lowercallsign_t62 		void copy_lower(const char (&s)[N])
63 		{
64 			static_assert(N <= array_length, "string too long");
65 			return copy_lower(s, N);
66 		}
fillcallsign_t67 	void fill(char c) { a.fill(c); }
68 	const char &operator[](std::size_t i) const
69 	{
70 		return a[i];
71 	}
72 	operator const char *() const
73 	{
74 		return &a[0];
75 	};
76 	bool operator==(const callsign_t &r) const
77 	{
78 		return a == r.a;
79 	}
80 	bool operator!=(const callsign_t &r) const
81 	{
82 		return !(*this == r);
83 	}
84 };
85 static_assert(sizeof(callsign_t) == CALLSIGN_LEN + 1, "callsign_t too big");
86 
87 #endif
88