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 (16 years, 11 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.19: +2 -0 lines
Log Message:
remove remainign compatibility cruft

File Contents

# User Rev Content
1 root 1.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 root 1.4 #include "global.h" // bug in cfperl.h, doesn't include interface_class stuff
26 root 1.1 #include "logger.h"
27     #include "cfperl.h"
28     #include "kw_hash.h"
29    
30     object_freezer::object_freezer ()
31 root 1.17 : dynbuf_text (128 * 1024, 64 * 1024)
32 root 1.1 {
33     av = newAV ();
34     }
35    
36     object_freezer::~object_freezer ()
37     {
38     SvREFCNT_dec (av);
39     }
40    
41 root 1.4 void
42     object_freezer::put (attachable *ext)
43 root 1.1 {
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 root 1.4 bool
58     object_freezer::save (const char *path)
59 root 1.1 {
60     CALL_BEGIN (3);
61 root 1.4 CALL_ARG_SV (newSVpv (path, 0));
62 root 1.1 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 root 1.13
67     return 1;
68 root 1.1 }
69    
70 root 1.4 char *
71     object_freezer::as_string ()
72 root 1.1 {
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 root 1.3 ? strdup (SvPVX (POPs))
80 root 1.1 : strdup ("[fatal error]");
81    
82     CALL_END;
83    
84     return res;
85     }
86    
87 root 1.20 #if 0
88 root 1.13 void
89 root 1.4 fprintf (object_freezer &freezer, const char *format, ...)
90 root 1.1 {
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 pippijn 1.12 // XXX: function not returning an int
104 root 1.13 void
105 root 1.4 fputs (const char *s, object_freezer &freezer)
106 root 1.1 {
107     freezer.add (s);
108     }
109 root 1.20 #endif
110 root 1.1
111     static const char thawer_eof[] = "\n\n\n\0\0\0";
112    
113 root 1.4 object_thawer::object_thawer (const char *path)
114     : name (strdup (path))
115 root 1.1 {
116     static const char eof[] = "\n\n\n\0\0\0";
117    
118 root 1.10 av = 0;
119     text = 0;
120     line = 0;
121 root 1.8 linenum = 0;
122 root 1.1
123 root 1.10 kw = KW_ERROR;
124     kw_str = 0;
125     value = 0;
126    
127 root 1.4 if (path)
128 root 1.1 {
129     CALL_BEGIN (1);
130 root 1.4 CALL_ARG_SV (newSVpv (path, 0));
131 root 1.1 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 root 1.4 : name (strdup ("(memory stream"))
162 root 1.1 {
163     av = perlav;
164     text = newSVpv (data, 0);
165     sv_catpv (text, thawer_eof);
166     line = SvPVbyte_nolen (text);
167     }
168    
169 root 1.4 void
170     object_thawer::get (attachable *obj, int oid)
171 root 1.1 {
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 root 1.15 LOG (llevError, "trying to thaw duplicate or never-issued oid %d, ignoring.\n", oid);
180 root 1.1 return;
181     }
182    
183     if (!SvROK (*svp))
184     {
185 root 1.15 LOG (llevError, "deserialised perl object is not an RV\n");
186 root 1.1 return;
187     }
188    
189     HV *hv = (HV *)SvRV (*svp);
190    
191     if (SvTYPE (hv) != SVt_PVHV)
192     {
193 root 1.15 LOG (llevError, "deserialised perl object is not a PVHV\n");
194 root 1.1 return;
195     }
196    
197     if (obj->self)
198     {
199     // the hard way(?)
200    
201 root 1.6 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 root 1.1 }
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 root 1.4
227     free ((void *)name);
228 root 1.1 }
229    
230 root 1.8 //TODO: remove
231 root 1.4 char *
232     fgets (char *s, int n, object_thawer &thawer)
233 root 1.1 {
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 root 1.8 {
249     ++thawer.linenum;
250     break;
251     }
252 root 1.1 }
253    
254     *q = 0;
255     thawer.line = p;
256    
257     return s == q ? 0 : s;
258     }
259    
260 root 1.8 bool
261 root 1.10 object_thawer::parse_error (const char *type, const char *name, bool skip)
262 root 1.8 {
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 root 1.10 LOG (llevError, "%s:%d error while reading %s '%s', at '%s', aborting load.\n",
275 root 1.8 this->name, linenum,
276 root 1.10 type, name,
277     kw_str ? kw_str : "<file load>");
278 root 1.8 return false;
279    
280     default:
281 root 1.9 LOG (llevError, "%s:%d unexpected line (%s %s) while reading %s '%s', %s.\n",
282 root 1.8 this->name, linenum,
283 root 1.10 kw_str ? kw_str : "<null>",
284     value ? value : "<null>",
285 root 1.8 type, name,
286     skip ? "skipping line" : "aborting load");
287     return skip;
288     }
289     }
290    
291 root 1.10 void
292 root 1.11 object_thawer::next ()
293 root 1.1 {
294     if (!line)
295 root 1.10 {
296     kw = KW_ERROR;
297     return;
298     }
299 root 1.1
300     for (;;)
301     {
302     char *p = line;
303    
304 root 1.16 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 root 1.1 if (!*p)
314 root 1.10 {
315     kw = KW_EOF;
316     break;
317     }
318 root 1.1
319     // parse keyword
320     while (*p > ' ')
321     p++;
322    
323     int klen = p - line;
324    
325 root 1.19 value_nn = "";
326 root 1.16 value = 0;
327    
328 root 1.1 if (*p++ != '\n')
329     {
330     // parse value
331 root 1.16 while (*(unsigned char *)p <= ' ' && *p != '\n')
332 root 1.1 ++p;
333    
334 root 1.19 value_nn = value = p;
335 root 1.1
336     while (*p != '\n')
337     p++;
338    
339     *p++ = 0;
340     }
341    
342 root 1.8 ++linenum;
343 root 1.1 line [klen] = 0;
344 root 1.10 keyword_idx *kw_idx = kw_lex::match (line, klen);
345 root 1.1
346 root 1.10 kw_str = line;
347 root 1.1 line = p;
348    
349 root 1.10 if (kw_idx)
350     {
351     kw = kw_idx->index;
352     break;
353     }
354     else if (!*kw_str || *kw_str == '#')
355 root 1.1 ; // empty/comment line
356     else
357 root 1.10 {
358     kw = KW_ERROR;
359     break;
360     }
361 root 1.1 }
362     }
363    
364 root 1.4 void
365 root 1.11 object_thawer::skip ()
366 root 1.1 {
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 pippijn 1.14 default: break;
375 root 1.1 }
376 root 1.10
377 root 1.11 next ();
378 root 1.1 }
379    
380 root 1.4 void
381     object_thawer::get_ml (keyword kend, shstr &sh)
382 root 1.1 {
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 root 1.8 ++linenum;
393    
394 root 1.1 // 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 root 1.8 // count line numbers
419     while (line < end)
420     linenum += *line++ == '\n';
421    
422     line += keyword_len [kend];
423 root 1.1
424     while (*line++ != '\n')
425     ;
426 root 1.8
427     ++linenum;
428 root 1.1 }
429     }
430    
431 root 1.4 sint32
432     object_thawer::get_sint32 () const
433 root 1.1 {
434 root 1.19 char *p = value_nn;
435 root 1.1
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