/*! @file Include/Classes/ActiveBasic/Strings/SPrintF.ab @brief SPrintfとその補助ルーチンが含まれるファイル。 SPrintfで数値変換が行われるとき、呼出の階層は、 SPrintf→FormatInteger, FormatFloat→FormatIntegerEx, FormatFloatExとなる。 また、次のような変換ルーチンが存在する。 @li FormatFloatE @li FormatFloatF @li FormatFloatG @li FormatFloatA @li FormatIntegerD @li FormatIntegerU @li FormatIntegerO @li FormatIntegerX @li FormatCharacter @li FormatString */ Namespace ActiveBasic Namespace Strings Namespace Detail /*! @brief 浮動小数点数を文字列化する低水準な関数。符号、指数、仮数に分けて出力。 @author Egtra @date 2007/09/18 @param[in] x 文字列化する浮動小数点数 @param[out] e 指数 @param[out] sign 符号 @return 仮数 仮数は1の位から下へ17桁で、小数点を含まない。そのため、誤差を無視すればVal(仮数) * 10 ^ (e - 17) = Abs(x)が成り立つ。 xに無限大、非数を渡した場合の動作は未定義。 */ Function FloatToChars(x As Double, ByRef e As Long, ByRef sign As Boolean) As String Imports System '0を弾く If x = 0 Then If GetQWord(VarPtr(x) As *QWord) And &h8000000000000000 Then sign = True Else sign = False End If e = 0 FloatToChars = "00000000000000000" Exit Function End If '符号の判断(同時に符号を取り除く) If x < 0 Then sign = True x = -x Else sign = False End If '1e16 <= x < 1e17へ正規化 '(元のx) = (正規化後のx) ^ (d - 17)である。 Dim d = Math.Floor(Math.Log10(x)) As Long If d < 16 Then x *= ipow(10, +17 - d) ElseIf d > 16 Then x /= ipow(10, -17 + d) End If '補正 While x < 1e16 x *= 10 d-- Wend While x >= 1e17 x /= 10 d++ Wend d-- e = d FloatToChars = FormatIntegerLU((x As Int64) As QWord, 17, 0, None) End Function /*! @brief 書式化関数群で使用するフラグ。 @author Egtra @date 2007/09/18 */ Const Enum FormatFlags '! 何も指定がない。 None = &h0 /*! 符号、+。符号付変換[diAaEeFfGg]のとき、正の値でも符号を付ける。 AdjustFieldWidthの仕様から、Format関数郡内からAdjustFieldWidthにかけて、 単に数値が符号付である(負の値である)ことを示す意味でも用いられる。 */ Sign = &h1 /*! 空白、空白文字。 符号付変換[diAaEeFfGg]のとき、正の値ならば符号分の空白を開ける。Signが立っているときには無視される。 */ Blank = &h2 /*! ゼロ、0。 [diouXxAaEeFfGg]で、フィールドの空きを0で埋める。leftが立っているときには無視される。 */ Zero = &h4 '! 左揃え、-。フィールド内で左揃えにする。 LeftSide = &h8 /*! 代替表記、#。 @li [OoXx]では、値が0でない場合、先頭に0、0xを付ける。 @li [AaEeFfGg]では、精度0でも小数点を付ける。 @li [Gg]では、それに加え、小数部末尾の0の省略を行わないようにする。 */ Alt = &h10 '! 大文字。使用するアルファベットを大文字にする。[aefgx]を[AEFGX]化する。 Cap = &h20 '!BASIC接頭辞。&h, &oなど。 BPrefix = &h40 /*! 内部処理用に予約。 @note Minusとして使用されている。 */ Reserved = &h80000000 End Enum /*! @brief 浮動小数点数をprintfの%e, %E(指数形式、十進法)相当の変換で文字列化する関数。 @author Egtra @date 2007/09/18 @param[in] x 文字列化する浮動小数点数値。 @param[in] precision 精度。小数点以下の桁数。DWORD_MAXのとき、指定なしとして既定値6となる。 @param[in] field フィールド幅。 @param[in] flags 書式フラグ。 @return xの文字列表現 */ Function FormatFloatE(x As Double, precision As DWord, field As DWord, flags As FormatFlags) As String FormatFloatE = FormatFloatEx(AddressOf(FormatFloatE_Convert), x, precision, field, flags) End Function /* @brief 浮動小数点数をprintfの%e, %E(指数形式、十進法)相当の変換で文字列化する関数。 @author Egtra @date 2008/03/08 @param[in,out] sb 書式化した文字列を追加するバッファ。 @param[in] x 文字列化する浮動小数点数値。 @param[in] precision 精度。小数点以下の桁数。DWORD_MAXのとき、指定なしとして既定値6となる。 @param[in] field フィールド幅。 @param[in] flags 書式フラグ。 */ Sub FormatFloatE(sb As System.Text.StringBuilder, x As Double, precision As DWord, field As DWord, ByRef flags As FormatFlags) FormatFloatEx(sb, AddressOf(FormatFloatE_Convert), x, precision, field, flags) End Sub /*! @brief 浮動小数点数をprintfの%e, %E(指数形式、十進法)相当の変換で文字列化する関数。 @author Egtra @date 2008/03/07 @param[in,out] sb 書式化した文字列を追加するバッファ。 @param[in] x 文字列化する浮動小数点数値。 @param[in] precision 精度。小数点以下の桁数。DWORD_MAXのとき、指定なしとして15となる。 @param[in] field フィールド幅。 @param[in,out] flags 書式フラグ。 @todo 他の実装での末尾桁の扱いを調べる(このコードでは何もしていないので切捨となっている)。 */ Sub FormatFloatE_Convert(sb As System.Text.StringBuilder, x As Double, precision As DWord, field As DWord, ByRef flags As FormatFlags) If precision = DWORD_MAX Then precision = 15 End If Dim e As Long, negative As Boolean Dim s = FloatToChars(x, e, negative) FormatFloatE_Base(sb, s, negative, precision, flags) FormatFloatE_Exponent(sb, e, flags) End Sub /** @brief FormatFloatEの符号・基数部の出力用。 @author Egtra @date 2007/10/27 */ Sub FormatFloatE_Base(sb As System.Text.StringBuilder, s As String, negative As Boolean, precision As DWord, ByRef flags As FormatFlags) With sb AppendSign(sb, negative, flags) .Append(s[0]) If (flags And Alt) Or precision > 0 Then .Append(".") Dim outputLen = s.Length - 1 If outputLen >= precision Then .Append(s, 1, precision) Else 'sで用意された桁が指定された精度より少ないとき .Append(s, 1, outputLen) .Append(&h30 As Char, precision - outputLen) '足りない桁は0埋め End If End If End With End Sub /** @brief FormatFloatEの指数部の出力用。 @author Egtra @date 2007/10/27 */ Sub FormatFloatE_Exponent(sb As System.Text.StringBuilder, e As Long, flags As FormatFlags) With sb If flags And Cap Then .Append("E") Else .Append("e") End If FormatIntegerD(sb, e, 2, 0, Sign Or Zero) End With End Sub /*! @brief 浮動小数点数をprintfの%f(小数形式、十進法)相当の変換で文字列化する関数。 @author Egtra @date 2007/10/23 @param[in] x 文字列化する浮動小数点数値。 @param[in] precision 精度。小数点以下の桁数。DWORD_MAXのとき、指定なしとして既定値15となる。 @param[in] field フィールド幅。 @param[in] flags 書式フラグ。 @return xの文字列表現 */ Function FormatFloatF(x As Double, precision As DWord, field As DWord, flags As FormatFlags) As String FormatFloatF = FormatFloatEx(AddressOf(FormatFloatF_Convert), x, precision, field, flags) End Function /* @brief 浮動小数点数をprintfの%f(小数形式、十進法)相当の変換で文字列化する関数。 @author Egtra @date 2008/03/08 @param[in,out] sb 書式化した文字列を追加するバッファ。 @param[in] x 文字列化する浮動小数点数値。 @param[in] precision 精度。小数点以下の桁数。DWORD_MAXのとき、指定なしとして既定値6となる。 @param[in] field フィールド幅。 @param[in] flags 書式フラグ。 */ Sub FormatFloatF(sb As System.Text.StringBuilder, x As Double, precision As DWord, field As DWord, ByRef flags As FormatFlags) FormatFloatEx(sb, AddressOf(FormatFloatF_Convert), x, precision, field, flags) End Sub /*! @brief 浮動小数点数をprintfの%f(小数形式、十進法)相当の変換で文字列化する関数。 @author Egtra @date 2008/03/07 @param[in,out] sb 書式化した文字列を追加するバッファ。 @param[in] x 文字列化する浮動小数点数値。 @param[in] precision 精度。小数点以下の桁数。DWORD_MAXのとき、指定なしとして既定値15となる。 @param[in] field フィールド幅。 @param[in,out] flags 書式フラグ。 */ Sub FormatFloatF_Convert(sb As System.Text.StringBuilder, x As Double, precision As DWord, field As DWord, ByRef flags As FormatFlags) If precision = DWORD_MAX Then precision = 15 End If Dim e As Long, negative As Boolean Dim s = FloatToChars(x, e, negative) FormatFloatF_Core(sb, s, e, negative, precision, flags) End Sub /** @author Egtra @date 2007/10/27 */ Sub FormatFloatF_Core(sb As System.Text.StringBuilder, s As String, e As Long, negative As Boolean, precision As DWord, ByRef flags As FormatFlags) With sb AppendSign(sb, negative, flags) Dim intPartLen = e + 1 Dim outputDigit = 0 As DWord If intPartLen >= 17 Then '有効桁が全て整数部に収まる場合 .Append(s) .Append(&h30 As Char, intPartLen - 17) outputDigit = 17 ElseIf intPartLen > 0 Then '有効桁の一部が整数部にかかる場合 .Append(s, 0, intPartLen) outputDigit = intPartLen Else '有効桁が全く整数部にかからない場合 .Append(&h30 As Char) End If If precision > 0 Or (flags And Alt) Then .Append(".") Dim lastDigit = s.Length - outputDigit If lastDigit >= precision Then '変換して得られた文字列の桁数が精度以上ある場合 Dim zeroDigit = 0 If intPartLen < 0 Then '1.23e-4 = 0.000123のように指数が負のため小数点以下に0が続く場合 zeroDigit = System.Math.Min(-intPartLen As DWord, precision) .Append(&h30 As Char, zeroDigit As Long) End If .Append(s, outputDigit, (precision - zeroDigit) As Long) Else .Append(s, outputDigit, lastDigit) .Append(&h30 As Char, (precision - lastDigit) As Long) '残りの桁は0埋め End If End If End With End Sub /*! @brief 浮動小数点数をprintfの%g, %G(小数・指数、十進法)相当の変換で文字列化する関数。 @author Egtra @date 2007/10/23 @param[in] x 文字列化する浮動小数点数値。 @param[in] precision 精度。小数点以下の桁数。DWORD_MAXまたは0のとき、指定なしとして既定値15となる。 @param[in] field フィールド幅。 @param[in] flags 書式フラグ。 @return xの文字列表現 @todo 下位桁の扱いの調査。 */ Function FormatFloatG(x As Double, precision As DWord, field As DWord, flags As FormatFlags) As String FormatFloatG = FormatFloatEx(AddressOf(FormatFloatG_Convert), x, precision, field, flags) End Function /* @brief 浮動小数点数をprintfの%g, %G(小数・指数、十進法)相当の変換で文字列化する関数。 @author Egtra @date 2008/03/08 @param[in,out] sb 書式化した文字列を追加するバッファ。 @param[in] x 文字列化する浮動小数点数値。 @param[in] precision 精度。小数点以下の桁数。DWORD_MAXのとき、指定なしとして既定値6となる。 @param[in] field フィールド幅。 @param[in] flags 書式フラグ。 */ Sub FormatFloatG(sb As System.Text.StringBuilder, x As Double, precision As DWord, field As DWord, ByRef flags As FormatFlags) FormatFloatEx(sb, AddressOf(FormatFloatG_Convert), x, precision, field, flags) End Sub /*! @brief 浮動小数点数をprintfの%g, %G(小数・指数、十進法)相当の変換で文字列化する関数。 @author Egtra @date 2007/10/23 @param[in,out] sb 書式化した文字列を追加するバッファ。 @param[in] x 文字列化する浮動小数点数値。 @param[in] precision 精度。小数点以下の桁数。DWORD_MAXまたは0のとき、指定なしとして既定値15となる。 @param[in] field フィールド幅。 @param[in,out] flags 書式フラグ。 @todo 下位桁の扱いの調査。 */ Sub FormatFloatG_Convert(sb As System.Text.StringBuilder, x As Double, precision As DWord, field As DWord, ByRef flags As FormatFlags) 'GではE/Fと違い整数部も有効桁数に数えるのでその分を引いておく。 If precision = DWORD_MAX Or precision = 0 Then precision = 14 Else precision-- End If Dim lastLength = sb.Length Dim e As Long, negative As Boolean Dim s = FloatToChars(x, e, negative) If -5 < e And e < precision Then FormatFloatF_Core(sb, s, e, negative, -e + precision, flags) FormatFloatG_RemoveLowDigit(sb, lastLength, flags) Else FormatFloatE_Base(sb, s, negative, precision, flags) FormatFloatG_RemoveLowDigit(sb, lastLength, flags) FormatFloatE_Exponent(sb, e, flags) End If End Sub /*! @brief FormatFloatG/A用の小数点以下末尾の0を削除するルーチン @author Egtra @date 2007/10/27 @param[in, out] sb 文字列バッファ @param[in] flags フラグ flagsでAltが立っているとき、この関数は何もしない。 */ Sub FormatFloatG_RemoveLowDigit(sb As System.Text.StringBuilder, start As Long, flags As FormatFlags) Imports ActiveBasic.Strings Dim count = sb.Length If (flags And Alt) = 0 Then Dim p = StrPtr(sb) Dim point = ChrFind(VarPtr(p[start]), (count - start) As SIZE_T, Asc(".")) If point = -1 Then Debug End If Dim i As Long For i = count - 1 To point + 1 Step -1 If sb[i] <> &h30 Then Exit For End If Next If i <> point Then i++ End If sb.Length = i End If End Sub /*! @brief 浮動小数点数をprintfの%a, %A(指数形式、十六進法)相当の変換で文字列化する関数。 @author Egtra @date 2007/09/18 @param[in] x 文字列化する浮動小数点数値。 @param[in] precision 精度。小数点以下の桁数。DWORD_MAXのとき、指定なしとして既定値13となる。 @param[in] field フィールド幅。 @param[in] flags 書式フラグ。 @return xの文字列表現 C99では、末尾の0を取り除いても良いとあるので、 このルーチンでは取り除くことにしている。 */ Function FormatFloatA(x As Double, precision As DWord, field As DWord, flags As FormatFlags) As String FormatFloatA = FormatFloatEx(AddressOf(FormatFloatA_Convert), x, precision, field, flags) End Function /* @brief 浮動小数点数をprintfの%a, %A(指数形式、十六進法)相当の変換で文字列化する関数。 @author Egtra @date 2008/03/08 @param[in,out] sb 書式化した文字列を追加するバッファ。 @param[in] x 文字列化する浮動小数点数値。 @param[in] precision 精度。小数点以下の桁数。DWORD_MAXのとき、指定なしとして既定値6となる。 @param[in] field フィールド幅。 @param[in] flags 書式フラグ。 */ Sub FormatFloatA(sb As System.Text.StringBuilder, x As Double, precision As DWord, field As DWord, ByRef flags As FormatFlags) FormatFloatEx(sb, AddressOf(FormatFloatA_Convert), x, precision, field, flags) End Sub /*! @brief 浮動小数点数をprintfの%a, %A(指数形式、十六進法)相当の変換で文字列化する関数。 @author Egtra @date 2008/03/07 @param[in,out] sb 書式化した文字列を追加するバッファ。 @param[in] x 文字列化する浮動小数点数値。 @param[in] precision 精度。小数点以下の桁数。DWORD_MAXのとき、指定なしとして既定値13となる。 @param[in] field フィールド幅。 @param[in,out] flags 書式フラグ。 C99では、末尾の0を取り除いても良いとあるので、 このルーチンでは取り除くことにしている。 */ Sub FormatFloatA_Convert(sb As System.Text.StringBuilder, x As Double, precision As DWord, field As DWord, ByRef flags As FormatFlags) If precision = DWORD_MAX Then precision = 13 End If Dim lastLength = sb.Length Dim pqw = VarPtr(x) As *QWord With sb Dim sign = (GetQWord(pqw) And &H8000000000000000) As Boolean pqw[0] And= &h7fffffffffffffff AppendSign(sb, sign, flags) If flags And BPrefix Then .Append("&H") Else .Append("0X") End If Dim biasedExp = (GetQWord(pqw) >> 52) As DWord And &h7FF Dim exp As Long If biasedExp = 0 Then If GetQWord(pqw) <> 0 Then exp = -1022 '非正規化数への対応 Else exp = 0 End If .Append("0") Else exp = biasedExp - 1023 .Append("1") End If If precision > 0 Or (flags And Alt) Then .Append(".") Dim fraction = GetQWord(pqw) And &h000fffffffffffff If precision < 13 Then Dim dropped = 13 - precision fraction >>= dropped * 4 FormatIntegerLX(sb, fraction, precision, 0, flags And Cap) Else FormatIntegerLX(sb, fraction, 13, 0, flags And Cap) .Append(&h30, precision - 13) End If End If FormatFloatG_RemoveLowDigit(sb, lastLength, flags) .Append("P") FormatIntegerD(sb, exp, 1, 0, Sign) AdjustAlphabet(sb, flags, lastLength) End With End Sub /*! @brief 先頭に符号もしくはその分の空白を出力する。FormatFloat用。 @author Egtra @date 2007/10/23 @param[in, out] sb 出力先 @param[in] negative 符号 @param[in, out] flags フラグ。negative = Trueなら、Signを立てて返す。 */ Sub AppendSign(sb As System.Text.StringBuilder, negative As Boolean, ByRef flags As FormatFlags) With sb If negative Then .Append("-") flags Or= Sign Else If flags And Sign Then .Append("+") ElseIf flags And Blank Then .Append(" ") End If End If End With End Sub /*! @brief 符号無し整数をprintfの%u(十進法表現)相当の変換で文字列化する関数。 @author Egtra @date 2007/09/18 @param[in] x 文字列化する整数値。 @param[in] d 精度、最小限表示される桁数。DWORD_MAXのとき、指定なしとして、既定値1となる。 @param[in] field フィールド幅。 @param[in] flags 書式フラグ。 @return xの文字列表現 */ Function FormatIntegerU(x As DWord, d As DWord, field As DWord, flags As FormatFlags) As String Return FormatIntegerEx(TraitsIntegerU[0], x, d, field, flags And (Not (Sign Or Blank))) End Function /*! @brief 符号無し整数をprintfの%u(十進法表現)相当の変換で文字列化する関数。 @author Egtra @date 2008/03/07 @param[in,out] sb 書式化した文字列を追加するバッファ。 @param[in] x 文字列化する整数値。 @param[in] d 精度、最小限表示される桁数。DWORD_MAXのとき、指定なしとして、既定値1となる。 @param[in] field フィールド幅。 @param[in] flags 書式フラグ。 */ Sub FormatIntegerU(sb As System.Text.StringBuilder, x As DWord, d As DWord, field As DWord, flags As FormatFlags) FormatIntegerEx(sb, TraitsIntegerU[0], x As QWord, d, field, flags And (Not (Sign Or Blank))) End Sub /*! @brief FormatIntegerUのQWord版 @author Egtra @date 2007/10/26 */ Function FormatIntegerLU(x As QWord, d As DWord, field As DWord, flags As FormatFlags) As String Return FormatIntegerEx(TraitsIntegerU[1], x, d, field, flags And (Not (Sign Or Blank))) End Function /*! @brief FormatIntegerUのQWord版 @author Egtra @date 2008/03/07 @param[in,out] sb 書式化した文字列を追加するバッファ。 @param[in] x 文字列化する整数値。 @param[in] d 精度、最小限表示される桁数。DWORD_MAXのとき、指定なしとして、既定値1となる。 @param[in] field フィールド幅。 @param[in] flags 書式フラグ。 */ Sub FormatIntegerLU(sb As System.Text.StringBuilder, x As QWord, d As DWord, field As DWord, flags As FormatFlags) FormatIntegerEx(sb, TraitsIntegerU[0], x, d, field, flags And (Not (Sign Or Blank))) End Sub /*! @brief 符号有り整数をprintfの%d(十進法表現)相当の変換で文字列化する関数。 @author Egtra @date 2007/10/13 @param[in] x 文字列化する整数値。 @param[in] d 精度、最小限表示される桁数。DWORD_MAXのとき、指定なしとして、既定値1となる。 @param[in] field フィールド幅。 @param[in] flags 書式フラグ。 @return xの文字列表現 */ Function FormatIntegerD(x As Long, d As DWord, field As DWord, flags As FormatFlags) As String Return FormatIntegerEx(TraitsIntegerD[0], (x As Int64) As QWord, d, field, flags) End Function /*! @brief 符号有り整数をprintfの%d(十進法表現)相当の変換で文字列化する関数。 @author Egtra @date 2008/03/07 @param[in,out] sb 書式化した文字列を追加するバッファ。 @param[in] x 文字列化する整数値。 @param[in] d 精度、最小限表示される桁数。DWORD_MAXのとき、指定なしとして、既定値1となる。 @param[in] field フィールド幅。 @param[in] flags 書式フラグ。 */ Sub FormatIntegerD(sb As System.Text.StringBuilder, x As Long, d As DWord, field As DWord, flags As FormatFlags) FormatIntegerEx(sb, TraitsIntegerD[0], (x As Int64) As QWord, d, field, flags) End Sub /*! @brief FormatIntegerDのInt64版 @author Egtra @date 2007/10/26 */ Function FormatIntegerLD(x As Int64, d As DWord, field As DWord, flags As FormatFlags) As String Return FormatIntegerEx(TraitsIntegerD[1], x As QWord, d, field, flags) End Function /*! @brief FormatIntegerDのInt64版 @author Egtra @date 2007/10/26 */ Sub FormatIntegerLD(sb As System.Text.StringBuilder, x As Int64, d As DWord, field As DWord, flags As FormatFlags) FormatIntegerEx(sb, TraitsIntegerD[1], x As QWord, d, field, flags) End Sub /*! @author Egtra @date 2007/10/26 */ Dim TraitsIntegerU[1] As IntegerConvertTraits With TraitsIntegerU[0] .Convert = AddressOf(IntegerU_Convert) .Prefix = AddressOf(IntegerU_Prefix) End With With TraitsIntegerU[1] .Convert = AddressOf(IntegerLU_Convert) .Prefix = AddressOf(IntegerU_Prefix) End With /*! @author Egtra @date 2007/10/28 */ Dim TraitsIntegerD[1] As IntegerConvertTraits With TraitsIntegerD[0] .Convert = AddressOf(IntegerD_Convert) .Prefix = AddressOf(IntegerD_Prefix) End With With TraitsIntegerD[1] .Convert = AddressOf(IntegerLD_Convert) .Prefix = AddressOf(IntegerD_Prefix) End With /*! @brief 負数を表すフラグ。FormatIntegerD, LDからIntegerDU_Prefixまでの内部処理用。 @author Egtra @date 2007/10/26 */ Const Minus = Reserved /*! @author Egtra @date 2007/10/26 */ Function IntegerU_Convert(buf As *Char, xq As QWord, flags As FormatFlags) As DWord Dim x = xq As DWord Dim i = MaxSizeLO While x <> 0 buf[i] = (x As Int64 Mod 10 + &h30) As Char 'Int64への型変換は#117対策 x \= 10 i-- Wend Return i End Function /*! @brief IntegerU_ConvertのQWord版 @author Egtra @date 2007/10/26 @bug #117のため、現在Int64の最大値を超える値を正しく処理できない。 */ Function IntegerLU_Convert(buf As *Char, x As QWord, flags As FormatFlags) As DWord Dim i = MaxSizeLO While x <> 0 buf[i] = (x As Int64 Mod 10 + &h30) As Char 'Int64への型変換は#117対策 x \= 10 i-- Wend Return i End Function /*! @author Egtra @date 2007/10/26 */ Function IntegerU_Prefix(x As QWord, flags As FormatFlags) As String End Function /*! @author Egtra @date 2007/10/28 */ Function IntegerD_Convert(buf As *Char, xq As QWord, flags As FormatFlags) As DWord Return IntegerU_Convert(buf, Abs((xq As DWord) As Long) As DWord, flags) End Function /*! @brief IntegerD_ConvertのInt64版 @author Egtra @date 2007/10/28 */ Function IntegerLD_Convert(buf As *Char, x As QWord, flags As FormatFlags) As DWord Return IntegerLU_Convert(buf, Abs(x As Int64) As QWord, flags) End Function /*! @author Egtra @date 2007/10/28 */ Function IntegerD_Prefix(x As QWord, flags As FormatFlags) As String If (x As Int64) < 0 Then IntegerD_Prefix = "-" ElseIf flags And Sign Then IntegerD_Prefix = "+" ElseIf flags And Blank Then IntegerD_Prefix = " " End If End Function /*! @brief QWordの最大値の八進法表現1777777777777777777777の文字数 - 1 + 1。IntegerO_Convert内で使用。 @author Egtra @date 2007/10/26 上の式で1を加えているのは、八進接頭辞の分。 */ Const MaxSizeLO = 22 /*! @author Egtra @date 2007/10/22 */ Dim TraitsIntegerO[1] As IntegerConvertTraits With TraitsIntegerO[0] .Convert = AddressOf(IntegerO_Convert) .Prefix = AddressOf(IntegerO_Prefix) End With With TraitsIntegerO[1] .Convert = AddressOf(IntegerLO_Convert) .Prefix = AddressOf(IntegerO_Prefix) End With /*! @brief 符号無し整数をprintfの%o(八進法表現)相当の変換で文字列化する関数。 @author Egtra @date 2007/10/19 @param[in] x 文字列化する整数値。 @param[in] d 精度、最小限表示される桁数。DWORD_MAXのとき、指定なしとして、既定値1となる。 @param[in] field フィールド幅。 @param[in] flags 書式フラグ。 @return xの文字列表現 */ Function FormatIntegerO(x As DWord, d As DWord, field As DWord, flags As FormatFlags) As String Return FormatIntegerEx(TraitsIntegerO[0], x, d, field, flags) End Function /*! @brief FormatIntegerOのQWord版。 @author Egtra @date 2007/10/26 */ Function FormatIntegerLO(x As QWord, d As DWord, field As DWord, flags As FormatFlags) As String Return FormatIntegerEx(TraitsIntegerO[1], x, d, field, flags) End Function /*! @author Egtra @date 2007/10/22 */ Function IntegerO_Convert(buf As *Char, xq As QWord, flags As FormatFlags) As DWord Dim x = xq As DWord Dim i = MaxSizeLO While x <> 0 buf[i] = ((x And &o7) + &h30) As Char x >>= 3 i-- Wend If flags And Alt Then buf[i] = &h30 i-- End If Return i End Function /*! @brief IntegerO_ConvertのQWord版。 @author Egtra @date 2007/10/26 */ Function IntegerLO_Convert(buf As *Char, x As QWord, flags As FormatFlags) As DWord Dim i = MaxSizeLO While x <> 0 buf[i] = ((x And &o7) + &h30) As Char x >>= 3 i-- Wend If flags And Alt Then buf[i] = &h30 i-- End If Return i End Function /*! @author Egtra @date 2007/10/22 @note #フラグ (Alt)の処理は、IntegerO/LO_Convert内で行うので、ここで処理することはない。 */ Function IntegerO_Prefix(x As QWord, flags As FormatFlags) As String If flags And BPrefix Then If x <> 0 Then IntegerO_Prefix = "&O" End If End If End Function /*! @author Egtra @date 2007/10/24 */ Dim TraitsIntegerX[1] As IntegerConvertTraits With TraitsIntegerX[0] .Convert = AddressOf(IntegerX_Convert) .Prefix = AddressOf(IntegerX_Prefix) End With With TraitsIntegerX[1] .Convert = AddressOf(IntegerLX_Convert) .Prefix = AddressOf(IntegerX_Prefix) End With /*! @brief 整数をprintfの%x, %X(十六進法)相当の変換で文字列化する関数。 @author Egtra @date 2007/10/19 @param[in] x 文字列化する整数値。 @param[in] d 精度、最小限表示される桁数。DWORD_MAXのとき、指定なしとして、既定値1となる。 @param[in] field フィールド幅。 @param[in] flags 書式フラグ。 @return xの文字列表現 */ Function FormatIntegerX(x As DWord, d As DWord, field As DWord, flags As FormatFlags) As String Return FormatIntegerEx(TraitsIntegerX[0], x, d, field, flags) End Function /*! @brief FormatIntegerXのQWord版。 @author Egtra @date 2007/10/22 */ Function FormatIntegerLX(x As QWord, d As DWord, field As DWord, flags As FormatFlags) As String Return FormatIntegerEx(TraitsIntegerX[1], x, d, field, flags) End Function /*! @brief FormatIntegerXのQWord, StringBuilder版。 @author Egtra @date 2008/03/07 */ Sub FormatIntegerLX(sb As System.Text.StringBuilder, x As QWord, d As DWord, field As DWord, flags As FormatFlags) FormatIntegerEx(sb, TraitsIntegerX[1], x, d, field, flags) End Sub /* @brief 0からFまでの文字を収めた表 @author egtra */ Dim HexadecimalTable[&h10] = [&h30, &h31, &h32, &h33, &h34, &h35, &h36, &h37, &h38, &h39, &h41, &h42, &h43, &h44, &h45, &h46] As Byte /*! @author Egtra @date 2007/10/22 */ Function IntegerX_Convert(buf As *Char, xq As QWord, flags As FormatFlags) As DWord Dim i = MaxSizeLO Dim x = xq As DWord While x <> 0 buf[i] = HexadecimalTable[x And &h0f] x >>= 4 i-- Wend Return i End Function /*! @brief IntegerX_ConvertのQWord版。 @author Egtra @date 2007/10/22 */ Function IntegerLX_Convert(buf As *Char, x As QWord, flags As FormatFlags) As DWord Dim i = MaxSizeLO While x <> 0 buf[i] = HexadecimalTable[x And &h0f] x >>= 4 i-- Wend Return i End Function /*! @author Egtra @date 2007/10/24 */ Function IntegerX_Prefix(x As QWord, flags As FormatFlags) As String If x <> 0 Then If flags And Alt Then IntegerX_Prefix = "0X" ElseIf flags And BPrefix Then IntegerX_Prefix = "&H" End If End If End Function /*! @brief FormatIntegerExへ渡す変換特性を表す構造体型。 @author Egtra @date 2007/10/22 FormatIntegerの都合上、このファイル内で宣言しているIntegerConvertTraits型の 変数は全て配列となっている;[0]が32ビット変換、[1]が64ビット変換である。 */ Type IntegerConvertTraits '!変換を行う関数へのポインタ。 Convert As *Function(buf As *Char, x As QWord, flags As FormatFlags) As DWord '!接頭辞を取得する関数へのポインタ。 Prefix As *Function(x As QWord, flags As FormatFlags) As String End Type /*! @brief 整数変換全てを行う関数。 @author Egtra @date 2007/10/22 @param[in] tr 特性情報。 @param[in] x 変換元の数値。 @param[in] d 精度。ここでは最低限出力する桁数。 @param[in] field フィールド幅。 @param[in] flags フラグ。 @return 変換された文字列 */ Function FormatIntegerEx(ByRef tr As IntegerConvertTraits, x As QWord, d As DWord, field As DWord, flags As FormatFlags) As String Dim sb = New System.Text.StringBuilder(32) FormatIntegerEx(sb, tr, x, d, field, flags) FormatIntegerEx = sb.ToString End Function /*! @brief 整数変換全てを行う関数。これを雛形とし、形式毎の差異はIntegerConvertTraitsで表現する。 @author Egtra @date 2008/03/06 @param[in,out] sb 書式化した文字列を追加するバッファ。 @param[in] tr 特性情報。 @param[in] x 変換元の数値。 @param[in] d 精度。ここでは最低限出力する桁数。 @param[in] field フィールド幅。 @param[in] flags フラグ。 */ Sub FormatIntegerEx(sb As System.Text.StringBuilder, ByRef tr As IntegerConvertTraits, x As QWord, d As DWord, field As DWord, flags As FormatFlags) If d = DWORD_MAX Then d = 1 Else '精度が指定されているとき、ゼロフラグは無視される。 '仕様上、左揃えのときも無視されるが、それはAdjustFieldWidthが行ってくれる。 flags And= Not Zero End If Dim lastLength = sb.Length With sb Dim prefixFunc = tr.Prefix Dim prefix = prefixFunc(x, flags) sb.Append(prefix) Dim prefixLen = 0 As DWord If String.IsNullOrEmpty(prefix) = False Then prefixLen = prefix.Length As DWord End If 'バッファの量は最も必要文字数の多くなるUInt64の8進法変換にあわせている Dim buf[MaxSizeLO] As Char Dim convertFunc = tr.Convert Dim bufStartPos = convertFunc(buf, x, flags) Dim len = (MaxSizeLO - bufStartPos) As Long If len < 0 Then Debug End If If len < d Then .Append(&h30 As Char, d - len) End If .Append(buf, bufStartPos + 1, len) AdjustFieldWidth(sb, field, flags And (Not (Sign Or Blank)), prefixLen, lastLength) AdjustAlphabet(sb, flags, lastLength) End With End Sub /*! @brief 浮動小数点数変換全てを行う関数。これを雛形とし、実際の変換関数は引数converterで与える。 @author Egtra @date 2008/03/07 @param[in,out] sb 書式化した文字列を追加するバッファ。 @param[in] converter 変換関数。 @param[in] x 変換元の数値。 @param[in] d 精度。ここでは最低限出力する桁数。 @param[in] field フィールド幅。 @param[in] flags フラグ。 */ Sub FormatFloatEx(sb As System.Text.StringBuilder, converter As FormatFloatProc, x As Double, precision As DWord, field As DWord, flags As FormatFlags) Dim lastLength = sb.Length If Math.IsNaN(x) Then sb.Append("NAN") AdjustAlphabet(sb, flags, lastLength) ElseIf Math.IsInf(x) Then AppendSign(sb, (GetQWord(VarPtr(x)) >> 63) As Boolean, flags) sb.Append("INFINITY") AdjustAlphabet(sb, flags, lastLength) Else converter(sb, x, precision, field, flags) End If AdjustFieldWidth(sb, field, flags, 0, lastLength) End Sub /*! @brief 浮動小数点数変換全てを行う関数。 @author Egtra @date 2008/03/08 @param[in] converter 変換関数。 @param[in] x 変換元の数値。 @param[in] d 精度。ここでは最低限出力する桁数。 @param[in] field フィールド幅。 @param[in] flags フラグ。 @return 変換された文字列。 */ Function FormatFloatEx(converter As FormatFloatProc, x As Double, precision As DWord, field As DWord, flags As FormatFlags) As String Dim sb = New System.Text.StringBuilder FormatFloatEx(sb, converter, x, precision, field, flags) FormatFloatEx = sb.ToString End Function /*! @brief 書式化の仕上げとして、Capフラグが指定されていないときに小文字化する作業を行う。 @author Egtra @date 2008/03/06 @param[in,out] sb 書式化した文字列を格納しているバッファ。 @param[in] flags フラグ。 @param[in] offset 書式変換した部分の開始位置。 */ Sub AdjustAlphabet(sb As System.Text.StringBuilder, flags As FormatFlags, offset As Long) If (flags And Cap) = 0 Then Dim len = sb.Length Dim i As Long For i = offset To ELM(len) sb[i] = CType.ToLower(sb[i]) Next End If End Sub /*! @brief 書式化の仕上げとして、変換部分がフィールド幅まで満たされるように空白などを挿入する。 @author Egtra @date 2007/10/13 @param[in,out] sb 対象文字列 @param[in] field フィールド幅 @param[in] hasSign 符号を持っている(負の値か)か否か @param[in] flags フラグ @param[in] prefixLen (あれば)接頭辞の文字数。ゼロ埋めする際、この数だけ挿入位置を後ろにする。 @param[in] offset 変換した部分へのオフセット。AppendではなくInsertを行う際に用いられる。 sbが"-1"のように負符号を持っている場合は、呼出元でSignフラグ(またはBlank)を立てること。 */ Sub AdjustFieldWidth(sb As System.Text.StringBuilder, field As DWord, flags As FormatFlags, prefixLen = 0 As DWord, offset = 0 As Long) With sb Dim len = .Length - offset If len < field Then Dim embeddedSize = field - len If flags And LeftSide Then .Append(&h20, embeddedSize) Else If (flags And Zero) <> 0 Then offset += prefixLen If (flags And Blank) Or (flags And Sign) Then offset++ End If .Insert(offset, String$(embeddedSize, "0")) Else .Insert(offset, String$(embeddedSize, " ")) End If End If End If End With End Sub /*! @brief 文字列をprintfの%s相当の変換で書式化する関数。 @author Egtra @date 2007/10/27 @param[in] x 文字列。 @param[in] d 精度、最大の文字数。 @param[in] field フィールド幅。 @param[in] flags 書式フラグ。 @return 書式化された文字列。 */ Function FormatString(x As String, d As DWord, field As DWord, flags As FormatFlags) As String Imports System Dim sb = New System.Text.StringBuilder( Math.Max(Math.Min(x.Length As DWord, d), field) As Long + 1) FormatString(sb, x, d, field, flags) AdjustFieldWidth(sb, field, flags And LeftSide) FormatString = sb.ToString() End Function /*! @brief 文字列をprintfの%s相当の変換で書式化する関数。 @author Egtra @date 2008/03/07 @param[in,out] sb 書式化した文字列を追加するバッファ。 @param[in] x 文字列。 @param[in] d 精度、最大の文字数。 @param[in] field フィールド幅。 @param[in] flags 書式フラグ。 @return 書式化された文字列。 */ Sub FormatString(sb As System.Text.StringBuilder, x As String, d As DWord, field As DWord, flags As FormatFlags) Dim len = sb.Length sb.Append(x, 0, System.Math.Min(x.Length As DWord, d) As Long) AdjustFieldWidth(sb, field, flags And LeftSide, 0, len) End Sub /*! @brief 文字をprintfの%c相当の変換で書式化する関数。 @author Egtra @date 2007/10/27 @param[in] x 文字。 @param[in] d 精度、最大の文字数。 @param[in] field フィールド幅。 @param[in] flags 書式フラグ。 @return 書式化された文字列。 */ Function FormatCharacter(x As Char, d As DWord, field As DWord, flags As FormatFlags) As String Dim sb = New System.Text.StringBuilder(field + 2) FormatCharacter(sb, x, d, field, flags) FormatCharacter = sb.ToString() End Function /*! @brief 文字列をprintfの%s相当の変換で書式化する関数。 @author Egtra @date 2008/03/07 @param[in,out] sb 書式化した文字列を追加するバッファ。 @param[in] x 文字。 @param[in] d 精度、最大の文字数。 @param[in] field フィールド幅。 @param[in] flags 書式フラグ。 @return 書式化された文字列。 */ Sub FormatCharacter(sb As System.Text.StringBuilder, x As Char, d As DWord, field As DWord, flags As FormatFlags) Dim len = sb.Length sb.Append(x) AdjustFieldWidth(sb, field, flags And LeftSide, 0, len) End Sub /*! @author Egtra @date 2007/10/28 */ TypeDef FormatFloatProc = *Sub(sb As System.Text.StringBuilder, x As Double, precision As DWord, fieldWidth As DWord, ByRef flags As FormatFlags) /*! @brief SPrintfから呼ばれる浮動小数点数用書式文字列化関数 @author Egtra @date 2007/10/28 */ Sub FormatFloat(s As System.Text.StringBuilder, formatProc As FormatFloatProc, param As Object, precision As DWord, field As DWord, flags As FormatFlags) Dim x As Double Dim typeName = param.GetType().FullName If typeName = "System.Double" Then x = param As System.Double ElseIf typeName = "System.Single" Then x = param As System.Single End If FormatFloatEx(s, formatProc, x, precision, field, flags) End Sub /*! @brief SPrintfから呼ばれる整数用書式文字列化関数 @author Egtra @date 2007/10/28 */ Sub FormatInteger(s As System.Text.StringBuilder, traits As *IntegerConvertTraits, param As Object, signed As Boolean, typeWidth As Long, precision As DWord, field As DWord, flags As FormatFlags) Dim x As QWord Dim typeName = param.GetType().FullName If typeName = "System.UInt64" Then x = param As System.UInt64 ElseIf typeName = "System.Int64" Then x = (param As System.Int64) As QWord ElseIf typeName = "System.UInt32" Then x = param As System.UInt32 ElseIf typeName = "System.Int32" Then x = (param As System.Int32) As QWord ElseIf typeName = "System.UInt16" Then x = param As System.UInt16 ElseIf typeName = "System.Int16" Then x = (param As System.Int16) As QWord ElseIf typeName = "System.UInt8" Then x = param As System.Byte ElseIf typeName = "System.Int8" Then x = (param As System.SByte) As QWord End If '一旦縮めた後、符号・ゼロ拡張させる。 'また、64ビット整数なら64ビット変換Traitsを選択する。 If signed Then If typeWidth = 1 Then traits = VarPtr(traits[1]) ElseIf typeWidth = 0 Then x = (((x As DWord) As Long) As Int64) As QWord ElseIf typeWidth = -1 Then x = (((x As Word) As Integer) As Int64) As QWord ElseIf typeWidth = -2 Then x = (((x As Byte) As SByte) As Int64) As QWord End If Else If typeWidth = 1 Then traits = VarPtr(traits[1]) ElseIf typeWidth = 0 Then x = x As DWord ElseIf typeWidth = -1 Then x = x As Word ElseIf typeWidth = -2 Then x = x As Byte End If End If FormatIntegerEx(s, ByVal traits, x, precision, field, flags) End Sub 'Format関数群ここまで '---- /*! @brief 文字列から数値への変換。さらに変換に使われなかった文字列の位置を返す。 @author Egtra @date 2007/11/11 @param[in] s 変換する文字 @param[out] p 変換に使われなかった部分の先頭を指すポインタ @return 変換して得られた数値。変換できなければ0。 */ Function StrToLong(s As *Char, ByRef p As *Char) As Long Dim negative As Boolean Dim i = 0 As Long If s[i] = &h2d Then 'Asc("-") i++ negative = True End If Do Dim c = s[i] If Not CType.IsDigit(c) Then Exit Do StrToLong *= 10 StrToLong += ((c As DWord) And &h0f) As Long i++ Loop If negative Then StrToLong = -StrToLong End If p = VarPtr(s[i]) End Function /*! @brief フィールド幅、精度用の数値読取 @author Egtra @date 2007/11/11 @param[in, out] fmt 読み途中の書式指定 @param[in] params @param[in, out] paramsCount @param[out] ret 読み取った数値。読み取られなかったときの値は不定。 @retval True 読取を行った @retval False 行わなかった fmt[0]が*のときにはparamsから1つ読み取る。 そうでなく、fmtに数字(先頭に-符号があっても可)が並んでいれば、それを読み取る。 */ Function ReadInt(ByRef fmt As *Char, params As *Object, ByRef paramsCount As SIZE_T, ByRef ret As Long) As Boolean If fmt[0] = &h2a Then '* fmt = VarPtr(fmt[1]) 'po ret = params[paramsCount] As System.Int32 paramsCount++ ReadInt = True Else Dim p As *Char ret = StrToLong(fmt, p) If fmt <> p Then fmt = p ReadInt = True Else ReadInt = False End If End If End Function /*! @brief フラグ指定の読み込み @author Egtra @date 2007/10/28 @param[in, out] fmt @param[out] flags @retval True 読み込みが完了した。 @retval False 読み取り中に文字列が終了した(ヌル文字が現れた)。 */ Function ReadFlags(ByRef fmt As *Char, ByRef flags As FormatFlags) As Boolean ReadFlags = False Do Select Case fmt[0] Case &h23 '# flags Or= Alt Case &h30 '0 flags Or= Zero Case &h20 '空白 flags Or= Blank Case &h2b '+ flags Or= Sign Case &h2d '- flags Or = LeftSide Case &h26 '& flags Or= BPrefix Case 0 Exit Function Case Else Exit Do End Select fmt = VarPtr(fmt[1]) 'po Loop ReadFlags = True End Function /*! @brief フィールド幅指定の読み込み @author Egtra @date 2007/10/29 @param[in, out] fmt @param[in] params @param[in, out] paramsCount @param[out] fieldWidth @param[in, out] flags */ Sub ReadFieldWidth(ByRef fmt As *Char, params As *Object, ByRef paramsCount As SIZE_T, ByRef fieldWidth As DWord, ByRef flags As FormatFlags) Dim t As Long If ReadInt(fmt, params, paramsCount, t) Then If t < 0 Then flags Or= LeftSide fieldWidth = -t As DWord Else fieldWidth = t As DWord End If Else fieldWidth = 0 End If End Sub /*! @brief 精度の読み込み @author Egtra @date 2007/10/29 @param[in, out] fmt @param[in] params @param[in, out] paramsCount @return 読み取った精度。指定がなかったときには、DWORD_MAX。 */ Function ReadPrecision(ByRef fmt As *Char, params As *Object, ByRef paramsCount As SIZE_T) As DWord If fmt[0] = &h2e Then '. fmt = VarPtr(fmt[1]) 'po Dim t As Long ReadPrecision = 0 If ReadInt(fmt, params, paramsCount, t) Then If t > 0 Then ReadPrecision = t As DWord End If End If Else ReadPrecision = DWORD_MAX End If End Function #ifdef _WIN64 Const PtrLength = 1 #else Const PtrLength = 0 #endif /*! @biref 長さ指定の読み込み @author Egtra @date 2007/10/29 @param[in, out] fmt @param[out] lengthSpec */ Sub ReadLength(ByRef fmt As *Char, ByRef lengthSpec As Long) Do Select Case fmt[0] Case &h6c 'l lengthSpec++ Case &h68 'h lengthSpec-- Case &h6a 'j (u)intmax_t = QWord, Int64 lengthSpec = 1 Case &h74 't ptrdiff_t lengthSpec = PtrLength Case &h7a 'z (s)size_t lengthSpec = PtrLength Case &h70 'p VoidPtr 本来は変換指定子だが、ここで先読み lengthSpec = PtrLength Exit Sub 'fmtを進められると困るので、ここで脱出 Case Else Exit Sub End Select fmt = VarPtr(fmt[1]) 'po Loop End Sub /*! @brief efg変換用に、精度が指定されていないときに既定の精度を設定する。 @auther Egtra @date 2008/03/07 */ Sub AdjustPrecision(ByRef precision As DWord) If precision = DWORD_MAX Then precision = 6 End If End Sub /*! @biref Cのsprintfのような書式文字列出力関数 @author Egtra @date 2007/10/27 @param[in] format 書式文字列。詳細は開発Wiki参照。 @param[in, out] params 変換対象の配列。n = 0のときにはNULLも可。 @param[in] n paramsの個数。 @return 書式化された文字列。 @todo %nへの対応 */ Function SPrintf(format As String, params As *Object, n As SIZE_T) As String Dim i = 0 As SIZE_T Dim paramsCount = 0 As SIZE_T Dim fmt = StrPtr(format) Dim s = New System.Text.StringBuilder Do Dim last = format.Length - (((fmt - StrPtr(format)) \ SizeOf (Char)) As LONG_PTR) As Long 'po Dim pos = ChrFind(fmt, last, &h25 As Char) As Long '&h25 = % If pos = -1 Then s.Append(fmt, 0, last) Exit Do End If '%以前の部分 s.Append(fmt, 0, pos) fmt = VarPtr(fmt[pos + 1]) 'po 'フラグの読取 Dim flags = None As FormatFlags If ReadFlags(fmt, flags) = False Then Exit Do End If 'フィールド幅 Dim fieldWidth As DWord ReadFieldWidth(fmt, params, i, fieldWidth, flags) '精度 Dim precision = ReadPrecision(fmt, params, i) '幅指定の読取 Dim typeWidth As Long ReadLength(fmt, typeWidth) Select Case fmt[0] Case &h64 'd FormatInteger(s, TraitsIntegerD, params[i], True, typeWidth, precision, fieldWidth, flags) Case &h69 'i FormatInteger(s, TraitsIntegerD, params[i], True, typeWidth, precision, fieldWidth, flags) Case &h75 'u FormatInteger(s, TraitsIntegerU, params[i], False, typeWidth, precision, fieldWidth, flags) Case &h4f 'O flags Or= Cap Goto *O Case &h6f 'o *O FormatInteger(s, TraitsIntegerO, params[i], False, typeWidth, precision, fieldWidth, flags) Case &h58 'X flags Or= Cap Goto *X Case &h78 'x *X FormatInteger(s, TraitsIntegerX, params[i], False, typeWidth, precision, fieldWidth, flags) '現状ではVoidPtrを引数にする手段は無いはず ' Case &h58 'p ' FormatInteger(s, TraitsIntegerX, params[i], False, typeWidth, precision, fieldWidth, flags Or Cap) Case &h45 'E flags Or= Cap Goto *E Case &h65 'e *E AdjustPrecision(precision) FormatFloat(s, AddressOf(FormatFloatE_Convert), params[i], precision, fieldWidth, flags) Case &h46 'F flags Or= Cap Goto *F Case &h66 'f *F AdjustPrecision(precision) FormatFloat(s, AddressOf(FormatFloatF_Convert), params[i], precision, fieldWidth, flags) Case &h47 'G flags Or= Cap Goto *G Case &h67 'g *G AdjustPrecision(precision) FormatFloat(s, AddressOf(FormatFloatG_Convert), params[i], precision, fieldWidth, flags) Case &h41 'A flags Or= Cap Goto *A Case &h61 'a *A FormatFloat(s, AddressOf(FormatFloatA), params[i], precision, fieldWidth, flags) Case &h73 's FormatString(s, params[i] As String, precision, fieldWidth, flags) Case &h63 'c FormatCharacter(s, params[i] As BoxedStrChar, precision, fieldWidth, flags) ' Case &h6e 'n Case &h25 '% s.Append(&h25 As Char) i-- Case 0 Exit Do End Select fmt = VarPtr(fmt[1]) 'po i++ Loop SPrintf = s.ToString End Function End Namespace 'Detail /*! @brief Cのsprintfのような書式化関数10引数版 @author Egtra @date 2007/10/27 @param[in] format 書式指定 @param[in] paramN 引数 @return 書式化された文字列 */ Function SPrintf(format As String, param0 As Object, param1 As Object, param2 As Object, param3 As Object, param4 As Object, param5 As Object, param6 As Object, param7 As Object, param8 As Object, param9 As Object) As String Dim params = VarPtr(param0) As *Object SPrintf = ActiveBasic.Strings.Detail.SPrintf(format, params, 10) End Function /*! @brief Cのsprintfのような書式化関数9引数版 @author Egtra @date 2007/10/27 @param[in] format 書式指定 @param[in] paramN 引数 @return 書式化された文字列 */ Function SPrintf(format As String, param0 As Object, param1 As Object, param2 As Object, param3 As Object, param4 As Object, param5 As Object, param6 As Object, param7 As Object, param8 As Object) As String Dim params = VarPtr(param0) As *Object SPrintf = ActiveBasic.Strings.Detail.SPrintf(format, params, 9) End Function /*! @brief Cのsprintfのような書式化関数8引数版 @author Egtra @date 2007/10/27 @param[in] format 書式指定 @param[in] paramN 引数 @return 書式化された文字列 */ Function SPrintf(format As String, param0 As Object, param1 As Object, param2 As Object, param3 As Object, param4 As Object, param5 As Object, param6 As Object, param7 As Object) As String Dim params = VarPtr(param0) As *Object SPrintf = ActiveBasic.Strings.Detail.SPrintf(format, params, 8) End Function /*! @brief Cのsprintfのような書式化関数7引数版 @author Egtra @date 2007/10/27 @param[in] format 書式指定 @param[in] paramN 引数 @return 書式化された文字列 */ Function SPrintf(format As String, param0 As Object, param1 As Object, param2 As Object, param3 As Object, param4 As Object, param5 As Object, param6 As Object) As String Dim params = VarPtr(param0) As *Object SPrintf = ActiveBasic.Strings.Detail.SPrintf(format, params, 7) End Function /*! @brief Cのsprintfのような書式化関数6引数版 @author Egtra @date 2007/10/27 @param[in] format 書式指定 @param[in] paramN 引数 @return 書式化された文字列 */ Function SPrintf(format As String, param0 As Object, param1 As Object, param2 As Object, param3 As Object, param4 As Object, param5 As Object) As String Dim params = VarPtr(param0) As *Object SPrintf = ActiveBasic.Strings.Detail.SPrintf(format, params, 6) End Function /*! @brief Cのsprintfのような書式化関数5引数版 @author Egtra @date 2007/10/27 @param[in] format 書式指定 @param[in] paramN 引数 @return 書式化された文字列 */ Function SPrintf(format As String, param0 As Object, param1 As Object, param2 As Object, param3 As Object, param4 As Object) As String Dim params = VarPtr(param0) As *Object SPrintf = ActiveBasic.Strings.Detail.SPrintf(format, params, 5) End Function /*! @brief Cのsprintfのような書式化関数4引数版 @author Egtra @date 2007/10/27 @param[in] format 書式指定 @param[in] paramN 引数 @return 書式化された文字列 */ Function SPrintf(format As String, param0 As Object, param1 As Object, param2 As Object, param3 As Object) As String Dim params = VarPtr(param0) As *Object SPrintf = ActiveBasic.Strings.Detail.SPrintf(format, params, 4) End Function /*! @brief Cのsprintfのような書式化関数3引数版 @author Egtra @date 2007/10/27 @param[in] format 書式指定 @param[in] paramN 引数 @return 書式化された文字列 */ Function SPrintf(format As String, param0 As Object, param1 As Object, param2 As Object) As String Dim params = VarPtr(param0) As *Object SPrintf = ActiveBasic.Strings.Detail.SPrintf(format, params, 3) End Function /*! @brief Cのsprintfのような書式化関数2引数版 @author Egtra @date 2007/10/27 @param[in] format 書式指定 @param[in] paramN 引数 @return 書式化された文字列 */ Function SPrintf(format As String, param0 As Object, param1 As Object) As String Dim params = VarPtr(param0) As *Object SPrintf = ActiveBasic.Strings.Detail.SPrintf(format, params, 2) End Function /*! @brief Cのsprintfのような書式化関数1引数版 @author Egtra @date 2007/10/27 @param[in] format 書式指定 @param[in] paramN 引数 @return 書式化された文字列 */ Function SPrintf(format As String, param0 As Object) As String Dim params = VarPtr(param0) As *Object SPrintf = ActiveBasic.Strings.Detail.SPrintf(format, params, 1) End Function /*! @brief Cのsprintfのような書式化関数0引数版 @author Egtra @date 2007/10/27 @param[in] format 書式指定 @param[in] paramN 引数 @return 書式化された文字列 */ Function SPrintf(format As String) As String SPrintf = ActiveBasic.Strings.Detail.SPrintf(format, 0, 0) End Function End Namespace 'Strings End Namespace 'ActiveBasic