ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/freezethaw.C
Revision: 1.7
Committed: Tue Jan 23 03:56:45 2007 UTC (17 years, 4 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.6: +0 -4 lines
Log Message:
I knew there was an explanation

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     : dynbuf (128 * 1024, 64 * 1024)
32     {
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     }
67    
68 root 1.4 char *
69     object_freezer::as_string ()
70 root 1.1 {
71     CALL_BEGIN (2);
72     CALL_ARG_SV (newRV_noinc (newSVpvn ((char *)linearise (), size ())));
73     CALL_ARG_SV (newRV_inc ((SV *)av));
74     CALL_CALL ("cf::object_freezer_as_string", G_SCALAR);
75    
76     char *res = count > 0
77 root 1.3 ? strdup (SvPVX (POPs))
78 root 1.1 : strdup ("[fatal error]");
79    
80     CALL_END;
81    
82     return res;
83     }
84    
85 root 1.4 int
86     fprintf (object_freezer &freezer, const char *format, ...)
87 root 1.1 {
88     va_list ap;
89    
90     va_start (ap, format);
91    
92     int len = vsnprintf ((char *)freezer.force (1024), 1024, format, ap);
93    
94     if (len >= 0)
95     freezer.alloc (len);
96    
97     va_end (ap);
98     }
99    
100 root 1.4 int
101     fputs (const char *s, object_freezer &freezer)
102 root 1.1 {
103     freezer.add (s);
104     }
105    
106     static const char thawer_eof[] = "\n\n\n\0\0\0";
107    
108 root 1.4 object_thawer::object_thawer (const char *path)
109     : name (strdup (path))
110 root 1.1 {
111     static const char eof[] = "\n\n\n\0\0\0";
112    
113     av = 0;
114     text = 0;
115     line = 0;
116    
117 root 1.4 if (path)
118 root 1.1 {
119     CALL_BEGIN (1);
120 root 1.4 CALL_ARG_SV (newSVpv (path, 0));
121 root 1.1 CALL_CALL ("cf::object_thawer_load", G_ARRAY);
122    
123     if (count == 2)
124     {
125     // second value - perl objects
126     {
127     SV *sv = POPs;
128     if (SvROK (sv))
129     av = (AV *)SvREFCNT_inc (SvRV (sv));
130     }
131    
132     // first value - text part, pad with 3 zeroes
133     {
134     SV *sv = POPs;
135     STRLEN len;
136     char *sv_ = SvPVbyte (sv, len);
137     text = newSV (len + sizeof (eof));
138     SvCUR_set (text, len);
139     memcpy (SvPVX (text), sv_, len);
140     memcpy (SvEND (text), eof, sizeof (eof)); // just to be sure
141    
142     line = SvPVX (text);
143     }
144     }
145    
146     CALL_END;
147     }
148     }
149    
150     object_thawer::object_thawer (const char *data, AV *perlav)
151 root 1.4 : name (strdup ("(memory stream"))
152 root 1.1 {
153     av = perlav;
154     text = newSVpv (data, 0);
155     sv_catpv (text, thawer_eof);
156     line = SvPVbyte_nolen (text);
157     }
158    
159 root 1.4 void
160     object_thawer::get (attachable *obj, int oid)
161 root 1.1 {
162     if (!av || oid < 0) // this is actually an error of sorts
163     return;
164    
165     SV **svp = av_fetch ((AV *)av, oid, 0);
166    
167     if (!svp || !SvROK (*svp))
168     {
169     printf ("trying to thaw duplicate or never-issued oid %d, ignoring.\n", oid);
170     return;
171     }
172    
173     if (!SvROK (*svp))
174     {
175     LOG (llevError, "deserialised perl object is not an RV");
176     return;
177     }
178    
179     HV *hv = (HV *)SvRV (*svp);
180    
181     if (SvTYPE (hv) != SVt_PVHV)
182     {
183     LOG (llevError, "deserialised perl object is not a PVHV");
184     return;
185     }
186    
187     if (obj->self)
188     {
189     // the hard way(?)
190    
191 root 1.6 CALL_BEGIN (2);
192     CALL_ARG_SV (newRV_inc ((SV *)obj->self));
193     CALL_ARG_SV (newRV_inc ((SV *)hv));
194     PUTBACK;
195     call_method ("thawer_merge", G_DISCARD | G_EVAL);
196     SPAGAIN;
197     CALL_END;
198 root 1.1 }
199     else
200     {
201     // the easy way(?)
202    
203     obj->self = hv;
204     SvRV_set (*svp, &PL_sv_undef);
205    
206     sv_magicext ((SV *)obj->self, 0, PERL_MAGIC_ext, &attachable::vtbl, (char *)obj, 0);
207     }
208    
209     obj->reattach ();
210     }
211    
212     object_thawer::~object_thawer ()
213     {
214     if (text) SvREFCNT_dec (text);
215     if (av) SvREFCNT_dec (av);
216 root 1.4
217     free ((void *)name);
218 root 1.1 }
219    
220 root 1.4 char *
221     fgets (char *s, int n, object_thawer &thawer)
222 root 1.1 {
223     char *p = thawer.line;
224     char *q = s;
225    
226     if (!p)
227     return 0;
228    
229     while (--n)
230     {
231     if (!*p)
232     break;
233    
234     *q++ = *p;
235    
236     if (*p++ == '\n')
237     break;
238     }
239    
240     *q = 0;
241     thawer.line = p;
242    
243     return s == q ? 0 : s;
244     }
245    
246 root 1.4 keyword
247     object_thawer::get_kv ()
248 root 1.1 {
249     if (!line)
250     return KW_EOF;
251    
252     for (;;)
253     {
254     char *p = line;
255    
256     if (!*p)
257     return KW_EOF;
258    
259     // parse keyword
260     while (*p > ' ')
261     p++;
262    
263     int klen = p - line;
264    
265     if (*p++ != '\n')
266     {
267     // parse value
268     while (*(unsigned char *)p <= ' ' && *p != '\n') // skip 0x01 .. 0x20
269     ++p;
270    
271     last_value = p;
272    
273     while (*p != '\n')
274     p++;
275    
276     *p++ = 0;
277     }
278     else
279     last_value = 0;
280    
281     line [klen] = 0;
282     keyword_idx *kw = kw_lex::match (line, klen);
283    
284     //printf ("KV %d<%s,%s>\n", kw ? kw->index : 0, line, last_value);//D
285    
286     last_keyword = line;
287     line = p;
288    
289     if (kw)
290     return kw->index;
291     else if (!*last_keyword || *last_keyword == '#')
292     ; // empty/comment line
293     else
294     return KW_ERROR;
295     }
296     }
297    
298 root 1.4 void
299     object_thawer::skip_kv (keyword kw)
300 root 1.1 {
301     shstr ml;
302    
303     switch (kw)
304     {
305     case KW_msg: get_ml (KW_endmsg , ml); break;
306     case KW_lore: get_ml (KW_endlore , ml); break;
307     case KW_maplore: get_ml (KW_endmaplore, ml); break;
308     }
309     }
310    
311 root 1.4 void
312     object_thawer::get (shstr &sh) const
313 root 1.1 {
314     if (last_value)
315     sh = last_value;
316     else
317     {
318     sh = "<value missing>";
319 root 1.5 LOG (llevError, "keyword \"%s\" requires value, substituting with <value missing>\n", last_keyword);//TODO: add filename
320 root 1.1 }
321     }
322    
323 root 1.4 void
324     object_thawer::get_ml (keyword kend, shstr &sh)
325 root 1.1 {
326     char kw[128];
327    
328     int klen = keyword_len [kend];
329    
330     kw [0] = '\n';
331     memcpy (kw + 1, keyword_str [kend], klen);
332     kw [klen + 1] = '\n';
333     kw [klen + 2] = 0;
334    
335     // first test for completely empty msg... "endXXX\n"
336     if (!strncmp (line, kw + 1, klen + 1))
337     {
338     sh = 0;
339    
340     line += klen + 1;
341    
342     return;
343     }
344     else
345     {
346     // multi-line strings are delimited by "\nendXXX\n" or "endXXX\n" (NULL)
347    
348     char *end = strstr (line, kw);
349    
350     if (!end)
351     {
352     sh = 0;
353     return;
354     }
355    
356     *end = 0;
357     sh = line;
358    
359     line = end + keyword_len [kend] + 1;
360    
361     while (*line++ != '\n')
362     ;
363     }
364     }
365    
366 root 1.4 sint32
367     object_thawer::get_sint32 () const
368 root 1.1 {
369     char *p = last_value;
370    
371     if (!p)
372     return 0;
373    
374     sint32 val = 0;
375     bool negate;
376    
377     if (*p == '-')
378     {
379     negate = true;
380     ++p;
381     }
382     else
383     negate = false;
384    
385     do
386     {
387     val *= 10;
388     val += *p++ - '0';
389     }
390     while (*p);
391    
392     return negate ? -val : val;
393     }
394    
395 root 1.4 sint64
396     object_thawer::get_sint64 () const
397 root 1.1 {
398     return last_value ? atoll (last_value) : 0;
399     }
400    
401 root 1.4 double
402     object_thawer::get_double () const
403 root 1.1 {
404     return last_value ? atof (last_value) : 0;
405     }
406