-
Notifications
You must be signed in to change notification settings - Fork 0
/
miscutil.cc
185 lines (168 loc) · 5.01 KB
/
miscutil.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
#define NO_MASK_MALLOC 1
#include "teg.hh"
#if !NO_OPENGL
#include "video.hh"
#endif
#include <string.h>
#include <stdarg.h>
#include <iostream>
#if __WIN32__
/* The following copyright notice applies to the implementation of vasprintf
that occurs below. */
/*
Copyright (C) 2014 insane coder (http://insanecoding.blogspot.com/,
http://asprintf.insanecoding.org/)
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <limits.h>
int vasprintf(char **strp, const char *fmt, va_list ap)
{
int r = -1, size = _vscprintf(fmt, ap);
if ((size >= 0) && (size < INT_MAX))
{
*strp = (char *)safe_malloc(size+1); //+1 for null
if (*strp)
{
r = vsnprintf(*strp, size+1, fmt, ap); //+1 for null
if ((r < 0) || (r > size))
{
safe_free(*strp);
r = -1;
}
}
}
else { *strp = 0; }
return(r);
}
#endif
extern void* safe_malloc(size_t size) {
if(size == 0) return NULL;
else {
void* ret = malloc(size);
if(ret == NULL) die("couldn't malloc %lu bytes", (unsigned long)size);
return ret;
}
}
extern void safe_free(void* ptr) {
if(ptr != NULL) free(ptr);
}
extern void* safe_calloc(size_t nmemb, size_t size) {
if(nmemb == 0 || size == 0) return NULL;
else {
void* ret = calloc(nmemb, size);
if(ret == NULL) die("couldn't calloc %lu x %lu bytes",
(unsigned long)nmemb, (unsigned long)size);
return ret;
}
}
extern void* safe_realloc(void* ptr, size_t size) {
if(size == 0) {
safe_free(ptr);
return NULL;
}
else if(ptr == NULL) return safe_malloc(size);
else {
void* ret = realloc(ptr, size);
if(ret == NULL) die("couldn't realloc %lu bytes", (unsigned long)size);
return ret;
}
}
#if !NO_OPENGL
extern void _assertgl(const char* file, int line, const char* name) {
GLenum error;
int had_error = 0;
while((error = glGetError()) != GL_NO_ERROR) {
if(!had_error)
fprintf(stderr, "%s:%i: OpenGL errors detected %s:\n", file, line, name);
had_error = 1;
fprintf(stderr, "%s:%i: %s\n", file, line, gluErrorString(error));
}
#if DEBUG
if(had_error)
die("OpenGL errors occurred, see stderr.");
#endif
}
#endif
extern char* teg_strdup(const char* src) {
/* Very annoyed at Microsoft right now. */
if(src == NULL) return NULL;
size_t len = strlen(src) + 1;
char* ret = (char*)safe_malloc(len);
memcpy(ret, src, len);
return ret;
}
#ifndef TEG_NO_DIE_IMPLEMENTATION
#if TEG_USE_SN
#include "sn.hh"
extern SN::Context sn;
#endif
extern void die(const char* format, ...) {
char error[1920]; // enough to fill up an 80x24 terminal
va_list arg;
va_start(arg, format);
vsnprintf(error, sizeof(error), format, arg);
va_end(arg);
#if !NO_OPENGL
Video::Kill();
#endif
#if TEG_USE_SN
std::cerr << sn.Get("CERR_FATAL_ERROR"_Key, {GAME_PRETTY_NAME, error});
#else
std::cerr << GAME_PRETTY_NAME << " encountered a fatal error:\n"
<< error << "\n";
#endif
#if TEG_USE_SN
std::string window_title_str = sn.Get("MESSAGEBOX_FATAL_ERROR"_Key,
{GAME_PRETTY_NAME});
const char* window_title = window_title_str.c_str();
#else
const char* window_title = GAME_PRETTY_NAME" encountered a fatal error.";
#endif
if(SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, window_title,
error, NULL)) {
#if TEG_USE_SN
std::cerr << sn.Get("CERR_FATAL_FALLBACK"_Key, {SDL_GetError()});
#else
std::cerr << "Additionally, there was an error when attempting to use SDL"
" to display this\nerror message: "
<< SDL_GetError() << "\n";
#endif
}
exit(1);
}
#endif
std::string TEG::format(const char* format, ...) {
va_list arg;
va_start(arg, format);
std::string ret = TEG::vformat(format, arg);
va_end(arg);
return ret;
}
std::string TEG::vformat(const char* format, va_list arg) {
char* new_p = NULL;
int count = vasprintf(&new_p, format, arg);
assert(count >= 0 && new_p);
(void)count; // when compiling with NDEBUG, count will otherwise be unused
std::string ret = std::string(new_p);
safe_free(new_p);
return ret;
}
std::string TEG::format(const std::string format, ...) {
va_list arg;
va_start(arg, format);
std::string ret = TEG::vformat(format.c_str(), arg);
va_end(arg);
return ret;
}
std::string TEG::vformat(const std::string format, va_list arg) {
return TEG::vformat(format.c_str(), arg);
}