in reply to Speed Improvement

Naive and brutal, but works for me ;-)

use strict; use warnings; use Inline 'C'; use constant ZERO_START => 0; # digit-sequence allows 0 start use constant NON_ZERO_START => 1; # digit-sequence must not start wi +th a leading 0 msg_subst_seed((time() + $$) % 32000); # just for tests, not a good id +ea where security matters do { my $x = msg_subst("3x: ({\\d4})x({\\d1})x({\\d10})", NON_ZERO_START) +; print "[$x]\n"; }; print msg_subst("empty: ({\\d0})\n", ZERO_START); print msg_subst("$_-dig: ({\\d$_})\n", ZERO_START) for (1..10); print msg_subst("2x : ({\\d3}) x ({\\d3})\n", NON_ZERO_START); print msg_subst("huge: ({\\d99})\n", ZERO_START); print msg_subst("err: ({\\d100})\n", ZERO_START); print msg_subst("err: ({\\d-10})\n", ZERO_START); print msg_subst('overflow: {\d99}{\d99}{\d99}{\d99}{\d99}{\d99}{\d99}{ +\d99}{\d99}{\d99}{\d99}'."\n", ZERO_START); __END__ __C__ #include <stdint.h> /* see: http://stackoverflow.com/questions/1167253/implementation-of +-rand */ static uint32_t z1 = 12345, z2 = 12345, z3 = 12345, z4 = 12345; /* s +eed */ void msg_subst_seed(int seed) { /* TODO: needs improvement */ if (seed < 0) seed = -seed; if (!seed) seed = 1; z1 = seed; /* z1: positive and >= 1 */ } uint32_t lfsr113_Bits (void) { uint32_t b; b = ((z1 << 6) ^ z1) >> 13; z1 = ((z1 & 4294967294U) << 18) ^ b; b = ((z2 << 2) ^ z2) >> 27; z2 = ((z2 & 4294967288U) << 2) ^ b; b = ((z3 << 13) ^ z3) >> 21; z3 = ((z3 & 4294967280U) << 7) ^ b; b = ((z4 << 3) ^ z4) >> 12; z4 = ((z4 & 4294967168U) << 13) ^ b; return (z1 ^ z2 ^ z3 ^ z4); } /* see.. until here */ char get_digit() {/* iterator to get an ASCII digit in range '0'..' +9', the naive way... */ static int count = 0; static uint32_t drawn_rand; char digit; if (!count) { drawn_rand = lfsr113_Bits(); count = 8; } digit = (char) ('0' + drawn_rand % 10); drawn_rand /= 10; count--; return digit; } SV * msg_subst(char* msg, int mode) { static char buf[1024]; /* keep the result smaller than this, increase the static b +uffer, or use malloc() */ char *to = buf; char *from = msg; while(*from && (to-buf) <= 1000) { /* for simplicity, we allow {\d0} .. {\d99} only */ if (*from == '{' && from[1] == '\\' && from[2] == 'd' && isdigi +t( from[3] )) { int i; int count = from[3] - '0'; int consumed = 4; if ( isdigit(from[4]) ) { count = count * 10 + from[4] - '0'; consumed++; } if ( from[consumed] == '}' ) { /* found a valid {\d##} sequenc +e */ if (count && mode == 1) { count--; *to = get_digit(); while (*to == '0') { *to = get_digit(); } /* no leading ze +ros wanted */ to++; } for (i=0; i<count && (to-buf) <= 1000 ; i++) *to++ = get_d +igit(); from += consumed; } else { /* err, just copy what we saw */ for (i=0; i<consumed; i++) *to++ = from[i]; from += consumed -1; } } else { /* no {\d++} sequence in sight */ *to++ = *from; } from++; } *to = '\0'; if ( (to-buf) >= 1000 ) strcpy( to, "... *OVERFLOW*!\n"); return newSVpv(buf, strlen(buf)); } /* further improvements: - profile / this alternative "can" be faster - other/better random generator or lookup-table () - parse pattern once (if pattern stays constant for a sufficiently l +ong period of time) - more than 99 digits - Modes: HEX, ASCII, SET(...), RANGE(...) - tweak "use inline C;" - pre-compute messages if possible - return a list of results - find more buffer overflows ;-) - find mem-leaks? - set $! - ... */

Sample:

[3x: (5800)x(9)x(4119272153)] empty: () 1-dig: (6) 2-dig: (00) 3-dig: (286) 4-dig: (3538) 5-dig: (76912) 6-dig: (152922) 7-dig: (1998601) 8-dig: (46526790) 9-dig: (272269142) 10-dig: (5036180257) 2x : (270) x (295) huge: (60698211971351646325662438145076882977674264083631891784014981 +6984333515486911733872823592611980610) err: ({\d100}) err: ({\d-10}) overflow: 388337913014518572079085655682352923685268720200399379872225 +309937696652401652578874749078259328418468960924412471336333591725866 +610726754040840249257924549575536281471052995818025767742622376415863 +863933450041956239915916349295988704367621957622747170445376882427886 +836368075301197163788171910212466615189214921253457526440240130287642 +877297593187189458587800219270169705119636312020472283690712168123351 +112899925547204701597189413213272345551314154916747140042506436194250 +360536730048179486951946798572111575588675513637404504421938424450645 +872242712239584218866179138498996988181042546504722655259441150264820 +656960415909356582097541742743117114058581773895455908059546695344897 +361883153435808150852670180088922568961467160025338460179243921987976 +441004315513268035989754880873846622730659638610226282538414297658365 +180965342365181518413709147137791131035270552146178096818064703332869 +696209005692384041910395288531887465999649751307270627069753831067510 +2369072243267355810846576590914699... *OVERFLOW*!