mkpass用CheckOptionクラス

投稿者: | 2017年2月4日

オプションチェッククラスを書きます。

自然数のチェックを含めてオプションの取得は数値をチェックするでやりましたね。これを書き直していきましょう。

クラスを書く

CheckOptionクラスのテストコードでまとめたオプションリストから、次のような条件を満たせばいいことになります。

  • -で始まる文字列か自然数以外は受け付けない(Invalid optionエラー)
  • -で始まる文字列はaulnsxのいずれか
  • 自然数の引数がない場合の桁数は8
  • -で始まる文字列がない場合はlnxが適用される
  • オプションスイッチにaが指定された場合はulnsが適用される

オプション指定しない場合は-lnx 8を適用することにしました。

class CheckOption {
  private var arguments: [String]
  private var argType: String
  private var option: String
  private var param: (upper: Bool, lower: Bool, number: Bool, symbol: Bool, exclude: Bool, length: Int, status: Int)
  init(arguments: [String], argType: String = "unknown", option: String = "",
               param: (upper: Bool, lower: Bool, number: Bool, symbol: Bool, exclude: Bool, length: Int, status: Int) = (false, false, false, false, false, 0, 0)) {
    self.arguments = arguments
    self.argType = argType
    self.option = option
    self.param = param
  }
  func checkArguments() {
    chk_opt: for n in 1..<arguments.count {
      option = arguments[n]
      for char in option.characters {
        if argType == "unknown" {
          switch char {
          case "-":
            argType = "optSW"
          case "1"..."9":
            argType = "length"
          default:
            argType = "error"
            param.status = 1
            break
          }
        } else if argType == "optSW" {
          switch char {
          case "a":
            param.upper = true
            param.lower = true
            param.number = true
            param.symbol = true
          case "u":
            param.upper = true
          case "l":
            param.lower = true
          case "n":
            param.number = true
          case "s":
            param.symbol = true
          case "x":
            param.exclude = true
          default:
            argType = "error"
            param.status = 1
            break
          }
        } else if argType == "length" {
          switch char {
          case "0"..."9":
            argType = "length"
          default:
            argType = "error"
            param.status = 1
            break
          }
        }
        if param.status != 0 {
          break chk_opt
        }
      }
      switch argType {
      case "length":
        param.length = Int(option)!
      default:
        break
      }
      argType = "unknown"
    }
  }
  func getOption() -> (Bool, Bool, Bool, Bool, Bool, Int, Int) {
    self.checkArguments()
    return (param.upper, param.lower, param.number, param.symbol, param.exclude, param.length, param.status)
  }
}

本当はargTypeの値は列挙型を使いたかったんですが、クラスの中でうまく定義することができなかったのでString型にしています。

enum ArgType {
  case unknown
  case optSw
  case length
  case error
}

mkpassプロトタイプ

今回のCheckOptionクラスと前回作ったGenerateMemberクラスとでmkpassの基本部分ができました。

今回エラー処理等は端折りましたが、基本的なオプションへの対応のみおこなったプロトタイプができました。

#! /usr/bin/swift
import Foundation
let arguments: [String] = CommandLine.arguments
var returnSet: (upper:Bool, lower:Bool, number:Bool, symbol:Bool, exclude:Bool, length:Int, status:Int)
var member: [String] = []
returnSet = CheckOption(arguments: arguments).getOption()
if !(returnSet.upper) {
  if !(returnSet.lower) {
    if !(returnSet.number) {
      if !(returnSet.symbol) {
        returnSet.lower = true
        returnSet.number = true
      }
    }
  }
}
if returnSet.length == 0 {
  returnSet.length = 8
}
if returnSet.upper {
  if returnSet.exclude {
    member += GenerateMember().getMember(range: [[65,90]], exclude: [14,8])
  } else {
    member += GenerateMember().getMember(range: [[65,90]], exclude: [])
  }
}
if returnSet.lower {
  if returnSet.exclude {
    member += GenerateMember().getMember(range: [[97,122]], exclude: [11])
  } else {
    member += GenerateMember().getMember(range: [[97,122]], exclude: [])
  }
}
if returnSet.number {
  if returnSet.exclude {
    member += GenerateMember().getMember(range: [[48,57]], exclude: [1,0])
  } else {
    member += GenerateMember().getMember(range: [[48,57]], exclude: [])
  }
}
if returnSet.symbol {
  if returnSet.exclude {
    member += GenerateMember().getMember(range: [[33,47],[58,64],[91,96],[123,126]], exclude: [29])
  } else {
    member += GenerateMember().getMember(range: [[33,47],[58,64],[91,96],[123,126]], exclude: [])
  }
}
var passwd: String = ""
for n in 1...returnSet.length {
  var code: UInt32  = arc4random_uniform(UInt32(member.count))
  passwd += member[Int(code)]
}
print(passwd)

いちおうmake一発でコンパイルできます。

all:
     cp -p mkpass.swift main.swift
     xcrun -sdk macosx swiftc -o mkpass main.swift ./GenerateMember/GenerateMember.swift ./CheckOption/CheckOption.swift
     rm main.swift

それぞれのクラスファイルはベースネームと同じ名前のディレクトリに保存されている前提です。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です