WinBatch Tech Support Home

Database Search

If you can't find the information using the categories below, post a question over in our WinBatch Tech Support Forum.

TechHome

Binary Operations

Can't find the information you are looking for here? Then leave a message over on our WinBatch Tech Support Forum.

UDF to Sort Variable Line-length Binary Buffers

Keywords: 	 sort variable line-length binary buffers

A Little UDF to sort variable line-length binary buffers, or Itemstrings by columns. Feel free to modify. Basis for BinarySortEx or ItemSortEx commands?

GOSUB INITFUNCTION                                ; Make sort_records function available.

GOTO EXAMPLE2
; Example 1 - sort variable length file/buffer

File="F:\Winbatch\Commands\setupscript.wbt"

X=BinaryAlloc(FileSize(File))                     ; Get size of buffer for file to sort.
BinaryRead(X,File)                                ; Load file into buffer.
Started=TimeYMDHMS()                              ; Timing.
Newfile=sort_Records(1,X,0,1,0,300,@CrLf,0)       ; Call function - see parm description in function.
BinaryFree(X)                                     ; Free buffer.

IF Newfile==-1
	Message("oops","bad parm")    ; Oops.
	EXIT
ENDIF 

Display(3,"Sorted",StrCat("Time:",TimeDiffSecs(TimeYMDHMS(),Started)," seconds")) ; How long did it take.
X=FileCreateTemp("srt")                           ; Create temp file for newly sorted records.
BinaryWrite(Newfile,X)                            ; Create newly sorted file.
BinaryFree(Newfile)                               ; Free buffer.
EXIT

; Example 2 - sort an item list
:EXAMPLE2
Data="abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
List=""
FOR X=1 TO 500                                    ; Create number of test items.
	List=ItemInsert(StrCat(StrSub(Data,Random(25)+1,10),"",StrSub(Data,Random(25)+1,10),"",StrSub(Data,Random(25)+1,10)),-1,List,":")
NEXT
Newlist=sort_Records(0,List,0,5,0,50,":",1)       ; Call function - see parm description in function.
Message(" ",StrReplace(Newlist,":",@CrLf))
EXIT

:INITFUNCTION
; Sort_Records function
; Written by Steffen Fraas  sfraas@zoo.co.uk  01/03/2001

#DefineFunction sort_Records(Intype,Input,Sort_sequence,Start_sort_on_column,Sort_number_of_columns,Max_line_length,Delim,Gx)

; Intype - 1 binary buffer, 0 itemstring
; Input - binary buffer/itemstring containing lines to be sorted
; Sort_sequence - 1 ascending, 0 descending
; Start_sort_on_column - start sorting on column x
; Sort_number_of_columns - number of columns to sort on, 0 to rest of line
; Max_line_length - maximum line length
; Delim - single or multi byte line delimiter
; Gx - 1 progress bar, 0 no progress bar
;
; Test return value for 1 integer, 2 string, 65 binary buffer, using the VarType instruction.
;
; Return (address of a new sorted binary buffer) or
; Return (itemstring of newly sorted itemstring) or
; return (-1) sort aborted - bad input parms
; return (-2) no data to sort
; return (-3) line length exceeded

GOSUB SETCONSTANTS                           ; Setup details.

IF Retcode<>0 THEN RETURN (Retcode)          ; Something's wrong with parms/input.
Brk=BinaryEodGet(Rbuf)-1

IF Brk Brk THEN GOTO ENDIN                 ; Go through input buffer.
Ll = BinaryIndexEx(Rbuf,Ls,Delim,@FwdScan,1)-Ls ; Ll is length of current line minus delimiter.
IF Ll < 0 THEN Ll=Brk-Ls+1                   ; If delimiter not found.  End of buffer;remaining data.
THEN Rc=0                                  ; Delimiter required.
Tsf=Tsf+1                                    ; Records processed.
IF Gx THEN aStatusBar(1,StrCat("Reading in... ",Tbar,"lines"),"Input phase",Tbar,Tsf) ; Show progress.
IF Ll > Xl THEN GOTO MAXLINE                 ; Max line exceeded.

IF Rc THEN BinaryCopy(Wbuf,Ose,Rbuf,Ls,Ll+Dx) ; If trailing delim,  copy data + delim into wbuf.
ELSE BinaryCopy(Wbuf,Ose,Rbuf,Ls,Ll)      ; Copy data only, no delim.
ELSE BinaryPokeStr(Wbuf,BinaryEodGet(Wbuf),Delim) ; Add missing delim, should be last rec.
Ls=Ls+Ll+Dx                                  ; Add length of old data + delim.
Ose=Ose+Xl2                                  ; Incr o/p buffer offset.

