Plateforme Level Extreme
Abonnement
Profil corporatif
Produits & Services
Support
Légal
English
Faststring.dll
Message
De
06/07/2020 18:04:12
 
 
À
06/07/2020 13:51:45
Information générale
Forum:
Visual FoxPro
Catégorie:
Produits tierce partie
Titre:
Divers
Thread ID:
01674989
Message ID:
01675119
Vues:
144
I have updated the code as a class definition and added some more methods. In particular I needed to do an extract of all segments so I added the GetFirstSegment() and GetNextSegment() methods to streamline this.

On my system with a file that is 41.5M in size I get the following results:

Selected Segment Extract: 3.370
All Segments Extract: 50.102
Segment Count: 20638
LOCAL lcFileText, lcBegDelimiter, lcEndDelimiter, loDrawingXML, lnSecs, lnCount
lcFileText     = FILETOSTR('drawing1.xml')
lcBegDelimiter = "<xdr:twoCellAnchor>"
lcEndDelimiter = "</xdr:twoCellAnchor>"

*-*	Create instance of FastString class
loFastString = CREATEOBJECT("FastStringClass")

*-*	Add the string to be parsed to FastString class
loDrawingXML = loFastString.AddStringToHeap(lcFileText)

*-*	Get a selected segment
lnSecs = SECONDS()
lcTwoCellAnchor = loFastString.StrExtract(loDrawingXML, lcBegDelimiter, lcEndDelimiter, 2000)
? "Selected Segment Extract: " +  TRANSFORM(SECONDS() - lnSecs)
_CLIPTEXT = lcTwoCellAnchor

*-*	Get all segments
lnCount = 0
lnSecs  = SECONDS()
lcAbsoluteAnchor = loFastString.GetFirstSegment(loDrawingXML, lcBegDelimiter, lcEndDelimiter)
DO WHILE !EMPTY(lcAbsoluteAnchor)
	lnCount = lnCount + 1 
	lcAbsoluteAnchor = loFastString.GetNextSegment(loDrawingXML)
ENDDO
? "All Segments Extract: " +  TRANSFORM(SECONDS() - lnSecs)
? "Segment Count: " + TRANSFORM(lnCount)

*-*	Release Fast string text from memory
loDrawingXML = loFastString.ReleaseStringFromHeap(loDrawingXML)


