File: n_stringclass.sru
Size: 13155
Date: Thu, 03 Oct 2019 05:08:04 +0200
$PBExportHeader$n_stringclass.sru
$PBExportComments$StringClass object
forward
global type n_stringclass from nonvisualobject
end type
end forward

global type n_stringclass from nonvisualobject autoinstantiate
end type

type prototypes

end prototypes

type variables
Private:

Blob iblob_string
Long il_position
Long il_currentsize

Public:

Long AllocSize = 4096

end variables
forward prototypes
public function boolean copy (readonly string as_string)
public subroutine free ()
public function string replaceall (readonly string as_oldstring, string as_findstr, string as_replace, boolean ab_case)
public function long size ()
public function boolean sortarray (ref string as_array[], string as_order)
public function long split (string as_text, string as_sep, ref string as_array[])
public function string value ()
public function long capacity ()
public subroutine clear ()
public function boolean empty ()
public subroutine reserve (long al_size)
public function long length ()
public function boolean append (readonly string as_string)
end prototypes

public function boolean copy (readonly string as_string);// -----------------------------------------------------------------------------
// SCRIPT:     Copy
//
// PURPOSE:    This function moves the position to 1 and calls Append so that
//             passed string is placed at the beginning.
//
// ARGUMENTS:  as_string   - The string to concatenate
//
// RETURN:     True=Success, False=Failed - not enough space
//
// DATE        CHANGED BY  DESCRIPTION OF CHANGE / REASON
// ----------  ----------  -----------------------------------------------------
// 10/19/2016  RolandS     Initial creation
// -----------------------------------------------------------------------------

il_position = 1

Return Append(as_string)

end function

public subroutine free ();// -----------------------------------------------------------------------------
// SCRIPT:     Free
//
// PURPOSE:    This function initializes the blob instance variable.
//
// DATE        CHANGED BY  DESCRIPTION OF CHANGE / REASON
// ----------  ----------  -----------------------------------------------------
// 10/19/2016  RolandS     Initial creation
// 07/26/2019  RolandS     Added reset of il_currentsize
// -----------------------------------------------------------------------------

SetNull(iblob_string)
il_position = 0
il_currentsize = 0

end subroutine

public function string replaceall (readonly string as_oldstring, string as_findstr, string as_replace, boolean ab_case);// -----------------------------------------------------------------------------
// SCRIPT:     ReplaceAll
//
// PURPOSE:    This function replaces all occurrences of a string.
//
// ARGUMENTS:  as_oldstring   - The string to be modified
//             as_findstr     - The substring to be replaced
//             as_replace     - The new string to replace with
//             as_case        - True = case sensitive, False = case insensitive
//
// RETURN:     Updated string
//
// DATE        CHANGED BY  DESCRIPTION OF CHANGE / REASON
// ----------  ----------  -----------------------------------------------------
// 09/25/2018  RolandS     Initial creation
// -----------------------------------------------------------------------------

String ls_oldstring, ls_findstr
Long ll_pos, ll_start, ll_findstr

If ab_case Then
   ls_oldstring = as_oldstring
   ls_findstr   = as_findstr
Else
   ls_oldstring = Lower(as_oldstring)
   ls_findstr   = Lower(as_findstr)
End If

ll_findstr = Len(as_findstr)
ll_start = 1

// allocate space in the blob
Reserve(Len(ls_oldstring))

// find first occurrence
ll_pos = Pos(ls_oldstring, ls_findstr)

do while ll_pos > 0
   // concatenate the part before the hit
   Append(Mid(as_oldstring, ll_start, ll_pos - ll_start))
   // concatenate the replacement string
   Append(as_replace)
   // find next occurrence
   ll_start = ll_pos + ll_findstr
   ll_pos = Pos(ls_oldstring, ls_findstr, ll_start)
loop

// concatenate the part after the last hit
Append(Mid(as_oldstring, ll_start))

Return Value()

end function

