Index: trunk/Include/Classes/ActiveBasic/Strings/SPrintF.ab
===================================================================
--- trunk/Include/Classes/ActiveBasic/Strings/SPrintF.ab	(revision 381)
+++ trunk/Include/Classes/ActiveBasic/Strings/SPrintF.ab	(revision 383)
@@ -102,4 +102,7 @@
 	Cap = &h20
 
+	'!BASIC接頭辞。&h, &oなど。
+	BPrefix = &h40
+
 	/*!
 	内部処理用に予約。
@@ -114,5 +117,5 @@
 @date	2007/09/18
 @param[in] x	文字列化する浮動小数点数値。
-@param[in] d	精度。小数点以下の桁数。DWORD_MAXのとき、指定なしとして既定値6となる。
+@param[in] precision	精度。小数点以下の桁数。DWORD_MAXのとき、指定なしとして既定値6となる。
 @param[in] field	フィールド幅。
 @param[in] flags	書式フラグ。
@@ -121,30 +124,49 @@
 @todo	他の実装での末尾桁の扱いを調べる（このコードでは何もしていないので切捨となっている）。
 */
-Function FormatFloatE(x As Double, d As DWord, field As DWord, flags As FormatFlags) As String
-	If d = DWORD_MAX Then
-		d = 6
+Function FormatFloatE(x As Double, precision As DWord, field As DWord, flags As FormatFlags) As String
+	If precision = DWORD_MAX Then
+		precision = 6
 	End If
 
 	Dim e As Long, negative As Boolean
 	Dim s = FloatToChars(x, e, negative)
-
-	Dim sb = New System.Text.StringBuilder
-	With sb
-
-		AppendSign(sb, negative, flags)
+	Dim sb = FormatFloatE_Base(s, negative, precision, flags)
+	FormatFloatE_Exponent(sb, e, flags)
+	AdjustFieldWidth(sb, field, flags)
+	FormatFloatE = sb.ToString()
+End Function
+
+/**
+@brief	FormatFloatEの符号・基数部の出力用。
+@author	Egtra
+@date	2007/10/27
+*/
+Function FormatFloatE_Base(s As String, negative As Boolean, precision As DWord, ByRef flags As FormatFlags) As System.Text.StringBuilder
+	FormatFloatE_Base = New System.Text.StringBuilder
+	With FormatFloatE_Base
+		AppendSign(FormatFloatE_Base, negative, flags)
 
 		.Append(s[0])
 
-		If (flags And Alt) Or d > 0 Then
+		If (flags And Alt) Or precision > 0 Then
 			.Append(".")
 			Dim outputLen = s.Length - 1
-			If outputLen >= d Then
-				.Append(s, 1, d)
+			If outputLen >= precision Then
+				.Append(s, 1, precision)
 			Else 'sで用意された桁が指定された精度より少ないとき
 				.Append(s, 1, outputLen)
-				.Append(&h30 As StrChar, d - outputLen) '足りない桁は0埋め
+				.Append(&h30 As StrChar, precision - outputLen) '足りない桁は0埋め
 			End If
 		End If
-
+	End With
+End Function
+
+/**
+@brief	FormatFloatEの指数部の出力用。
+@author	Egtra
+@date	2007/10/27
+*/
+Sub FormatFloatE_Exponent(buf As System.Text.StringBuilder, e As Long, flags As FormatFlags)
+	With buf
 		If flags And Cap Then
 			.Append("E")
@@ -152,11 +174,7 @@
 			.Append("e")
 		End If
-
 		.Append(FormatIntegerD(e, 2, 0, Sign Or Zero))
-
-		AdjustFieldWidth(sb, field, flags)
 	End With
-	FormatFloatE = sb.ToString()
-End Function
+End Sub
 
 /*!
@@ -177,8 +195,17 @@
 	Dim e As Long, negative As Boolean
 	Dim s = FloatToChars(x, e, negative)
-
-	Dim sb = New System.Text.StringBuilder
-	With sb
-		AppendSign(sb, negative, flags)
+	Dim sb = FormatFloatF_Core(s, e, negative, precision, flags)
+	AdjustFieldWidth(sb, field, flags)
+	FormatFloatF = sb.ToString()
+End Function
+
+/**
+@author	Egtra
+@date	2007/10/27
+*/
+Function FormatFloatF_Core(s As String, e As Long, negative As Boolean, precision As DWord, ByRef flags As FormatFlags) As System.Text.StringBuilder
+	FormatFloatF_Core = New System.Text.StringBuilder
+	With FormatFloatF_Core
+		AppendSign(FormatFloatF_Core, negative, flags)
 
 		Dim intPartLen = e + 1
