penguins  1.0.0
utils.c
Go to the documentation of this file.
1 #include "utils.h"
2 #include <assert.h>
3 #include <ctype.h>
4 #include <errno.h>
5 #include <stdbool.h>
6 #include <stddef.h>
7 #include <stdint.h>
8 #include <stdlib.h>
9 #include <string.h>
10 
11 #ifdef _WIN32
12 #define WIN32_LEAN_AND_MEAN
13 #include <windows.h>
14 #else
15 #include <time.h>
16 #endif
17 
20  [DIRECTION_RIGHT] = { 1, 0 },
21  [DIRECTION_DOWN] = { 0, 1 },
22  [DIRECTION_LEFT] = { -1, 0 },
23  [DIRECTION_UP] = { 0, -1 },
24 };
25 
28  [NEIGHBOR_RIGHT] = { 1, 0 }, [NEIGHBOR_BOTTOM_RIGHT] = { 1, 1 },
29  [NEIGHBOR_BOTTOM] = { 0, 1 }, [NEIGHBOR_BOTTOM_LEFT] = { -1, 1 },
30  [NEIGHBOR_LEFT] = { -1, 0 }, [NEIGHBOR_TOP_LEFT] = { -1, -1 },
31  [NEIGHBOR_TOP] = { 0, -1 }, [NEIGHBOR_TOP_RIGHT] = { 1, -1 },
32 };
33 
40 };
41 
42 extern bool coords_same(Coords a, Coords b);
43 
46 const char* strip_prefix(const char* str, const char* prefix) {
47  // Based on <https://stackoverflow.com/a/4770992>
48  size_t prefix_len = strlen(prefix);
49  return strncmp(prefix, str, prefix_len) == 0 ? str + prefix_len : NULL;
50 }
51 
64 bool parse_number(const char* str, long* result) {
65  char* end;
66  while (isspace(*str)) str++; // Skip the leading whitespace
67  errno = 0;
68  *result = strtol(str, &end, 10);
69  while (isspace(*end)) end++; // Skip the trailing whitespace
70  return !(
71  // The parsing fails if:
72  errno == ERANGE || // The value falls outside the range of the `long` type
73  end == str || // The string is empty or nothing could be parsed at all
74  *end != '\0' // There is junk at the end of the string
75  );
76 }
77 
79 void* memdup(const void* src, size_t size) {
80  // Taken from <https://stackoverflow.com/a/29035370>.
81  void* dest = malloc(size);
82  if (dest != NULL) memcpy(dest, src, size);
83  return dest;
84 }
85 
86 // Taken from <https://cplusplus.com/faq/beginners/random-numbers/#seeding>.
87 static void random_init(void) {
88 #ifdef _WIN32
89  FILETIME t;
90  ULARGE_INTEGER i;
91  GetSystemTimeAsFileTime(&t);
92  i.u.LowPart = t.dwLowDateTime;
93  i.u.HighPart = t.dwHighDateTime;
94  ULONGLONG seed = i.QuadPart / 1000;
95 #else
96  struct timespec ts, res;
97  clock_getres(CLOCK_REALTIME, &res);
98  clock_gettime(CLOCK_REALTIME, &ts);
99  unsigned long seed = ts.tv_nsec / res.tv_nsec;
100 #endif
101  srand((unsigned int)seed);
102 }
103 
104 // Taken from <https://cplusplus.com/faq/beginners/random-numbers/#random_int_in_range>.
105 static int random_range(Rng* rng, int min, int max) {
106  UNUSED(rng);
107  assert(min <= max);
108  unsigned int n = (max - min <= RAND_MAX) ? (max - min + 1U) : (RAND_MAX + 1U);
109  unsigned int x = (RAND_MAX + 1U) / n;
110  unsigned int y = x * n;
111  unsigned int r;
112  do {
113  r = rand();
114  } while (r >= y);
115  return r / x + min;
116 }
117 
124  random_init();
125  Rng rng;
126  rng.random_range = &random_range;
127  return rng;
128 }
129 
130 extern uint32_t fnv32_hash(uint32_t state, const void* buf, size_t len);
A pair of 2D coordinates, used for addressing the Game::board_grid.
Definition: utils.h:15
bool coords_same(Coords a, Coords b)
Checks if two Coords pairs are equal.
Definition: utils.h:46
A wrapper around random number generators.
Definition: utils.h:129
int(* random_range)(struct Rng *self, int min, int max)
Generates and returns a value in the range [min; max) (i.e. from min inclusive to max exclusive).
Definition: utils.h:132
Rng init_stdlib_rng(void)
Returns an RNG implementation based on the rand function from <stdlib.h> (and seeds it with srand).
Definition: utils.c:123
void * memdup(const void *src, size_t size)
A shorthand for malloc + memcpy (analogous to strdup).
Definition: utils.c:79
const Coords NEIGHBOR_TO_COORDS[NEIGHBOR_MAX]
A table that maps Neighbor variants to relative Coords.
Definition: utils.c:27
const Coords DIRECTION_TO_COORDS[DIRECTION_MAX]
A table that maps Direction variants to relative Coords.
Definition: utils.c:19
bool parse_number(const char *str, long *result)
Converts a string into a number, returns false if the string was invalid.
Definition: utils.c:64
static void random_init(void)
Definition: utils.c:87
const Neighbor DIRECTION_TO_NEIGHBOR[DIRECTION_MAX]
A table that maps Direction variants to corresponding Neighbor variants.
Definition: utils.c:35
uint32_t fnv32_hash(uint32_t state, const void *buf, size_t len)
Computes the 32-bit FNV-1a hash of a given byte sequence.
Definition: utils.h:151
static int random_range(Rng *rng, int min, int max)
Definition: utils.c:105
const char * strip_prefix(const char *str, const char *prefix)
Returns a substring with the prefix removed if the given string starts with the prefix,...
Definition: utils.c:46
@ DIRECTION_MAX
Definition: utils.h:25
@ DIRECTION_DOWN
Definition: utils.h:22
@ DIRECTION_LEFT
Definition: utils.h:23
@ DIRECTION_UP
Definition: utils.h:24
@ DIRECTION_RIGHT
Definition: utils.h:21
#define UNUSED(var)
Helper for silencing warnings about unused variables.
Definition: utils.h:72
Neighbor
Definition: utils.h:28
@ NEIGHBOR_TOP_RIGHT
Definition: utils.h:36
@ NEIGHBOR_BOTTOM_RIGHT
Definition: utils.h:30
@ NEIGHBOR_BOTTOM
Definition: utils.h:31
@ NEIGHBOR_TOP_LEFT
Definition: utils.h:34
@ NEIGHBOR_RIGHT
Definition: utils.h:29
@ NEIGHBOR_MAX
Definition: utils.h:37
@ NEIGHBOR_TOP
Definition: utils.h:35
@ NEIGHBOR_BOTTOM_LEFT
Definition: utils.h:32
@ NEIGHBOR_LEFT
Definition: utils.h:33