public function long size ();// -----------------------------------------------------------------------------
// SCRIPT:     Size
//
// PURPOSE:    This function returns the current size of the string in bytes.
//
// RETURN:     The size of the string in bytes
//
// DATE        CHANGED BY  DESCRIPTION OF CHANGE / REASON
// ----------  ----------  -----------------------------------------------------
// 10/19/2016  RolandS     Initial creation
// -----------------------------------------------------------------------------

Return il_position - 1

end function

public function boolean sortarray (ref string as_array[], string as_order);// -----------------------------------------------------------------------------
// SCRIPT:     SortArray
//
// PURPOSE:    This function sorts the passed array using a DataStore created
//             on-the-fly.
//
//             This is based on code from Real Gagnon:
//             http://www.rgagnon.com/pbdetails/pb-0114.html
//
// ARGUMENTS:  as_array - Array of values to sort
//             as_order - The sort order:
//
//             Order value                Resulting sort order
//             ------------------------   ---------------------------
//             a, asc, ascending, ai, i   Case-insensitive ascending
//             d, desc, descending, di    Case-insensitive descending
//             as, s                      Case-sensitive ascending
//             ds                         Case-sensitive descending
//
// RETURN:     True=Success, False=Error
// -----------------------------------------------------------------------------

DataStore lds_sort
String ls_source, ls_error
Long ll_idx, ll_max, ll_len, ll_maxlen
Integer li_rc

// determine maximum length of values
ll_max = UpperBound(as_array)
If ll_max = 0 Then Return False
For ll_idx = 1 To ll_max
   ll_len = Len(as_array[ll_idx])
   If ll_len > ll_maxlen Then
      ll_maxlen = ll_len
   End If
Next

// build DataWindow source code
ls_source = "release 6; datawindow( processing=0 ) " + &
            "table(column=(type=char(" + String(ll_maxlen) + &
            ") name=array dbname=~"array~" ) )"

// create DataStore
lds_sort = Create DataStore
li_rc = lds_sort.Create(ls_source, ls_error)
If li_rc = 1 Then
   // put data into DataStore
   lds_sort.Object.array.Current = as_array
   // sort the data
   lds_sort.SetSort("array " + as_order)
   lds_sort.Sort()
   // set array to sorted data
   as_array = lds_sort.Object.array.Current
Else
   Return False
End If

// destroy DataStore
Destroy lds_sort

Return True

end function

public function long split (string as_text, string as_sep, ref string as_array[]);// -----------------------------------------------------------------------------
// SCRIPT:     Split
//
// PURPOSE:    This function splits a string into an array.
//
// ARGUMENTS:  as_text  - The text to be split
//             as_sep   - The separator characters
//             as_array - By ref output array
//
// RETURN:     The number of items in the array
//
// DATE        CHANGED BY  DESCRIPTION OF CHANGE / REASON
// ----------  ----------  -----------------------------------------------------
// 10/19/2016  RolandS     Initial creation
// -----------------------------------------------------------------------------

String ls_empty[], ls_work
Long ll_pos

as_array = ls_empty

If IsNull(as_text) Or as_text = "" Then Return 0

ll_pos = Pos(as_text, as_sep)
DO WHILE ll_pos > 0
   ls_work = Trim(Left(as_text, ll_pos - 1))
   as_text = Trim(Mid(as_text, ll_pos + Len(as_sep)))
   as_array[UpperBound(as_array) + 1] = ls_work
   ll_pos = Pos(as_text, as_sep)
LOOP
If Len(as_text) > 0 Then
   as_array[UpperBound(as_array) + 1] = as_text
End If

Return UpperBound(as_array)

end function

public function string value ();// -----------------------------------------------------------------------------
// SCRIPT:     Value
//
// PURPOSE:    This function returns the value from the blob instance variable.
//
// RETURN:     Current string value
//
// DATE        CHANGED BY  DESCRIPTION OF CHANGE / REASON
// ----------  ----------  -----------------------------------------------------
// 10/19/2016  RolandS     Initial creation
// -----------------------------------------------------------------------------

Return String(iblob_string)

end function

public function long capacity ();// -----------------------------------------------------------------------------
// SCRIPT:     Capacity
//
// PURPOSE:    This function returns the current size of the allocated
//             space in bytes.
//
// RETURN:     The size of the blob
//
// DATE        CHANGED BY  DESCRIPTION OF CHANGE / REASON
// ----------  ----------  -----------------------------------------------------
// 09/30/2019  RolandS     Initial creation
// -----------------------------------------------------------------------------