@@ -215,7 +242,144 @@
 			End If
 		End If
-		AdjustFieldWidth(sb, field, flags)
 	End With
-	FormatFloatF = sb.ToString()
+End Function
+
+/*!
+@brief	浮動小数点数をprintfの%g, %G（小数・指数、十進法）相当の変換で文字列化する関数。
+@author	Egtra
+@date	2007/10/23
+@param[in]	x	文字列化する浮動小数点数値。
+@param[in]	precision	精度。小数点以下の桁数。DWORD_MAXまたは0のとき、指定なしとして既定値6となる。
+@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
+	'GではE/Fと違い整数部も有効桁数に数えるのでその分を引いておく。
+	If precision = DWORD_MAX Or precision = 0 Then
+		precision = 5
+	Else
+		precision--
+	End If
+
+	Dim e As Long, negative As Boolean
+	Dim s = FloatToChars(x, e, negative)
+
+	Dim sb = Nothing As System.Text.StringBuilder
+
+	If -5 < e And e < precision Then
+		sb = FormatFloatF_Core(s, e, negative, -e + precision, flags)
+		FormatFloatG_RemoveLowDigit(sb, flags)
+	Else
+		sb = FormatFloatE_Base(s, negative, precision, flags)
+		FormatFloatG_RemoveLowDigit(sb, flags)
+		FormatFloatE_Exponent(sb, e, flags)
+	End If
+
+	AdjustFieldWidth(sb, field, flags)
+	FormatFloatG = sb.ToString()
+End Function
+
+/*!
+@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, flags As FormatFlags)
+	Imports ActiveBasic.Strings
+	
+	Dim count = sb.Length
+	If (flags And Alt) = 0 Then
+		Dim point = ChrFind(StrPtr(sb), count 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
+	If precision = DWORD_MAX Then
+		precision = 13
+	End If
+
+	Dim pqw = VarPtr(x) As *QWord
+
+	Dim sb = New System.Text.StringBuilder
+	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 base = FormatIntegerLX(GetQWord(pqw) And &h000fffffffffffff, 13, 0, flags And Cap)
+			Dim diff = precision - 13 As Long
+			If diff <= 0 Then
+				.Append(Left$(base, precision))
+			Else
+				.Append(base).Append(&h30, diff)
+			End If
+		End If
+
+		FormatFloatG_RemoveLowDigit(sb, flags)
+
+		.Append("P")
+		.Append(FormatIntegerD(exp, 1, 0, Sign))
+		
+		FormatFloatA = .ToString()
+	End With
+
+	If (flags And Cap) = 0 Then
+		FormatFloatA = FormatFloatA.ToLower()
+	End If
 End Function
 
@@ -261,5 +425,5 @@
 */
 Function FormatIntegerU(x As DWord, d As DWord, field As DWord, flags As FormatFlags) As String
-	Return FormatIntegerEx(TraitsIntegerDU, x, d, field, flags And (Not (Sign Or Blank)))
+	Return FormatIntegerEx(TraitsIntegerU[0], x, d, field, flags And (Not (Sign Or Blank)))
 End Function
 
@@ -270,5 +434,5 @@
 */
 Function FormatIntegerLU(x As QWord, d As DWord, field As DWord, flags As FormatFlags) As String
-	Return FormatIntegerEx(TraitsIntegerLDU, x, d, field, flags And (Not (Sign Or Blank)))
+	Return FormatIntegerEx(TraitsIntegerU[1], x, d, field, flags And (Not (Sign Or Blank)))
 End Function
 
@@ -284,13 +448,5 @@
 */
 Function FormatIntegerD(x As Long, d As DWord, field As DWord, flags As FormatFlags) As String
