Commit | Line | Data |
---|---|---|
f0ffaed8 | 1 | ;# $Id: Storable.pm,v 0.7.1.3 2000/08/23 22:49:25 ram Exp $ |
7a6a85bf RG |
2 | ;# |
3 | ;# Copyright (c) 1995-2000, Raphael Manfredi | |
4 | ;# | |
5 | ;# You may redistribute only under the terms of the Artistic License, | |
6 | ;# as specified in the README file that comes with the distribution. | |
7 | ;# | |
8 | ;# $Log: Storable.pm,v $ | |
f0ffaed8 JH |
9 | ;# Revision 0.7.1.3 2000/08/23 22:49:25 ram |
10 | ;# patch3: updated version number | |
11 | ;# | |
7a6a85bf RG |
12 | ;# Revision 0.7.1.2 2000/08/14 07:18:40 ram |
13 | ;# patch2: increased version number | |
14 | ;# | |
15 | ;# Revision 0.7.1.1 2000/08/13 20:08:58 ram | |
16 | ;# patch1: mention new Clone(3) extension in SEE ALSO | |
17 | ;# patch1: contributor Marc Lehmann added overloading and ref to tied items | |
18 | ;# patch1: updated e-mail from Benjamin Holzman | |
19 | ;# | |
20 | ;# Revision 0.7 2000/08/03 22:04:44 ram | |
21 | ;# Baseline for second beta release. | |
22 | ;# | |
23 | ||
24 | require DynaLoader; | |
25 | require Exporter; | |
26 | package Storable; @ISA = qw(Exporter DynaLoader); | |
27 | ||
28 | @EXPORT = qw(store retrieve); | |
29 | @EXPORT_OK = qw( | |
30 | nstore store_fd nstore_fd retrieve_fd | |
31 | freeze nfreeze thaw | |
32 | dclone | |
33 | ); | |
34 | ||
35 | use AutoLoader; | |
36 | use vars qw($forgive_me $VERSION); | |
37 | ||
f0ffaed8 | 38 | $VERSION = '0.703'; |
7a6a85bf RG |
39 | *AUTOLOAD = \&AutoLoader::AUTOLOAD; # Grrr... |
40 | ||
41 | # | |
42 | # Use of Log::Agent is optional | |
43 | # | |
44 | ||
45 | eval "use Log::Agent"; | |
46 | ||
47 | unless (defined @Log::Agent::EXPORT) { | |
48 | eval q{ | |
49 | sub logcroak { | |
50 | require Carp; | |
51 | Carp::croak(@_); | |
52 | } | |
53 | }; | |
54 | } | |
55 | ||
56 | sub logcroak; | |
57 | ||
58 | bootstrap Storable; | |
59 | 1; | |
60 | __END__ | |
61 | ||
62 | # | |
63 | # store | |
64 | # | |
65 | # Store target object hierarchy, identified by a reference to its root. | |
66 | # The stored object tree may later be retrieved to memory via retrieve. | |
67 | # Returns undef if an I/O error occurred, in which case the file is | |
68 | # removed. | |
69 | # | |
70 | sub store { | |
71 | return _store(\&pstore, @_); | |
72 | } | |
73 | ||
74 | # | |
75 | # nstore | |
76 | # | |
77 | # Same as store, but in network order. | |
78 | # | |
79 | sub nstore { | |
80 | return _store(\&net_pstore, @_); | |
81 | } | |
82 | ||
83 | # Internal store to file routine | |
84 | sub _store { | |
85 | my $xsptr = shift; | |
86 | my $self = shift; | |
87 | my ($file) = @_; | |
88 | logcroak "not a reference" unless ref($self); | |
89 | logcroak "too many arguments" unless @_ == 1; # No @foo in arglist | |
90 | local *FILE; | |
91 | open(FILE, ">$file") || logcroak "can't create $file: $!"; | |
92 | binmode FILE; # Archaic systems... | |
93 | my $da = $@; # Don't mess if called from exception handler | |
94 | my $ret; | |
95 | # Call C routine nstore or pstore, depending on network order | |
96 | eval { $ret = &$xsptr(*FILE, $self) }; | |
97 | close(FILE) or $ret = undef; | |
98 | unlink($file) or warn "Can't unlink $file: $!\n" if $@ || !defined $ret; | |
99 | logcroak $@ if $@ =~ s/\.?\n$/,/; | |
100 | $@ = $da; | |
101 | return $ret ? $ret : undef; | |
102 | } | |
103 | ||
104 | # | |
105 | # store_fd | |
106 | # | |
107 | # Same as store, but perform on an already opened file descriptor instead. | |
108 | # Returns undef if an I/O error occurred. | |
109 | # | |
110 | sub store_fd { | |
111 | return _store_fd(\&pstore, @_); | |
112 | } | |
113 | ||
114 | # | |
115 | # nstore_fd | |
116 | # | |
117 | # Same as store_fd, but in network order. | |
118 | # | |
119 | sub nstore_fd { | |
120 | my ($self, $file) = @_; | |
121 | return _store_fd(\&net_pstore, @_); | |
122 | } | |
123 | ||
124 | # Internal store routine on opened file descriptor | |
125 | sub _store_fd { | |
126 | my $xsptr = shift; | |
127 | my $self = shift; | |
128 | my ($file) = @_; | |
129 | logcroak "not a reference" unless ref($self); | |
130 | logcroak "too many arguments" unless @_ == 1; # No @foo in arglist | |
131 | my $fd = fileno($file); | |
132 | logcroak "not a valid file descriptor" unless defined $fd; | |
133 | my $da = $@; # Don't mess if called from exception handler | |
134 | my $ret; | |
135 | # Call C routine nstore or pstore, depending on network order | |
136 | eval { $ret = &$xsptr($file, $self) }; | |
137 | logcroak $@ if $@ =~ s/\.?\n$/,/; | |
138 | $@ = $da; | |
139 | return $ret ? $ret : undef; | |
140 | } | |
141 | ||
142 | # | |
143 | # freeze | |
144 | # | |
145 | # Store oject and its hierarchy in memory and return a scalar | |
146 | # containing the result. | |
147 | # | |
148 | sub freeze { | |
149 | _freeze(\&mstore, @_); | |
150 | } | |
151 | ||
152 | # | |
153 | # nfreeze | |
154 | # | |
155 | # Same as freeze but in network order. | |
156 | # | |
157 | sub nfreeze { | |
158 | _freeze(\&net_mstore, @_); | |
159 | } | |
160 | ||
161 | # Internal freeze routine | |
162 | sub _freeze { | |
163 | my $xsptr = shift; | |
164 | my $self = shift; | |
165 | logcroak "not a reference" unless ref($self); | |
166 | logcroak "too many arguments" unless @_ == 0; # No @foo in arglist | |
167 | my $da = $@; # Don't mess if called from exception handler | |
168 | my $ret; | |
169 | # Call C routine mstore or net_mstore, depending on network order | |
170 | eval { $ret = &$xsptr($self) }; | |
171 | logcroak $@ if $@ =~ s/\.?\n$/,/; | |
172 | $@ = $da; | |
173 | return $ret ? $ret : undef; | |
174 | } | |
175 | ||
176 | # | |
177 | # retrieve | |
178 | # | |
179 | # Retrieve object hierarchy from disk, returning a reference to the root | |
180 | # object of that tree. | |
181 | # | |
182 | sub retrieve { | |
183 | my ($file) = @_; | |
184 | local *FILE; | |
185 | open(FILE, "$file") || logcroak "can't open $file: $!"; | |
186 | binmode FILE; # Archaic systems... | |
187 | my $self; | |
188 | my $da = $@; # Could be from exception handler | |
189 | eval { $self = pretrieve(*FILE) }; # Call C routine | |
190 | close(FILE); | |
191 | logcroak $@ if $@ =~ s/\.?\n$/,/; | |
192 | $@ = $da; | |
193 | return $self; | |
194 | } | |
195 | ||
196 | # | |
197 | # retrieve_fd | |
198 | # | |
199 | # Same as retrieve, but perform from an already opened file descriptor instead. | |
200 | # | |
201 | sub retrieve_fd { | |
202 | my ($file) = @_; | |
203 | my $fd = fileno($file); | |
204 | logcroak "not a valid file descriptor" unless defined $fd; | |
205 | my $self; | |
206 | my $da = $@; # Could be from exception handler | |
207 | eval { $self = pretrieve($file) }; # Call C routine | |
208 | logcroak $@ if $@ =~ s/\.?\n$/,/; | |
209 | $@ = $da; | |
210 | return $self; | |
211 | } | |
212 | ||
213 | # | |
214 | # thaw | |
215 | # | |
216 | # Recreate objects in memory from an existing frozen image created | |
217 | # by freeze. If the frozen image passed is undef, return undef. | |
218 | # | |
219 | sub thaw { | |
220 | my ($frozen) = @_; | |
221 | return undef unless defined $frozen; | |
222 | my $self; | |
223 | my $da = $@; # Could be from exception handler | |
224 | eval { $self = mretrieve($frozen) }; # Call C routine | |
225 | logcroak $@ if $@ =~ s/\.?\n$/,/; | |
226 | $@ = $da; | |
227 | return $self; | |
228 | } | |
229 | ||
230 | =head1 NAME | |
231 | ||
232 | Storable - persistency for perl data structures | |
233 | ||
234 | =head1 SYNOPSIS | |
235 | ||
236 | use Storable; | |
237 | store \%table, 'file'; | |
238 | $hashref = retrieve('file'); | |
239 | ||
240 | use Storable qw(nstore store_fd nstore_fd freeze thaw dclone); | |
241 | ||
242 | # Network order | |
243 | nstore \%table, 'file'; | |
244 | $hashref = retrieve('file'); # There is NO nretrieve() | |
245 | ||
246 | # Storing to and retrieving from an already opened file | |
247 | store_fd \@array, \*STDOUT; | |
248 | nstore_fd \%table, \*STDOUT; | |
249 | $aryref = retrieve_fd(\*SOCKET); | |
250 | $hashref = retrieve_fd(\*SOCKET); | |
251 | ||
252 | # Serializing to memory | |
253 | $serialized = freeze \%table; | |
254 | %table_clone = %{ thaw($serialized) }; | |
255 | ||
256 | # Deep (recursive) cloning | |
257 | $cloneref = dclone($ref); | |
258 | ||
259 | =head1 DESCRIPTION | |
260 | ||
261 | The Storable package brings persistency to your perl data structures | |
262 | containing SCALAR, ARRAY, HASH or REF objects, i.e. anything that can be | |
263 | convenientely stored to disk and retrieved at a later time. | |
264 | ||
265 | It can be used in the regular procedural way by calling C<store> with | |
266 | a reference to the object to be stored, along with the file name where | |
267 | the image should be written. | |
268 | The routine returns C<undef> for I/O problems or other internal error, | |
269 | a true value otherwise. Serious errors are propagated as a C<die> exception. | |
270 | ||
271 | To retrieve data stored to disk, use C<retrieve> with a file name, | |
272 | and the objects stored into that file are recreated into memory for you, | |
273 | a I<reference> to the root object being returned. In case an I/O error | |
274 | occurs while reading, C<undef> is returned instead. Other serious | |
275 | errors are propagated via C<die>. | |
276 | ||
277 | Since storage is performed recursively, you might want to stuff references | |
278 | to objects that share a lot of common data into a single array or hash | |
279 | table, and then store that object. That way, when you retrieve back the | |
280 | whole thing, the objects will continue to share what they originally shared. | |
281 | ||
282 | At the cost of a slight header overhead, you may store to an already | |
283 | opened file descriptor using the C<store_fd> routine, and retrieve | |
284 | from a file via C<retrieve_fd>. Those names aren't imported by default, | |
285 | so you will have to do that explicitely if you need those routines. | |
286 | The file descriptor you supply must be already opened, for read | |
287 | if you're going to retrieve and for write if you wish to store. | |
288 | ||
289 | store_fd(\%table, *STDOUT) || die "can't store to stdout\n"; | |
290 | $hashref = retrieve_fd(*STDIN); | |
291 | ||
292 | You can also store data in network order to allow easy sharing across | |
293 | multiple platforms, or when storing on a socket known to be remotely | |
294 | connected. The routines to call have an initial C<n> prefix for I<network>, | |
295 | as in C<nstore> and C<nstore_fd>. At retrieval time, your data will be | |
296 | correctly restored so you don't have to know whether you're restoring | |
297 | from native or network ordered data. | |
298 | ||
299 | When using C<retrieve_fd>, objects are retrieved in sequence, one | |
300 | object (i.e. one recursive tree) per associated C<store_fd>. | |
301 | ||
302 | If you're more from the object-oriented camp, you can inherit from | |
303 | Storable and directly store your objects by invoking C<store> as | |
304 | a method. The fact that the root of the to-be-stored tree is a | |
305 | blessed reference (i.e. an object) is special-cased so that the | |
306 | retrieve does not provide a reference to that object but rather the | |
307 | blessed object reference itself. (Otherwise, you'd get a reference | |
308 | to that blessed object). | |
309 | ||
310 | =head1 MEMORY STORE | |
311 | ||
312 | The Storable engine can also store data into a Perl scalar instead, to | |
313 | later retrieve them. This is mainly used to freeze a complex structure in | |
314 | some safe compact memory place (where it can possibly be sent to another | |
315 | process via some IPC, since freezing the structure also serializes it in | |
316 | effect). Later on, and maybe somewhere else, you can thaw the Perl scalar | |
317 | out and recreate the original complex structure in memory. | |
318 | ||
319 | Surprisingly, the routines to be called are named C<freeze> and C<thaw>. | |
320 | If you wish to send out the frozen scalar to another machine, use | |
321 | C<nfreeze> instead to get a portable image. | |
322 | ||
323 | Note that freezing an object structure and immediately thawing it | |
324 | actually achieves a deep cloning of that structure: | |
325 | ||
326 | dclone(.) = thaw(freeze(.)) | |
327 | ||
328 | Storable provides you with a C<dclone> interface which does not create | |
329 | that intermediary scalar but instead freezes the structure in some | |
330 | internal memory space and then immediatly thaws it out. | |
331 | ||
332 | =head1 SPEED | |
333 | ||
334 | The heart of Storable is written in C for decent speed. Extra low-level | |
335 | optimization have been made when manipulating perl internals, to | |
336 | sacrifice encapsulation for the benefit of a greater speed. | |
337 | ||
338 | =head1 CANONICAL REPRESENTATION | |
339 | ||
340 | Normally Storable stores elements of hashes in the order they are | |
341 | stored internally by Perl, i.e. pseudo-randomly. If you set | |
342 | C<$Storable::canonical> to some C<TRUE> value, Storable will store | |
343 | hashes with the elements sorted by their key. This allows you to | |
344 | compare data structures by comparing their frozen representations (or | |
345 | even the compressed frozen representations), which can be useful for | |
346 | creating lookup tables for complicated queries. | |
347 | ||
348 | Canonical order does not imply network order, those are two orthogonal | |
349 | settings. | |
350 | ||
351 | =head1 ERROR REPORTING | |
352 | ||
353 | Storable uses the "exception" paradigm, in that it does not try to workaround | |
354 | failures: if something bad happens, an exception is generated from the | |
355 | caller's perspective (see L<Carp> and C<croak()>). Use eval {} to trap | |
356 | those exceptions. | |
357 | ||
358 | When Storable croaks, it tries to report the error via the C<logcroak()> | |
359 | routine from the C<Log::Agent> package, if it is available. | |
360 | ||
361 | =head1 WIZARDS ONLY | |
362 | ||
363 | =head2 Hooks | |
364 | ||
365 | Any class may define hooks that will be called during the serialization | |
366 | and deserialization process on objects that are instances of that class. | |
367 | Those hooks can redefine the way serialization is performed (and therefore, | |
368 | how the symetrical deserialization should be conducted). | |
369 | ||
370 | Since we said earlier: | |
371 | ||
372 | dclone(.) = thaw(freeze(.)) | |
373 | ||
374 | everything we say about hooks should also hold for deep cloning. However, | |
375 | hooks get to know whether the operation is a mere serialization, or a cloning. | |
376 | ||
377 | Therefore, when serializing hooks are involved, | |
378 | ||
379 | dclone(.) <> thaw(freeze(.)) | |
380 | ||
381 | Well, you could keep them in sync, but there's no guarantee it will always | |
382 | hold on classes somebody else wrote. Besides, there is little to gain in | |
383 | doing so: a serializing hook could only keep one attribute of an object, | |
384 | which is probably not what should happen during a deep cloning of that | |
385 | same object. | |
386 | ||
387 | Here is the hooking interface: | |
388 | ||
389 | =over | |
390 | ||
391 | =item C<STORABLE_freeze> I<obj>, I<cloning> | |
392 | ||
393 | The serializing hook, called on the object during serialization. It can be | |
394 | inherited, or defined in the class itself, like any other method. | |
395 | ||
396 | Arguments: I<obj> is the object to serialize, I<cloning> is a flag indicating | |
397 | whether we're in a dclone() or a regular serialization via store() or freeze(). | |
398 | ||
399 | Returned value: A LIST C<($serialized, $ref1, $ref2, ...)> where $serialized | |
400 | is the serialized form to be used, and the optional $ref1, $ref2, etc... are | |
401 | extra references that you wish to let the Storable engine serialize. | |
402 | ||
403 | At deserialization time, you will be given back the same LIST, but all the | |
404 | extra references will be pointing into the deserialized structure. | |
405 | ||
406 | The B<first time> the hook is hit in a serialization flow, you may have it | |
407 | return an empty list. That will signal the Storable engine to further | |
408 | discard that hook for this class and to therefore revert to the default | |
409 | serialization of the underlying Perl data. The hook will again be normally | |
410 | processed in the next serialization. | |
411 | ||
412 | Unless you know better, serializing hook should always say: | |
413 | ||
414 | sub STORABLE_freeze { | |
415 | my ($self, $cloning) = @_; | |
416 | return if $cloning; # Regular default serialization | |
417 | .... | |
418 | } | |
419 | ||
420 | in order to keep reasonable dclone() semantics. | |
421 | ||
422 | =item C<STORABLE_thaw> I<obj>, I<cloning>, I<serialized>, ... | |
423 | ||
424 | The deserializing hook called on the object during deserialization. | |
425 | But wait. If we're deserializing, there's no object yet... right? | |
426 | ||
427 | Wrong: the Storable engine creates an empty one for you. If you know Eiffel, | |
428 | you can view C<STORABLE_thaw> as an alternate creation routine. | |
429 | ||
430 | This means the hook can be inherited like any other method, and that | |
431 | I<obj> is your blessed reference for this particular instance. | |
432 | ||
433 | The other arguments should look familiar if you know C<STORABLE_freeze>: | |
434 | I<cloning> is true when we're part of a deep clone operation, I<serialized> | |
435 | is the serialized string you returned to the engine in C<STORABLE_freeze>, | |
436 | and there may be an optional list of references, in the same order you gave | |
437 | them at serialization time, pointing to the deserialized objects (which | |
438 | have been processed courtesy of the Storable engine). | |
439 | ||
440 | It is up to you to use these information to populate I<obj> the way you want. | |
441 | ||
442 | Returned value: none. | |
443 | ||
444 | =back | |
445 | ||
446 | =head2 Predicates | |
447 | ||
448 | Predicates are not exportable. They must be called by explicitely prefixing | |
449 | them with the Storable package name. | |
450 | ||
451 | =over | |
452 | ||
453 | =item C<Storable::last_op_in_netorder> | |
454 | ||
455 | The C<Storable::last_op_in_netorder()> predicate will tell you whether | |
456 | network order was used in the last store or retrieve operation. If you | |
457 | don't know how to use this, just forget about it. | |
458 | ||
459 | =item C<Storable::is_storing> | |
460 | ||
461 | Returns true if within a store operation (via STORABLE_freeze hook). | |
462 | ||
463 | =item C<Storable::is_retrieving> | |
464 | ||
465 | Returns true if within a retrieve operation, (via STORABLE_thaw hook). | |
466 | ||
467 | =back | |
468 | ||
469 | =head2 Recursion | |
470 | ||
471 | With hooks comes the ability to recurse back to the Storable engine. Indeed, | |
472 | hooks are regular Perl code, and Storable is convenient when it comes to | |
473 | serialize and deserialize things, so why not use it to handle the | |
474 | serialization string? | |
475 | ||
476 | There are a few things you need to know however: | |
477 | ||
478 | =over | |
479 | ||
480 | =item * | |
481 | ||
482 | You can create endless loops if the things you serialize via freeze() | |
483 | (for instance) point back to the object we're trying to serialize in the hook. | |
484 | ||
485 | =item * | |
486 | ||
487 | Shared references among objects will not stay shared: if we're serializing | |
488 | the list of object [A, C] where both object A and C refer to the SAME object | |
489 | B, and if there is a serializing hook in A that says freeze(B), then when | |
490 | deserializing, we'll get [A', C'] where A' refers to B', but C' refers to D, | |
491 | a deep clone of B'. The topology was not preserved. | |
492 | ||
493 | =back | |
494 | ||
495 | That's why C<STORABLE_freeze> lets you provide a list of references | |
496 | to serialize. The engine guarantees that those will be serialized in the | |
497 | same context as the other objects, and therefore that shared objects will | |
498 | stay shared. | |
499 | ||
500 | In the above [A, C] example, the C<STORABLE_freeze> hook could return: | |
501 | ||
502 | ("something", $self->{B}) | |
503 | ||
504 | and the B part would be serialized by the engine. In C<STORABLE_thaw>, you | |
505 | would get back the reference to the B' object, deserialized for you. | |
506 | ||
507 | Therefore, recursion should normally be avoided, but is nonetheless supported. | |
508 | ||
509 | =head2 Deep Cloning | |
510 | ||
511 | There is a new Clone module available on CPAN which implements deep cloning | |
512 | natively, i.e. without freezing to memory and thawing the result. It is | |
513 | aimed to replace Storable's dclone() some day. However, it does not currently | |
514 | support Storable hooks to redefine the way deep cloning is performed. | |
515 | ||
516 | =head1 EXAMPLES | |
517 | ||
518 | Here are some code samples showing a possible usage of Storable: | |
519 | ||
520 | use Storable qw(store retrieve freeze thaw dclone); | |
521 | ||
522 | %color = ('Blue' => 0.1, 'Red' => 0.8, 'Black' => 0, 'White' => 1); | |
523 | ||
524 | store(\%color, '/tmp/colors') or die "Can't store %a in /tmp/colors!\n"; | |
525 | ||
526 | $colref = retrieve('/tmp/colors'); | |
527 | die "Unable to retrieve from /tmp/colors!\n" unless defined $colref; | |
528 | printf "Blue is still %lf\n", $colref->{'Blue'}; | |
529 | ||
530 | $colref2 = dclone(\%color); | |
531 | ||
532 | $str = freeze(\%color); | |
533 | printf "Serialization of %%color is %d bytes long.\n", length($str); | |
534 | $colref3 = thaw($str); | |
535 | ||
536 | which prints (on my machine): | |
537 | ||
538 | Blue is still 0.100000 | |
539 | Serialization of %color is 102 bytes long. | |
540 | ||
541 | =head1 WARNING | |
542 | ||
543 | If you're using references as keys within your hash tables, you're bound | |
544 | to disapointment when retrieving your data. Indeed, Perl stringifies | |
545 | references used as hash table keys. If you later wish to access the | |
546 | items via another reference stringification (i.e. using the same | |
547 | reference that was used for the key originally to record the value into | |
548 | the hash table), it will work because both references stringify to the | |
549 | same string. | |
550 | ||
551 | It won't work across a C<store> and C<retrieve> operations however, because | |
552 | the addresses in the retrieved objects, which are part of the stringified | |
553 | references, will probably differ from the original addresses. The | |
554 | topology of your structure is preserved, but not hidden semantics | |
555 | like those. | |
556 | ||
557 | On platforms where it matters, be sure to call C<binmode()> on the | |
558 | descriptors that you pass to Storable functions. | |
559 | ||
560 | Storing data canonically that contains large hashes can be | |
561 | significantly slower than storing the same data normally, as | |
562 | temprorary arrays to hold the keys for each hash have to be allocated, | |
563 | populated, sorted and freed. Some tests have shown a halving of the | |
564 | speed of storing -- the exact penalty will depend on the complexity of | |
565 | your data. There is no slowdown on retrieval. | |
566 | ||
567 | =head1 BUGS | |
568 | ||
569 | You can't store GLOB, CODE, FORMLINE, etc... If you can define | |
570 | semantics for those operations, feel free to enhance Storable so that | |
571 | it can deal with them. | |
572 | ||
573 | The store functions will C<croak> if they run into such references | |
574 | unless you set C<$Storable::forgive_me> to some C<TRUE> value. In that | |
575 | case, the fatal message is turned in a warning and some | |
576 | meaningless string is stored instead. | |
577 | ||
578 | Setting C<$Storable::canonical> may not yield frozen strings that | |
579 | compare equal due to possible stringification of numbers. When the | |
580 | string version of a scalar exists, it is the form stored, therefore | |
581 | if you happen to use your numbers as strings between two freezing | |
582 | operations on the same data structures, you will get different | |
583 | results. | |
584 | ||
585 | Due to the aforementionned optimizations, Storable is at the mercy | |
586 | of perl's internal redesign or structure changes. If that bothers | |
587 | you, you can try convincing Larry that what is used in Storable | |
588 | should be documented and consistently kept in future revisions. | |
589 | ||
590 | =head1 CREDITS | |
591 | ||
592 | Thank you to (in chronological order): | |
593 | ||
594 | Jarkko Hietaniemi <jhi@iki.fi> | |
595 | Ulrich Pfeifer <pfeifer@charly.informatik.uni-dortmund.de> | |
596 | Benjamin A. Holzman <bah@ecnvantage.com> | |
597 | Andrew Ford <A.Ford@ford-mason.co.uk> | |
598 | Gisle Aas <gisle@aas.no> | |
599 | Jeff Gresham <gresham_jeffrey@jpmorgan.com> | |
600 | Murray Nesbitt <murray@activestate.com> | |
601 | Marc Lehmann <pcg@opengroup.org> | |
602 | ||
603 | for their bug reports, suggestions and contributions. | |
604 | ||
605 | Benjamin Holzman contributed the tied variable support, Andrew Ford | |
606 | contributed the canonical order for hashes, and Gisle Aas fixed | |
607 | a few misunderstandings of mine regarding the Perl internals, | |
608 | and optimized the emission of "tags" in the output streams by | |
609 | simply counting the objects instead of tagging them (leading to | |
610 | a binary incompatibility for the Storable image starting at version | |
611 | 0.6--older images are of course still properly understood). | |
612 | Murray Nesbitt made Storable thread-safe. Marc Lehmann added overloading | |
613 | and reference to tied items support. | |
614 | ||
615 | =head1 TRANSLATIONS | |
616 | ||
617 | There is a Japanese translation of this man page available at | |
618 | http://member.nifty.ne.jp/hippo2000/perltips/storable.htm , | |
619 | courtesy of Kawai, Takanori <kawai@nippon-rad.co.jp>. | |
620 | ||
621 | =head1 AUTHOR | |
622 | ||
623 | Raphael Manfredi F<E<lt>Raphael_Manfredi@pobox.comE<gt>> | |
624 | ||
625 | =head1 SEE ALSO | |
626 | ||
627 | Clone(3). | |
628 | ||
629 | =cut | |
630 |