File Coverage

blib/lib/Config/JSON/Enhanced.pm
Criterion Covered Total %
statement 121 135 89.6
branch 44 56 78.5
condition 29 50 58.0
subroutine 10 10 100.0
pod 1 1 100.0
total 205 252 81.3


line stmt bran cond sub pod time code
1             package Config::JSON::Enhanced;
2              
3 15     15   2227177 use 5.010;
  15         233  
4 15     15   98 use strict;
  15         41  
  15         345  
5 15     15   79 use warnings;
  15         43  
  15         628  
6              
7             our $VERSION = '0.09';
8              
9 15     15   106 use strict;
  15         73  
  15         331  
10 15     15   102 use warnings;
  15         63  
  15         598  
11              
12             # which loads JSON::XS with a purel-perl JSON fallback
13 15     15   7601 use JSON;
  15         126986  
  15         122  
14              
15 15     15   8828 use Data::Roundtrip qw/json2perl perl2dump no-unicode-escape-permanently/;
  15         1116340  
  15         140  
16              
17 15     15   1650 use Exporter; # we have our own import() don't import it
  15         44  
  15         27660  
18             our @ISA = qw(Exporter);
19             our @EXPORT = qw/
20             config2perl
21             /;
22              
23             # Convert enhanced JSON string into a Perl data structure.
24             # The input parameters hashref:
25             # * specify where is the content to be parsed via:
26             # 'filename',
27             # 'filehandle', or,
28             # 'string'
29             # * optional 'commentstyle' is a string of comma separated
30             # commentstyles (valid styles are C, CPP, shell)
31             # * optional 'variable-substitutions' is a hashref with
32             # keys as template variable names to be substutited
33             # inside the content with their corresponding values.
34             # For example {'xx' => 'hello'} will substitute
35             # <% xx %> with hello
36             # * optional 'remove-comments-in-strings' to remove comments from JSON strings
37             # (both keys and values), default is to KEEP anything inside a string
38             # even if it looks like comments we are supposed to remove (because string
39             # can be a bash script, for example).
40             # * optional 'debug' for setting verbosity, default is zero.
41             #
42             # It returns the created Perl data structure or undef on failure.
43             sub config2perl {
44 628   50 628 1 3142077 my $params = shift // {};
45              
46 628         1213 my $contents;
47 628 100 66     5146 if( exists($params->{'filename'}) && defined(my $infile=$params->{'filename'}) ){
    100 66        
    50 33        
48 19         40 my $fh;
49 19 50   7   729 if( ! open $fh, '<:encoding(UTF-8)', $infile ){ warn __PACKAGE__.'::configfile2perl()'." (line ".__LINE__.") : error, failed to open file '$infile' for reading, $!"; return undef }
  0         0  
  0         0  
  7         53  
  7         15  
  7         44  
50 19         9902 { local $/ = undef; $contents = <$fh> }; close $fh;
  19         116  
  19         701  
  19         859  
51             } elsif( exists($params->{'filehandle'}) && defined(my $fh=$params->{'filehandle'}) ){
52 11         26 { local $/ = undef; $contents = <$fh> }
  11         49  
  11         456  
53             # we are not closing the filehandle, it is caller-specified, so caller responsibility
54             } elsif( exists($params->{'string'}) && defined($params->{'string'}) ){
55 598         1355 $contents = $params->{'string'};
56             }
57 628 50       1411 if( ! defined $contents ){ warn __PACKAGE__.'::configfile2perl()'." (line ".__LINE__.") : error, one of 'filename', 'filehandle' or 'string' must be specified in the parameters hash as the source of the configuration contents."; return undef }
  0         0  
  0         0  
58              
59             my $debug = exists($params->{'debug'}) && defined($params->{'debug'})
60 628 50 33     1873 ? $params->{'debug'} : 0
61             ;
62              
63             my $commentstyle = exists($params->{'commentstyle'}) && defined($params->{'commentstyle'})
64 628 50 33     2528 ? $params->{'commentstyle'} : 'C'
65             ;
66              
67 628         1105 my ($tvop, $tvcl);
68 628 100 66     1549 if( exists($params->{'tags'}) && defined($params->{'tags'}) ){
69 22 100       139 if( ref($params->{'tags'}) ne 'ARRAY' ){ warn __PACKAGE__.'::configfile2perl()'." (line ".__LINE__.") : error, input parameter 'tags' must be an ARRAYref of exactly 2 items and not a ".ref($params->{'tags'})."."; return undef }
  1         15  
  1         6  
70 21 50       33 if( scalar(@{ $params->{'tags'} }) != 2 ){ warn __PACKAGE__.'::configfile2perl()'." (line ".__LINE__.") : error, input parameter 'tags' must be an ARRAYref of exactly 2 items and not ".scalar(@{ $params->{'tags'} })."."; return undef }
  21         59  
  0         0  
  0         0  
  0         0  
71 21         35 ($tvop, $tvcl) = @{ $params->{'tags'} };
  21         54  
72 606         1145 } else { $tvop = '<%'; $tvcl = '%>' }
  606         939  
73              
74             # check that the tags for verbatim sections is not the same as comments
75 627         3944 while( $commentstyle =~ /\bcustom\((.+?)\)\((.*?)\)/ig ){
76 2013         4664 my $coop = $1; my $cocl = $2;
  2013         3324  
77 2013 50       3997 if( $debug > 0 ){ warn __PACKAGE__.'::configfile2perl()'." (line ".__LINE__.") : checking comment tags '${coop}' and '${cocl}' not to be the same or contain verbatim/variables tags '${tvop}' and '${tvcl}' ..." }
  0         0  
78 2013 50 100     10304 if( ($tvop eq $coop) || ($tvop eq $cocl)
      66        
      66        
79             || ($tvcl eq $coop) || ($tvcl eq $cocl)
80 3         111 ){ warn __PACKAGE__.'::configfile2perl()'." (line ".__LINE__.") : error, there is a clash (exact match) with verbatim/variable tags ('${tvop}' and '${tvcl}') and comment tags ('${coop}' and '${cocl}')."; return undef }
  3         26  
81             # also check if one contains the other
82 2010 100 66     43848 if( ($tvop =~ /\Q${coop}\E/) || ($tvop =~ /\Q${cocl}\E/)
      66        
      66        
83             || ($tvcl =~ /\Q${coop}\E/) || ($tvcl =~ /\Q${cocl}\E/)
84 3         54 ){ warn __PACKAGE__.'::configfile2perl()'." (line ".__LINE__.") : error, there is a clash (one contains the other) with verbatim/variable tags ('${tvop}' and '${tvcl}') and comment tags ('${coop}' and '${cocl}')."; return undef }
  3         21  
85 2007 100 33     19481 if( ($coop =~ /\Q${tvop}\E/) || ($coop =~ /\Q${tvcl}\E/)
      33        
      66        
86             || ($cocl =~ /\Q${tvop}\E/) || ($cocl =~ /\Q${tvcl}\E/)
87 1         42 ){ warn __PACKAGE__.'::configfile2perl()'." (line ".__LINE__.") : error, there is a clash (one contains the other) with verbatim/variable tags ('${tvop}' and '${tvcl}') and comment tags ('${coop}' and '${cocl}')."; return undef }
  1         7  
88             }
89              
90             my $tsubs = exists($params->{'variable-substitutions'})
91 620 100       1654 ? $params->{'variable-substitutions'} : undef
92             ;
93              
94             # remove comments inside strings? default is NO, keep comments if inside strings
95             # because they may not be our comments (e.g. string contains a bash script)
96             my $remove_comments_in_strings = exists($params->{'remove-comments-in-strings'}) && defined($params->{'remove-comments-in-strings'})
97 620 100 66     1491 ? $params->{'remove-comments-in-strings'} : 0
98             ;
99              
100             # firstly, substitute templated variables if any
101             # with the user-specified data.
102             # This includes ANYTHNING in the input enhanced JSON including
103             # verbatim sections, keys, values, etc.
104             # The opening and closing tags of vars are user-specified
105             # and are NOT allowed to contain spaces in between
106             # (e.g. '< %' will not be matched if '<%' was specified)
107 620         1920 for my $ak (keys %$tsubs){
108 35         79 my $av = $tsubs->{$ak};
109 35 50       437 if( ($ak =~ /(?:\Q${tvop}\E)|(?:\Q${tvcl}\E)/) ){ warn __PACKAGE__.'::config2perl()'." (line ".__LINE__.") : error, variable names can not contain the specified opening ($tvop) and/or closing ($tvcl) variable name tags."; return undef }
  0         0  
  0         0  
110 35         949 $contents =~ s!\Q${tvop}\E\s*${ak}\s*\Q${tvcl}\E!${av}!g;
111             }
112             # this is a warning:
113             # we can not be sure if this <% xyz %> is part of the content or a forgotten templated variable
114             # NOTE: During test t/090-config2perl-failed-verbatim.t some CPAN testers
115             # report a failure. The fact is that this test deliberately tests a failed case
116             # and the line below should cause the sub to exit and print a long winded, multiline error message.
117             # So, some testers (3/15) report a failure.
118             # see https://www.cpantesters.org/cpan/report/fbbe94b6-62e8-11ee-9f69-c1f66d8775ea
119             # So, I am replacing the comment with a short comment.
120             #if( $contents =~ /\Q${tvop}\E\s*!(:?(:?begin-verbatim-section)|(:?end-verbatim-section))\s*\Q${tvcl}\E/ ){ print STDERR "--begin content:\n".$contents."\n--end content.\n".__PACKAGE__.'::config2perl()'." (line ".__LINE__.") : warning, there may still be remains of templated variables in the specified content (tags used: '${tvop}' and '${tvcl} -- ignore the enclosing single quotes), see above what remained after all template variables substitutions were done." }
121 620 50       3511 if( $contents =~ /\Q${tvop}\E\s*!(:?(:?begin-verbatim-section)|(:?end-verbatim-section))\s*\Q${tvcl}\E/ ){ print STDERR __PACKAGE__.'::config2perl()'." (line ".__LINE__.") : warning, there may still be remains of templated variables in the specified content (tags used: '${tvop}' and '${tvcl}' -- ignore the enclosing single quotes), see above what remained after all template variables substitutions were done." }
  0         0  
122              
123             # secondly, remove the VERBATIM multiline sections and transform them.
124             # Comments inside the verbatim section will NOT BE touched.
125             # The only thing touched was the templated variables earlier
126             # it substitutes each verbatim section with a code
127             # then does the comments and then replaces the code with the verbatim section at the very end
128 620         1129 my @verbs;
129 620         1043 my $idx = 0;
130 620         5096 while( $contents =~ s/\Q${tvop}\E\s*begin-verbatim-section\s*\Q${tvcl}\E(.*?)\Q${tvop}\E\s*end-verbatim-section\s*\Q${tvcl}\E/"___my___verbatim-section-${idx}___my___"/s ){
131 72         256 my $vc = $1;
132             # remove from start and end of whole string newlines+spaces
133 72         420 $vc =~ s/^[\n\t ]+//;
134 72         956 $vc =~ s/[\n\t ]+$//;
135             # remove newlines followed by optional spaces at the beginning of each line
136 72         698 $vc =~ s/\n+[ \t]*/\\n/gs;
137             # escape all double quotes (naively)
138             # but not those which are already escaped (naively)
139 72         405 $vc =~ s/\\"/<%__abcQQxyz__%>/g;
140 72         441 $vc =~ s/"/\\"/g;
141 72         357 $vc =~ s/<%__abcQQxyz__%>/\\\\\\"/g;
142             # so echo "aa \"xx\""
143             # becomes echo \"aa \\\"xx\\\"\"
144 72         163 push @verbs, $vc;
145 72         1082 $idx++;
146             }
147              
148             # thirdly, replace all JSON strings (keys or values) with indexed markers
149             # so that their contained comments
150             # to be left intact after the comment substitution which will
151             # be done later on.
152 620         1109 my @stringsubs;
153 620 100       1310 if( $remove_comments_in_strings == 0 ){
154 612         945 $idx = 0;
155 612         7544 while( $contents =~ s/(?
156 5105         12209 push @stringsubs, $1;
157 5105         42544 $idx++;
158             }
159             }
160              
161             # thirdly, remove comments: 'shell' and/or 'C' and/or 'CPP'
162             # and/or multiple instances of 'custom()()'
163 620         1110 my $tc = $commentstyle;
164 620 100       3045 if( $tc =~ s/\bC\b//i ){
165 474         4333 $contents =~ s/\/\*(?:(?!\*\/).)*\*\/\n?//sg;
166             }
167 620 100       2832 if( $tc =~ s/\bCPP\b//i ){
168 471         2134 $contents =~ s/\/\*(?:(?!\*\/).)*\*\/\n?//sg;
169 471         3082 $contents =~ s!//.*$!!mg;
170             }
171 620 100       2545 if( $tc =~ s/\bshell\b//i ){
172             # TODO: we must also remove the newline left!
173 459         2665 $contents =~ s/#.*$//mg;
174             }
175              
176             # specify a custom comment style with required opening string
177             # and an optional closing
178             # e.g. custom(required)(optional), custom(<<)(>>) or custom(REM)()
179 620         3045 while( $tc =~ s/\bcustom\((.+?)\)\((.*?)\)//i ){
180             # mulitple custom(opening)(closing) commentstyle are allowed
181             # 'opening' and 'closing' can be any string
182             # And need not be balanced e.g. <<< and >>
183             # And can be the same e.g. <<< and <<<
184 2006         4802 my $coop = $1; my $cocl = $2;
  2006         3213  
185 2006 100       5360 if( $cocl =~ /^\s*$/ ){
186             # TODO: we must also remove the newline left!
187 357         3437 $contents =~ s/\Q${coop}\E.*$//mg;
188             } else {
189 1649         39243 $contents =~ s/\Q${coop}\E(?:(?!\Q${cocl}\E\s*).)*\Q${cocl}\E\s*\n?//sg;
190             }
191             }
192 620 50       1810 if( $tc =~ /[a-z]/i ){ warn __PACKAGE__.'::config2perl()'." (line ".__LINE__.") : error, comments style '${commentstyle}' was not understood, this is what was left after parsing it: '${tc}'."; return undef }
  0         0  
  0         0  
193              
194             # this is a warning:
195             # we can not be sure if this <% xyz %> is part of the content or a forgotten templated variable
196 620 100       2930 if( $contents =~ /\Q${tvop}\E.+?-verbatim-section\s*\Q${tvcl}\E/ ){ warn "--begin content:\n".$contents."\n--end content.\n".__PACKAGE__.'::config2perl()'." (line ".__LINE__.") : warning, there may still be remains of templated variables in the specified content, see above what remained after all verbatime sections were removed." }
  1         85  
197              
198 620 100       1502 if( $remove_comments_in_strings == 0 ){
199 612         952 $idx = 0;
200 612         1739 for($idx=scalar(@stringsubs);$idx-->0;){
201 5105         9544 my $astring = $stringsubs[$idx];
202 5105         69340 $contents =~ s/___my___EJSTRING\($idx\)___my___/"${astring}"/g
203             }
204             }
205              
206             # and now substitute the transformed verbatim sections back
207 620         1754 for($idx=scalar(@verbs);$idx-->0;){
208 72         1098 $contents =~ s/___my___verbatim-section-${idx}___my___/$verbs[$idx]/g;
209             }
210              
211 620 50       1288 if( $debug > 0 ){ warn $contents."\n\n".__PACKAGE__.'::config2perl()'." (line ".__LINE__.") : produced above standard JSON from enhanced JSON content." }
  0         0  
212              
213             # here $contents must contain standard JSON which we parse:
214 620         2270 my $inhash = json2perl($contents);
215 620 100       16379 if( ! defined $inhash ){ warn $contents."\n\n".__PACKAGE__.'::config2perl()'." (line ".__LINE__.") : error, call to ".'Data::Roundtrip::json2perl()'." has failed for above json string and comments style '${commentstyle}'."; return undef }
  1         17  
  1         9  
216 619         2681 return $inhash
217             }
218              
219             =pod
220              
221             =head1 NAME
222              
223             Config::JSON::Enhanced - JSON-based config with C/Shell-style comments, verbatim sections and variable substitutions
224              
225             =head1 VERSION
226              
227             Version 0.09
228              
229             =head1 SYNOPSIS
230              
231             This module provides subroutine C for parsing configuration content,
232             from files or strings, based on, what I call, "enhanced JSON" (see section
233             L for more details). Briefly, it is standard JSON which allows:
234              
235             =over 2
236              
237             =item * C-style, C-style, C-style or custom comments.
238              
239             =item * Template-style variables (e.g. C% appdir %E>)
240             which are substituted with user-specified data during parsing.
241              
242             =item * Verbatim sections which are a sort of here-doc for JSON,
243             allowing strings to span multiple
244             lines, to contain single and double quotes unescaped,
245             to contain template-style variables.
246              
247             =back
248              
249             This module was created because I needed to include
250             long shell scripts containing lots of quotes and newlines,
251             in a configuration file which started as JSON.
252              
253             The process is simple: so-called "enhanced JSON" is parsed
254             by L. Comments are removed, variables are
255             substituted, verbatim sections become one line again
256             and standard JSON is created. This is parsed with
257             L (via L) to
258             produce a Perl data structure which is returned.
259              
260             It has been tested with unicode data
261             (see C)
262             with success. But who knows ?!?!
263              
264             Here is an example:
265              
266             use Config::JSON::Enhanced;
267              
268             # simple "enhanced" JSON with comments in 3 styles: C,shell,CPP
269             my $configdata = <<'EOJ';
270             {
271             /* 'a' is ... */
272             "a" : "abc",
273             # b is ...
274             "b" : [1,2,3],
275             "c" : 12 // c is ...
276             }
277             EOJ
278             my $perldata = config2perl({
279             'string' => $configdata,
280             'commentstyle' => "C,shell,CPP",
281             });
282             die "call to config2perl() has failed" unless defined $perldata;
283             # the standard JSON:
284             # {"a" : "abc","b" : [1,2,3], "c" : 12}
285              
286              
287             # this "enhanced" JSON demonstrates the use of variables
288             # which will be substituted during the transformation to
289             # standard JSON with user-specified data.
290             # Notice that the opening and closing tags enclosing variable
291             # names can be customised using the 'tags' input parameter,
292             # so as to avoid clashes with content in the JSON.
293             my $configdata = <<'EOJ';
294             {
295             "d" : [1,2,<% tempvar0 %>],
296             "configfile" : "<%SCRIPTDIR%>/config/myapp.conf",
297             "username" : "<% username %>"
298             }
299             }
300             EOJ
301             my $perldata = config2perl({
302             'string' => $configdata,
303             'commentstyle' => "C,shell,CPP",
304             # optionally customise the tags enclosing the variables
305             # when you want to avoid clashes with other strings in JSON
306             #'tags' => ['<%', '%>'], # <<< these are the default values
307             # user-specified data to replace the variables in
308             # the "enhanced" JSON above:
309             'variable-substitutions' => {
310             'tempvar0' => 42,
311             'username' => getlogin(),
312             'SCRIPTDIR' => $FindBin::Bin,
313             },
314             });
315             die "call to config2perl() has failed" unless defined $perldata;
316             # the standard JSON
317             # (notice how all variables in <%...%> are now replaced):
318             # {"d" : [1,2,42],
319             # "username" : "yossarian",
320             # "configfile" : "/home/yossarian/B52/config/myapp.conf"
321             # }
322              
323              
324             # this "enhanced" JSON demonstrates "verbatim sections"
325             # the puprose of which is to make more readable JSON strings
326             # by allowing them to span over multiple lines.
327             # There is also no need for escaping double quotes.
328             # template variables (like above) will be substituted
329             # There will be no comments removal from the verbatim sections.
330             my $configdata = <<'EOJ';
331             {
332             "a" : <%begin-verbatim-section%>
333             This is a multiline
334             string
335             "quoted text" and 'quoted like this also'
336             will be retained in the string escaped.
337             White space from beginning and end will be chomped.
338            
339             <%end-verbatim-section%>
340             ,
341             "b" = 123
342             }
343             EOJ
344             my $perldata = config2perl({
345             'string' => $configdata,
346             'commentstyle' => "C,shell,CPP",
347             });
348             die "call to config2perl() has failed" unless defined $perldata;
349             # the standard JSON (notice that "a" value is in a single line,
350             # here printed broken for readability):
351             # {"a" :
352             # "This is a multiline\nstring\n\"quoted text\" and 'quoted like
353             # this also'\nwill be retained in the string escaped.\nComments
354             # will not be removed.\nWhite space from
355             # beginning and end will be chomped.",
356             # "b" : 123
357             # };
358              
359              
360             =head1 EXPORT
361              
362             =over 4
363              
364             =item * C is exported by default.
365              
366             =back
367              
368              
369             =head1 SUBROUTINES
370              
371             =head2 C
372              
373             my $ret = config2perl($params);
374             die unless defined $ret;
375              
376             Arguments:
377              
378             =over 4
379              
380             =item * C<$params> : a hashref of input parameters.
381              
382             =back
383              
384             Return value:
385              
386             =over 4
387              
388             =item * the parsed content as a Perl data structure
389             on success or C on failure.
390              
391             =back
392              
393             Given input content in L, this sub removes comments
394             (as per preferences via input parameters),
395             replaces all template variables, if any,
396             compacts L, if any, into a single-line
397             string and then parses
398             what remains as standard JSON into a Perl data structure
399             which is returned to caller. JSON parsing is done with
400             L, which uses L.
401              
402             Comments outside of JSON fields will always be removed,
403             otherwise JSON can not be parsed.
404              
405             Comments inside of JSON fields, keys, values, strings etc.
406             will not be removed unless input parameter C
407             is set to 1 by the caller.
408              
409             Comments (or what looks like comments with the current input parameters)
410             inside L will never be removed.
411              
412             The input content to-be-parsed can be specified
413             with one of the following input parameters (entries in the
414             C<$params>):
415              
416             =over 4
417              
418             =item * C : content is read from a file with this name.
419              
420             =item * C : content is read from a file which has already
421             been opened for reading by the caller.
422              
423             =item * C : content is contained in this string.
424              
425             =back
426              
427             Additionally, input parameters can contain the following keys:
428              
429             =over 4
430              
431             =item * C : specify what comment style(s) to be expected
432             in the input content (if any) as a B. For example
433             C<'C,CPP,shell,custom(EE)(EE),custom(REM)()'>.
434             These are the values it understands:
435              
436             =over 2
437              
438             =item * C : comments take the form of C-style comments which
439             are exclusively within C. For example C<* I am a comment */>.
440             This is the B if none specified.
441              
442             =item * C : comments can the the form of C++-style comments
443             which are within C or after C until the end of line.
444             For example C, C.
445              
446             =item * C : comments can be after C<#> until the end of line.
447             For example, C<# I am a comment to the end of line>.
448              
449             =item * C : comments are enclosed (or preceded) by custom,
450             user-specified tags. The form is C.
451             C is required. C is optional meaning that
452             the comment extends to the end of line (just like C comments).
453             For example CE)(EE)> or
454             C or C or CEEE)(EE)>.
455             C and C do not need to be of
456             the same character length as it is
457             obvious from the previous example. A word of warning:
458             the regex for identifying comments (and variables and verbatim sections)
459             has the custom tags escaped for special regex characters
460             (with the C<\Q ... \E> construct). So you are pretty safe in using
461             any character. Please report weird behaviour.
462              
463             B : either opening or closing comment tags must not
464             be the same as opening or closing variables / verbatim section tags.
465              
466             =back
467              
468             =item * C : a hashref whose keys are
469             variable names as they occur in the input I content
470             and their corresponding values should substitute them. I,
471             can contain template variables in the form C% my-var-1 %E>. These
472             must be replaced with data which is supplied to the call of C
473             under the parameters key C, for example:
474            
475             config2perl({
476             "variable-substitutions" => {
477             "my-var-1" => 42,
478             "SCRIPTDIR" => "/home/abc",
479             },
480             "string" => '{"a":"<% my-var-1 %>", "b":"<% SCRIPTDIR %>/app.conf"}',
481             });
482              
483             Variable substitution will be performed in both
484             keys and values of the input JSON, including L.
485              
486             =item * C : by default no attempt
487             to remove what-looks-like-comments from JSON strings
488             (both keys and values). However, if this flag is set to
489             C<1> anything that looks like comments (as per the 'C'
490             parameter) will be removed from inside all JSON strings
491             (keys or values) unless they were part of verbatim section.
492              
493             This does not apply for the content verbatim sections.
494             What looks like comments to us, inside verbatim sections
495             will be left intact.
496              
497             For example consider the JSON string C<"hello/*a comment*/">
498             (which can be a key or a value). If C is
499             set to 1, then the JSON string will become C. If set to
500             0 (which is the default) it will be unchanged.
501              
502             =item * C : specify the opening and closing tags for template
503             variables and verbatim section as an ARRAYref of exactly 2 items (the
504             opening and the closing tags). By default the opening tag is C%>
505             and the closing tag is C<%E>. A word of warning:
506             the regex for identifying variables and verbatim sections (and comments)
507             has the custom tags escaped for special regex characters
508             (with the C<\Q ... \E> construct). So you are pretty safe in using
509             any character. Please report weird behaviour.
510              
511             If you set C [ '[::', '::]' ]>
512             then your template variables should look like this: C<{:: var1 ::]> and
513             verbatim sections like this: C<[:: begin-verbatim-section ::]>.
514              
515             =item * C : set this to a positive integer to increase verbosity
516             and dump debugging messages. Default is zero for zero verbosity.
517              
518             =back
519              
520             See section L for details on the format
521             of B I.
522              
523             C returns the parsed content as a Perl data structure
524             on success or C on failure.
525              
526              
527             =head1 ENHANCED JSON FORMAT
528              
529             This is JSON with added reasonable, yet completely ad-hoc, enhancements
530             (from my point of view).
531              
532             These enhancements are:
533              
534             =over 4
535              
536             =item * B:
537              
538             =over 2
539              
540             =item * C-style comments take the form of C-style comments which
541             are exclusively within C. For example C<* I am a comment */>
542              
543             =item * C-style comments can the the form of C++-style comments
544             which are within C or after C until the end of line.
545             For example C, C
546              
547             =item * C-style comments can be after C<#> until the end of line.
548             For example, C<# I am a comment to the end of line.>
549              
550             =item * comments with C, user-specified, opening and
551             optional closing tags
552             which allows fine-tuning the process of deciding on something being a
553             comment.
554              
555             =back
556              
557             =item * B