-	Dim unsignedX As DWord
-	If x < 0 Then
-		unsignedX = (-x) As DWord
-		flags Or= Minus
-	Else
-		unsignedX = x As DWord
-	End If
-
-	Return FormatIntegerEx(TraitsIntegerDU, unsignedX, d, field, flags)
+	Return FormatIntegerEx(TraitsIntegerD[0], (x As Int64) As QWord, d, field, flags)
 End Function
 
@@ -301,13 +457,5 @@
 */
 Function FormatIntegerLD(x As Int64, d As DWord, field As DWord, flags As FormatFlags) As String
-	Dim unsignedX As QWord
-	If x < 0 Then
-		unsignedX = (-x) As QWord
-		flags Or= Minus
-	Else
-		unsignedX = x As QWord
-	End If
-
-	Return FormatIntegerEx(TraitsIntegerLDU, unsignedX, d, field, flags)
+	Return FormatIntegerEx(TraitsIntegerD[1], x As QWord, d, field, flags)
 End Function
 
@@ -316,23 +464,35 @@
 @date	2007/10/26
 */
-Dim TraitsIntegerDU As IntegerConvertTraits
-With TraitsIntegerDU
-	.Convert = AddressOf(IntegerDU_Convert)
-	.Prefix = AddressOf(IntegerDU_Prefix)
+Dim TraitsIntegerU[1] As IntegerConvertTraits
+With TraitsIntegerU[0]
+	.Convert = AddressOf(IntegerU_Convert)
+	.Prefix = AddressOf(IntegerU_Prefix)
 	.MaxSize = MaxSizeU
 End With
 
-/*!
-@author	Egtra
-@date	2007/10/26
-*/
-Dim TraitsIntegerLDU As IntegerConvertTraits
-With TraitsIntegerLDU
-	.Convert = AddressOf(IntegerLDU_Convert)
-	.Prefix = AddressOf(IntegerDU_Prefix)
+With TraitsIntegerU[1]
+	.Convert = AddressOf(IntegerLU_Convert)
+	.Prefix = AddressOf(IntegerU_Prefix)
 	.MaxSize = MaxSizeLU
 End With
 
 /*!
+@author	Egtra
+@date	2007/10/28
+*/
+Dim TraitsIntegerD[1] As IntegerConvertTraits
+With TraitsIntegerD[0]
+	.Convert = AddressOf(IntegerD_Convert)
+	.Prefix = AddressOf(IntegerD_Prefix)
+	.MaxSize = MaxSizeU
+End With
+
+With TraitsIntegerD[1]
+	.Convert = AddressOf(IntegerLD_Convert)
+	.Prefix = AddressOf(IntegerD_Prefix)
+	.MaxSize = MaxSizeLU
+End With
+
+/*!
 @brief	負数を表すフラグ。FormatIntegerD, LDからIntegerDU_Prefixまでの内部処理用。
 @author	Egtra
@@ -345,5 +505,5 @@
 @date	2007/10/26
 */
-Function IntegerDU_Convert(buf As *StrChar, xq As QWord, flags As FormatFlags) As DWord
+Function IntegerU_Convert(buf As *StrChar, xq As QWord, flags As FormatFlags) As DWord
 	Dim x = xq As DWord
 	Dim i = MaxSizeU
@@ -357,10 +517,10 @@
 
 /*!
-@brief	IntegerDU_ConvertのQWord版
+@brief	IntegerU_ConvertのQWord版
 @author	Egtra
 @date	2007/10/26
 @bug	#117のため、現在Int64の最大値を超える値を正しく処理できない。
 */
-Function IntegerLDU_Convert(buf As *StrChar, x As QWord, flags As FormatFlags) As DWord
+Function IntegerLU_Convert(buf As *StrChar, x As QWord, flags As FormatFlags) As DWord
 	Dim i = MaxSizeLU
 	While x <> 0
@@ -376,11 +536,35 @@
 @date	2007/10/26
 */