GOTO STARTIN
:ENDIN
BinaryEodSet(Wbuf,Ose)                       ; Set eod.
IF Sort_sequence THEN BinarySort(Wbuf,Xl2,Start_sort_on_column-1,Sort_number_of_columns,@String|@Ascending) ; Sort lines in asc.
ELSE
BinarySort(Wbuf,Xl2,Start_sort_on_column-1,Sort_number_of_columns,@String|@Descending) ; Sort in desc.

Ose=0                                        ; Offset for i/p buffer.
Tsf=0
Ls=BinaryIndex(Wbuf,0,"",@FwdScan)           ; Skip over nulls in asc sort, 0 in des.

FOR X=1 TO Tbar                              ; Go through input buffer, now fixed xl2 length.
	BinaryCopy(Wbuf,Ose,Wbuf,Ls,Xl2)        ; Create output.
	Ose=BinaryIndexNc(Wbuf,Ose+Xl2-1,"",@BackScan)+1 ; Find first non null, should be delimiter.
	Ls=Ls+Xl2                               ; Input buffer's new offset.
	Tsf=Tsf+1                               ; O/p lines created.
	
	IF Gx THEN aStatusBar(1,StrCat("Writing out... ",Tbar," lines"),"Output phase",Tbar,Tsf) ; Show progress.
NEXT

IF Gx THEN aStatusBar(2,"","",0,0)           ; Close bar.

IF Rc THEN BinaryEodSet(Wbuf,Ose)           ; Set eod last rec had a delimiter.
ELSE BinaryEodSet(Wbuf,Ose-Dx)            ; This one did not.

IF Intype THEN RETURN (Wbuf)                 ; Return newly sorted buffer.
BinaryFree(Rbuf)                             ; Delete input buffer.

Input2=BinaryPeekStr(Wbuf,0,BinaryEodGet(Wbuf)) ; New itemstring.
BinaryFree(Wbuf)                             ; Free output buffer.
RETURN (Input2)                              ; Finished.

:MAXLINE
IF Gx THEN aStatusBar(2,"","",0,0)           ; Close bar.
Badline=BinaryPeekStr(Rbuf,Ls,Min(Xl,Ll))    ; Get bad line.
Display(3,"Line %Tsf% length exceeded - Sort aborted",Badline)
BinaryFree(Wbuf)                             ; Free output buffer.

IF Intype THEN RETURN (-3)                   ; Line length exceeded code.
BinaryFree(Rbuf)                             ; Free input itemstring buffer.
RETURN (-3)                                  ; Itemstring line length exceeded.

:SETCONSTANTS
Retcode=-1                                   ; Assume bad parms.

AddExtender("wwsop34i.DLL")                  ; Used for graph and retry.
Ls=0                                         ; # of bytes read so far.
Ose=0                                        ; Offset for o/p buffer.
Tsf=0                                        ; No of lines sorted.
Rc=1                                         ; Line has delimiter.
Tbar=0                                       ; Astatusbus total.
IF !(Gx==0 || Gx==1) THEN RETURN             ; Invalid graph request.
IF !StrLen(Delim) THEN RETURN                ; Zero length delimiter.
Dx=StrLen(Delim)                             ; Size of delimiter.

IF !(IsNumber(Sort_sequence) && IsNumber(Start_sort_on_column) && IsNumber(Sort_number_of_columns) && IsNumber(Max_line_length)) THEN
RETURN ; Ensure all numerical values.

IF !(Sort_sequence==0 || Sort_sequence==1) THEN RETURN ; Not ascending or descending.
IF Max_line_length<1 THEN RETURN             ; Invalid max length.

Xl=Max_line_length
Xl2=Xl+Dx                                    ; Size of each record.
IF Start_sort_on_column<1 || Start_sort_on_column>Xl THEN RETURN ; Invalid start sort column.

IF Sort_number_of_columns<0 || Sort_number_of_columns>Max_line_length THEN RETURN ; In invalid sort number of columns.
IF Sort_number_of_columns==0 THEN Sort_number_of_columns=Xl-Start_sort_on_column+1 ; Default sort number of columns.
IF Sort_number_of_columns>Xl-Start_sort_on_column+1 THEN RETURN ; Sort number of columns exceed max length.

Retcode=0                                    ; Parms ok.
IF Intype THEN IF BinaryEodGet(Input)<1 THEN Retcode=-2 ; Nothing to sort.
IF !Intype THEN IF !StrLen(Input) THEN Retcode=-2 ; Nothing to sort.
IF Retcode<>0 THEN RETURN                    ; Bad parms, or bad input.
IF !Intype THEN Rbuf=BinaryAlloc(StrLen(Input)) ; Alloc buffer for itemstring.
THEN BinaryPokeStr(Rbuf,0,Input)             ; Load item string into a binary buffer.
ELSE Rbuf=Input                              ; Lines in binary buffer to sort.
RETURN

#EndFunction                                 ; End of function.


RETURN                                       ; Function's `log on` return.


Article ID:   W14997
File Created: 2001:11:08:12:41:18
Last Updated: 2001:11:08:12:41:18