BlitzArgs - Kommandozeilenparameter parsen

Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Neue Antwort erstellen

amon

Betreff: BlitzArgs - Kommandozeilenparameter parsen

BeitragMo, Jun 29, 2009 23:48
Antworten mit Zitat
Benutzer-Profile anzeigen
Anbei ein kleines Codestück um die Kommandozeilenparameter nach einem gewissen Muster zu analysieren:

Blitzmax hält die Kommandozeilenparameter im Array AppArgs vor, das erste Element davon ist der Name der Applikation - dieses erste Element darf in dieser Version des Parsers noch nicht mit übergeben werden Smile

So, was kann dieses Ding nun:

Man instanziert eine die TArgs Klasse und übergibt dem Konstruktor (Create Funktion) zwei Parameter:

Der erste Parameter ist das Schema bzw. Format der Parmeter - ein String wie "l,p#,d*". Dieser String definiert drei Kommandozeilenparameter. Der Erste -l ist ein boolsches Argument (False wenn er nicht das ist, true wenn er angegeben ist). Der zweite, -p, ist ein Integer-Parameter. Der dritte -d ist ein String-Parameter.

Das heisst der Benutzer hatt das Programm mit: "demo.exe -l -p 22 -d HelloWorld" aufgerufen.

Der Aufruf der Klasse würde so aussehen:
Code: [AUSKLAPPEN]
argumente:TArgs = TArgs.Create("l,p#,d*", AppArgs[1..])


Mittels der verschiedenen Methoden kann man nun die Werte und auch die Existenz der einzelnen Paramter holen. Genaueres in dem kleinen Demo / Beispielprogramm.

Ich hab versucht das ganze so gut wie möglich nach den OOP Tugenden zu programmieren, ich denke das ist auch ganz gut gelungen. Fields die mit "_" anfangen sind / sollten sog. private Members sein, das heisst hätte BlitzMax sowas wir private und protected würde die mal als Benutzer dieser Klassen nicht sehen.

Hier mal die Grundklassen selbst:

Code: [AUSKLAPPEN]
SuperStrict

Type TArgs
   Field _marshalers:TMap
   Field _argsFound:TList
   Field _currentArgument:TLink
   
   Function Create:TArgs(schema:String, args:String[])
      Local this:TArgs = New TArgs
      this._marshalers = New TMap
      this._argsFound = New TList
      this._parseSchema(schema)
      this._parseArguments(this._arrayToList(args))
      Return this
   End Function
   
   
   Method _parseSchema(schema:String)
      Local elements:String[] = schema.Split(",")
      For Local e:String = EachIn elements
         If e.Length > 0
            _parseSchemaElement(e.Trim())
         End If
      Next
   End Method

   Method _parseSchemaElement(element:String)
      Local elementId:String = element[0..1]
      Local elementTail:String = element[1..]
      _validateSchemaElementId(elementId)
      If elementTail.Length = 0
         _marshalers.Insert(elementId, New TBooleanArgumentMarshaler)
       Else If elementTail.Compare("*") = 0
         _marshalers.Insert(elementId, New TStringArgumentMarshaler)
      Else If elementTail.Compare("#") = 0
         _marshalers.Insert(elementId, New TIntegerArgumentMarshaler)
      Else If elementTail.Compare("##") = 0
         _marshalers.Insert(elementId, New TDoubleArgumentMarshaler)
      Else If elementTail.Compare("[*]") = 0
         _marshalers.Insert(elementId, New TStringArrayArgumentMarshaler)
      Else
         Throw TArgsException.Create(TArgsException.INVALID_ARGUMENT_FORMAT, elementId, elementTail)
      End If
   End Method
   
   Method _validateSchemaElementId(elementId:String)
      If Not _isLetter(elementId)
         Throw TArgsException.Create(TArgsException.INVALID_ARGUMENT_NAME, elementId)
      EndIf
   End Method
   
   Method _parseArguments(args:TList)
      _currentArgument = args.FirstLink()
      
      While _currentArgument <> Null
         Local argString:String = String(_currentArgument.Value())
         If argString.StartsWith("-")
            _parseArgumentCharacters(argString[1..])
         EndIf
         _currentArgument = _currentArgument.NextLink()
      Wend
      _currentArgument = args.LastLink()
   End Method
   
   Method _parseArgumentCharacters(argChars:String)
      For Local i:Int = 0 To argChars.Length - 1
         _parseArgumentCharacter(argChars[i..i + 1])
      Next
   End Method
   
   Method _parseArgumentCharacter(argChar:String)
      Local m:TArgumentMarshaler = TArgumentMarshaler(Self._marshalers.ValueForKey(argChar))
      If m = Null
         Throw TArgsException.Create(TArgsException.UNEXCPECTED_ARGUMENT, argChar)
      Else
         _argsFound.AddLast(argChar)
         Try
               m._set(_currentArgument)
            Catch ex:TArgsException
            TArgsException(ex).errorArgumentId = argChar
            Throw ex
            End Try
      End If
   End Method
   
   Method _isLetter:Int(char:String)
      If Asc(char) >= 65 And Asc(char) <= 90 Return True
      If Asc(char) >= 97 And Asc(char) <= 122 Return True
      Return False
   End Method
   
   Method _arrayToList:TList(array:String[])
      Local list:TList = New TList
      For Local element:String = EachIn array
         list.AddLast(element)
      Next
      Return list
   End Method
   
   Method has:Int(arg:String)
      For Local element:String = EachIn _argsFound
         If element.Compare(arg) = 0
            Return True
         End If
      Next
      Return False
   End Method
   
   Method nextArgument:Int()
      Local nextArg:String = String(_currentArgument.NextLink().Value())
      Local i:Int = 1
      For Local element:String = EachIn _argsFound
         If element.Compare(nextArg)
            Return i
         EndIf
         i:+1
      Next
   End Method
   
   Method getBoolean:Int(arg:String)
      Return TBooleanArgumentMarshaler.getValue(TArgumentMarshaler(_marshalers.ValueForKey(arg)))
   End Method
   
   Method getString:String(arg:String)
      Return TStringArgumentMarshaler.getValue(TArgumentMarshaler(_marshalers.ValueForKey(arg)))
   End Method
   
   Method getInt:Int(arg:String)
      Return TIntegerArgumentMarshaler.getValue(TArgumentMarshaler(_marshalers.ValueForKey(arg)))
   End Method
   
   Method getDouble:Double(arg:String)
      Return TDoubleArgumentMarshaler.getValue(TArgumentMarshaler(_marshalers.ValueForKey(arg)))
   End Method
   
   Method getStringArray:String[] (arg:String)
      Return TStringArrayArgumentMarshaler.getValue(TArgumentMarshaler(_marshalers.ValueForKey(arg)))
   End Method