-Function IntegerDU_Prefix(x As QWord, flags As FormatFlags) As String
-	If flags And Minus Then
-		IntegerDU_Prefix = "-"
+Function IntegerU_Prefix(x As QWord, flags As FormatFlags) As String
+End Function
+
+/*!
+@author	Egtra
+@date	2007/10/28
+*/
+Function IntegerD_Convert(buf As *StrChar, 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 *StrChar, 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
-		IntegerDU_Prefix = "+"
+		IntegerD_Prefix = "+"
 	ElseIf flags And Blank Then
-		IntegerDU_Prefix = " "
+		IntegerD_Prefix = " "
 	End If
 End Function
@@ -406,6 +590,6 @@
 @date	2007/10/22
 */
-Dim TraitsIntegerO As IntegerConvertTraits
-With TraitsIntegerO
+Dim TraitsIntegerO[1] As IntegerConvertTraits
+With TraitsIntegerO[0]
 	.Convert = AddressOf(IntegerO_Convert)
 	.Prefix = AddressOf(IntegerO_Prefix)
@@ -413,10 +597,5 @@
 End With
 
-/*!
-@author	Egtra
-@date	2007/10/26
-*/
-Dim TraitsIntegerLO As IntegerConvertTraits
-With TraitsIntegerLO
+With TraitsIntegerO[1]
 	.Convert = AddressOf(IntegerLO_Convert)
 	.Prefix = AddressOf(IntegerO_Prefix)
@@ -435,5 +614,5 @@
 */
 Function FormatIntegerO(x As DWord, d As DWord, field As DWord, flags As FormatFlags) As String
-	Return FormatIntegerEx(TraitsIntegerO, x, d, field, flags)
+	Return FormatIntegerEx(TraitsIntegerO[0], x, d, field, flags)
 End Function
 
@@ -444,5 +623,5 @@
 */
 Function FormatIntegerLO(x As QWord, d As DWord, field As DWord, flags As FormatFlags) As String
-	Return FormatIntegerEx(TraitsIntegerLO, x, d, field, flags)
+	Return FormatIntegerEx(TraitsIntegerO[1], x, d, field, flags)
 End Function
 
@@ -491,4 +670,9 @@
 */
 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
 
@@ -511,6 +695,6 @@
 @date	2007/10/24
 */
-Dim TraitsIntegerX As IntegerConvertTraits
-With TraitsIntegerX
+Dim TraitsIntegerX[1] As IntegerConvertTraits
+With TraitsIntegerX[0]
 	.Convert = AddressOf(IntegerX_Convert)
 	.Prefix = AddressOf(IntegerX_Prefix)
@@ -518,10 +702,5 @@
 End With
 
-/*!
-@author	Egtra
-@date	2007/10/26
-*/
-Dim TraitsIntegerLX As IntegerConvertTraits
-With TraitsIntegerLX
+With TraitsIntegerX[1]
 	.Convert = AddressOf(IntegerLX_Convert)
 	.Prefix = AddressOf(IntegerX_Prefix)
@@ -540,5 +719,5 @@
 */
 Function FormatIntegerX(x As DWord, d As DWord, field As DWord, flags As FormatFlags) As String
-	Return FormatIntegerEx(TraitsIntegerX, x, d, field, flags)
+	Return FormatIntegerEx(TraitsIntegerX[0], x, d, field, flags)
 End Function
 
@@ -549,5 +728,5 @@
 */
 Function FormatIntegerLX(x As QWord, d As DWord, field As DWord, flags As FormatFlags) As String
-	Return FormatIntegerEx(TraitsIntegerLX, x, d, field, flags)
+	Return FormatIntegerEx(TraitsIntegerX[1], x, d, field, flags)
 End Function
 
@@ -587,7 +766,9 @@
 */
 Function IntegerX_Prefix(x As QWord, flags As FormatFlags) As String
-	If flags And Alt Then
-		If x <> 0 Then
+	If x <> 0 Then
+		If flags And Alt Then
 			IntegerX_Prefix = "0X"
+		ElseIf flags And BPrefix Then
+			IntegerX_Prefix = "&H"
 		End If
 	End If
@@ -598,4 +779,7 @@
 @author	Egtra
 @date	2007/10/22
+
+FormatIntegerの都合上、このファイル内で宣言しているIntegerConvertTraits型の
+変数は全て配列となっている；[0]が32ビット変換、[1]が64ビット変換である。
 */
 Type IntegerConvertTraits
@@ -701,5 +885,595 @@
 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
+	Dim sb = New System.Text.StringBuilder(
+		x, 0, System.Math.Min(x.Length As DWord, d) As Long, field)
+	AdjustFieldWidth(sb, field, flags And Left)
+	FormatString = sb.ToString()
+End Function
+
+/*!
+@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 StrChar, d As DWord, field As DWord, flags As FormatFlags) As String
+	Dim sb = New System.Text.StringBuilder(field + 1)
+	sb.Append(x)
+	AdjustFieldWidth(sb, field, flags And Left)
+	FormatCharacter = sb.ToString()
+End Function
+
+/*!
+@author	Egtra
+@date	2007/10/28
+*/
+TypeDef FormatFloatProc = *Function(x As Double, precision As DWord, fieldWidth As DWord, flags As FormatFlags) As String
+
+/*!
+@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
+	s.Append(formatProc(x, precision, field, flags))
+End Sub
+
+/*!
+@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
+
+	s.Append(FormatIntegerEx(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 *StrChar, ByRef p As *StrChar) 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 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] c	調べる文字
+@retval True	0から9の文字である
+@retval False	そうでない
+*/
+Function IsDigit(c As StrChar) As Boolean
+	Dim dw = (c As DWord)
+	IsDigit = (dw - &h30) < 10
+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 *StrChar, params As *Object, ByRef paramsCount As SIZE_T, ByRef ret As Long) As Boolean
+	If fmt[0] = &h2a Then '*
+		fmt++ 'p
+		ret = params[paramsCount] As System.Int32
+		paramsCount++
+		ReadInt = True
+	Else
+		Dim p As PSTR
+		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 *StrChar, 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 = Left
+			Case &h26 '&
+				flags Or= BPrefix
+			Case 0
+				Exit Function
+			Case Else
+				Exit Do
+		End Select
+		fmt++ 'p
+	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 *StrChar, 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= Left
+			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 *StrChar,
+	params As *Object, ByRef paramsCount As SIZE_T) As DWord
+
+	If fmt[0] = &h2e Then '.
+		fmt++
+		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
+
+/*!
+@biref	長さ指定の読み込み
+@author	Egtra
+@date	2007/10/29
+@param[in, out] fmt
+@param[out] lengthSpec
+*/
+Sub ReadLength(ByRef fmt As *StrChar, ByRef lengthSpec As Long)
+	Do
+		Select Case fmt[0]
+			Case &h6c 'l
+				lengthSpec++
+			Case &h68 'h
+				lengthSpec--
+			Case &h6a 'j (u)intmax_t
+				lengthSpec = 1
+#ifdef _WIN64
+			Case &h74 't ptrdiff_t
+				lengthSpec = 1
+			Case &h7a 'z (s)size_t,
+				lengthSpec = 1
+#else
+			Case &h74 't ptrdiff_t
+				lengthSpec = 0
+			Case &h7a 'z (s)size_t,
+				lengthSpec = 0
+#endif
+			Case Else
+				Exit Sub
+		End Select
+		fmt++ 'p
+	Loop
+End Sub
+
+/*!
+@author	Egtra
+@date	2007/10/27
+@todo	%nへの対応
+*/
+Function SPrintf(format As String, params As *Object, n As SIZE_T) As String
+	Dim i = 0 As DWord
+	Dim paramsCount = 0 As SIZE_T
+	Dim fmt = StrPtr(format)
+	Dim s = New System.Text.StringBuilder
+	Do
+		Dim last = format.Length - (fmt - StrPtr(format)) As Long 'p
+		Dim pos = ActiveBasic.Strings.ChrFind(fmt, last, &h25 As StrChar) '&h25 = %
+		If pos = -1 Then
+			s.Append(fmt, 0, last)
+			Exit Do
+		End If
+		'%以前の部分
+		s.Append(fmt, 0, pos)
+		fmt += pos + 1 'p
+		'フラグの読取
+		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 &h6f 'o
+				FormatInteger(s, TraitsIntegerO, params[i], False, typeWidth, precision, fieldWidth, flags)
+			Case &h4f 'O
+				FormatInteger(s, TraitsIntegerO, params[i], False, typeWidth, precision, fieldWidth, flags Or Cap)
+			Case &h78 'x
+				FormatInteger(s, TraitsIntegerX, params[i], False, typeWidth, precision, fieldWidth, flags)
+			Case &h58 'X
+				FormatInteger(s, TraitsIntegerX, params[i], False, typeWidth, precision, fieldWidth, flags Or Cap)
+			Case &h65 'e
+				FormatFloat(s, AddressOf(FormatFloatE), params[i], precision, fieldWidth, flags)
+			Case &h45 'E
+				FormatFloat(s, AddressOf(FormatFloatE), params[i], precision, fieldWidth, flags Or Cap)
+			Case &h66 'f
+				FormatFloat(s, AddressOf(FormatFloatF), params[i], precision, fieldWidth, flags)
+			Case &h46 'F
+				FormatFloat(s, AddressOf(FormatFloatF), params[i], precision, fieldWidth, flags Or Cap)
+			Case &h67 'g
+				FormatFloat(s, AddressOf(FormatFloatG), params[i], precision, fieldWidth, flags)
+			Case &h47 'G
+				FormatFloat(s, AddressOf(FormatFloatG), params[i], precision, fieldWidth, flags Or Cap)
+			Case &h61 'a
+				FormatFloat(s, AddressOf(FormatFloatA), params[i], precision, fieldWidth, flags)
+			Case &h41 'A
+				FormatFloat(s, AddressOf(FormatFloatA), params[i], precision, fieldWidth, flags Or Cap)
+			Case &h73 's
+				s.Append(FormatString(params[i] As String, precision, fieldWidth, flags))
+			Case &h63 'c
+				s.Append(FormatCharacter(params[i] As BoxedStrChar, precision, fieldWidth, flags))
+'			Case &h6e 'n
+			Case &h25 '%
+				s.Append(&h25 As StrChar)
+				i--
+			Case 0
+				Exit Do
+		End Select
+		fmt++ 'p
+		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
+#ifdef _WIN64
+	'コンパイラがどういうコードを吐くのかわからないので、安全策を取る。
+	Dim params[9] = [param0, param1, param2, param3, param4,
+		param5, param6, param7, param8, param9] As Object
+#else
+	Dim params = VarPtr(param0) As *Object
+#endif
+	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
+#ifdef _WIN64
+	Dim params[8] = [param0, param1, param2, param3, param4,
+		param5, param6, param7, param8] As Object
+#else
+	Dim params = VarPtr(param0) As *Object
+#endif
+	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
+#ifdef _WIN64
+	Dim params[7] = [param0, param1, param2, param3, param4,
+		param5, param6, param7] As Object
+#else
+	Dim params = VarPtr(param0) As *Object
+#endif
+	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
+#ifdef _WIN64
+	Dim params[6] = [param0, param1, param2, param3, param4,
+		param5, param6] As Object
+#else
+	Dim params = VarPtr(param0) As *Object
+#endif
+	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
+#ifdef _WIN64
+	Dim params[5] = [param0, param1, param2, param3, param4,
+		param5] As Object
+#else
+	Dim params = VarPtr(param0) As *Object
+#endif
+	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
+#ifdef _WIN64
+	Dim params[4] = [param0, param1, param2, param3, param4] As Object
+#else
+	Dim params = VarPtr(param0) As *Object
+#endif
+	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
+#ifdef _WIN64
+	Dim params[3] = [param0, param1, param2, param3] As Object
+#else
+	Dim params = VarPtr(param0) As *Object
+#endif
+	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
+#ifdef _WIN64
+	Dim params[2] = [param0, param1, param2] As Object
+#else
+	Dim params = VarPtr(param0) As *Object
+#endif
+	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
+#ifdef _WIN64
+	Dim params[1] = [param0, param1] As Object
+#else
+	Dim params = VarPtr(param0) As *Object
+#endif
+	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
Index: trunk/Include/Classes/ActiveBasic/Strings/Strings.ab
===================================================================
--- trunk/Include/Classes/ActiveBasic/Strings/Strings.ab	(revision 381)
+++ trunk/Include/Classes/ActiveBasic/Strings/Strings.ab	(revision 383)
@@ -11,15 +11,17 @@
 
 Sub ChrFill(p As PWSTR, n As SIZE_T, c As WCHAR)
