Plateforme Level Extreme
Abonnement
Profil corporatif
Produits & Services
Support
Légal
English
Speeding up string conversion
Message
De
16/03/2005 08:16:39
 
 
À
16/03/2005 03:26:00
Information générale
Forum:
Visual FoxPro
Catégorie:
Codage, syntaxe et commandes
Divers
Thread ID:
00996197
Message ID:
00996265
Vues:
18
>I need to convert binary strings to ascii by changing nonprintable non-ascii
>charaters to a \\nnn strings where nnn is octal representation.
>
>I created the following routine. For 381 KB byte strings, the conversion takes 5 (!) minutes and task manager shows that my application takes a lot of MBs memory.
>
>Any way to speed up this conversion ?
>
>
FUNCTION toBYTEA( cStr )
>
>LOCAL i, j, cRes, nChr, cDig
>
>cRes = ''
>FOR i=1 TO LEN(m.cStr)
>  nChr = ASC( SUBSTR( m.cStr, m.i,1))
>  * The following four lines cna be removed if this can speed the conversion.
>  IF BETWEEN( nChr, 32,126 ) AND !INLIST( nChr,39,92)
>    cRes = m.cRes + SUBSTR( m.cStr, m.i,1)
>    LOOP
>    ENDIF
>
>  cDig = ''
>  FOR j=1 TO 3
>    cDig= CHR(ASC('0')+ m.nChr%8) + m.cDig
>    nChr = INT(m.nChr/8)
>    ENDFOR
>  cRes = m.cRes + '\\'+ m.cDig
>  ENDFOR
>RETURN m.cRes
>ENDFUNC
This thread is a interesting point for publishing the only solution
that can reduce the VFP long string processing, without write a C code.
The solution is not immediate, because it is RECURSION.
The problem of VFP with a strings and native command is that into
a native command is not possible pass a var by reference ( a mem pointer ),
then VFP copy the string into a engine buffer.
With Recursion you can create of the virtual pointer, breaking the string in substring,
this have another important effect, VFP move and work on short string, then the
job is done in first level cache
( the only area of memory where the cpu efficiency works is sufficient ).

On next code, STRCONV() return a the expected time for a C implementation
Then:
#DEFINE MAXLEN 2048

X=''
FOR K=0 TO 255
 X=X+CHR(K)
NEXT
ACTIVATE WINDOW "Debug Output"
DEBUGOUT toBYTEA(REPLICATE(m.x,100))== toBYTEA3(REPLICATE(m.x,100))
FOR j=2 TO MAXLEN STEP 0
	T0=SECONDS()
	=toBYTEA(REPLICATE(m.x,m.j))
	t1=SECONDS()-T0
	T0=SECONDS()
	=toBYTEA2(REPLICATE(m.x,m.j))
	t2=SECONDS()-T0
	T0=SECONDS()
	=toBYTEA3(REPLICATE(m.x,m.j))
	t3=SECONDS()-T0
	T0=SECONDS()
	=STRCONV(REPLICATE(m.x,m.j),15)
	t4=SECONDS()-T0
	DEBUGOUT m.j,m.t1,m.t2,m.t3,M.T4
	j=j*2
NEXT

FUNCTION toBYTEA( cStr )

	PRIVATE i,  cRes, cChr, nChr

	cRes = ''
	FOR i=1 TO LEN(m.cStr)
		STORE SUBSTR( m.cStr, m.i,1)	TO cChr
		STORE ASC( m.cChr)				TO nChr
		cRes = m.cRes + IIF(BETWEEN( m.nChr, 32,126 ) AND !INLIST( m.nChr,39,92);
	  			,	m.cChr	;
	  			,	'\\'+ CHR(48+ BITAND(m.nChr/64,7))+CHR(48+ BITAND(m.nChr/8,7))+CHR(48+ BITAND(m.nChr,7)))
	ENDFOR
	RETURN m.cRes
ENDFUNC

FUNCTION toBYTEA2( cStr )

	STORE STRTRAN(STRTRAN(m.cStr,[\],[\\134]),['],[\\047]) TO cStr
	PRIVATE nChr
	FOR nChr=0 TO 255
		IF m.nChr=32
			STORE 126 TO nChr
			LOOP
		ENDIF
		STORE STRTRAN(m.cStr;
				,	CHR(m.nChr);
				,	'\\'+ CHR(48+ BITAND(m.nChr/64,7))+CHR(48+ BITAND(m.nChr/8,7))+CHR(48+ BITAND(m.nChr,7)));
			TO cStr
	NEXT
	RETURN m.cStr
ENDFUNC

FUNCTION toBYTEA3( cStr,lenght )
	IF PARAMETERS()=1
		* this is a slow op
		STORE LEN(m.cStr) TO lenght
	ENDIF
	IF m.lenght>100
		* this is a slow op
		RETURN	toBYTEA3(LEFT( m.cStr ,BITRSHIFT(m.lenght+1,1)) ,BITRSHIFT(m.lenght+1,1))	;
			+	toBYTEA3(RIGHT(m.cStr ,BITRSHIFT(m.lenght,1))   ,BITRSHIFT(m.lenght  ,1))
	ENDIF
	PRIVATE cRes, cChr
	STORE [] TO cRes
	FOR lenght=1 TO m.lenght
		* this is a slow op
		STORE SUBSTR( m.cStr, m.lenght,1)	TO cChr
		* this is a fast op
		cRes = m.cRes + IIF(BETWEEN( ASC( m.cChr), 32,126 ) AND !INLIST( ASC( m.cChr),39,92);
	  			,	m.cChr	;
	  			,	'\\'+ CHR(48+ BITRSHIFT(ASC(m.cChr),6))+CHR(48+ BITAND(BITRSHIFT(ASC(m.cChr),3),7))+CHR(48+ BITAND(ASC(m.cChr),7)))
	ENDFOR
	* this is a slow op
	RETURN m.cRes
ENDFUNC
Fabio
Précédent
Suivant
Répondre
Fil
Voir

Click here to load this message in the networking platform