OSDN Git Service

[Fix] 名前の長いアイテムを博物館に寄贈しようとするとクラッシュする
[hengbandforosx/hengbandosx.git] / src / term / z-util.cpp
1 /* File: z-util.c */
2
3 /*
4  * Copyright (c) 1997 Ben Harrison
5  *
6  * This software may be copied and distributed for educational, research,
7  * and not for profit purposes provided that this copyright and statement
8  * are included in all such copies.
9  */
10
11 /* Purpose: Low level utilities -BEN- */
12
13 #include "term/z-util.h"
14
15 /*
16  * Convenient storage of the program name
17  */
18 concptr argv0 = nullptr;
19
20 /*
21  * Determine if string "t" is equal to string "t"
22  */
23 bool streq(std::string_view a, std::string_view b)
24 {
25     return a == b;
26 }
27
28 /*
29  * Determine if string "t" is a suffix of string "s"
30  */
31 bool suffix(std::string_view s, std::string_view t)
32 {
33     //! @todo C++20 では ends_with が使用可能
34     if (t.size() > s.size()) {
35         return false;
36     }
37
38     return s.compare(s.size() - t.size(), s.npos, t) == 0;
39 }
40
41 /*
42  * Determine if string "t" is a prefix of string "s"
43  */
44 bool prefix(std::string_view s, std::string_view t)
45 {
46     //! @todo C++20 では starts_with が使用可能
47     return s.substr(0, t.size()) == t;
48 }
49
50 /*
51  * Redefinable "plog" action
52  */
53 void (*plog_aux)(concptr) = nullptr;
54
55 /*
56  * Print (or log) a "warning" message (ala "perror()")
57  * Note the use of the (optional) "plog_aux" hook.
58  */
59 void plog(concptr str)
60 {
61     /* Use the "alternative" function if possible */
62     if (plog_aux) {
63         (*plog_aux)(str);
64     }
65
66     /* Just do a labeled fprintf to stderr */
67     else {
68         (void)(fprintf(stderr, "%s: %s\n", argv0 ? argv0 : "???", str));
69     }
70 }
71
72 /*
73  * Redefinable "quit" action
74  */
75 void (*quit_aux)(concptr) = nullptr;
76
77 /*
78  * Exit (ala "exit()").  If 'str' is nullptr, do "exit(0)".
79  * If 'str' begins with "+" or "-", do "exit(atoi(str))".
80  * Otherwise, plog() 'str' and exit with an error code of -1.
81  * But always use 'quit_aux', if set, before anything else.
82  */
83 void quit(concptr str)
84 {
85     /* Attempt to use the aux function */
86     if (quit_aux) {
87         (*quit_aux)(str);
88     }
89
90     /* Success */
91     if (!str) {
92         (void)(exit(0));
93     }
94
95     /* Extract a "special error code" */
96     if ((str[0] == '-') || (str[0] == '+')) {
97         (void)(exit(atoi(str)));
98     }
99
100     /* Send the string to plog() */
101     plog(str);
102
103     /* Failure */
104     (void)(exit(EXIT_FAILURE));
105 }
106
107 /*
108  * Redefinable "core" action
109  */
110 void (*core_aux)(concptr) = nullptr;
111
112 /*
113  * Dump a core file, after printing a warning message
114  * As with "quit()", try to use the "core_aux()" hook first.
115  */
116 void core(concptr str)
117 {
118     char *crash = nullptr;
119
120     /* Use the aux function */
121     if (core_aux) {
122         (*core_aux)(str);
123     }
124
125     /* Dump the warning string */
126     if (str) {
127         plog(str);
128     }
129
130     /* Attempt to Crash */
131     (*crash) = (*crash);
132
133     /* Be sure we exited */
134     quit("core() failed");
135 }
136
137 /*** 64-bit integer operations ***/
138
139 void s64b_lshift(int32_t *hi, uint32_t *lo, const int n)
140 {
141     if (n == 0) {
142         return;
143     }
144
145     *hi = (int32_t)((uint32_t)(*hi << n) | (*lo >> (32 - n)));
146     *lo <<= n;
147 }
148
149 void s64b_rshift(int32_t *hi, uint32_t *lo, const int n)
150 {
151     if (n == 0) {
152         return;
153     }
154
155     *lo = ((uint32_t)*hi << (32 - n)) | (*lo >> n);
156     *hi >>= n;
157 }
158
159 /* Add B to A */
160 void s64b_add(int32_t *A1, uint32_t *A2, int32_t B1, uint32_t B2)
161 {
162     (*A2) += B2;
163
164     /* Overflawed? */
165     if ((*A2) < B2) {
166         (*A1) += B1 + 1;
167     } else {
168         (*A1) += B1;
169     }
170 }
171
172 /* Subtract B from A */
173 void s64b_sub(int32_t *A1, uint32_t *A2, int32_t B1, uint32_t B2)
174 {
175     /* Underflaw? */
176     if ((*A2) < B2) {
177         (*A1) -= B1 + 1;
178     } else {
179         (*A1) -= B1;
180     }
181
182     (*A2) -= B2;
183 }
184
185 /*
186  * Multiply A by B
187  *
188  * (A1*2^32 + A2h*2^16 + A2l) * (B1*2^32 + B2h*2^16 + B2l)
189  *  = (A1*B2 & 0xffffffff)*2^32
190  *   +(A2*B1 & 0xffffffff)*2^32
191  *   +(A2h*B2h & 0xffffffff)*2^32
192  *   +(A2h*B2l & 0xffff0000)*2^16
193  *   +(A2l*B2h & 0xffff0000)*2^16
194  *   +(A2*B2 & 0xffffffff)
195  */
196 void s64b_mul(int32_t *A1, uint32_t *A2, int32_t B1, uint32_t B2)
197 {
198     int32_t tmp1;
199     uint32_t A2val = (*A2);
200
201     uint32_t B2high = (B2 >> 16);
202     uint32_t A2high = (A2val >> 16);
203
204     (*A2) *= B2;
205     tmp1 = (*A1) * B2;
206     tmp1 += A2val * B1;
207     tmp1 += A2high * B2high;
208     tmp1 += (A2high * (uint16_t)B2) >> 16;
209     tmp1 += ((uint16_t)A2val * B2high) >> 16;
210
211     (*A1) = tmp1;
212 }
213
214 /* Compare A to B */
215 int s64b_cmp(int32_t A1, uint32_t A2, int32_t B1, uint32_t B2)
216 {
217     if (A1 > B1) {
218         return 1;
219     }
220     if (A1 < B1) {
221         return -1;
222     }
223     if (A2 > B2) {
224         return 1;
225     }
226     if (A2 < B2) {
227         return -1;
228     }
229     return 0;
230 }
231
232 /*
233  * Divide A by B
234  *
235  * Assumes that both A and B are positive
236  */
237 void s64b_div(int32_t *A1, uint32_t *A2, int32_t B1, uint32_t B2)
238 {
239     int32_t result1 = 0;
240     uint32_t result2 = 0;
241     int32_t A1val = (*A1);
242     uint32_t A2val = (*A2);
243     int bit = 0;
244
245     /* No result for B==0 */
246     if (B1 == 0 && B2 == 0) {
247         return;
248     }
249
250     /*
251      * Find the highest bit of quotient
252      */
253     while (s64b_cmp(A1val, A2val, B1, B2) == 1) {
254         s64b_lshift(&B1, &B2, 1);
255         bit++;
256     }
257
258     /* Extract bits of quotient one by one */
259     while (bit >= 0) {
260         if (s64b_cmp(A1val, A2val, B1, B2) >= 0) {
261             if (bit >= 32) {
262                 result1 |= (0x00000001UL << (bit - 32));
263             } else {
264                 result2 |= (0x00000001UL << bit);
265             }
266
267             s64b_sub(&A1val, &A2val, B1, B2);
268         }
269
270         s64b_rshift(&B1, &B2, 1);
271         bit--;
272     }
273
274     (*A1) = result1;
275     (*A2) = result2;
276 }
277
278 /* Reminder of ENERGY_DIVISION (A % B) */
279 void s64b_mod(int32_t *A1, uint32_t *A2, int32_t B1, uint32_t B2)
280 {
281     int32_t tmp1 = (*A1);
282     uint32_t tmp2 = (*A2);
283
284     s64b_div(&tmp1, &tmp2, B1, B2);
285     s64b_mul(&tmp1, &tmp2, B1, B2);
286     s64b_sub(A1, A2, tmp1, tmp2);
287 }
288
289 /*!
290  * @brief 符号なし32ビット整数のビット数を返す。
291  * @param x ビット数を調べたい変数
292  * @return ビット数
293  */
294 int count_bits(BIT_FLAGS x)
295 {
296     int n = 0;
297
298     if (x) {
299         do {
300             n++;
301         } while (0 != (x = x & (x - 1)));
302     }
303
304     return n;
305 }