develooper Front page | perl.perl5.porters | Postings from February 2000

tr/// returns histogram

Thread Previous
From:
simon
Date:
February 19, 2000 10:05
Subject:
tr/// returns histogram
Message ID:
slrn8atmpu.1j1.simon@othersideofthe.earth.li
This was on the Todo, so I had a look at it. I've tried to keep within
the do_trans_XX_operation thing, which may not have been such a good
idea. On the other hand, I don't think we'd be better off special-casing
in pp.c; your mileage may vary. I've not managed to work out how to
convert it to Unicode as well, but I'm hoping someone else will have a
look at that if I don't have time. Here's a patch, anyway, it works.
Be sure to regen headers.

% perl -le '$_=q/abcdbaa/; %a=tr/abc/def/; print "$k,$v\n" while each %a"'
a,3
b,2
c,1

diff -ruN perl5.5.660/doop.c perl5.5.660-new/doop.c
--- perl5.5.660/doop.c	Mon Feb  7 04:32:59 2000
+++ perl5.5.660-new/doop.c	Sun Feb 20 02:57:55 2000
@@ -131,6 +131,85 @@
 
     return matches;
 }
+STATIC I32
+S_do_trans_CC_histogram(pTHX_ SV *sv)
+{
+	dSP;
+    U8 *s;
+    U8 *send;
+    U8 *d;
+	HV *histo;
+    STRLEN len;
+    short *tbl;
+    I32 ch;
+	SV *value;
+	char *key; 
+	I32 keylen;
+	
+    tbl = (short*)cPVOP->op_pv;
+
+	histo = newHV();
+	
+    if (!tbl)
+	Perl_croak(aTHX_ "panic: do_trans");
+
+    s = (U8*)SvPV(sv, len);
+    send = s + len;
+
+    d = s;
+    if (PL_op->op_private & OPpTRANS_SQUASH) {
+	U8* p = send;
+
+	while (s < send) {
+	    if ((ch = tbl[*s]) >= 0) {
+		/* $histo{$ch}++ - A Prime Example of Why Perl is not C */
+		if(hv_exists(histo,s,1))
+			(void)hv_store(histo, s, 1, 
+				newSViv(1+SvIV((hv_fetch(histo,s,1,FALSE))[0])),0);
+		 else 
+			(void)hv_store(histo,s,1,newSViv(1),0);
+
+		*d = ch;
+		if (p != d - 1 || *p != *d)
+		    p = d++;
+		}
+	    else if (ch == -1)		/* -1 is unmapped character */
+		*d++ = *s;		/* -2 is delete character */
+	    s++;
+	}
+	}
+    else {
+	while (s < send) {
+	    if ((ch = tbl[*s]) >= 0) {
+		if(hv_exists(histo,s,1))
+			(void)hv_store(histo, s, 1, 
+				newSViv(1+SvIV((hv_fetch(histo,s,1,FALSE))[0])),0);
+		 else 
+			(void)hv_store(histo,s,1,newSViv(1),0);
+		*d = ch;
+		d++;
+	    }
+	    else if (ch == -1)		/* -1 is unmapped character */
+		*d++ = *s;		/* -2 is delete character */
+	    s++;
+	}
+    }
+    *d = '\0';
+    SvCUR_set(sv, d - (U8*)SvPVX(sv));
+    SvSETMAGIC(sv);
+
+	/* Take care of pushing the hash onto the stack */
+	
+	(void)hv_iterinit(histo);
+	while(value=hv_iternextsv(histo,&key,&keylen)) {
+		XPUSHs(sv_2mortal(newSVpv(key,keylen)));
+		XPUSHs(sv_2mortal(newSViv(SvIV(value))));
+	}
+	PUTBACK;
+
+	hv_undef(histo);
+    return -1;
+}
 
 STATIC I32
 S_do_trans_UU_simple(pTHX_ SV *sv)
@@ -596,6 +675,13 @@
 
     DEBUG_t( Perl_deb(aTHX_ "2.TBL\n"));
 
+	if (GIMME == G_ARRAY) {
+		if (PL_op->op_private & (OPpTRANS_FROM_UTF|OPpTRANS_TO_UTF))
+			Perl_croak(aTHX_ "Not yet here");
+		else
+			return do_trans_CC_histogram(sv);
+	}
+	
     switch (PL_op->op_private & 63) {
     case 0:
 	return do_trans_CC_simple(sv);
diff -ruN perl5.5.660/embed.pl perl5.5.660-new/embed.pl
--- perl5.5.660/embed.pl	Wed Feb 16 21:42:30 2000
+++ perl5.5.660-new/embed.pl	Thu Feb 17 23:38:44 2000
@@ -2153,6 +2153,7 @@
 s	|I32	|do_trans_CC_simple	|SV *sv
 s	|I32	|do_trans_CC_count	|SV *sv
 s	|I32	|do_trans_CC_complex	|SV *sv
+s	|I32	|do_trans_CC_histogram	|SV *sv
 s	|I32	|do_trans_UU_simple	|SV *sv
 s	|I32	|do_trans_UU_count	|SV *sv
 s	|I32	|do_trans_UU_complex	|SV *sv
diff -ruN perl5.5.660/opcode.pl perl5.5.660-new/opcode.pl
--- perl5.5.660/opcode.pl	Thu Jan 13 06:03:56 2000
+++ perl5.5.660-new/opcode.pl	Thu Feb 17 23:29:47 2000
@@ -392,7 +392,7 @@
 qr		pattern quote (qr//)	ck_match	s/
 subst		substitution (s///)	ck_null		dis/	S
 substcont	substitution iterator	ck_null		dis|	
-trans		transliteration (tr///)	ck_null		is"	S
+trans		transliteration (tr///)	ck_null		i"	S
 
 # Lvalue operators.
 # sassign is special-cased for op class
diff -ruN perl5.5.660/pp.c perl5.5.660-new/pp.c
--- perl5.5.660/pp.c	Mon Feb  7 15:37:51 2000
+++ perl5.5.660-new/pp.c	Sun Feb 20 02:24:28 2000
@@ -726,6 +726,7 @@
 {
     djSP; dTARG;
     SV *sv;
+	IV retval;
 
     if (PL_op->op_flags & OPf_STACKED)
 	sv = POPs;
@@ -734,8 +735,12 @@
 	EXTEND(SP,1);
     }
     TARG = sv_newmortal();
-    PUSHi(do_trans(sv));
-    RETURN;
+    retval = (IV)do_trans(sv);
+	if (retval >0) {
+		PUSHs(newSViv(retval));
+		PUTBACK;
+	}
+	return NORMAL;
 }
 
 /* Lvalue operators. */

-- 
`And when you've been *plonk*ed by Simon C., you've been *plonked*
by someone who knows when, and why, and how.' - Mike Andrews, asr

Thread Previous


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About