Add a key flag HVhek_KEYCANONICAL for Perl_hv_common(), which signals that the
Nicholas Clark [Sun, 28 Dec 2008 13:06:42 +0000 (13:06 +0000)]
key is in canonical form - any key passed encoded in UTF-8 cannot be represented
as bytes, hence the downgrade check can be skipped. Use this internally for
shared hash key scalars, as they are always canonical.

hv.c
hv.h

diff --git a/hv.c b/hv.c
index b764c55..79f5973 100644 (file)
--- a/hv.c
+++ b/hv.c
@@ -388,8 +388,12 @@ Perl_hv_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen,
        if (flags & HVhek_FREEKEY)
            Safefree(key);
        key = SvPV_const(keysv, klen);
-       flags = 0;
        is_utf8 = (SvUTF8(keysv) != 0);
+       if (SvIsCOW_shared_hash(keysv)) {
+           flags = HVhek_KEYCANONICAL | (is_utf8 ? HVhek_UTF8 : 0);
+       } else {
+           flags = 0;
+       }
     } else {
        is_utf8 = ((flags & HVhek_UTF8) ? TRUE : FALSE);
     }
@@ -595,7 +599,7 @@ Perl_hv_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen,
        }
     }
 
-    if (is_utf8) {
+    if (is_utf8 & !(flags & HVhek_KEYCANONICAL)) {
        char * const keysave = (char *)key;
        key = (char*)bytes_from_utf8((U8*)key, &klen, &is_utf8);
         if (is_utf8)
diff --git a/hv.h b/hv.h
index 2265326..9322377 100644 (file)
--- a/hv.h
+++ b/hv.h
@@ -367,6 +367,9 @@ C<SV*>.
 #define HVhek_FREEKEY  0x100 /* Internal flag to say key is malloc()ed.  */
 #define HVhek_PLACEHOLD        0x200 /* Internal flag to create placeholder.
                                * (may change, but Storable is a core module) */
+#define HVhek_KEYCANONICAL 0x400 /* Internal flag - key is in canonical form.
+                                   If the string is UTF-8, it cannot be
+                                   converted to bytes. */
 #define HVhek_MASK     0xFF
 
 /* Which flags enable HvHASKFLAGS? Somewhat a hack on a hack, as