FF_USING

Started by Paul Squires, August 19, 2015, 08:57:20 PM

Previous topic - Next topic

Paul Squires




''
''  FF_USING
''  Format one or more string or numeric expressions, based upon the contents
''  of the format mask string.
''
''  This function can format both numeric and string expressions, and can take
''  multiple arguments. Be careful to ensure that your number of expressions
''  match the number of format codes in the formatting mask.
''
''  Character
''  When the expression is a string, the following format codes apply within sMask:
''
''  !     The first character of the string is returned.
''
''  &     The entire string is returned.
''
''  \\    The first two characters are returned.
''
''  \ \   If backslashes enclose n spaces, n + 2 characters of the string expression are returned.
''
''  _     Escape (underscore) character. The following character is interpreted as a literal
''        character instead of a mask format character.
''
''  Numeric
''  When expression is numeric, this function uses the same formatting codes as found in
''  FreeBASIC's Format function. Be aware of this because those codes differ somewhat from the
''  numeric formatting codes used in PowerBASIC's Using function.
''
''  IMPORTANT - When passing numeric values to this function you must always convert them
''              to Double format first, otherwise this function will not recognize it.
''              eg.  st = FF_Using("This is \  \ my ##### mask", "Paul", CDbl(12345))
''

#Include Once "string.bi"

Function FF_Using CDECL ( ByRef sMask As String, ...) As String

   Dim sBuffer    As String    = String(1024, 0)    ' 1K buffer. This is what PowerBASIC uses.
   Dim arg        As Any Ptr   = Va_first()
   Dim pMask      As UByte Ptr = Strptr(sMask)
   Dim pBuffer    As UByte Ptr = Strptr(sBuffer)
   Dim nRemaining As Integer   = Len(sMask)
   Dim nPosBuf    As Integer   = 0                  ' offset to write into sBuffer
   Dim nPosMask   As Integer   = 0                  ' offset to read from the mask
   
   
   While (nRemaining > 0)
      Dim char    As Integer = pMask[nPosMask]
      Dim sString As String  = ""
      Dim nFloat  As Double  = 0
      Dim i       As Integer = 0
       
      nPosMask += 1
      nRemaining -= 1

      ' Determine if this is possibly a format character
      Select Case char
       
         Case 95  ' Asc("_")
            ' Treat next character as a literal and put it in buffer
            If (nRemaining <> 0) Then
               pBuffer[nPosBuf] = pMask[nPosMask]
               nPosBuf += 1
               nRemaining -= 1
               nPosMask += 1
            End If
           
         Case 33  ' Asc("!")
            ' First character of the expression is put in buffer
            sString = *Va_arg(arg, ZString Ptr)
            pBuffer[nPosBuf] = sString[0]
            nPosBuf += 1
            arg = Va_next(arg, ZString Ptr)

         Case 92  ' Asc("\")       
            ' This could be the start of a string literal sequence. Need
            ' to scan to find the ending back slash. If there is no ending
            ' backslash then we simply skip this expression.
            Dim nNumChars As Integer = 1

            ' The characters can only be either a space or a backslash. Anything
            ' else is invalid and will cause us to bypass this expression.
            For i = 1 To nRemaining   
               If pMask[nPosMask] = 32 Then       ' space
                  nNumChars += 1
                  nRemaining -= 1
                  nPosMask += 1
               ElseIf pMask[nPosMask] = 92 Then   ' backslash
                  nNumChars += 1
                  nRemaining -= 1
                  nPosMask += 1
                  sString = Space(nNumChars)
                  Lset sString = *Va_arg(arg, ZString Ptr)
                  MemMove( @pBuffer[nPosBuf], Strptr(sString), Len(sString) )
                  nPosBuf += Len(sString)
                  arg = Va_next(arg, ZString Ptr)
                  Exit For
               Else
                  ' Error in the formatting of this mask expression so we must
                  ' now abort processing the Mask and return buffer to caller.
                  Return Left(sBuffer, nPosBuf+1) 
                  Exit For
               End If
            Next
           

         Case 38  ' Asc("&")
            ' Whole string of the expression is put in buffer
            sString = *Va_arg(arg, ZString Ptr)
            MemMove( @pBuffer[nPosBuf], Strptr(sString), Len(sString) )
            nPosBuf += Len(sString)
            arg = Va_next(arg, ZString Ptr)

         
         ' Numeric formats
         Case 35, 36, 43, 44, 45, 46, 48  ' Asc("#$+,-.0")
            ' Build the formatting mask
            Dim sNumMask As String = Chr(char)
           
            nFloat = Va_arg(arg, Double)

            For i = 1 To nRemaining   
               char = pMask[nPosMask]
               If (char=35) Or (char=36) Or (char=43) Or (char=44) Or _
                  (char=45) Or (char=46) Or (char=48) Then    ' #$+,-.0
                  sNumMask += Chr(char)
                  nRemaining -= 1
                  nPosMask += 1
               Else
                  ' Process the number formatting and then iterate
                  ' to process the waiting character.
                  sString = Format( nFloat, sNumMask )
                  MemMove( @pBuffer[nPosBuf], Strptr(sString), Len(sString) )
                  nPosBuf += Len(sString)
                  arg = Va_next(arg, Double)
                  Continue While
               End If
            Next
           
            ' If we get to here then we hit the end of the mask buffer but
            ' still need to process the formatting mask for the numeric expression.
            sString = Format( nFloat, sNumMask )
            MemMove( @pBuffer[nPosBuf], Strptr(sString), Len(sString) )
            nPosBuf += Len(sString)
           

      Case Else
         ' Ordinary character
          pBuffer[nPosBuf] = char
          nPosBuf += 1
      End Select
   
    Wend                         

    Function = Left(sBuffer, nPosBuf+1)
   
End Function



Paul Squires
PlanetSquires Software

Paul Squires

I wrote this code tonight to help emulate PB's USING$ function. It is somewhat complicated but it does do a fair amount of what PB's USING function does.

Paul Squires
PlanetSquires Software

Paul Squires

Note: This function will not work on 64-bit Windows because of the way that FB handles variable number unspecified parameters. Use it on 32-bit only.
Paul Squires
PlanetSquires Software