Return il_currentsize

end function

public subroutine clear ();// -----------------------------------------------------------------------------
// SCRIPT:     Clear
//
// PURPOSE:    This function clears the string by resetting the position.
//
// DATE        CHANGED BY  DESCRIPTION OF CHANGE / REASON
// ----------  ----------  -----------------------------------------------------
// 09/30/2019  RolandS     Initial creation
// -----------------------------------------------------------------------------

il_position = 0

end subroutine

public function boolean empty ();// -----------------------------------------------------------------------------
// SCRIPT:     Empty
//
// PURPOSE:    This function returns whether the string is empty or not.
//
// DATE        CHANGED BY  DESCRIPTION OF CHANGE / REASON
// ----------  ----------  -----------------------------------------------------
// 09/30/2019  RolandS     Initial creation
// -----------------------------------------------------------------------------

If il_position = 0 Then
   Return True
End If

Return False

end function

public subroutine reserve (long al_size);// -----------------------------------------------------------------------------
// SCRIPT:     Reserve
//
// PURPOSE:    This function allocates the blob instance variable. It needs
//             to be run once per instantiation.
//
// ARGUMENTS:  al_size  - The size of the allocated blob (in characters)
//
// DATE        CHANGED BY  DESCRIPTION OF CHANGE / REASON
// ----------  ----------  -----------------------------------------------------
// 09/30/2019  RolandS     Initial creation
// -----------------------------------------------------------------------------

Long ll_newsize

// multiply by 2 because Unicode
ll_newsize = al_size * 2

// allocate the instance blob if newsize is larger than current
If ll_newsize > il_currentsize Then
   iblob_string = Blob(Space(ll_newsize), EncodingAnsi!)
   il_currentsize = ll_newsize
End If

il_position = 1

end subroutine

public function long length ();// -----------------------------------------------------------------------------
// SCRIPT:     Length
//
// PURPOSE:    This function returns the current size of the string in bytes.
//
// RETURN:     The size of the string in bytes
//
// DATE        CHANGED BY  DESCRIPTION OF CHANGE / REASON
// ----------  ----------  -----------------------------------------------------
// 10/19/2016  RolandS     Initial creation
// -----------------------------------------------------------------------------

Return il_position - 1

end function

public function boolean append (readonly string as_string);// -----------------------------------------------------------------------------
// SCRIPT:     Append
//
// PURPOSE:    This function concatenates the passed string to the instance
//             blob variable.
//
// ARGUMENTS:  as_string   - The string to concatenate
//
// RETURN:     True=Success, False=Failed - not enough space
//
// DATE        CHANGED BY  DESCRIPTION OF CHANGE / REASON
// ----------  ----------  -----------------------------------------------------
// 10/19/2016  RolandS     Initial creation
// 09/30/2019  RolandS     Changes suggested by Rodney Kempler
// -----------------------------------------------------------------------------

ULong lul_rtn
Long ll_strlen, ll_newsize, ll_addedsize

// default allocation if empty
If il_currentsize = 0 Then
   Reserve(AllocSize)
End If

// string length is times 2 because Unicode
ll_strlen = Len(as_string) * 2

// append more space to end (amount needed plus AllocSize)
ll_newsize = (il_position - 1) + ll_strlen
If ll_newsize >= il_currentsize Then
   ll_addedsize = (ll_newsize - il_currentsize) + (AllocSize * 2)
   iblob_string = iblob_string + Blob(Space(ll_addedsize), EncodingAnsi!)
   il_currentsize += ll_addedsize
End If

// append the passed string and advance the position
lul_rtn = BlobEdit(iblob_string, il_position, as_string)
If IsNull(lul_rtn) Then
   Return False
End If
il_position += ll_strlen

Return True

end function

on n_stringclass.create
call super::create
TriggerEvent( this, "constructor" )
end on

on n_stringclass.destroy
TriggerEvent( this, "destructor" )
call super::destroy
end on