ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/freezethaw.C
Revision: 1.20
Committed: Sun May 27 23:14:37 2007 UTC (17 years ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.19: +2 -0 lines
Log Message:
remove remainign compatibility cruft

File Contents

# Content
1 /*****************************************************************************/
2 /* CrossFire, A roguelike realtime multiplayer game */
3 /*****************************************************************************/
4
5 /*
6 * This code is placed under the GNU General Public Licence (GPL)
7 *
8 * Copyright (C) 2006 by Marc Lehmann <crossfire@schmorp.de>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 #include "global.h" // bug in cfperl.h, doesn't include interface_class stuff
26 #include "logger.h"
27 #include "cfperl.h"
28 #include "kw_hash.h"
29
30 object_freezer::object_freezer ()
31 : dynbuf_text (128 * 1024, 64 * 1024)
32 {
33 av = newAV ();
34 }
35
36 object_freezer::~object_freezer ()
37 {
38 SvREFCNT_dec (av);
39 }
40
41 void
42 object_freezer::put (attachable *ext)
43 {
44 ext->optimise ();
45
46 if (ext->self)
47 {
48 int idx = AvFILLp ((AV *)av) + 1;
49 av_store (av, idx, newRV_inc ((SV *)ext->self));
50
51 add ((void *)"oid ", 4);
52 add ((sint32)idx);
53 add ('\n');
54 }
55 }
56
57 bool
58 object_freezer::save (const char *path)
59 {
60 CALL_BEGIN (3);
61 CALL_ARG_SV (newSVpv (path, 0));
62 CALL_ARG_SV (newRV_noinc (newSVpvn ((char *)linearise (), size ())));
63 CALL_ARG_SV (newRV_inc ((SV *)av));
64 CALL_CALL ("cf::object_freezer_save", G_VOID | G_DISCARD);
65 CALL_END;
66
67 return 1;
68 }
69
70 char *
71 object_freezer::as_string ()
72 {
73 CALL_BEGIN (2);
74 CALL_ARG_SV (newRV_noinc (newSVpvn ((char *)linearise (), size ())));
75 CALL_ARG_SV (newRV_inc ((SV *)av));
76 CALL_CALL ("cf::object_freezer_as_string", G_SCALAR);
77
78 char *res = count > 0
79 ? strdup (SvPVX (POPs))
80 : strdup ("[fatal error]");
81
82 CALL_END;
83
84 return res;
85 }
86
87 #if 0
88 void
89 fprintf (object_freezer &freezer, const char *format, ...)
90 {
91 va_list ap;
92
93 va_start (ap, format);
94
95 int len = vsnprintf ((char *)freezer.force (1024), 1024, format, ap);
96
97 if (len >= 0)
98 freezer.alloc (len);
99
100 va_end (ap);
101 }
102
103 // XXX: function not returning an int
104 void
105 fputs (const char *s, object_freezer &freezer)
106 {
107 freezer.add (s);
108 }
109 #endif
110
111 static const char thawer_eof[] = "\n\n\n\0\0\0";
112
113 object_thawer::object_thawer (const char *path)
114 : name (strdup (path))
115 {
116 static const char eof[] = "\n\n\n\0\0\0";
117
118 av = 0;
119 text = 0;
120 line = 0;
121 linenum = 0;
122
123 kw = KW_ERROR;
124 kw_str = 0;
125 value = 0;
126
127 if (path)
128 {
129 CALL_BEGIN (1);
130 CALL_ARG_SV (newSVpv (path, 0));
131 CALL_CALL ("cf::object_thawer_load", G_ARRAY);
132
133 if (count == 2)
134 {
135 // second value - perl objects
136 {
137 SV *sv = POPs;
138 if (SvROK (sv))
139 av = (AV *)SvREFCNT_inc (SvRV (sv));
140 }
141
142 // first value - text part, pad with 3 zeroes
143 {
144 SV *sv = POPs;
145 STRLEN len;
146 char *sv_ = SvPVbyte (sv, len);
147 text = newSV (len + sizeof (eof));
148 SvCUR_set (text, len);
149 memcpy (SvPVX (text), sv_, len);
150 memcpy (SvEND (text), eof, sizeof (eof)); // just to be sure
151
152 line = SvPVX (text);
153 }
154 }
155
156 CALL_END;
157 }
158 }
159
160 object_thawer::object_thawer (const char *data, AV *perlav)
161 : name (strdup ("(memory stream"))
162 {
163 av = perlav;
164 text = newSVpv (data, 0);
165 sv_catpv (text, thawer_eof);
166 line = SvPVbyte_nolen (text);
167 }
168
169 void
170 object_thawer::get (attachable *obj, int oid)
171 {
172 if (!av || oid < 0) // this is actually an error of sorts
173 return;
174
175 SV **svp = av_fetch ((AV *)av, oid, 0);
176
177 if (!svp || !SvROK (*svp))
178 {
179 LOG (llevError, "trying to thaw duplicate or never-issued oid %d, ignoring.\n", oid);
180 return;
181 }
182
183 if (!SvROK (*svp))
184 {
185 LOG (llevError, "deserialised perl object is not an RV\n");
186 return;
187 }
188
189 HV *hv = (HV *)SvRV (*svp);
190
191 if (SvTYPE (hv) != SVt_PVHV)
192 {
193 LOG (llevError, "deserialised perl object is not a PVHV\n");
194 return;
195 }
196
197 if (obj->self)
198 {
199 // the hard way(?)
200
201 CALL_BEGIN (2);
202 CALL_ARG_SV (newRV_inc ((SV *)obj->self));
203 CALL_ARG_SV (newRV_inc ((SV *)hv));
204 PUTBACK;
205 call_method ("thawer_merge", G_DISCARD | G_EVAL);
206 SPAGAIN;
207 CALL_END;
208 }
209 else
210 {
211 // the easy way(?)
212
213 obj->self = hv;
214 SvRV_set (*svp, &PL_sv_undef);
215
216 sv_magicext ((SV *)obj->self, 0, PERL_MAGIC_ext, &attachable::vtbl, (char *)obj, 0);
217 }
218
219 obj->reattach ();
220 }
221
222 object_thawer::~object_thawer ()
223 {
224 if (text) SvREFCNT_dec (text);
225 if (av) SvREFCNT_dec (av);
226
227 free ((void *)name);
228 }
229
230 //TODO: remove
231 char *
232 fgets (char *s, int n, object_thawer &thawer)
233 {
234 char *p = thawer.line;
235 char *q = s;
236
237 if (!p)
238 return 0;
239
240 while (--n)
241 {
242 if (!*p)
243 break;
244
245 *q++ = *p;
246
247 if (*p++ == '\n')
248 {
249 ++thawer.linenum;
250 break;
251 }
252 }
253
254 *q = 0;
255 thawer.line = p;
256
257 return s == q ? 0 : s;
258 }
259
260 bool
261 object_thawer::parse_error (const char *type, const char *name, bool skip)
262 {
263 if (!type) type = "file section";
264 if (!name) name = "generic";
265
266 switch (kw)
267 {
268 case KW_EOF:
269 LOG (llevError, "%s:%d end of file while reading %s '%s', aborting load.\n",
270 this->name, linenum, type, name);
271 return false;
272
273 case KW_ERROR:
274 LOG (llevError, "%s:%d error while reading %s '%s', at '%s', aborting load.\n",
275 this->name, linenum,
276 type, name,
277 kw_str ? kw_str : "<file load>");
278 return false;
279
280 default:
281 LOG (llevError, "%s:%d unexpected line (%s %s) while reading %s '%s', %s.\n",
282 this->name, linenum,
283 kw_str ? kw_str : "<null>",
284 value ? value : "<null>",
285 type, name,
286 skip ? "skipping line" : "aborting load");
287 return skip;
288 }
289 }
290
291 void
292 object_thawer::next ()
293 {
294 if (!line)
295 {
296 kw = KW_ERROR;
297 return;
298 }
299
300 for (;;)
301 {
302 char *p = line;
303
304 if (*p <= ' ')
305 {
306 // skip whitespace (only some files need this)
307 while (*p == ' ' || *p == '\t')
308 p++;
309
310 line = p;
311 }
312
313 if (!*p)
314 {
315 kw = KW_EOF;
316 break;
317 }
318
319 // parse keyword
320 while (*p > ' ')
321 p++;
322
323 int klen = p - line;
324
325 value_nn = "";
326 value = 0;
327
328 if (*p++ != '\n')
329 {
330 // parse value
331 while (*(unsigned char *)p <= ' ' && *p != '\n')
332 ++p;
333
334 value_nn = value = p;
335
336 while (*p != '\n')
337 p++;
338
339 *p++ = 0;
340 }
341
342 ++linenum;
343 line [klen] = 0;
344 keyword_idx *kw_idx = kw_lex::match (line, klen);
345
346 kw_str = line;
347 line = p;
348
349 if (kw_idx)
350 {
351 kw = kw_idx->index;
352 break;
353 }
354 else if (!*kw_str || *kw_str == '#')
355 ; // empty/comment line
356 else
357 {
358 kw = KW_ERROR;
359 break;
360 }
361 }
362 }
363
364 void
365 object_thawer::skip ()
366 {
367 shstr ml;
368
369 switch (kw)
370 {
371 case KW_msg: get_ml (KW_endmsg , ml); break;
372 case KW_lore: get_ml (KW_endlore , ml); break;
373 case KW_maplore: get_ml (KW_endmaplore, ml); break;
374 default: break;
375 }
376
377 next ();
378 }
379
380 void
381 object_thawer::get_ml (keyword kend, shstr &sh)
382 {
383 char kw[128];
384
385 int klen = keyword_len [kend];
386
387 kw [0] = '\n';
388 memcpy (kw + 1, keyword_str [kend], klen);
389 kw [klen + 1] = '\n';
390 kw [klen + 2] = 0;
391
392 ++linenum;
393
394 // first test for completely empty msg... "endXXX\n"
395 if (!strncmp (line, kw + 1, klen + 1))
396 {
397 sh = 0;
398
399 line += klen + 1;
400
401 return;
402 }
403 else
404 {
405 // multi-line strings are delimited by "\nendXXX\n" or "endXXX\n" (NULL)
406
407 char *end = strstr (line, kw);
408
409 if (!end)
410 {
411 sh = 0;
412 return;
413 }
414
415 *end = 0;
416 sh = line;
417
418 // count line numbers
419 while (line < end)
420 linenum += *line++ == '\n';
421
422 line += keyword_len [kend];
423
424 while (*line++ != '\n')
425 ;
426
427 ++linenum;
428 }
429 }
430
431 sint32
432 object_thawer::get_sint32 () const
433 {
434 char *p = value_nn;
435
436 sint32 val = 0;
437 bool negate;
438
439 if (*p == '-')
440 {
441 negate = true;
442 ++p;
443 }
444 else
445 negate = false;
446
447 do
448 {
449 val *= 10;
450 val += *p++ - '0';
451 }
452 while (*p);
453
454 return negate ? -val : val;
455 }
456