EndType

Type TArgumentMarshaler
   Method _set(currentArgument:TLink) Abstract
End Type

Type TBooleanArgumentMarshaler Extends TArgumentMarshaler
   Field _booleanValue:Int = False
   
   Method _set(currentArgument:TLink)
      _booleanValue = True
   End Method
   
   Function getValue:Int(am:TArgumentMarshaler)
      If am <> Null
         Return TBooleanArgumentMarshaler(am)._booleanValue
      Else
         Return False
       EndIf
   End Function
End Type

Type TStringArgumentMarshaler Extends TArgumentMarshaler
   Field _stringValue:String = ""

   Method _set(currentArgument:TLink)
      _stringValue = String(currentArgument.NextLink().Value())
      If _stringValue = Null
         Throw TArgsException.Create(TArgsException.MISSING_STRING)
      End If
   End Method
   
   Function getValue:String(am:TArgumentMarshaler)
      If am <> Null
         Return TStringArgumentMarshaler(am)._stringValue
      Else
         Return ""
       EndIf
   End Function   
End Type

Type TIntegerArgumentMarshaler Extends TArgumentMarshaler
   Field _integerValue:Int = 0

   Method _set(currentArgument:TLink)
      Local stringParameter:String = String(currentArgument.NextLink().Value())
      If stringParameter.Length = 0 Or stringParameter = Null
         Throw TArgsException.Create(TArgsException.MISSING_INTEGER)
      End If
      If Not isNumber(stringParameter)
         Throw TArgsException.Create(TArgsException.INVALID_INTEGER, stringParameter)
      End If
      _integerValue = stringParameter.ToInt()
   End Method
   
   Function getValue:Int(am:TArgumentMarshaler)
      If am <> Null
         Return TIntegerArgumentMarshaler(am)._integerValue
      Else
         Return 0
       EndIf
   End Function
   
   Function isNumber:Byte(S:String)
      If S = "" Then Return False
      For Local index:Int = 97 To 122
         If Lower(S).Find(Chr(index)) <> - 1 Then
            Return False
         EndIf
      Next
      Return True
   End Function
End Type

