File Coverage

blib/lib/App/Asciio/Io.pm
Criterion Covered Total %
statement 30 150 20.0
branch 0 48 0.0
condition 0 24 0.0
subroutine 10 16 62.5
pod 0 6 0.0
total 40 244 16.3


line stmt bran cond sub pod time code
1              
2             package App::Asciio ;
3              
4             $|++ ;
5              
6 4     4   26 use strict;
  4         9  
  4         166  
7 4     4   21 use warnings;
  4         7  
  4         278  
8              
9 4     4   24 use Data::TreeDumper ;
  4         7  
  4         388  
10 4     4   29 use File::Slurp ;
  4         7  
  4         279  
11 4     4   22 use Readonly ;
  4         8  
  4         235  
12 4     4   2921 use Compress::Bzip2 qw(:all :utilities :gzip);
  4         49980  
  4         2520  
13              
14 4         425 use Sereal qw(
15             get_sereal_decoder
16             get_sereal_encoder
17             clear_sereal_object_cache
18            
19             encode_sereal
20             decode_sereal
21 4     4   2490 ) ;
  4         5135  
22 4     4   30 use Sereal::Encoder qw(SRL_SNAPPY SRL_ZLIB SRL_ZSTD) ;
  4         38  
  4         5164  
23              
24             #-----------------------------------------------------------------------------
25              
26             sub load_file
27             {
28 0     0 0   my ($self, $file_name) = @_;
29              
30 0 0         return unless defined $file_name ;
31              
32 0           my ($base_name, $path, $extension) = File::Basename::fileparse($file_name, ('\..*')) ;
33 0           $extension =~ s/^\.// ;
34              
35 0 0         my $type = $extension ne q{} ? $extension : 'internal_asciio_format';
36              
37 0           my $title ;
38              
39 0 0 0       if
40             (
41             exists $self->{IMPORT_EXPORT_HANDLERS}{$type}{IMPORT}
42             && defined $self->{IMPORT_EXPORT_HANDLERS}{$type}{IMPORT}
43             )
44             {
45 0           my ($saved_self, $handler_data) ;
46            
47             ($saved_self, $title, $handler_data) =
48             $self->{IMPORT_EXPORT_HANDLERS}{$type}{IMPORT}->
49 0           (
50             $self,
51             $file_name,
52             ) ;
53            
54 0           $self->load_self($saved_self) ; # resurrect from mummified
55 0           $self->{IMPORT_EXPORT_HANDLERS}{HANDLER_DATA} = $handler_data ;
56             }
57             else
58             {
59 0 0 0       if(-e $file_name && -s $file_name)
60             {
61 0           my $serialized_self = decompress(read_file($file_name)) ;
62 0           my $decoder = get_sereal_decoder() ;
63 0           my $saved_self = $serialized_self = $decoder->decode($serialized_self) ;
64            
65 0 0         if($@)
66             {
67 0           write_file("failed_resurection_source.pl", {binmode => ':utf8'}, $serialized_self) ;
68 0           die "load_file: can't load file '$file_name': $! $@\n" ;
69             }
70            
71 0           $self->load_self($saved_self) ; # resurrect
72 0           delete $self->{IMPORT_EXPORT_HANDLERS}{HANDLER_DATA} ;
73 0           delete $self->{CACHE} ;
74            
75 0           $title = $file_name ;
76             }
77             else
78             {
79 0           my $element = $self->add_new_element_named('Asciio/box', 0, 0) ;
80 0           my $box_type = $element->get_box_type() ;
81 0           $box_type->[1][0] = 1 ; # title separator
82 0           $element->set_box_type($box_type) ;
83            
84 0           $element->set_text('Warning!', "'$file_name' has no content.");
85            
86 0           $self->select_elements(1, $element) ;
87 0           $self->update_display() ;
88            
89 0           $title = $file_name ;
90             }
91             }
92              
93 0           return $title ;
94             }
95              
96             #-----------------------------------------------------------------------------
97              
98             Readonly my @ELEMENTS_TO_KEEP_AWAY_FROM_CURRENT_OBJECT =>
99             qw
100             (
101             widget
102             root_window
103             sc_window
104             ACTIONS CURRENT_ACTIONS ACTIONS_BY_NAME
105             HOOKS IMPORT_EXPORT_HANDLERS
106             TITLE
107             ELEMENT_TYPES_BY_NAME
108             ELEMENT_TYPES
109             MIDDLE_BUTTON_SELECTION_FILTER
110             CACHE
111             COLORS
112             ACTION_VERBOSE
113             DO_STACK_POINTER DO_STACK
114             ) ;
115              
116             sub load_self
117             {
118 0     0 0   my ($self, $new_self) = @_;
119              
120 0 0         return unless defined $new_self ;
121              
122 0           delete @{$new_self}{@ELEMENTS_TO_KEEP_AWAY_FROM_CURRENT_OBJECT} ;
  0            
123              
124 0           my @keys = keys %{$new_self} ;
  0            
125 0           @{$self}{@keys} = @{$new_self}{@keys} ;
  0            
  0            
126             }
127              
128             #-----------------------------------------------------------------------------
129              
130             sub load_elements
131             {
132 0     0 0   my ($self, $file_name, $path) = @_;
133              
134 0 0         return unless defined $file_name ;
135              
136 0 0         my $elements = do $file_name or die "can't load file '$file_name': $! $@\n" ;
137 0 0         $path = '' unless defined $path ;
138              
139 0           for my $new_element (@{$elements})
  0            
140             {
141 0 0         my $new_element_type = ref $new_element or die "element without type in file '$file_name'!" ;
142            
143 0 0         unless(exists $self->{LOADED_TYPES}{$new_element_type})
144             {
145 0           eval "use $new_element_type" ;
146 0 0         die "Error loading type '$new_element_type' :$@" if $@ ;
147            
148 0           $self->{LOADED_TYPES}{$new_element_type}++ ;
149             }
150            
151 0           my $next_element_type_index = @{$self->{ELEMENT_TYPES}} ;
  0            
152            
153 0           $new_element->{NAME} = "$path/$new_element->{NAME}" ;
154 0           $new_element->{NAME} =~ s~/+~/~g ;
155 0           $new_element->{NAME} =~ s~^/~~g ;
156            
157 0 0         if(exists $new_element->{NAME})
158             {
159 0 0         if(exists $self->{ELEMENT_TYPES_BY_NAME}{$new_element->{NAME}})
160             {
161 0           print "Overriding element type '$new_element->{NAME}'!\n" ;
162 0           $self->{ELEMENT_TYPES}[$self->{ELEMENT_TYPES_BY_NAME}{$new_element->{NAME}}]
163             = $new_element ;
164             }
165             else
166             {
167 0           $self->{ELEMENT_TYPES_BY_NAME}{$new_element->{NAME}} = $next_element_type_index ;
168 0           push @{$self->{ELEMENT_TYPES}}, $new_element ;
  0            
169            
170 0           $next_element_type_index++ ;
171             }
172             }
173            
174 0 0         if(exists $new_element->{X})
175             {
176 0           push @{$self->{ELEMENTS}}, $new_element ;
  0            
177             }
178             }
179             }
180              
181             #-----------------------------------------------------------------------------
182              
183             sub save_stencil
184             {
185 0     0 0   my ($self) = @_ ;
186              
187 0           my $name = $self->display_edit_dialog('stencil name', '', $self) ;
188              
189 0 0 0       if(defined $name && $name ne q[])
190             {
191 0           my $file_name = $self->get_file_name('save') ;
192            
193 0 0 0       if(defined $file_name && $file_name ne q[])
194             {
195 0 0         if(-e $file_name)
196             {
197 0           my $override = $self->display_yes_no_cancel_dialog
198             (
199             "Override file!",
200             "File '$file_name' exists!\nOverride file?"
201             ) ;
202            
203 0 0         $file_name = undef unless $override eq 'yes' ;
204             }
205             }
206            
207 0 0 0       if(defined $file_name && $file_name ne q[])
208             {
209 4     4   2834 use Data::Dumper ;
  4         36951  
  4         2698  
210 0           my ($element) = $self->get_selected_elements(1) ;
211            
212 0           my $cache = $element->{CACHE} ;
213 0           delete $element->{CACHE} ;
214            
215 0           my $stencil = Clone::clone($element) ;
216            
217 0           $element->{CACHE} = $cache ;
218            
219 0           delete $stencil->{X} ;
220 0           delete $stencil->{Y} ;
221 0           $stencil->{NAME} = $name;
222            
223 0           write_file($file_name, {binmode => ':utf8'}, Dumper [$stencil]) ;
224             }
225             }
226             }
227              
228             #-----------------------------------------------------------------------------
229              
230             sub serialize_self
231             {
232 0     0 0   my ($self, $indent) = @_ ;
233              
234 0           local $self->{widget} = undef ;
235 0           local $self->{ACTIONS} = [] ;
236 0           local $self->{HOOKS} = [] ;
237 0           local $self->{CURRENT_ACTIONS} = [] ;
238 0           local $self->{ACTIONS_BY_NAME} = [] ;
239 0           local $self->{DO_STACK} = undef ;
240 0           local $self->{DO_STACK_POINTER} = undef ;
241 0           local $self->{IMPORT_EXPORT_HANDLERS} = undef ;
242 0           local $self->{MODIFIED} => 0 ;
243 0           local $self->{TITLE} = '' ;
244 0           local $self->{CREATE_BACKUP} = undef ;
245 0           local $self->{MIDDLE_BUTTON_SELECTION_FILTER} = undef ;
246 0           local $self->{ELEMENT_TYPES} = undef ;
247 0           local $self->{ELEMENT_TYPES_BY_NAME} = undef ;
248 0           local $self->{ACTION_VERBOSE} = undef ;
249              
250 0           my @elements_cache ;
251 0           for my $element (@{$self->{ELEMENTS}})
  0            
252             {
253 0           push @elements_cache, [$element, $element->{CACHE}] ;
254 0           $element->{CACHE} = undef ;
255             }
256              
257 0   0       $self->{CACHE}{ENCODER} = my $encoder = $self->{CACHE}{ENCODER} // get_sereal_encoder({compress => SRL_ZLIB}) ;
258 0           local $self->{CACHE} = undef ;
259              
260 0           my $serialized = $encoder->encode($self) ;
261              
262 0           $_->[0]{CACHE} = $_->[1] for @elements_cache ;
263              
264 0           return $serialized ;
265             }
266              
267             #-----------------------------------------------------------------------------
268              
269             sub save_with_type
270             {
271 0     0 0   my ($self, $elements_to_save, $type, $file_name) = @_ ;
272              
273 0           my $title ;
274              
275 0 0 0       if
276             (
277             exists $self->{IMPORT_EXPORT_HANDLERS}{$type}{EXPORT}
278             && defined $self->{IMPORT_EXPORT_HANDLERS}{$type}{EXPORT}
279             )
280             {
281             $title = $self->{IMPORT_EXPORT_HANDLERS}{$type}{EXPORT}->
282             (
283             $self,
284             $elements_to_save,
285             $file_name,
286             $self->{IMPORT_EXPORT_HANDLERS}{HANDLER_DATA},
287 0           ) ;
288             }
289             else
290             {
291 0 0 0       if($self->{CREATE_BACKUP} && -e $file_name)
292             {
293 4     4   2719 use File::Copy;
  4         17279  
  4         953  
294 0 0         copy($file_name,"$file_name.bak") or die "save_with_type: Copy failed while making backup copy: $!" ;
295             }
296            
297 0           $title = $file_name ;
298 0 0         write_file($file_name, compress($self->serialize_self() .'$VAR1 ;')) or $title = undef ;
299             }
300            
301 0           return $title ;
302             }
303              
304             #-----------------------------------------------------------------------------
305              
306             1 ;