InsertString: #PB_String_InPlace would be useful

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
freak
PureBasic Team
PureBasic Team
Posts: 5940
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Re: InsertString: #PB_String_InPlace would be useful

Post by freak »

I forgot about the null, sorry :)
quidquid Latine dictum sit altum videtur
User avatar
GeBonet
Enthusiast
Enthusiast
Posts: 135
Joined: Fri Apr 04, 2008 6:20 pm
Location: Belgium

Re: InsertString: #PB_String_InPlace would be useful

Post by GeBonet »

netmaestro wrote:CopyMemory is usable but the code you have to write to allow for unicode, while it works, looks ugly to me. CopyMemoryString also writes the terminating zero, so it's no use either. I just want the flag.
Hi,
I have also this problem with for make fixed lenght record from PB data !
Here on code... for illustration... I I hope to be clear with my English.

Code: Select all

; ____________________________________________________________________________________
; //////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\;
; Objet  : Etudes 2 de formatage d'un Buffer de longueur FIXE   ATTENTION : Pas Unicode 
;        : Studies of formatting a buffer of fixed length       CAUTION   : No unicode 
; ------ : ---------------------------------------------------------------------------/
;
; Le problème se pose par le fait que si on peux déterminer et fixer facilement la longueur des champs
; Alphanumérique, par contre les champs numériques ne peuvent avoir de longueur fixes sauf si on utilise
; leurs forme de rangement en mémoire qui elle est fixe : 4=Entier, Long et Flottant, 8 pour un Double ou Quad ! 
; 
; C'est sur base de cette propriété que ce code est construit :
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
; The problem is the fact that If we can easily identify And fix the length of alphanumeric fields, 
; numeric fields by cons can Not have a fixed length unless you use their form of storage in memory 
; that it is fixed: 4 for Integer, Long, Float, 8 for Double Or Quad!
;
; It is based on the property that the code is built : 
; (But Not WOrk propelely every time because we Not controle the Null at the end of the various poke... 
;  and also the Copy or Move memory stop when the null is encontred... )
;  When whe do move or Copymemory(*origin, *Destnation, LenghtOfData) the "LenghtOfData" 
;  no fonction If one null exit on the memory between the begin and the end of the Lenght Of Data... 
; ----------------------------------------------------------------------------- :
; NOTE :  If I use the fields is precisely not to be related to fixed structure. I need to create 
; and process files that are created by the program itself and therefore completely dynamic. 
; Array's are well suited To do that. In addition To creating the records from these array's must 
; be directly accessible And lockable. Hence the problem move To a digital Data fields that can be 
; an integer, float, double Or quad. And become a chain of fixed length of 4 Or 8 bytes in recording.
; 
; With the code below, I create a Data block from a array's of values including numeque... And of 
; course I Read the block To place it in a Array's.
; After he no longer has To manage these blocks As records Or Read / write To disk
; Which is Not very difficult.
;
; Now, If someone has a simpler solution, I'm interested, but be careful not file structure possible.
; Random file Open With, there was also the style converters Value$=MKS$(value), CVS$(value) Or 
; MKD$(... CVD(... Etc... which have fixed-length strings To numbers, which was convenient.
;  
; ----------------------------------------------------------------------------- : 
;{- Attribution du répertoire Rep$ -
Global Rep$                         ; Localisation de l'application                                              
Rep$=GetPathPart(ProgramFilename()) ; Le programme actuel se trouve ICI 
     SetCurrentDirectory(Rep$)		  ; On fixe le répertoire  
; -------------                    ; I know the "IncludePath" but with this, the directory where the code is
;}                                     executed based, at the beginning becomes the directory reference.
;
Define i, j, Type, NbChamp, LongTOT, NbRecord

Structure Nombre    ; Utilisé pour convertir des valeur en chaines fixe !
  ENTIER.i  ;4        Used to convert fixed value chains!
  ENLONG.l  ;4  8
  FLOTAN.f  ;4  12
  DOUBLE.d  ;8  20
  QUAD_D.q  ;8  28
EndStructure
Global mes.Nombre
; ----------------------- 
NbChamp = 7
NbRecord=10
LongTOT=0

Debug SizeOf(Nombre)

Dim Type(NbChamp)
Dim Long(NbChamp)
Dim Champ$(NbChamp)
Global Dim Posit(NbChamp)

Dim Record$(NbRecord)
; ----------------------------------------------------------:
Declare.s conver_En_DataBLOC(NbChamp, LongTOT, Array Type(1), Array Long(1), Array Champ$(1))
Declare.s conver_Record_EnCHAMP(NbChamp, Record$, Array Type(1), Array Long(1), Array Champ$(1))
; ----------------------------------------------------------:
Restore Carnet1:LongTOT=0
For i=1 To NbChamp:Read.i Type(i):Next i ; Lecture des Types
For i=1 To NbChamp:Read.i Long(i):LongTOT+Long(i):Next i ; Lecture des longueurs des champs
; ----------------------------------------------------------:
;
Restore Carnet2  
For i=1 To NbRecord          ; Transforme les Champs() en ENREGISTREMENTS de longueur Fixe
  ;
  For j=1 To NbChamp:Read.s Champ$(j):Next j
  ;
  blocDATA$=conver_En_DataBLOC(NbChamp, LongTOT, Type(), Long(),Champ$())
  ;
  Debug blocDATA$+" : "+Str(Len(blocDATA$))
  ;
  Record$(i)=blocDATA$; Memorise les enregsitrements .... 
  
Next i
Debug "*********************************************************************************"
a+1
; -------------------- PARTIE 2 Convertion du Record$ en Champ$() -----------------------
;{ 
For i=1 To NbRecord
  
  Record$=Record$(i)          ; Prise de l'enregistrement à partir de Record$()
  Debug Record$ :Debug ""     ; Transfert les données de Record$ dans les Champ$()
  ;
  conver_Record_EnCHAMP(NbChamp, Record$, Type(), Long(), Champ$())
  Debug ""
  
Next i
;}
Debug "*********************************************************************************"
;
End
; -------------------------------------------------------------------------------
;      LECTURE des Champ$() et converti en un BLOC de longueur FIXE ! 
;      READ Fields() and convert in one Fixed lengh dataBLOC
; -------------------------------------------------------------------------------
Procedure.s conver_En_DataBLOC(NbChamp, LongTOT, Array Type(1), Array Long(1), Array Champ$(1))
  
  Protected j, Type, Ok
  ;                       
  ; Formatage du Buffer... 
  ;                       
  If LongTOT<>0 And Ok=0  
    Ok=1 : *MemoryID=AllocateMemory(LongTOT+2)
    FillMemory(*MemoryID, LongTOT+2)
    ;Debug "> 1- "+Str(*MemoryID)
    Posit(1)=*MemoryID:Long1=long(1)
    For j=2 To NbChamp  
      Posit(j)=*MemoryID+Long1
      Long1=Long1+Long(j)
    Next j  
  EndIf  
  ;
  ; Debug "--------------"
  ;
  For j=1 To NbChamp  
    ;
    Type=Type(j)
    If Type=0 Or Type=6
      Donnee$=LSet(Champ$(j),long(j),"_"):Else:Donnee$=Champ$(j)
    EndIf
    ;
    Select Type
      Case 0        ; AlphaNumérique 
        PokeS(Posit(j), Donnee$)
        Debug Str(Posit(j))+" "+Donnee$
        Debug Str(Posit(j))+" "+PeekS(Posit(j))+" <= Mem"
        
      Case 1        ; Entier
        mes\ENTIER.i=Val(Donnee$) 
        PokeI(Posit(j),mes\ENTIER.i)
        Debug Str(Posit(j))+" "+Str(mes\ENTIER.i)
        Debug Str(Posit(j))+" "+Str(PeekI(Posit(j)))+" <= Mem"
        
      Case 2        ;  Long
        mes\ENLONG.l=Val(Donnee$) 
        PokeL(Posit(j), mes\ENLONG.l)
        Debug Str(Posit(j))+" "+Str(mes\ENLONG)
        Debug Str(Posit(j))+" "+Str(PeekL(Posit(j)))+" <= Mem"
        
      Case 3        ; Flottant 
        mes\FLOTAN.f=ValF(Donnee$) 
        PokeF(Posit(j), mes\FLOTAN.f)
        Debug Str(Posit(j))+" "+StrF(mes\FLOTAN,3)
        Debug Str(Posit(j))+" "+StrF(PeekF(Posit(j)),3)+" <= Mem"
        
      Case 4        ; Double 
        mes\DOUBLE.d=ValD(Donnee$) 
        PokeD(Posit(j), mes\DOUBLE.d)
        Debug Str(Posit(j))+" "+StrD(mes\DOUBLE,4)
        Debug Str(Posit(j))+" "+StrD(PeekD(Posit(j)),4)+" <= Mem"
         
      Case 5        ; Quad 
        mes\QUAD_D.q=Val(Donnee$) 
        PokeQ(Posit(j), mes\QUAD_D.q)
        Debug Str(Posit(j))+" "+Str(mes\QUAD_D.q)
        Debug Str(Posit(j))+" "+Str(PeekQ(Posit(j)))+" <= Mem"
         
      Case 6        ; Date forme "jj/mm/aaaa"  
        PokeS(Posit(j), Donnee$)
        Debug Str(Posit(j))+" "+Donnee$
        Debug Str(Posit(j))+" "+PeekS(Posit(j))+" <= Mem"
         
    EndSelect
  Next j  
  Debug "==================================="
  a+1
  ; ---------------------
  ;
  dataBLOC$="";PeekS(Posit(1),LongTOT);:*Destnation=@dataBLOC$
  Debug "> The lenght must be : "+Str(LongTOT)
  Debug "> -------------------------------"
  For j=Posit(1) To Posit(1)+LongTOT-1
    dataBLOC$+Chr(PeekB(j))
  Next j  
  Debug dataBLOC$+" = "+Str(Len(dataBLOC$))
  Enregistrement$=Space(LongTOT) 
  *Destination=@Enregistrement$
  MoveMemory(Posit(1),*Destination,LongTOT)
  Debug Enregistrement$+" = "+Str(Len(Enregistrement$))
  CallDebugger
  ProcedureReturn Enregistrement$; dataBLOC$  
    
EndProcedure
; -------------------------------------------------------------------------------
;      LECTURE d'un enregistrement de longueur FIXE et place dans CHAMPS()
;      READ Fixed lengh Record$ and convert back in Field()
; -------------------------------------------------------------------------------
Procedure.s conver_Record_EnCHAMP(NbChamp, Record$, Array Type(1), Array Long(1), Array Champ$(1))
    
  Protected j, Type
  ; -------------------
  For j=1 To NbChamp    
    
    Champ$(j)=Left(Record$,long(j))
    Record$=Mid(Record$,long(j)+1)
    Type=Type(j)
    ;   
    Select Type
        
      Case 1        ;   Entier
        *ADRESSE=@mes\ENTIER.i
        PokeS(*Adresse, Champ$(j),4)
        Champ$(j)=StrF(mes\ENTIER)
        
      Case 2        ;   Long
        *ADRESSE=@mes\ENLONG.l
        PokeS(*Adresse, Champ$(j),4)
        Champ$(j)=Str(mes\ENLONG)
        
      Case 3        ;   Flottant 
        *ADRESSE=@mes\FLOTAN.f
        PokeS(*ADRESSE, Champ$(j),4)
        Champ$(j)= StrF(mes\FLOTAN,2)
        
      Case 4        ;   Double 
        *ADRESSE=@mes\DOUBLE.d
        PokeS(*ADRESSE, Champ$(j),4)
        Champ$(j)= StrD(mes\DOUBLE,2)
        
      Case 5        ;   Quad 
        *ADRESSE=@mes\QUAD_D.q
        PokeS(*ADRESSE, Champ$(j),4)
        Champ$(j)= Str(mes\QUAD_D)
        
      Case 6        ;   Date forme "jj/mm/aaaa"  
        ; Champ$(j)= FormatDate("%dd/%mm/%yyyy",Val(Val(Donnee$))
        
    EndSelect
    Debug Champ$(j)
  Next j  
  ProcedureReturn "OK"
   
EndProcedure
; -------------------------------------------------------------------------------
;                      10 lignes de DATA pour faire les TESTS
; -------------------------------------------------------------------------------
DataSection ;{ 
  Carnet1:  
  Data.i     0    ,    0                , 3 ,      0      , 3 ,       0       ,      6            ; Type(i) type of data 
  Data.i    16    ,   34                , 4 ,     10      , 4 ,      29       ,      10           ; Long(i)
  ;
  Carnet2:  
  ;"          1    ,    2                , 3 ,      4      , 5  ,       6       ,       7        "; Number Field !  
  ; Data.s "Sujet" , "Titre"             , N1, "NomFamille", N2 , "Nom Editeur" , "AnnéeCopyright" 
  ;        " ----------------------------------------------------------------------------------- "
  Data.s "Histoire","Fisionomía histórica de Chile","223.6","Eyzaguirre","31236.17","Editorial universitaria","03/05/1999"
  Data.s "Tourisme","Salvador da Bahia : 100 Colorfotos","-556.9","Richter","218915.152","Alpina-Ceú azul de Copacabana","02/06/2000"
  Data.s "Poésie de france","Oeuvres complètes Tome premier","3265.32","Boileau","25322.60","Hachette","12/06/1830"
  Data.s "Vie pratique","Manuel scout des arbres","15.65","Vieux Castor","2253.36","Au Lasso (éd. Scoutes)","22/12/1938"
  Data.s "Album enfant","Nouvelles aventures du petit diable Malice, Les","832.86","Scheggia","5523.36","Chagor","11/10/1959"
  Data.s "Enseignement","Allemand sans peine, L","122","Chérel","653.47","Assimil","01/01/1960"
  Data.s "Album enfant","Album des jeunes 1961, L'","563.85","Collectif","225.33","Sélection du Reader's Digest","18/05/1960"
  Data.s "Religion","Sainte Bible, La","854.134","Collectif","875.3","Cerf","22/10/1961"
  Data.s "Essai","Présence de Camus","66532.121","Simon","12.41","Renaissance du livre","26/11/1961"
  Data.s "Biographie","Napoléon","124.16","Bainville","8965332.22","Librairie générale française","15/08/1965"
  
EndDataSection;}
; --------------------------------------
Note : in the data the Data line, "type" if you change the "3" (float) with Integer, long or other the result change because of the "nul"...
Sorry for my english :wink: ! (Windows Xp, Vista and Windows 7, Windows 10)
buddymatkona
Enthusiast
Enthusiast
Posts: 252
Joined: Mon Aug 16, 2010 4:29 am

Re: InsertString: #PB_String_InPlace would be useful

Post by buddymatkona »

Thanks netmaestro for the info and wilbert for the x64 version of UpdateString at

http://www.purebasic.fr/english/viewtop ... 9#p362759.

UpdateString ran in 1/2 the time used by ReplaceRegularExpression even after I added typical overhead.

Using netmaestro's example:

Code: Select all

a$ = "Hello World!"
b$ = "Girls"
I compared

Code: Select all

 CreateRegularExpression(0, "World") 
 Result$ = ReplaceRegularExpression(0, a$, b$)
With

Code: Select all

Loc = FindString(a$,"World")
c = UpdateString(@a$, @b$, loc)
If an existing compiled expression is reused , UpdateString is still 20% faster.

Edited because of a mistake :
Whoops! These things are not comparable. The ReplaceRegularExpression I used is replacing the search string everywhere but UpdateString is only doing one replace per call. :oops:
Post Reply