*-******************************************************************************************************
*-*	Fast String class using SYS(2600)
*-*
*-* Idea for class by Rick Hodgin on Universal Thread (Thread Id 01674989)
*-* Class Written by Gregory Green
*-* Based on suggestion by Christof Wollenhaupt
*-******************************************************************************************************
DEFINE CLASS FastStringClass AS Custom
	NAME = "FastStringClass"

	PROCEDURE LoadDLLs
		DECLARE INTEGER HeapAlloc   IN Win32Api AS apiHeapAlloc INTEGER, INTEGER, INTEGER
		DECLARE INTEGER HeapFree    IN Win32APi AS apiHeapFree INTEGER, INTEGER, INTEGER
		DECLARE LONG GetProcessHeap IN Win32API AS apiGetProcessHeap
	ENDPROC

	PROCEDURE Init
		this.LoadDLLs()
	ENDPROC

	PROCEDURE AddStringToHeap
		LPARAMETERS tcString
		LOCAL loString
		loString = CREATEOBJECT("Empty")
		ADDPROPERTY(loString, "Length", 0)
		ADDPROPERTY(loString, "BaseAdr", 0)
		ADDPROPERTY(loString, "LastAdr", 0)
		ADDPROPERTY(loString, "BegDelimiter", "")
		ADDPROPERTY(loString, "EndDelimiter", "")
		loString.Length  = LEN(tcString)
		loString.BaseAdr = apiHeapAlloc(apiGetProcessHeap(), 0, loString.Length)
		SYS(2600, loString.BaseAdr, loString.Length, tcString)
		RETURN loString
	ENDPROC


	PROCEDURE GetFirstSegment
		LPARAMETERS toString, tcBegDelimiter, tcEndDelimiter
		LOCAL lnBeg, lcVal, lnEnd, lnBegLen, lnEndLen
		toString.BegDelimiter = tcBegDelimiter
		toString.EndDelimiter = tcEndDelimiter
		lnBegLen = LEN(toString.BegDelimiter)
		lnEndLen = LEN(toString.EndDelimiter)
		lnBeg = 1
		DO WHILE lnBeg < toString.Length
			lcVal = SYS(2600, toString.BaseAdr-1 + lnBeg, lnBegLen)
			IF lcVal == toString.BegDelimiter
				FOR lnEnd=lnBeg+lnBegLen TO toString.Length
					lcVal = SYS(2600, toString.BaseAdr-1 + lnEnd, lnEndLen)
					IF lcVal == toString.EndDelimiter
						toString.LastAdr = lnEnd + lnEndLen
						RETURN SYS(2600, toString.BaseAdr-1 + lnBeg, lnEnd - lnBeg + lnBegLen + 1)
					ENDIF
				ENDFOR
				lnBeg = toString.Length
			ENDIF
			lnBeg = lnBeg + 1
		ENDDO
		toString.LastAdr = toString.Length
		RETURN ""
	ENDPROC
	
	
	PROCEDURE GetNextSegment
		LPARAMETERS toString
		LOCAL lnBeg, lcVal, lnEnd, lnBegLen, lnEndLen
		lnBegLen = LEN(toString.BegDelimiter)
		lnEndLen = LEN(toString.EndDelimiter)
		lnBeg = toString.LastAdr
		DO WHILE lnBeg < toString.Length
			lcVal = SYS(2600, toString.BaseAdr-1 + lnBeg, lnBegLen)
			IF lcVal == toString.BegDelimiter
				FOR lnEnd=lnBeg+lnBegLen TO toString.Length
					lcVal = SYS(2600, toString.BaseAdr-1 + lnEnd, lnEndLen)
					IF lcVal == toString.EndDelimiter
						toString.LastAdr = lnEnd + lnEndLen
						RETURN SYS(2600, toString.BaseAdr-1 + lnBeg, lnEnd - lnBeg + lnBegLen + 1)
					ENDIF
				ENDFOR
				lnBeg = toString.Length
			ENDIF
			lnBeg = lnBeg + 1
		ENDDO
		toString.LastAdr = toString.Length
		RETURN ""
	ENDPROC


	PROCEDURE ATC
		LPARAMETERS tcFindText, toString, tnOccurrence
		LOCAL lnBeg, lcVal, lnLen
		IF PCOUNT() = 2
			tnOccurrence = 1
		ENDIF
		tcFindText = UPPER(tcFindText)
		lnLen = LEN(tcFindText)
		lnOccurrence = 0
		lnBeg = 1
		DO WHILE lnBeg < toString.Length
			lcVal = UPPER(SYS(2600, toString.BaseAdr-1 + lnBeg, lnLen))
			IF lcVal == tcFindText
				lnOccurrence = lnOccurrence + 1
				IF lnOccurrence = tnOccurrence
					RETURN lnBeg
				ENDIF
			ENDIF
			lnBeg = lnBeg + 1
		ENDDO
		RETURN 0
	ENDPROC


	PROCEDURE AT
		LPARAMETERS tcFindText, toString, tnOccurrence
		LOCAL lnBeg, lcVal, lnLen
		IF PCOUNT() = 2
			tnOccurrence = 1
		ENDIF
		lnLen = LEN(tcFindText)
		lnOccurrence = 0
		lnBeg = 1
		DO WHILE lnBeg < toString.Length
			lcVal = SYS(2600, toString.BaseAdr-1 + lnBeg, lnLen)
			IF lcVal == tcFindText
				lnOccurrence = lnOccurrence + 1
				IF lnOccurrence = tnOccurrence
					RETURN lnBeg
				ENDIF
			ENDIF
			lnBeg = lnBeg + 1
		ENDDO
		RETURN 0
	ENDPROC


	PROCEDURE StrExtract
		LPARAMETERS toString, tcBegDelimiter, tcEndDelimiter, tnOccurrence
		LOCAL lnBeg, lcVal, lnEnd, lnBegLen, lnEndLen
		lnBegLen     = LEN(tcBegDelimiter)
		lnEndLen     = LEN(tcEndDelimiter)
		lnOccurrence = 0
		lnBeg = 1
		DO WHILE lnBeg < toString.Length
			lcVal = SYS(2600, toString.BaseAdr-1 + lnBeg, lnBegLen)
			IF lcVal == tcBegDelimiter
				FOR lnEnd=lnBeg+lnBegLen TO toString.Length
					lcVal = SYS(2600, toString.BaseAdr-1 + lnEnd, lnEndLen)
					IF lcVal == tcEndDelimiter
						lnOccurrence = lnOccurrence + 1
						IF lnOccurrence = tnOccurrence
							RETURN SYS(2600, toString.BaseAdr-1 + lnBeg, lnEnd - lnBeg + lnBegLen + 1)
						ENDIF
						lnBeg = lnEnd - 1
						EXIT
					ENDIF
				ENDFOR
			ENDIF
			lnBeg = lnBeg + 1 
		ENDDO
		RETURN ""
	ENDPROC
	
	
	PROCEDURE ReleaseStringFromHeap
		LPARAMETERS toString
		apiHeapFree(apiGetProcessHeap(), 0, toString.BaseAdr)
		RETURN .NULL.
	ENDPROC

ENDDEFINE
Précédent
Répondre
Fil
Voir

Click here to load this message in the networking platform