Line data Source code
1 : // implementation of generic tools
2 :
3 : #include <cstring>
4 : #include <functional>
5 : #include <string>
6 : #include <algorithm>
7 : #include <array>
8 :
9 : #include <SDL.h>
10 : #include <zlib.h>
11 :
12 : #include "../libprimis-headers/tools.h"
13 : #include "../libprimis-headers/geom.h"
14 :
15 : #include "stream.h"
16 :
17 : ////////////////////////// strings ////////////////////////////////////////
18 :
19 6 : char *tempformatstring(const char *fmt, ...)
20 : {
21 : static std::array<string, 4> tmpstr;
22 : static int tmpidx = 0;
23 6 : tmpidx = (tmpidx+1)%4;
24 :
25 : va_list v;
26 6 : va_start(v, fmt);
27 6 : vformatstring(tmpstr[tmpidx], fmt, v);
28 6 : va_end(v);
29 :
30 6 : return tmpstr[tmpidx];
31 : }
32 :
33 : ////////////////////////// bit packing ////////////////////////////////////
34 :
35 : // these functions are useful for packing ints/chars into smaller chunks, which
36 : // is useful for reducing file save sizes
37 :
38 : // note that the parent put*_ template functions is not defined here but in tools.h
39 :
40 : //* signed integers *//
41 13 : void putint(ucharbuf &p, int n)
42 : {
43 13 : putint_(p, n);
44 13 : }
45 :
46 : //Stores the passed integer into a uchar array, by splitting it into four bytes.
47 2 : void putint(std::vector<uchar> &p, int n)
48 : {
49 2 : p.push_back((n >> 24) & 0xFF);
50 2 : p.push_back((n >> 16) & 0xFF);
51 2 : p.push_back((n >> 8 ) & 0xFF);
52 2 : p.push_back(n & 0xFF);
53 2 : }
54 :
55 : //Removes the last four values from the uchar array, returning its int representation.
56 2 : int getint(std::vector<uchar> &p)
57 : {
58 2 : int a = 0;
59 2 : a += static_cast<int>(p.back());
60 2 : p.pop_back();
61 2 : a += static_cast<int>(p.back()) << 8;
62 2 : p.pop_back();
63 2 : a += static_cast<int>(p.back()) << 16;
64 2 : p.pop_back();
65 2 : a += static_cast<int>(p.back()) << 24;
66 2 : p.pop_back();
67 2 : return a;
68 : }
69 :
70 : //Stores the passed float into a uchar array, by splitting it into four bytes.
71 2 : void putfloat(std::vector<uchar> &p, float n)
72 : {
73 : uchar arr[sizeof(float)];
74 2 : std::memcpy(arr, &n, sizeof(float));
75 10 : for(unsigned long i = 0; i < sizeof(float); ++i)
76 : {
77 8 : p.push_back(arr[sizeof(float)-i-1]);
78 : }
79 2 : }
80 :
81 : //Removes the last four values from the uchar array, returning its float representation.
82 2 : float getfloat(std::vector<uchar> &p)
83 : {
84 : uchar arr[sizeof(float)];
85 10 : for(unsigned long i = 0; i < sizeof(float); ++i)
86 : {
87 8 : arr[i] = p.back();
88 8 : p.pop_back();
89 : }
90 2 : float n = 0.f;
91 2 : std::memcpy(&n, arr, sizeof(float));
92 2 : return n;
93 : }
94 :
95 :
96 13 : int getint(ucharbuf &p)
97 : {
98 13 : int c = static_cast<char>(p.get());
99 13 : if(c == -128)
100 : {
101 1 : int n = p.get();
102 1 : n |= static_cast<char>(p.get()) << 8;
103 1 : return n;
104 : }
105 12 : else if(c == -127)
106 : {
107 1 : int n = p.get();
108 1 : n |= p.get() << 8;
109 1 : n |= p.get() << 16;
110 1 : return n|(p.get()<<24);
111 : }
112 : else
113 : {
114 11 : return c;
115 : }
116 : }
117 :
118 : //* unisigned integers *//
119 : // much smaller encoding for unsigned integers up to 28 bits, but can handle signed
120 :
121 4 : void putuint(ucharbuf &p, int n)
122 : {
123 4 : putuint_(p, n);
124 4 : }
125 :
126 4 : int getuint(ucharbuf &p)
127 : {
128 4 : int n = p.get();
129 4 : if(n & 0x80)
130 : {
131 3 : n += (p.get() << 7) - 0x80;
132 3 : if(n & (1<<14))
133 : {
134 2 : n += (p.get() << 14) - (1<<14);
135 : }
136 3 : if(n & (1<<21))
137 : {
138 1 : n += (p.get() << 21) - (1<<21);
139 : }
140 3 : if(n & (1<<28))
141 : {
142 1 : n |= ~0U<<28;
143 : }
144 : }
145 4 : return n;
146 : }
147 :
148 : //* floats *//
149 2 : void putfloat(ucharbuf &p, float f)
150 : {
151 2 : putfloat_(p, f);
152 2 : }
153 :
154 2 : float getfloat(ucharbuf &p)
155 : {
156 : float f;
157 2 : p.get(reinterpret_cast<uchar *>(&f), sizeof(float));
158 2 : return f;
159 : }
160 :
161 : //* strings *//
162 2 : void sendstring(const char *t, ucharbuf &p)
163 : {
164 2 : sendstring_(t, p);
165 2 : }
166 0 : void sendstring(const char *t, std::vector<uchar> &p)
167 : {
168 0 : sendstring_(t, p);
169 0 : }
170 :
171 2 : void getstring(char *text, ucharbuf &p, size_t len)
172 : {
173 2 : char *t = text;
174 : do
175 : {
176 10 : if(t >= &text[len])
177 : {
178 0 : text[len-1] = 0;
179 0 : return;
180 : }
181 10 : if(!p.remaining())
182 : {
183 0 : *t = 0;
184 0 : return;
185 : }
186 10 : *t = getint(p);
187 10 : } while(*t++);
188 : }
189 :
190 5 : void filtertext(char *dst, const char *src, bool whitespace, bool forcespace, size_t len)
191 : {
192 37 : for(int c = static_cast<uchar>(*src); c; c = static_cast<uchar>(*++src))
193 : {
194 33 : if(c == '\f')
195 : {
196 3 : if(!*++src)
197 : {
198 0 : break;
199 : }
200 3 : continue;
201 : }
202 30 : if(!iscubeprint(c))
203 : {
204 0 : if(!iscubespace(c) || !whitespace)
205 : {
206 0 : continue;
207 : }
208 0 : if(forcespace)
209 : {
210 0 : c = ' ';
211 : }
212 : }
213 30 : *dst++ = c;
214 30 : if(!--len)
215 : {
216 1 : break;
217 : }
218 : }
219 5 : *dst = '\0';
220 5 : }
|