Type TDoubleArgumentMarshaler Extends TArgumentMarshaler
   Field _doubleValue:Double = 0.0

   Method _set(currentArgument:TLink)
      Local stringParameter:String = String(currentArgument.NextLink().Value())
      If stringParameter.Length = 0 Or stringParameter = Null
         Throw TArgsException.Create(TArgsException.MISSING_DOUBLE)
      End If
      If Not isNumber(stringParameter)
         Throw TArgsException.Create(TArgsException.INVALID_DOUBLE, stringParameter)
      End If
      _doubleValue = stringParameter.ToDouble ()
   End Method
   
   Function getValue:Double(am:TArgumentMarshaler)
      If am <> Null
         Return TDoubleArgumentMarshaler(am)._doubleValue
      Else
         Return 0.0
       EndIf
   End Function
   
   Function isNumber:Byte(S:String)
      If S = "" Then Return False
      For Local index:Int = 97 To 122
         If Lower(S).Find(Chr(index)) <> - 1 Then
            Return False
         EndIf
      Next
      Return True
   End Function
End Type

Type TStringArrayArgumentMarshaler Extends TArgumentMarshaler
   Field _stringArrayValue:String[]

   Method _set(currentArgument:TLink)
      _stringArrayValue = String[] String((currentArgument.NextLink().Value())).Split(",")
      If _stringArrayValue = Null
         Throw TArgsException.Create(TArgsException.MISSING_STRING)
      End If
   End Method
   
   Function getValue:String[] (am:TArgumentMarshaler)
      If am <> Null
         Return TStringArrayArgumentMarshaler(am)._stringArrayValue
      Else
         Return Null
       EndIf
   End Function   
End Type

Type TArgsException Extends TBlitzException

   Const OK:Int = 0
   Const INVALID_ARGUMENT_FORMAT:Int = 1
   Const UNEXCPECTED_ARGUMENT:Int = 2
   Const INVALID_ARGUMENT_NAME:Int = 3
   Const MISSING_STRING:Int = 4
   Const MISSING_INTEGER:Int = 5
   Const INVALID_INTEGER:Int = 6
   Const MISSING_DOUBLE:Int = 7
   Const INVALID_DOUBLE:Int = 8

   Field errorCode:Int
   Field errorArgumentId:String
   Field errorParameter:String

   Function Create:TArgsException(errorCode:Int, errorArgumentId:String = "", errorParameter:String = "")
      Local this:TArgsException = New TArgsException
      this.errorCode = errorCode
      this.errorArgumentId = errorArgumentId
      this.errorParameter = errorParameter
      Return this
   End Function

   Method ToString:String()
      Select errorCode
         Case OK
            Return "TILT: Should not get here."
         Case UNEXCPECTED_ARGUMENT
            Return "Argument " + errorArgumentId + " unexpected."
         Case MISSING_STRING
            Return "Could not find string parameter for " + errorArgumentId
         Case INVALID_INTEGER
            Return "Argument " + errorArgumentId + " expects an integer but was " + errorParameter
         Case MISSING_INTEGER
            Return "Could not find integer parameter for " + errorArgumentId
         Case INVALID_DOUBLE
            Return "Argument " + errorArgumentId + " expects an double but was " + errorParameter
         Case MISSING_DOUBLE
            Return "Could not find double parameter for " + errorArgumentId
         Case INVALID_ARGUMENT_NAME
            Return errorArgumentId + " is not a valid argument name."
          Case INVALID_ARGUMENT_FORMAT
            Return errorParameter + " is not a valid argument format."
      End Select
      
      Return ""
      
   End Method
EndType


Und hier ein kleines Testprogramm:


Code: [AUSKLAPPEN]
  Local testArgs:TArgs
   Try
      testArgs = TArgs.Create("l,p#,d*,u,r[*],v##", ["-l", "-p", "22", "-d", "BlitzMax", "-u", "-r", "One,Two,Three", "-v", "3.141592"])
   Catch ex:TArgsException
      Assert ex.ToString()
   End Try
   Print "Boolean Parameter l: " + testArgs.getBoolean("l")
   Print "Integer Parameter p: " + testArgs.getInt("p")
   Print "String Parameter  d: " + testArgs.getString("d")
   Print "Boolean Parameter u: " + testArgs.getBoolean("u")
   Print "Is there a parameter named x: " + testArgs.has("x")
   Print "Is there a parameter named u: " + testArgs.has("u")
   Print "String Array Parameter r: "
   Local temp:String[] = testArgs.getStringArray("r")
   For Local e:String = EachIn temp
      Print "->" + e
   Next
   Print "Double Parameter v: " + testArgs.getDouble("v")

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group