-	Dim i As SIZE_T
-	For i = 0 To ELM(n)
+	Dim i = 0 As SIZE_T
+	While i <> n
 		p[i] = c
-	Next
+		i++
+	Wend
 End Sub
 
 Sub ChrFill(p As PSTR, n As SIZE_T, c As SByte)
-	Dim i As SIZE_T
-	For i = 0 To ELM(n)
+	Dim i = 0 As SIZE_T
+	While i <> n
 		p[i] = c
-	Next
+		i++
+	Wend
 End Sub
 
@@ -105,40 +107,44 @@
 
 Function ChrPBrk(str As PCWSTR, cStr As SIZE_T, chars As PCWSTR, cChars As SIZE_T) As SIZE_T
-	Dim i As SIZE_T
-	For i = 0 To ELM(cStr)
+	Dim i = 0 As SIZE_T
+	While i <> cStr
 		If ChrFind(chars, cChars, str[i]) <> -1 Then
 			Return i
 		End If
-	Next
+		i++
+	Wend
 	Return -1 As SIZE_T
 End Function
 
 Function ChrPBrk(str As PCSTR, cStr As SIZE_T, Chars As PCSTR, cChars As SIZE_T) As SIZE_T
-	Dim i As SIZE_T
-	For i = 0 To ELM(cStr)
+	Dim i = 0 As SIZE_T
+	While i <> cStr
 		If ChrFind(Chars, cChars, str[i]) <> -1 Then
 			Return i
 		End If
