OSSP CVS Repository

ossp - Check-in [4866]
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [Patchset]  [Tagging/Branching

Check-in Number: 4866
Date: 2004-Nov-20 18:09:34 (local)
2004-Nov-20 17:09:34 (UTC)
User:rse
Branch:
Comment: Add OSSP:::cfg::simple Perl convenience API which is an ultra high-level API allowing especially the bi-directional conversion between the C API node tree representation and a simplified Perl data structure representation.
Tickets:
Inspections:
Files:
ossp-pkg/cfg/ChangeLog      added-> 1.21
ossp-pkg/cfg/perl/cfg.pm      1.6 -> 1.7     182 inserted, 0 deleted
ossp-pkg/cfg/perl/cfg.pod      1.2 -> 1.3     26 inserted, 3 deleted

ossp-pkg/cfg/ChangeLog -> 1.21

*** /dev/null    Sat Nov 23 01:01:05 2024
--- -    Sat Nov 23 01:01:11 2024
***************
*** 0 ****
--- 1,88 ----
+    _        ___  ____ ____  ____          __
+   |_|_ _   / _ \/ ___/ ___||  _ \    ___ / _| __ _
+   _|_||_| | | | \___ \___ \| |_) |  / __| |_ / _` |
+  |_||_|_| | |_| |___) |__) |  __/  | (__|  _| (_| |
+   |_|_|_|  \___/|____/____/|_|      \___|_|  \__, |
+                                              |___/
+   OSSP cfg - Configuration Parsing
+ 
+   CHANGELOG
+ 
+  Changes between 0.9.4 and 0.9.5 (31-Oct-2004 to xx-Nov-2004):
+ 
+    *) Add OSSP:::cfg::simple Perl convenience API which is an
+       ultra high-level API allowing especially the bi-directional
+       conversion between the C API node tree representation and a
+       simplified Perl data structure representation.
+       [Ralf S. Engelschall <rse@engelschall.com>]
+ 
+    *) Change cfg_node_root() API function to be able to both
+       set and/or get the root node.
+       [Ralf S. Engelschall <rse@engelschall.com>]
+ 
+    *) Fixed cfg_test program by correctly passing the used number of
+       bytes in the buffer instead of the size of the buffer.
+       [Ralf S. Engelschall <rse@engelschall.com>]
+ 
+    *) Accept zero-length strings for parsing. Correctly handle
+       end-of-file during plain text token scanning.
+       [Ralf S. Engelschall <rse@engelschall.com>]
+ 
+    *) Do not let Flex generate the unused yyunput() and yy_top_state()
+       functions in order to shut up compilation warnings.
+       [Ralf S. Engelschall <rse@engelschall.com>]
+ 
+    *) Return an empty string instead of NULL from internal
+       cfg_buf_content() function to not make visible to the caller the
+       implementation special case of an initial buffer.
+       [Ralf S. Engelschall <rse@engelschall.com>]
+ 
+    *) Added initial cut for Perl bindings.
+       [Ralf S. Engelschall <rse@engelschall.com>]
+ 
+  Changes between 0.9.3 and 0.9.4 (23-Apr-2003 to 31-Oct-2004):
+ 
+    *) Upgrade to GNU bison 1.875d and GNU flex 2.5.31
+       [Ralf S. Engelschall <rse@engelschall.com>]
+ 
+    *) Fixed warnings under GCC 3.4/3.5.
+       [Ralf S. Engelschall <rse@engelschall.com>]
+ 
+    *) Adjust copyright messages for new year 2004.
+       [Ralf S. Engelschall <rse@engelschall.com>]
+ 
+    *) Upgraded build environment to GNU libtool 1.5.10
+       and GNU shtool 2.0.1
+       [Ralf S. Engelschall <rse@engelschall.com>]
+ 
+  Changes between 0.9.2 and 0.9.3 (10-Nov-2003 to 23-Apr-2004):
+ 
+    *) Import change introduced in OSSP l2 0.9.7:
+       Replace modf(3) calls in cfg_fmt.c with a hand-crafted
+       inlined cfg_fmt_modf() function to avoid dependency to external
+       libm on systems where modf(3) is not part of libc, i.e. Tru64 and
+       QNX. Reported by Karl Vogel.
+       [Thomas Lotterer <thomas@lotterer.net>]
+ 
+   Changes between 0.9.1 and 0.9.2 (10-Nov-2003 to 10-Nov-2003)
+ 
+    *) Upgraded build environment to GNU libtool 1.5 and
+       GNU autoconf 2.58.
+       [Ralf S. Engelschall <rse@engelschall.com>]
+ 
+   Changes between 0.9.0 and 0.9.1 (01-Jul-2002 to 10-Nov-2003)
+ 
+    *) Added Bison-locations option to scanner, fixing the missing
+       reentrant "yylloc" with flex 2.5.31. Taken over from OSSP l2.
+       [Thomas Lotterer <thomas@lotterer.net>]
+ 
+    *) Enhanced test suite by comparing against previously saved output
+       [Ralf S. Engelschall <rse@engelschall.com>]
+ 
+    *) Switch from text-based VERSION file to C-based cfg_vers.c
+       and use this to provide a cfg_version(3) API function.
+       [Ralf S. Engelschall <rse@engelschall.com>]
+ 
+    *) Source tree cleanups.
+       [Ralf S. Engelschall <rse@engelschall.com>]
+ 


ossp-pkg/cfg/perl/cfg.pm 1.6 -> 1.7

--- cfg.pm       2004/11/20 16:51:52     1.6
+++ cfg.pm       2004/11/20 17:09:35     1.7
@@ -326,5 +326,187 @@
 #   static-loading functions
 XSLoader::load('OSSP::cfg', $VERSION);
 
+##
+##  Highest-Level Perl Convenience API
+##  (based on OSSP::cfg Perl API above)
+##
+
+package OSSP::cfg::simple;
+
+use 5.008;
+use strict;
+use warnings;
+use Carp;
+use IO::File;
+
+#   object constructor
+sub new ($;$) {
+    my ($proto, $input) = @_;
+    my $class = ref($proto) || $proto;
+    my $self = {};
+    bless ($self, $class);
+    $self->{-cfg} = new OSSP::cfg
+        or croak "failed to create OSSP::cfg object";
+    $self->parse($input) if (defined($input));
+    return $self;
+}
+
+#   object destructor
+sub DESTROY ($) {
+    my ($self) = @_;
+    undef $self->{-cfg};
+    return;
+}
+
+#   parse textual syntax into node tree
+sub parse ($$) {
+    my ($self, $input) = @_;
+    my $cfg = $self->{-cfg};
+    if (length($input) < 1024 and $input !~ m|[{}&\n\s]|s) {
+        if (-f $input) {
+            my $io = new IO::File "<" . $input
+               or croak "unable to read from configuration file \"".$input."\"";
+            { local $/; $input = <$io>; }
+            $io->close();
+        }
+    }
+    $cfg->import(\0, $cfg->CFG_FMT_CFG, $input)
+        or die "failed to parse configuration: " . $cfg->error();
+    return $self;
+}
+
+#   format textual syntax from node tree
+sub format ($$) {
+    my ($self) = @_;
+    my $cfg = $self->{-cfg};
+    my $root = $cfg->node_root();
+    my $str = $cfg->export($root, $cfg->CFG_FMT_CFG)
+        or die "failed to format configuration: " . $cfg->error();
+    return $str;
+}
+
+#   pack Perl complex data structure into node tree
+sub pack ($$) {
+    my ($self, $tree) = @_;
+
+    #   destroy old and create new OSSP::cfg object
+    undef $self->{-cfg};
+    my $cfg = new OSSP::cfg
+        or croak "failed to create OSSP::cfg object";
+    $self->{-cfg} = $cfg;
+
+    #   start parsing with a sequence
+    my $node = &parse_seq($cfg, $tree);
+
+    #   parse a sequence (reference) scalar
+    sub parse_seq {
+        my ($cfg, $seq) = @_;
+        my $node = undef;
+        if (ref($seq) eq 'ARRAY') {
+            $node = $cfg->node_create();
+            $cfg->node_set($node, $cfg->CFG_NODE_ATTR_TYPE, $cfg->CFG_NODE_TYPE_SEQ);
+            if (@{$seq} > 0) {
+                my $child = &parse_dir($cfg, $seq->[0]);
+                $cfg->node_set($node, $cfg->CFG_NODE_ATTR_CHILD1, $child);
+                my $sibling = $child;
+                foreach my $dir (@{$seq}[1..$#{$seq}]) {
+                    $child = &parse_dir($cfg, $dir);
+                    $cfg->node_set($sibling, $cfg->CFG_NODE_ATTR_RBROTH, $child);
+                    $sibling = $child;
+                }
+            }
+        }
+        return $node;
+    }
+
+    #   parse a directive (reference) scalar
+    sub parse_dir {
+        my ($cfg, $dir) = @_;
+        my $node = undef;
+        if (ref($dir) eq 'ARRAY') {
+            $node = $cfg->node_create();
+            $cfg->node_set($node, $cfg->CFG_NODE_ATTR_TYPE, $cfg->CFG_NODE_TYPE_DIR);
+            if (@{$dir} > 0) {
+                my $child = &parse_tok($cfg, $dir->[0]);
+                $cfg->node_set($node, $cfg->CFG_NODE_ATTR_CHILD1, $child);
+                my $sibling = $child;
+                foreach my $tok (@{$dir}[1..$#{$dir}]) {
+                    $child = &parse_tok($cfg, $tok);
+                    $cfg->node_set($sibling, $cfg->CFG_NODE_ATTR_RBROTH, $child);
+                    $sibling = $child;
+                }
+            }
+        }
+        return $node;
+    }
+
+    #   parse a token scalar
+    sub parse_tok {
+        my ($cfg, $tok) = @_;
+        my $node;
+        if (ref($tok) eq 'ARRAY') {
+            #   token is actually a sub-sequence
+            $node = &parse_seq($cfg, $tok); # recursion
+        }
+        else {
+            #   token is a plain one
+            $node = $cfg->node_create();
+            $cfg->node_set($node, $cfg->CFG_NODE_ATTR_TYPE, $cfg->CFG_NODE_TYPE_ARG);
+            $cfg->node_set($node, $cfg->CFG_NODE_ATTR_TOKEN, $tok);
+        }
+        return $node;
+    }
+
+    #   set generated node tree into OSSP::cfg object
+    $cfg->node_root($node);
+
+    return $self;
+}
+
+#   unpack Perl complex data structure from node tree
+sub unpack ($) {
+    my ($self) = @_;
+    my $cfg = $self->{-cfg};
+
+    #   start traversing the node tree from the root node
+    my $root = $cfg->node_root();
+    my $tree = &traverse($cfg, $root);
+
+    #   node processing function
+    sub traverse {
+        my ($cfg, $node) = @_;
+        return if (not(ref($node) and $$node != 0));
+        my $type = $cfg->node_get($node, $cfg->CFG_NODE_ATTR_TYPE);
+        if ($type == $cfg->CFG_NODE_TYPE_SEQ) {
+            #   node is a sequence
+            my $seq = [];
+            $node = $cfg->node_get($node, $cfg->CFG_NODE_ATTR_CHILD1);
+            while (ref($node) and $$node != 0) {
+                my $tree = &traverse($cfg, $node); # recursion
+                push(@{$seq}, $tree) if (defined($tree));
+                $node = $cfg->node_get($node, $cfg->CFG_NODE_ATTR_RBROTH);
+            }
+            return $seq;
+        }
+        elsif ($type == $cfg->CFG_NODE_TYPE_DIR) {
+            #   node is a directive
+            my $dir = [];
+            $node = $cfg->node_get($node, $cfg->CFG_NODE_ATTR_CHILD1);
+            while (ref($node) and $$node != 0) {
+                my $tree = &traverse($cfg, $node); # recursion
+                push(@{$dir}, $tree) if (defined($tree));
+                $node = $cfg->node_get($node, $cfg->CFG_NODE_ATTR_RBROTH);
+            }
+            return $dir;
+        }
+        else {
+            #   node is a token
+            my $token = $cfg->node_get($node, $cfg->CFG_NODE_ATTR_TOKEN);
+            return $token;
+        }
+    }
+    return $tree;
+}
+
 1;
 


ossp-pkg/cfg/perl/cfg.pod 1.2 -> 1.3

--- cfg.pod      2004/11/17 13:15:35     1.2
+++ cfg.pod      2004/11/20 17:09:35     1.3
@@ -40,18 +40,41 @@
 
 B<OSSP cfg> is ...
 
-B<OSSP::cfg> provides two Perl APIs:
+B<OSSP::cfg> provides three Perl APIs:
+
+=head2 SIMPLE API
+
+The simple API is a wrapper around the OO-style API and intended
+for working with configurations the really simple but less flexible way:
+
+=over 4
+
+=item C<use OSSP::cfg;>
+
+=item C<$cfg = >B<new>C< OSSP::cfg::simple;>
+
+=item C<$cfg-E<gt>>B<parse>C<($txt);>
+
+=item C<$cfg-E<gt>>B<pack>C<($tree);>
+
+=item C<$txt  = $cfg-E<gt>>B<format>C<();>
+
+=item C<$tree = $cfg-E<gt>>B<unpack>C<();>
+
+=item C<undef $cfg;>
+
+=back
 
 =head2 OO-STYLE API
 
 The OO-style API is a wrapper around the C-style API and intended for
-high-level and regular programming.
+high-level and flexible programming.
 
 =over 4
 
 =item C<use OSSP::cfg;>
 
-=item C<my $cfg = >B<new>C< OSSP::cfg;>
+=item C<$cfg = >B<new>C< OSSP::cfg;>
 
 =item C<undef $cfg;>
 

CVSTrac 2.0.1