Author: timbo
Date: Wed May 28 07:26:43 2008
New Revision: 11338

Modified:
   dbi/trunk/DBI.xs
   dbi/trunk/t/18concathash.t

Log:
Fix _concat_hash_sorted (test wasn't testing xs code, mixed hashes needed work)


Modified: dbi/trunk/DBI.xs
==============================================================================
--- dbi/trunk/DBI.xs    (original)
+++ dbi/trunk/DBI.xs    Wed May 28 07:26:43 2008
@@ -219,17 +219,19 @@
     const void *val1;
     const void *val2;
 {
-    int first, second;
+    UV first  = ((struct num_srt_info *)val1)->numeric;
+    UV second = ((struct num_srt_info *)val2)->numeric;
 
-    first = ((struct num_srt_info *)val1)->numeric;
-    second = ((struct num_srt_info *)val2)->numeric;
-
-    if (first == second)
-        return 0;
-    else if (first > second)
+    if (first > second)
        return 1;
-    else 
+    if (first < second)
        return -1;
+    /* only likely to reach here if numeric sort forced for non-numeric keys */
+    /* fallback to comparing the key strings */
+    return strcmp(
+        ((struct num_srt_info *)val1)->key,
+        ((struct num_srt_info *)val2)->key
+    );
 }
 
 static int 
@@ -252,22 +254,24 @@
     char **keys;
     unsigned int idx = 0;
     STRLEN tot_len = 0;
-    bool numberish = 1;
+    bool has_non_numerics = 0;
     struct num_srt_info *numbers;
 
     hv_len = hv_iterinit(hash);
     if (!hv_len)
         return 0;
 
-    New(0, keys, hv_len, char *);
-    New(0, numbers, hv_len, struct num_srt_info);
+    Newz(0, keys, hv_len, char *);
+    Newz(0, numbers, hv_len, struct num_srt_info);
 
     while ((entry = hv_iternext(hash))) {
         *(keys+idx) = hv_iterkey(entry, &key_len);
         tot_len += key_len;
         
-        if (grok_number(*(keys+idx), key_len, &(numbers+idx)->numeric) != 
IS_NUMBER_IN_UV)
-            numberish = 0;
+        if (grok_number(*(keys+idx), key_len, &(numbers+idx)->numeric) != 
IS_NUMBER_IN_UV) {
+            has_non_numerics = 1;
+            (numbers+idx)->numeric = 0;
+        }
 
         (numbers+idx)->key = *(keys+idx);
         ++idx;
@@ -276,16 +280,16 @@
     if (0 != total_length)
         *total_length = tot_len;
 
-    if (sort_order <0)
-        sort_order = numberish ? 1 : 0;
+    if (sort_order < 0)
+        sort_order = (has_non_numerics) ? 0 : 1;
 
-    if (0 == sort_order || 0 == numberish ) {
+    if (0 == sort_order) {
         qsort(keys, hv_len, sizeof(char*), _cmp_str);
-    } else {
+    }
+    else {
         qsort(numbers, hv_len, sizeof(struct num_srt_info), _cmp_number);
         for (idx = 0; idx < hv_len; ++idx)
             *(keys+idx) = (numbers+idx)->key;
-/* SvPV_nolen(sv_2mortal(newSViv(numbers[idx])));  */
     }
 
     Safefree(numbers);
@@ -305,7 +309,6 @@
         I32 hv_len;
         STRLEN kv_sep_len, pair_sep_len, hv_val_len, total_len = 0;
         char **keys;
-        char *value_string;
         unsigned int i = 0;
         SV **hash_svp;
         SV *return_sv;
@@ -330,11 +333,16 @@
                 continue;
             }
 
-            value_string = (not_neat) ? 
-                (SvOK(*hash_svp) ? SvPV(*hash_svp, hv_val_len) : "") : 
-                neatsvpv(*hash_svp,0);
-            sv_catpvf(return_sv, (not_neat) ? "%s%s'%s'%s" : "%s%s%s%s",
-                keys[i], kv_sep, value_string, (i<hv_len-1) ? pair_sep : "");
+            sv_catpvf(return_sv, "%s%s", keys[i], kv_sep);
+            if (not_neat) {
+                if (SvOK(*hash_svp))
+                     sv_catpvf(return_sv, "'%s'", SvPV(*hash_svp, hv_val_len));
+                else sv_catpv(return_sv, "undef");
+            }
+            else     sv_catpv(return_sv, neatsvpv(*hash_svp,0));
+
+            if (i < hv_len-1)
+                sv_catpv(return_sv, pair_sep);
         }
 
         Safefree(keys);
@@ -4385,15 +4393,12 @@
     SV *pair_sep_sv
     SV *value_format_sv
     SV *sort_type_sv
-
     PREINIT:
-
     STRLEN kv_sep_len, pair_sep_len;
     char *kv_sep, *pair_sep;
     int not_neat, sort;
 
     CODE:
-
         kv_sep = SvPV(kv_sep_sv, kv_sep_len);
         pair_sep = SvPV(pair_sep_sv, pair_sep_len);
 
@@ -4401,10 +4406,8 @@
             mg_get(value_format_sv);
         not_neat = SvTRUE(value_format_sv);
 
-
         sort = (SvOK(sort_type_sv)) ? SvIV(sort_type_sv) : -1;
 
-
         RETVAL = _join_hash_sorted(hash,kv_sep, pair_sep, not_neat, sort);
 
     OUTPUT:

Modified: dbi/trunk/t/18concathash.t
==============================================================================
--- dbi/trunk/t/18concathash.t  (original)
+++ dbi/trunk/t/18concathash.t  Wed May 28 07:26:43 2008
@@ -6,9 +6,12 @@
 # change 'tests => 1' to 'tests => last_test_to_print';
 
 use strict;
+use Benchmark qw(:all);
+no warnings 'uninitialized';
+
 use Test::More tests => 36;
+
 BEGIN { use_ok('DBI') };
-no warnings 'uninitialized';
 
 # null and undefs -- segfaults?;
 is (DBI::_concat_hash_sorted({ }, "=", ":", 0, undef), "");
@@ -19,26 +22,24 @@
 is (DBI::_concat_hash_sorted({ }, "=", undef, 0, undef), "");
 is (DBI::_concat_hash_sorted({ }, "=", ":", undef, undef),"");
 
-# Simple segfault tests?
+# Simple stress tests
 ok(DBI::_concat_hash_sorted({bob=>'two', fred=>'one' }, "="x12000, ":", 1, 
undef));
 ok(DBI::_concat_hash_sorted({bob=>'two', fred=>'one' }, "=", ":"x12000, 1, 
undef));
 ok(DBI::_concat_hash_sorted({map {$_=>undef} (1..1000)}, "="x12000, ":", 1, 
undef));
-ok(DBI::_concat_hash_sorted({map {$_=>undef} (1..10000)}, "=", ":"x12000, 1, 
undef), 'test');
+ok(DBI::_concat_hash_sorted({map {$_=>undef} (1..1000)}, "=", ":"x12000, 1, 
undef), 'test');
 ok(DBI::_concat_hash_sorted({map {$_=>undef} (1..100)}, "="x12000, ":"x12000, 
1, undef), 'test');
 
 my $simple_hash = {
     bob=>"there",
     jack=>12,
-     fred=>"there",
-     norman=>"there",
+    fred=>"there",
+    norman=>"there",
     # sam =>undef
 };
 
 my $simple_numeric = {
     1=>"there",
     2=>"there",
-    3=>"there",
-    32=>"there",
     16 => 'yo',
     07 => "buddy",
     49 => undef,
@@ -47,22 +48,18 @@
 my $simple_mixed = {
     bob=>"there",
     jack=>12,
-     fred=>"there",
-     norman=>"there",
-     sam =>undef,
+    fred=>"there",
+    sam =>undef,
     1=>"there",
-    2=>"there",
-    3=>"there",
     32=>"there",
     16 => 'yo',
     07 => "buddy",
-           49 => undef,
+    49 => undef,
 };
 
 my $simple_float = {
     1.12 =>"there",
     3.1415926 =>"there",
-    2.718281828 =>"there",
     32=>"there",
     1.6 => 'yo',
     0.78 => "buddy",
@@ -106,21 +103,16 @@
 
 sub test_concat_hash {
     my ($hash, $neat, $sort_type) = @_;
+    my @args = ($hashes{$hash}, "=", ":",$neats{$neat}, 
$sort_types{$sort_type});
     is (
-        #DBI::_concat_hash_sorted(
-        _concat_hash_sorted(
-            $hashes{$hash}, "=", ":",$neats{$neat}, $sort_types{$sort_type}
-        ),
-        _concat_hash_sorted(
-            $hashes{$hash} , "=", ":",$neats{$neat}, $sort_types{$sort_type}
-        ),
+        DBI::_concat_hash_sorted(@args),
+        _concat_hash_sorted(@args),
         "$hash - $neat $sort_type"
     );
 }
 
 if (0) {
     eval {
-        use Benchmark qw(:all);
         cmpthese(200_000, {
            Perl => sub {_concat_hash_sorted($simple_hash, "=", ":",0,undef); },
            C=> sub {DBI::_concat_hash_sorted($simple_hash, "=", ":",0,1);}
@@ -136,7 +128,6 @@
             }
         });
     };
-
 }
 #CatHash::_concat_hash_values({ }, ":-",,"::",1,1);
 
@@ -165,22 +156,20 @@
 use Scalar::Util qw(looks_like_number);
 sub _get_sorted_hash_keys {
     my ($hash_ref, $sort_type) = @_;
-    my $sort_guess = 1;
     if (not defined $sort_type) {
-        #my $first_key = (each %$hash_ref)[0];
-        #$sort_type = looks_like_number($first_key);
-
-        $sort_guess =  
-            (1!=looks_like_number($_)) ? 0:$sort_guess for keys %$hash_ref;
-        $sort_type = $sort_guess unless (defined $sort_type);
+        my $sort_guess = 1;
+        $sort_guess = (not looks_like_number($_)) ? 0 : $sort_guess
+            for keys %$hash_ref;
+        $sort_type = $sort_guess;
     }
     
     my @keys = keys %$hash_ref;
     no warnings 'numeric';
-    return [ ($sort_type && $sort_guess)
-        ? sort {$a <=> $b} @keys
-        : sort    @keys
-    ];
+    my @sorted = ($sort_type)
+        ? sort { $a <=> $b or $a cmp $b } @keys
+        : sort    @keys;
+    warn "$sort_type = @sorted\n";
+    return [EMAIL PROTECTED];
 }
 
 1;

Reply via email to