-	Next
+		i++
+	Wend
 	Return -1 As SIZE_T
 End Function
 
 Function ChrFind(s As PCWSTR, size As SIZE_T, c As WCHAR) As SIZE_T
-	Dim i As SIZE_T
-	For i = 0 To ELM(size)
+	Dim i = 0 As SIZE_T
+	While i <> size
 		If s[i] = c Then
 			Return i
 		End If
-	Next
+		i++
+	Wend
 	Return -1 As SIZE_T
 End Function
 
 Function ChrFind(s As PCSTR, size As SIZE_T, c As CHAR) As SIZE_T
-	Dim i As SIZE_T
-	For i = 0 To ELM(size)
+	Dim i = 0 As SIZE_T
+	While i <> size
 		If s[i] = c Then
 			Return i
 		End If
-	Next
+		i++
+	Wend
 	Return -1 As SIZE_T
 End Function
@@ -210,4 +216,5 @@
 	Loop
 End Function
+
 End Namespace 'Detail
 
Index: trunk/Include/Classes/System/String.ab
===================================================================
--- trunk/Include/Classes/System/String.ab	(revision 381)
+++ trunk/Include/Classes/System/String.ab	(revision 383)
@@ -6,11 +6,18 @@
 
 #ifdef __STRING_IS_NOT_ALWAYS_UNICODE
