chiark / gitweb /
Fix the fix in the prior fix for nested empty arrays/tables
authorJeff Ober <jober@ziprecruiter.com>
Fri, 17 Jan 2020 14:55:48 +0000 (09:55 -0500)
committerJeff Ober <jober@ziprecruiter.com>
Fri, 17 Jan 2020 14:55:48 +0000 (09:55 -0500)
lib/TOML/Tiny/Writer.pm

index f5a206c607e2ce40603617a42a42ca0697e3aad7..f9fb9c9e613224514b901c82ba207659b0cacff2 100644 (file)
@@ -26,51 +26,74 @@ sub to_toml {
 
   for (ref $data) {
     when ('HASH') {
-      if (!keys(%$data)) {
-        push @buff, '{}';
-      } else {
-        for my $k (grep{ ref($data->{$_}) !~ /HASH|ARRAY/ } sort keys %$data) {
+      # Generate simple key/value pairs for scalar data
+      for my $k (grep{ ref($data->{$_}) !~ /HASH|ARRAY/ } sort keys %$data) {
+        my $key = to_toml_key($k);
+        my $val = to_toml($data->{$k}, %param);
+        push @buff, "$key=$val";
+      }
+
+      # For values which are arrays, generate inline arrays for non-table
+      # values, array-of-tables for table values.
+      ARRAY: for my $k (grep{ ref $data->{$_} eq 'ARRAY' } sort keys %$data) {
+        # Empty table
+        if (!@{$data->{$k}}) {
           my $key = to_toml_key($k);
-          my $val = to_toml($data->{$k}, %param);
-          push @buff, "$key=$val";
+          push @buff, "$key=[]";
+          next ARRAY;
         }
 
-        for my $k (grep{ ref $data->{$_} eq 'ARRAY' } sort keys %$data) {
-          my @inline;
-          my @table_array;
+        my @inline;
+        my @table_array;
 
-          for my $v (@{$data->{$k}}) {
-            if (ref $v eq 'HASH') {
-              push @table_array, $v;
-            } else {
-              push @inline, $v;
-            }
+        # Sort table and non-table values into separate containers
+        for my $v (@{$data->{$k}}) {
+          if (ref $v eq 'HASH') {
+            push @table_array, $v;
+          } else {
+            push @inline, $v;
           }
+        }
 
-          if (@inline) {
-            my $key = to_toml_key($k);
-            my $val = to_toml(\@inline, %param);
-            push @buff, "$key=$val";
-          }
+        # Non-table values become an inline table
+        if (@inline) {
+          my $key = to_toml_key($k);
+          my $val = to_toml(\@inline, %param);
+          push @buff, "$key=$val";
+        }
+
+        # Table values become an array-of-tables
+        if (@table_array) {
+          push @KEYS, $k;
 
-          if (@table_array) {
-            push @KEYS, $k;
+          for (@table_array) {
+            push @buff, '', '[[' . join('.', map{ to_toml_key($_) } @KEYS) . ']]';
 
-            for (@table_array) {
-              push @buff, '', '[[' . join('.', map{ to_toml_key($_) } @KEYS) . ']]';
+            for my $k (sort keys %$_) {
+              my $key = to_toml_key($k);
+              my $val = to_toml($_->{$k}, %param);
 
-              for my $k (sort keys %$_) {
-                my $key = to_toml_key($k);
-                my $val = to_toml($_->{$k}, %param);
-                push @buff, "$key=$val";
+              unless ($val) {
+                $val = '{}' if ref $_->{$k} eq 'HASH';
+                $val = '[]' if ref $_->{$k} eq 'ARRAY';
               }
-            }
 
-            pop @KEYS;
+              push @buff, "$key=$val";
+            }
           }
+
+          pop @KEYS;
         }
+      }
 
-        for my $k (grep{ ref $data->{$_} eq 'HASH' } sort keys %$data) {
+      # Sub-tables
+      for my $k (grep{ ref $data->{$_} eq 'HASH' } sort keys %$data) {
+        if (!keys(%{$data->{$k}})) {
+          # Empty table
+          my $key = to_toml_key($k);
+          push @buff, "$key={}";
+        } else {
+          # Generate [table]
           push @KEYS, $k;
           push @buff, '', '[' . join('.', map{ to_toml_key($_) } @KEYS) . ']';
           push @buff, to_toml($data->{$k}, %param);