File Coverage

blib/lib/Spp/Estr.pm
Criterion Covered Total %
statement 61 198 30.8
branch 33 70 47.1
condition n/a
subroutine 7 18 38.8
pod 0 14 0.0
total 101 300 33.6


line stmt bran cond sub pod time code
1             package Spp::Estr;
2              
3 2     2   33 use 5.012;
  2         8  
4 2     2   13 no warnings "experimental";
  2         833  
  2         65  
5              
6 2     2   9 use Exporter;
  2         3  
  2         107  
7             our @ISA = qw(Exporter);
8             our @EXPORT = qw(to_estr from_estr
9             atoms flat cons efirst esecond
10             etail elen epush eappend eunshift);
11              
12 2     2   10 use Spp::Builtin;
  2         2  
  2         2824  
13              
14             sub to_estr {
15 3     3 0 9 my $json = shift;
16 3         7 my @chars = ();
17             # 0: array mode
18             # 1: str-mode
19             # 2: int-mode
20             # 3: str escape mode
21 3         7 my $mode = 0;
22 3         36 for my $ch (split '', $json) {
23 162 100       332 if ($mode == 0) {
    50          
    0          
24 71 100       181 if ($ch eq '[') { push @chars, In }
  18 100       54  
    100          
    50          
25             elsif ($ch eq ']') {
26 18         40 push @chars, Out;
27             }
28             elsif ($ch eq '"') {
29 19         35 push @chars, Qstr;
30 19         30 $mode = 1;
31             }
32             elsif (is_digit($ch)) {
33 0         0 push @chars, Qint;
34 0         0 push @chars, $ch;
35 0         0 $mode = 2;
36             }
37             } elsif ($mode == 1) {
38 91         119 given ($ch) {
39 91         188 when ('"') { $mode = 0 }
  19         42  
40 72         100 when ("\\") { $mode = 3 }
  0         0  
41 72         86 default { push @chars, $ch }
  72         154  
42             }
43             } elsif ($mode == 2) {
44 0 0       0 if ($ch eq ',') { $mode = 0 }
  0 0       0  
    0          
45             elsif ($ch eq ']') {
46 0         0 push @chars, Out;
47 0         0 $mode = 0;
48             }
49             elsif (is_digit($ch)) {
50 0         0 push @chars, $ch;
51             }
52             } else {
53 0         0 $mode = 1;
54 0         0 given ($ch) {
55 0         0 when ('t') { push @chars, "\t" }
  0         0  
56 0         0 when ('r') { push @chars, "\r" }
  0         0  
57 0         0 when ('n') { push @chars, "\n" }
  0         0  
58 0         0 default { push @chars, $ch }
  0         0  
59             }
60             }
61             }
62 3         39 return join('', @chars);
63             }
64              
65             sub from_estr {
66 0     0 0 0 my $estr = shift;
67 0         0 my @chars = ();
68             # 0 start array mode
69             # 1 str mode
70             # 2 int mode
71             # 3 middle array mode
72 0         0 my $mode = 0;
73 0         0 for my $ch (split '', $estr) {
74 0 0       0 if ($mode == 0) {
    0          
    0          
75 0         0 given ($ch) {
76 0         0 when (In) { push @chars, '['; }
  0         0  
77 0         0 when (Qstr) { push @chars, '"'; $mode = 1 }
  0         0  
  0         0  
78 0         0 when (Qint) { $mode = 2; }
  0         0  
79 0         0 when (Out) { push @chars, ']'; $mode = 3 }
  0         0  
  0         0  
80             }
81             }
82             elsif ($mode == 1) {
83 0         0 given ($ch) {
84 0         0 when (Qstr) { push @chars, '","'; }
  0         0  
85 0         0 when (Qint) { push @chars, '",'; $mode = 2; }
  0         0  
  0         0  
86 0         0 when (In) { push @chars, '",['; $mode = 0; }
  0         0  
  0         0  
87 0         0 when (Out) { push @chars, '"]'; $mode = 3; }
  0         0  
  0         0  
88 0         0 default { push @chars, char_to_json($ch); }
  0         0  
89             }
90             }
91             elsif ($mode == 2) {
92 0         0 given ($ch) {
93 0         0 when (Qstr) {
94 0         0 push @chars, ',"';
95 0         0 $mode = 1;
96             }
97 0         0 when (Qint) {
98 0         0 push @chars, ',';
99             }
100 0         0 when (In) {
101 0         0 push @chars, ',[';
102 0         0 $mode = 0;
103             }
104 0         0 when (Out) {
105 0         0 push @chars, ']';
106 0         0 $mode = 3;
107             }
108 0         0 default {
109 0 0       0 if (is_digit($ch)) {
110 0         0 push @chars, $ch;
111             }
112             }
113             }
114             }
115             else {
116 0         0 given ($ch) {
117 0         0 when (Qstr) {
118 0         0 push @chars, ',"';
119 0         0 $mode = 1;
120             }
121 0         0 when (Qint) {
122 0         0 push @chars, ',';
123 0         0 $mode = 2;
124             }
125 0         0 when (In) {
126 0         0 push @chars, ',[';
127 0         0 $mode = 0
128             }
129 0         0 default {
130 0 0       0 if ($ch eq Out) {
131 0         0 push @chars, ']';
132             }
133             }
134             }
135             }
136             }
137 0         0 return join('', @chars);
138             }
139              
140             sub char_to_json {
141 0     0 0 0 my $ch = shift;
142 0         0 given ($ch) {
143 0         0 when ("\t") { return '\t' }
  0         0  
144 0         0 when ("\n") { return '\n' }
  0         0  
145 0         0 when ("\r") { return '\r' }
  0         0  
146 0         0 when ("\\") { return '\\\\' }
  0         0  
147 0         0 when ('"') { return '\"' }
  0         0  
148 0         0 default { return $ch }
  0         0  
149             }
150             }
151              
152             sub atoms {
153 18     18 0 26 my $estr = shift;
154 18         26 my @estrs = ();
155 18         27 my $chars = '';
156 18         26 my $depth = 0;
157             # 0 chars has char 1: chars is blank
158 18         36 my $mode = 0;
159 18         91 for my $ch (split '', $estr) {
160 491 100       867 if ($depth == 0) {
    100          
161 18 50       42 $depth++ if $ch eq In;
162             } elsif ($depth == 1) {
163 124 100       276 if ($ch eq In) {
    100          
    50          
    100          
164 15         23 $depth++;
165 15 100       29 if ($mode == 0) { $mode = 1 }
  5         9  
166 10         18 else { push @estrs, $chars; $chars = '' }
  10         16  
167 15         27 $chars .= $ch;
168             }
169             elsif ($ch eq Qstr) {
170 19 100       34 if ($mode == 0) { $mode = 1 }
  13         22  
171 6         14 else { push @estrs, $chars; $chars = '' }
  6         13  
172             }
173             elsif ($ch eq Qint) {
174 0 0       0 if ($mode == 0) { $mode = 1 }
  0         0  
175 0         0 else { push @estrs, $chars; $chars = '' }
  0         0  
176             # int return qint
177 0         0 $chars .= $ch;
178             }
179             elsif ($ch eq Out) {
180 18 50       42 if ($mode == 1) { push @estrs, $chars }
  18         44  
181             last
182 18         31 }
183             else {
184 72 50       130 if ($mode == 1) { $chars .= $ch }
  72         105  
185             }
186             } else {
187 349 100       698 if ($ch eq In) { $depth++ }
  27 100       33  
188 42         52 elsif ($ch eq Out) { $depth-- }
189 349         499 $chars .= $ch;
190             }
191             }
192 18         91 return @estrs;
193             }
194              
195             sub cons {
196 0     0 0 0 my @atoms = @_;
197 0         0 my @estrs = map { estr($_) } @atoms;
  0         0  
198 0         0 return In . join('', @estrs) . Out;
199             }
200              
201             sub estr {
202 0     0 0 0 my $atom = shift;
203 0 0       0 if (is_estr($atom)) { return $atom }
  0         0  
204 0 0       0 if (is_int($atom)) { return Qint . $atom }
  0         0  
205 0 0       0 if (is_str($atom)) { return Qstr . $atom }
  0         0  
206 0 0       0 if (is_array($atom)) { return cons(@{$atom}) }
  0         0  
  0         0  
207 0         0 say "could not estr hash or func";
208 0         0 return False
209             }
210              
211             sub flat {
212 13     13 0 21 my $estr = shift;
213 13         24 my @atoms = atoms($estr);
214 13 50       51 if (len([@atoms]) == 2) {
215 13         51 return @atoms;
216             }
217 0 0         if (len([@atoms]) > 2) {
218 0           my $rest = rest([@atoms]);
219 0           return $atoms[0], cons(@{$rest});
  0            
220             }
221 0           say from_estr($estr);
222 0           say "Could not Flat!";
223             }
224              
225             sub efirst {
226 0     0 0   my $estr = shift;
227 0           my @atoms = atoms($estr);
228 0           return $atoms[0];
229             }
230              
231             sub esecond {
232 0     0 0   my $estr = shift;
233 0           my @atoms = atoms($estr);
234 0           return $atoms[1];
235             }
236              
237             sub etail {
238 0     0 0   my $estr = shift;
239 0           my @atoms = atoms($estr);
240 0           return $atoms[-1];
241             }
242              
243             sub elen {
244 0     0 0   my $estr = shift;
245 0           my @atoms = atoms($estr);
246 0           return scalar(@atoms);
247             }
248              
249             sub epush {
250 0     0 0   my ($array, $elem) = @_;
251 0           return cutlast(estr($array)) . estr($elem) . Out;
252             }
253              
254             sub eappend {
255 0     0 0   my ($a_one, $a_two) = @_;
256 0           return cutlast(estr($a_one)) . rest(estr($a_two));
257             }
258              
259             sub eunshift {
260 0     0 0   my ($elem, $array) = @_;
261 0           return In . estr($elem) . rest(estr($array));
262             }
263              
264             1;