+
+#ifndef UNICODE
 TypeDef StrChar = Char
-#ifndef UNICODE
 #define __STRING_IS_NOT_UNICODE
 #endif
+
+#endif
+
+#ifndef __STRING_IS_NOT_UNICODE
+TypeDef StrChar = WCHAR
+
+#ifdef UNICODE
+#define __STRING_IS_UNICODE
 #else
-TypeDef StrChar = WCHAR
-#ifndef UNICODE
 #define __STRING_UNICODE_WINDOWS_ANSI
 #endif
@@ -77,5 +84,5 @@
 			Assign(initStr + start, length)
 		End Sub
-		
+
 		Sub String(initStr As String)
 			If Not String.IsNullOrEmpty(initStr) Then
@@ -592,5 +599,5 @@
 			End If
 		End Sub
-		
+
 		Const Sub rangeCheck(start As Long, length As Long)
 			If start < 0 Or start > This.m_Length Or length < 0 Then
Index: trunk/Include/Classes/System/Text/StringBuilder.ab
===================================================================
--- trunk/Include/Classes/System/Text/StringBuilder.ab	(revision 381)
+++ trunk/Include/Classes/System/Text/StringBuilder.ab	(revision 383)
@@ -520,5 +520,5 @@
 		If Not String.IsNullOrEmpty(s) Then
 			s.CopyTo(startIndex, chars, 0, length)
-			size = s.Length
+			size = length
 		End If
 	End Sub
