Changeset 468 for trunk/Include/Classes/ActiveBasic/Strings
- Timestamp:
- Mar 9, 2008, 12:00:01 PM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Include/Classes/ActiveBasic/Strings/SPrintF.ab
r457 r468 1 'Classes/ActiveBasic/Strings/SPrintF.ab 1 /*! 2 @file Include/Classes/ActiveBasic/Strings/SPrintF.ab 3 @brief SPrintfとその補助ルーチンが含まれるファイル。 4 5 SPrintfで数値変換が行われるとき、呼出の階層は、 6 SPrintf→FormatInteger, FormatFloat→FormatIntegerEx, FormatFloatExとなる。 7 8 また、次のような変換ルーチンが存在する。 9 @li FormatFloatE 10 @li FormatFloatF 11 @li FormatFloatG 12 @li FormatFloatA 13 @li FormatIntegerD 14 @li FormatIntegerU 15 @li FormatIntegerO 16 @li FormatIntegerX 17 @li FormatCharacter 18 @li FormatString 19 */ 2 20 3 21 Namespace ActiveBasic … … 92 110 LeftSide = &h8 93 111 /*! 代替表記、#。 94 <ul> 95 <li>[OoXx]では、値が0でない場合、先頭に0、0xを付ける。</ul> 96 <li>[AaEeFfGg]では、精度0でも小数点を付ける。</ul> 97 <li>[Gg]では、それに加え、小数部末尾の0の省略を行わないようにする。</ul> 98 </ul> 112 @li [OoXx]では、値が0でない場合、先頭に0、0xを付ける。</ul> 113 @li [AaEeFfGg]では、精度0でも小数点を付ける。</ul> 114 @li [Gg]では、それに加え、小数部末尾の0の省略を行わないようにする。</ul> 99 115 */ 100 116 Alt = &h10 … … 121 137 @param[in] flags 書式フラグ。 122 138 @return xの文字列表現 123 139 */ 140 Function FormatFloatE(x As Double, precision As DWord, field As DWord, flags As FormatFlags) As String 141 FormatFloatE = FormatFloatEx(AddressOf(FormatFloatE_Convert), x, precision, field, flags) 142 End Function 143 144 /* 145 @brief 浮動小数点数をprintfの%e, %E(指数形式、十進法)相当の変換で文字列化する関数。 146 @author Egtra 147 @date 2008/03/08 148 @param[in,out] sb 書式化した文字列を追加するバッファ。 149 @param[in] x 文字列化する浮動小数点数値。 150 @param[in] precision 精度。小数点以下の桁数。DWORD_MAXのとき、指定なしとして既定値6となる。 151 @param[in] field フィールド幅。 152 @param[in] flags 書式フラグ。 153 */ 154 Sub FormatFloatE(sb As System.Text.StringBuilder, x As Double, precision As DWord, field As DWord, ByRef flags As FormatFlags) 155 FormatFloatEx(sb, AddressOf(FormatFloatE_Convert), x, precision, field, flags) 156 End Sub 157 158 /*! 159 @brief 浮動小数点数をprintfの%e, %E(指数形式、十進法)相当の変換で文字列化する関数。 160 @author Egtra 161 @date 2008/03/07 162 @param[in,out] sb 書式化した文字列を追加するバッファ。 163 @param[in] x 文字列化する浮動小数点数値。 164 @param[in] precision 精度。小数点以下の桁数。DWORD_MAXのとき、指定なしとして15となる。 165 @param[in] field フィールド幅。 166 @param[in,out] flags 書式フラグ。 124 167 @todo 他の実装での末尾桁の扱いを調べる(このコードでは何もしていないので切捨となっている)。 125 168 */ 126 Function FormatFloatE(x As Double, precision As DWord, field As DWord, flags As FormatFlags) As String 169 Sub FormatFloatE_Convert(sb As System.Text.StringBuilder, x As Double, precision As DWord, field As DWord, ByRef flags As FormatFlags) 127 170 If precision = DWORD_MAX Then 128 precision = 6 129 End If 130 171 precision = 15 172 End If 131 173 Dim e As Long, negative As Boolean 132 174 Dim s = FloatToChars(x, e, negative) 133 Dim sb = FormatFloatE_Base(s, negative, precision, flags)175 FormatFloatE_Base(sb, s, negative, precision, flags) 134 176 FormatFloatE_Exponent(sb, e, flags) 135 AdjustFieldWidth(sb, field, flags) 136 FormatFloatE = sb.ToString() 137 End Function 177 End Sub 138 178 139 179 /** … … 142 182 @date 2007/10/27 143 183 */ 144 Function FormatFloatE_Base(s As String, negative As Boolean, precision As DWord, ByRef flags As FormatFlags) As System.Text.StringBuilder 145 FormatFloatE_Base = New System.Text.StringBuilder 146 With FormatFloatE_Base 147 AppendSign(FormatFloatE_Base, negative, flags) 148 184 Sub FormatFloatE_Base(sb As System.Text.StringBuilder, s As String, negative As Boolean, precision As DWord, ByRef flags As FormatFlags) 185 With sb 186 AppendSign(sb, negative, flags) 149 187 .Append(s[0]) 150 151 188 If (flags And Alt) Or precision > 0 Then 152 189 .Append(".") … … 156 193 Else 'sで用意された桁が指定された精度より少ないとき 157 194 .Append(s, 1, outputLen) 158 .Append(&h30 As StrChar, precision - outputLen) '足りない桁は0埋め195 .Append(&h30 As Char, precision - outputLen) '足りない桁は0埋め 159 196 End If 160 197 End If 161 198 End With 162 End Function199 End Sub 163 200 164 201 /** … … 167 204 @date 2007/10/27 168 205 */ 169 Sub FormatFloatE_Exponent( bufAs System.Text.StringBuilder, e As Long, flags As FormatFlags)170 With buf206 Sub FormatFloatE_Exponent(sb As System.Text.StringBuilder, e As Long, flags As FormatFlags) 207 With sb 171 208 If flags And Cap Then 172 209 .Append("E") … … 174 211 .Append("e") 175 212 End If 176 .Append(FormatIntegerD(e, 2, 0, Sign Or Zero))213 FormatIntegerD(sb, e, 2, 0, Sign Or Zero) 177 214 End With 178 215 End Sub … … 183 220 @date 2007/10/23 184 221 @param[in] x 文字列化する浮動小数点数値。 185 @param[in] precision 精度。小数点以下の桁数。DWORD_MAXのとき、指定なしとして既定値 6となる。222 @param[in] precision 精度。小数点以下の桁数。DWORD_MAXのとき、指定なしとして既定値15となる。 186 223 @param[in] field フィールド幅。 187 224 @param[in] flags 書式フラグ。 … … 189 226 */ 190 227 Function FormatFloatF(x As Double, precision As DWord, field As DWord, flags As FormatFlags) As String 228 FormatFloatF = FormatFloatEx(AddressOf(FormatFloatF_Convert), x, precision, field, flags) 229 End Function 230 231 /* 232 @brief 浮動小数点数をprintfの%f(小数形式、十進法)相当の変換で文字列化する関数。 233 @author Egtra 234 @date 2008/03/08 235 @param[in,out] sb 書式化した文字列を追加するバッファ。 236 @param[in] x 文字列化する浮動小数点数値。 237 @param[in] precision 精度。小数点以下の桁数。DWORD_MAXのとき、指定なしとして既定値6となる。 238 @param[in] field フィールド幅。 239 @param[in] flags 書式フラグ。 240 */ 241 Sub FormatFloatF(sb As System.Text.StringBuilder, x As Double, precision As DWord, field As DWord, ByRef flags As FormatFlags) 242 FormatFloatEx(sb, AddressOf(FormatFloatF_Convert), x, precision, field, flags) 243 End Sub 244 245 /*! 246 @brief 浮動小数点数をprintfの%f(小数形式、十進法)相当の変換で文字列化する関数。 247 @author Egtra 248 @date 2008/03/07 249 @param[in,out] sb 書式化した文字列を追加するバッファ。 250 @param[in] x 文字列化する浮動小数点数値。 251 @param[in] precision 精度。小数点以下の桁数。DWORD_MAXのとき、指定なしとして既定値15となる。 252 @param[in] field フィールド幅。 253 @param[in,out] flags 書式フラグ。 254 */ 255 Sub FormatFloatF_Convert(sb As System.Text.StringBuilder, x As Double, precision As DWord, field As DWord, ByRef flags As FormatFlags) 191 256 If precision = DWORD_MAX Then 192 precision = 6 193 End If 194 257 precision = 15 258 End If 195 259 Dim e As Long, negative As Boolean 196 260 Dim s = FloatToChars(x, e, negative) 197 Dim sb = FormatFloatF_Core(s, e, negative, precision, flags) 198 AdjustFieldWidth(sb, field, flags) 199 FormatFloatF = sb.ToString() 200 End Function 261 FormatFloatF_Core(sb, s, e, negative, precision, flags) 262 End Sub 201 263 202 264 /** … … 204 266 @date 2007/10/27 205 267 */ 206 Function FormatFloatF_Core(s As String, e As Long, negative As Boolean, precision As DWord, ByRef flags As FormatFlags) As System.Text.StringBuilder 207 FormatFloatF_Core = New System.Text.StringBuilder(128) 208 With FormatFloatF_Core 209 AppendSign(FormatFloatF_Core, negative, flags) 268 Sub FormatFloatF_Core(sb As System.Text.StringBuilder, s As String, e As Long, negative As Boolean, precision As DWord, ByRef flags As FormatFlags) 269 With sb 270 AppendSign(sb, negative, flags) 210 271 211 272 Dim intPartLen = e + 1 … … 214 275 '有効桁が全て整数部に収まる場合 215 276 .Append(s) 216 .Append(&h30 As StrChar, intPartLen - 17)277 .Append(&h30 As Char, intPartLen - 17) 217 278 outputDigit = 17 218 279 ElseIf intPartLen > 0 Then … … 222 283 Else 223 284 '有効桁が全く整数部にかからない場合 224 .Append(&h30 As StrChar)285 .Append(&h30 As Char) 225 286 End If 226 287 … … 234 295 '1.23e-4 = 0.000123のように指数が負のため小数点以下に0が続く場合 235 296 zeroDigit = System.Math.Min(-intPartLen As DWord, precision) 236 .Append(&h30 As StrChar, zeroDigit As Long)297 .Append(&h30 As Char, zeroDigit As Long) 237 298 End If 238 299 .Append(s, outputDigit, (precision - zeroDigit) As Long) 239 300 Else 240 301 .Append(s, outputDigit, lastDigit) 241 .Append(&h30 As StrChar, (precision - lastDigit) As Long) '残りの桁は0埋め302 .Append(&h30 As Char, (precision - lastDigit) As Long) '残りの桁は0埋め 242 303 End If 243 304 End If 244 305 End With 245 End Function306 End Sub 246 307 247 308 /*! … … 250 311 @date 2007/10/23 251 312 @param[in] x 文字列化する浮動小数点数値。 252 @param[in] precision 精度。小数点以下の桁数。DWORD_MAXまたは0のとき、指定なしとして既定値 6となる。313 @param[in] precision 精度。小数点以下の桁数。DWORD_MAXまたは0のとき、指定なしとして既定値15となる。 253 314 @param[in] field フィールド幅。 254 315 @param[in] flags 書式フラグ。 … … 257 318 */ 258 319 Function FormatFloatG(x As Double, precision As DWord, field As DWord, flags As FormatFlags) As String 320 FormatFloatG = FormatFloatEx(AddressOf(FormatFloatG_Convert), x, precision, field, flags) 321 End Function 322 323 /* 324 @brief 浮動小数点数をprintfの%g, %G(小数・指数、十進法)相当の変換で文字列化する関数。 325 @author Egtra 326 @date 2008/03/08 327 @param[in,out] sb 書式化した文字列を追加するバッファ。 328 @param[in] x 文字列化する浮動小数点数値。 329 @param[in] precision 精度。小数点以下の桁数。DWORD_MAXのとき、指定なしとして既定値6となる。 330 @param[in] field フィールド幅。 331 @param[in] flags 書式フラグ。 332 */ 333 Sub FormatFloatG(sb As System.Text.StringBuilder, x As Double, precision As DWord, field As DWord, ByRef flags As FormatFlags) 334 FormatFloatEx(sb, AddressOf(FormatFloatG_Convert), x, precision, field, flags) 335 End Sub 336 337 /*! 338 @brief 浮動小数点数をprintfの%g, %G(小数・指数、十進法)相当の変換で文字列化する関数。 339 @author Egtra 340 @date 2007/10/23 341 @param[in,out] sb 書式化した文字列を追加するバッファ。 342 @param[in] x 文字列化する浮動小数点数値。 343 @param[in] precision 精度。小数点以下の桁数。DWORD_MAXまたは0のとき、指定なしとして既定値15となる。 344 @param[in] field フィールド幅。 345 @param[in,out] flags 書式フラグ。 346 @todo 下位桁の扱いの調査。 347 */ 348 Sub FormatFloatG_Convert(sb As System.Text.StringBuilder, x As Double, precision As DWord, field As DWord, ByRef flags As FormatFlags) 259 349 'GではE/Fと違い整数部も有効桁数に数えるのでその分を引いておく。 260 350 If precision = DWORD_MAX Or precision = 0 Then 261 precision = 5351 precision = 14 262 352 Else 263 353 precision-- 264 354 End If 265 355 Dim lastLength = sb.Length 266 356 Dim e As Long, negative As Boolean 267 357 Dim s = FloatToChars(x, e, negative) 268 269 Dim sb = Nothing As System.Text.StringBuilder270 271 358 If -5 < e And e < precision Then 272 sb = FormatFloatF_Core(s, e, negative, -e + precision, flags)273 FormatFloatG_RemoveLowDigit(sb, flags)359 FormatFloatF_Core(sb, s, e, negative, -e + precision, flags) 360 FormatFloatG_RemoveLowDigit(sb, lastLength, flags) 274 361 Else 275 sb = FormatFloatE_Base(s, negative, precision, flags)276 FormatFloatG_RemoveLowDigit(sb, flags)362 FormatFloatE_Base(sb, s, negative, precision, flags) 363 FormatFloatG_RemoveLowDigit(sb, lastLength, flags) 277 364 FormatFloatE_Exponent(sb, e, flags) 278 365 End If 279 280 AdjustFieldWidth(sb, field, flags) 281 FormatFloatG = sb.ToString() 282 End Function 366 End Sub 283 367 284 368 /*! … … 290 374 flagsでAltが立っているとき、この関数は何もしない。 291 375 */ 292 Sub FormatFloatG_RemoveLowDigit(sb As System.Text.StringBuilder, flags As FormatFlags)376 Sub FormatFloatG_RemoveLowDigit(sb As System.Text.StringBuilder, start As Long, flags As FormatFlags) 293 377 Imports ActiveBasic.Strings 294 378 295 379 Dim count = sb.Length 296 380 If (flags And Alt) = 0 Then 297 Dim point = ChrFind(StrPtr(sb), count As SIZE_T, Asc(".")) 381 Dim p = StrPtr(sb) 382 Dim point = ChrFind(VarPtr(p[start]), (count - start) As SIZE_T, Asc(".")) 298 383 If point = -1 Then 299 384 Debug … … 327 412 */ 328 413 Function FormatFloatA(x As Double, precision As DWord, field As DWord, flags As FormatFlags) As String 414 FormatFloatA = FormatFloatEx(AddressOf(FormatFloatA_Convert), x, precision, field, flags) 415 End Function 416 417 /* 418 @brief 浮動小数点数をprintfの%a, %A(指数形式、十六進法)相当の変換で文字列化する関数。 419 @author Egtra 420 @date 2008/03/08 421 @param[in,out] sb 書式化した文字列を追加するバッファ。 422 @param[in] x 文字列化する浮動小数点数値。 423 @param[in] precision 精度。小数点以下の桁数。DWORD_MAXのとき、指定なしとして既定値6となる。 424 @param[in] field フィールド幅。 425 @param[in] flags 書式フラグ。 426 */ 427 Sub FormatFloatA(sb As System.Text.StringBuilder, x As Double, precision As DWord, field As DWord, ByRef flags As FormatFlags) 428 FormatFloatEx(sb, AddressOf(FormatFloatA_Convert), x, precision, field, flags) 429 End Sub 430 431 /*! 432 @brief 浮動小数点数をprintfの%a, %A(指数形式、十六進法)相当の変換で文字列化する関数。 433 @author Egtra 434 @date 2008/03/07 435 @param[in,out] sb 書式化した文字列を追加するバッファ。 436 @param[in] x 文字列化する浮動小数点数値。 437 @param[in] precision 精度。小数点以下の桁数。DWORD_MAXのとき、指定なしとして既定値13となる。 438 @param[in] field フィールド幅。 439 @param[in,out] flags 書式フラグ。 440 441 C99では、末尾の0を取り除いても良いとあるので、 442 このルーチンでは取り除くことにしている。 443 */ 444 Sub FormatFloatA_Convert(sb As System.Text.StringBuilder, x As Double, precision As DWord, field As DWord, ByRef flags As FormatFlags) 329 445 If precision = DWORD_MAX Then 330 446 precision = 13 331 447 End If 332 448 Dim lastLength = sb.Length 333 449 Dim pqw = VarPtr(x) As *QWord 334 450 335 Dim sb = New System.Text.StringBuilder336 451 With sb 337 452 Dim sign = (GetQWord(pqw) And &H8000000000000000) As Boolean … … 362 477 If precision > 0 Or (flags And Alt) Then 363 478 .Append(".") 364 Dim base = FormatIntegerLX(GetQWord(pqw) And &h000fffffffffffff, 13, 0, flags And Cap) 365 Dim diff = precision - 13 As Long 366 If diff <= 0 Then 367 .Append(Left$(base, precision)) 479 Dim fraction = GetQWord(pqw) And &h000fffffffffffff 480 If precision < 13 Then 481 Dim dropped = 13 - precision 482 fraction >>= dropped * 4 483 FormatIntegerLX(sb, fraction, precision, 0, flags And Cap) 368 484 Else 369 .Append(base).Append(&h30, diff) 485 FormatIntegerLX(sb, fraction, 13, 0, flags And Cap) 486 .Append(&h30, precision - 13) 370 487 End If 371 488 End If 372 373 FormatFloatG_RemoveLowDigit(sb, flags) 374 489 FormatFloatG_RemoveLowDigit(sb, lastLength, flags) 375 490 .Append("P") 376 .Append(FormatIntegerD(exp, 1, 0, Sign)) 377 378 FormatFloatA = .ToString() 491 FormatIntegerD(sb, exp, 1, 0, Sign) 492 AdjustAlphabet(sb, flags, lastLength) 379 493 End With 380 381 If (flags And Cap) = 0 Then 382 FormatFloatA = FormatFloatA.ToLower() 383 End If 384 End Function 494 End Sub 385 495 386 496 /*! … … 408 518 409 519 /*! 410 @brief DWordの最大値4294967295の文字数 - 1。FormatIntegerU内で使用。411 @author Egtra412 @date 2007/09/18413 */414 Const MaxSizeU = 9415 416 /*!417 520 @brief 符号無し整数をprintfの%u(十進法表現)相当の変換で文字列化する関数。 418 521 @author Egtra … … 429 532 430 533 /*! 534 @brief 符号無し整数をprintfの%u(十進法表現)相当の変換で文字列化する関数。 535 @author Egtra 536 @date 2008/03/07 537 @param[in,out] sb 書式化した文字列を追加するバッファ。 538 @param[in] x 文字列化する整数値。 539 @param[in] d 精度、最小限表示される桁数。DWORD_MAXのとき、指定なしとして、既定値1となる。 540 @param[in] field フィールド幅。 541 @param[in] flags 書式フラグ。 542 */ 543 Sub FormatIntegerU(sb As System.Text.StringBuilder, x As DWord, d As DWord, field As DWord, flags As FormatFlags) 544 FormatIntegerEx(sb, TraitsIntegerU[0], x As QWord, d, field, flags And (Not (Sign Or Blank))) 545 End Sub 546 547 /*! 431 548 @brief FormatIntegerUのQWord版 432 549 @author Egtra … … 436 553 Return FormatIntegerEx(TraitsIntegerU[1], x, d, field, flags And (Not (Sign Or Blank))) 437 554 End Function 555 556 /*! 557 @brief FormatIntegerUのQWord版 558 @author Egtra 559 @date 2008/03/07 560 @param[in,out] sb 書式化した文字列を追加するバッファ。 561 @param[in] x 文字列化する整数値。 562 @param[in] d 精度、最小限表示される桁数。DWORD_MAXのとき、指定なしとして、既定値1となる。 563 @param[in] field フィールド幅。 564 @param[in] flags 書式フラグ。 565 */ 566 Sub FormatIntegerLU(sb As System.Text.StringBuilder, x As QWord, d As DWord, field As DWord, flags As FormatFlags) 567 FormatIntegerEx(sb, TraitsIntegerU[0], x, d, field, flags And (Not (Sign Or Blank))) 568 End Sub 438 569 439 570 /*! … … 452 583 453 584 /*! 585 @brief 符号有り整数をprintfの%d(十進法表現)相当の変換で文字列化する関数。 586 @author Egtra 587 @date 2008/03/07 588 @param[in,out] sb 書式化した文字列を追加するバッファ。 589 @param[in] x 文字列化する整数値。 590 @param[in] d 精度、最小限表示される桁数。DWORD_MAXのとき、指定なしとして、既定値1となる。 591 @param[in] field フィールド幅。 592 @param[in] flags 書式フラグ。 593 */ 594 Sub FormatIntegerD(sb As System.Text.StringBuilder, x As Long, d As DWord, field As DWord, flags As FormatFlags) 595 FormatIntegerEx(sb, TraitsIntegerD[0], (x As Int64) As QWord, d, field, flags) 596 End Sub 597 598 /*! 454 599 @brief FormatIntegerDのInt64版 455 600 @author Egtra … … 459 604 Return FormatIntegerEx(TraitsIntegerD[1], x As QWord, d, field, flags) 460 605 End Function 606 607 /*! 608 @brief FormatIntegerDのInt64版 609 @author Egtra 610 @date 2007/10/26 611 */ 612 Sub FormatIntegerLD(sb As System.Text.StringBuilder, x As Int64, d As DWord, field As DWord, flags As FormatFlags) 613 FormatIntegerEx(sb, TraitsIntegerD[1], x As QWord, d, field, flags) 614 End Sub 461 615 462 616 /*! … … 468 622 .Convert = AddressOf(IntegerU_Convert) 469 623 .Prefix = AddressOf(IntegerU_Prefix) 470 .MaxSize = MaxSizeU471 624 End With 472 625 … … 474 627 .Convert = AddressOf(IntegerLU_Convert) 475 628 .Prefix = AddressOf(IntegerU_Prefix) 476 .MaxSize = MaxSizeLU477 629 End With 478 630 … … 485 637 .Convert = AddressOf(IntegerD_Convert) 486 638 .Prefix = AddressOf(IntegerD_Prefix) 487 .MaxSize = MaxSizeU488 639 End With 489 640 … … 491 642 .Convert = AddressOf(IntegerLD_Convert) 492 643 .Prefix = AddressOf(IntegerD_Prefix) 493 .MaxSize = MaxSizeLU494 644 End With 495 645 … … 505 655 @date 2007/10/26 506 656 */ 507 Function IntegerU_Convert(buf As * StrChar, xq As QWord, flags As FormatFlags) As DWord657 Function IntegerU_Convert(buf As *Char, xq As QWord, flags As FormatFlags) As DWord 508 658 Dim x = xq As DWord 509 Dim i = MaxSize U659 Dim i = MaxSizeLO 510 660 While x <> 0 511 buf[i] = (x As Int64 Mod 10 + &h30) As StrChar 'Int64への型変換は#117対策661 buf[i] = (x As Int64 Mod 10 + &h30) As Char 'Int64への型変換は#117対策 512 662 x \= 10 513 663 i-- … … 522 672 @bug #117のため、現在Int64の最大値を超える値を正しく処理できない。 523 673 */ 524 Function IntegerLU_Convert(buf As * StrChar, x As QWord, flags As FormatFlags) As DWord525 Dim i = MaxSizeL U674 Function IntegerLU_Convert(buf As *Char, x As QWord, flags As FormatFlags) As DWord 675 Dim i = MaxSizeLO 526 676 While x <> 0 527 buf[i] = (x As Int64 Mod 10 + &h30) As StrChar 'Int64への型変換は#117対策677 buf[i] = (x As Int64 Mod 10 + &h30) As Char 'Int64への型変換は#117対策 528 678 x \= 10 529 679 i-- … … 543 693 @date 2007/10/28 544 694 */ 545 Function IntegerD_Convert(buf As * StrChar, xq As QWord, flags As FormatFlags) As DWord695 Function IntegerD_Convert(buf As *Char, xq As QWord, flags As FormatFlags) As DWord 546 696 Return IntegerU_Convert(buf, Abs((xq As DWord) As Long) As DWord, flags) 547 697 End Function … … 552 702 @date 2007/10/28 553 703 */ 554 Function IntegerLD_Convert(buf As * StrChar, x As QWord, flags As FormatFlags) As DWord704 Function IntegerLD_Convert(buf As *Char, x As QWord, flags As FormatFlags) As DWord 555 705 Return IntegerLU_Convert(buf, Abs(x As Int64) As QWord, flags) 556 706 End Function … … 570 720 End Function 571 721 572 /*! 573 @brief DWordの最大値の八進法表現37777777777の文字数 - 1 + 1。IntegerO_Convert内で使用。 574 @author Egtra 575 @date 2007/10/19 576 上の式で1を加えているのは、八進接頭辞の分。 577 */ 578 Const MaxSizeO = 11 722 579 723 580 724 /*! … … 594 738 .Convert = AddressOf(IntegerO_Convert) 595 739 .Prefix = AddressOf(IntegerO_Prefix) 596 .MaxSize = MaxSizeO597 740 End With 598 741 … … 600 743 .Convert = AddressOf(IntegerLO_Convert) 601 744 .Prefix = AddressOf(IntegerO_Prefix) 602 .MaxSize = MaxSizeLO603 745 End With 604 746 … … 630 772 @date 2007/10/22 631 773 */ 632 Function IntegerO_Convert(buf As * StrChar, xq As QWord, flags As FormatFlags) As DWord774 Function IntegerO_Convert(buf As *Char, xq As QWord, flags As FormatFlags) As DWord 633 775 Dim x = xq As DWord 634 Dim i = MaxSize O776 Dim i = MaxSizeLO 635 777 While x <> 0 636 buf[i] = ((x And &o7) + &h30) As StrChar778 buf[i] = ((x And &o7) + &h30) As Char 637 779 x >>= 3 638 780 i-- … … 650 792 @date 2007/10/26 651 793 */ 652 Function IntegerLO_Convert(buf As * StrChar, x As QWord, flags As FormatFlags) As DWord794 Function IntegerLO_Convert(buf As *Char, x As QWord, flags As FormatFlags) As DWord 653 795 Dim i = MaxSizeLO 654 796 While x <> 0 655 buf[i] = ((x And &o7) + &h30) As StrChar797 buf[i] = ((x And &o7) + &h30) As Char 656 798 x >>= 3 657 799 i-- … … 678 820 679 821 /*! 680 @brief DWordの最大値の十六進法表現ffffffffの文字数 - 1。FormatIntegerO内で使用。681 @author Egtra682 @date 2007/10/24683 */684 Const MaxSizeX = 7685 686 /*!687 @brief QWordの最大値の十六進法表現ffffffffffffffffの文字数 - 1。FormatIntegerO内で使用。688 @author Egtra689 @date 2007/10/26690 */691 Const MaxSizeLX = 15692 693 /*!694 822 @author Egtra 695 823 @date 2007/10/24 … … 699 827 .Convert = AddressOf(IntegerX_Convert) 700 828 .Prefix = AddressOf(IntegerX_Prefix) 701 .MaxSize = MaxSizeX702 829 End With 703 830 … … 705 832 .Convert = AddressOf(IntegerLX_Convert) 706 833 .Prefix = AddressOf(IntegerX_Prefix) 707 .MaxSize = MaxSizeLX708 834 End With 709 835 … … 731 857 End Function 732 858 859 /*! 860 @brief FormatIntegerXのQWord, StringBuilder版。 861 @author Egtra 862 @date 2008/03/07 863 */ 864 Sub FormatIntegerLX(sb As System.Text.StringBuilder, x As QWord, d As DWord, field As DWord, flags As FormatFlags) 865 FormatIntegerEx(sb, TraitsIntegerX[1], x, d, field, flags) 866 End Sub 867 733 868 /* 734 869 @brief 0からFまでの文字を収めた表 … … 741 876 @date 2007/10/22 742 877 */ 743 Function IntegerX_Convert(buf As * StrChar, xq As QWord, flags As FormatFlags) As DWord744 Dim i = MaxSize X878 Function IntegerX_Convert(buf As *Char, xq As QWord, flags As FormatFlags) As DWord 879 Dim i = MaxSizeLO 745 880 Dim x = xq As DWord 746 881 While x <> 0 … … 757 892 @date 2007/10/22 758 893 */ 759 Function IntegerLX_Convert(buf As * StrChar, x As QWord, flags As FormatFlags) As DWord760 Dim i = MaxSizeL X894 Function IntegerLX_Convert(buf As *Char, x As QWord, flags As FormatFlags) As DWord 895 Dim i = MaxSizeLO 761 896 While x <> 0 762 897 buf[i] = HexadecimalTable[x And &h0f] … … 791 926 Type IntegerConvertTraits 792 927 '!変換を行う関数へのポインタ。 793 Convert As *Function(buf As * StrChar, x As QWord, flags As FormatFlags) As DWord928 Convert As *Function(buf As *Char, x As QWord, flags As FormatFlags) As DWord 794 929 '!接頭辞を取得する関数へのポインタ。 795 930 Prefix As *Function(x As QWord, flags As FormatFlags) As String 796 '!必要なバッファの大きさ。797 MaxSize As DWord798 931 End Type 799 932 800 933 /*! 801 @brief 整数変換全てを行う関数。 これを雛形とし、形式毎の差異はIntegerConvertTraitsで表現する。934 @brief 整数変換全てを行う関数。 802 935 @author Egtra 803 936 @date 2007/10/22 … … 807 940 @param[in] field フィールド幅。 808 941 @param[in] flags フラグ。 942 @return 変換された文字列 809 943 */ 810 944 Function FormatIntegerEx(ByRef tr As IntegerConvertTraits, x As QWord, d As DWord, field As DWord, flags As FormatFlags) As String 945 Dim sb = New System.Text.StringBuilder(32) 946 FormatIntegerEx(sb, tr, x, d, field, flags) 947 FormatIntegerEx = sb.ToString 948 End Function 949 950 /*! 951 @brief 整数変換全てを行う関数。これを雛形とし、形式毎の差異はIntegerConvertTraitsで表現する。 952 @author Egtra 953 @date 2008/03/06 954 @param[in,out] sb 書式化した文字列を追加するバッファ。 955 @param[in] tr 特性情報。 956 @param[in] x 変換元の数値。 957 @param[in] d 精度。ここでは最低限出力する桁数。 958 @param[in] field フィールド幅。 959 @param[in] flags フラグ。 960 */ 961 Sub FormatIntegerEx(sb As System.Text.StringBuilder, ByRef tr As IntegerConvertTraits, x As QWord, d As DWord, field As DWord, flags As FormatFlags) 811 962 If d = DWORD_MAX Then 812 963 d = 1 … … 817 968 End If 818 969 819 Dim sb = New System.Text.StringBuilder 970 Dim lastLength = sb.Length 971 820 972 With sb 821 973 Dim prefixFunc = tr.Prefix … … 828 980 End If 829 981 830 ' Dim buf = GC_malloc_atomic((tr.MaxSize + 1) * SizeOf (StrChar)) As *StrChar 831 Dim buf[MaxSizeLO] As StrChar982 'バッファの量は最も必要文字数の多くなるUInt64の8進法変換にあわせている 983 Dim buf[MaxSizeLO] As Char 832 984 Dim convertFunc = tr.Convert 833 985 Dim bufStartPos = convertFunc(buf, x, flags) 834 986 835 Dim len = ( tr.MaxSize- bufStartPos) As Long987 Dim len = (MaxSizeLO - bufStartPos) As Long 836 988 If len < 0 Then 837 989 Debug 838 990 End If 839 991 If len < d Then 840 .Append(&h30 As StrChar, d - len) 841 End If 842 992 .Append(&h30 As Char, d - len) 993 End If 843 994 .Append(buf, bufStartPos + 1, len) 844 845 Adjust FieldWidth(sb, field, flags And (Not (Sign Or Blank)), prefixLen)995 AdjustFieldWidth(sb, field, flags And (Not (Sign Or Blank)), prefixLen, lastLength) 996 AdjustAlphabet(sb, flags, lastLength) 846 997 End With 847 FormatIntegerEx = sb.ToString() 848 849 If (flags And Cap) = 0 Then 850 FormatIntegerEx = FormatIntegerEx.ToLower() 851 End If 852 End Function 853 Sub FormatIntegerEx(sb As System.Text.StringBuilder, ByRef tr As IntegerConvertTraits, x As QWord, d As DWord, field As DWord, flags As FormatFlags) 854 855 If d = DWORD_MAX Then 856 d = 1 998 End Sub 999 1000 /*! 1001 @brief 浮動小数点数変換全てを行う関数。これを雛形とし、実際の変換関数は引数converterで与える。 1002 @author Egtra 1003 @date 2008/03/07 1004 @param[in,out] sb 書式化した文字列を追加するバッファ。 1005 @param[in] converter 変換関数。 1006 @param[in] x 変換元の数値。 1007 @param[in] d 精度。ここでは最低限出力する桁数。 1008 @param[in] field フィールド幅。 1009 @param[in] flags フラグ。 1010 */ 1011 Sub FormatFloatEx(sb As System.Text.StringBuilder, converter As FormatFloatProc, x As Double, precision As DWord, field As DWord, flags As FormatFlags) 1012 Dim lastLength = sb.Length 1013 If Math.IsNaN(x) Then 1014 sb.Append("NAN") 1015 AdjustAlphabet(sb, flags, lastLength) 1016 ElseIf Math.IsInf(x) Then 1017 AppendSign(sb, (GetQWord(VarPtr(x)) >> 63) As Boolean, flags) 1018 sb.Append("INFINITY") 1019 AdjustAlphabet(sb, flags, lastLength) 857 1020 Else 858 '精度が指定されているとき、ゼロフラグは無視される。 859 '仕様上、左揃えのときも無視されるが、それはAdjustFieldWidthが行ってくれる。 860 flags And= Not Zero 861 End If 862 863 Dim lastLength = sb.Length 864 865 With sb 866 Dim prefixFunc = tr.Prefix 867 Dim prefix = prefixFunc(x, flags) 868 sb.Append(prefix) 869 870 Dim prefixLen = 0 As DWord 871 If String.IsNullOrEmpty(prefix) = False Then 872 prefixLen = prefix.Length As DWord 873 End If 874 875 ' Dim buf = GC_malloc_atomic((tr.MaxSize + 1) * SizeOf (StrChar)) As *StrChar 876 Dim buf[MaxSizeLO] As StrChar 877 Dim convertFunc = tr.Convert 878 Dim bufStartPos = convertFunc(buf, x, flags) 879 880 Dim len = (tr.MaxSize - bufStartPos) As Long 881 If len < 0 Then 882 Debug 883 End If 884 If len < d Then 885 .Append(&h30 As StrChar, d - len) 886 End If 887 888 .Append(buf, bufStartPos + 1, len) 889 890 AdjustFieldWidth(sb, field, flags And (Not (Sign Or Blank)), prefixLen, lastLength) 891 End With 892 Dim t = sb.ToString() 893 1021 converter(sb, x, precision, field, flags) 1022 End If 1023 AdjustFieldWidth(sb, field, flags, 0, lastLength) 1024 End Sub 1025 1026 1027 /*! 1028 @brief 浮動小数点数変換全てを行う関数。 1029 @author Egtra 1030 @date 2008/03/08 1031 @param[in] converter 変換関数。 1032 @param[in] x 変換元の数値。 1033 @param[in] d 精度。ここでは最低限出力する桁数。 1034 @param[in] field フィールド幅。 1035 @param[in] flags フラグ。 1036 @return 変換された文字列。 1037 */ 1038 Function FormatFloatEx(converter As FormatFloatProc, x As Double, precision As DWord, field As DWord, flags As FormatFlags) As String 1039 Dim sb = New System.Text.StringBuilder 1040 FormatFloatEx(sb, converter, x, precision, field, flags) 1041 FormatFloatEx = sb.ToString 1042 End Function 1043 1044 /*! 1045 @brief 書式化の仕上げとして、Capフラグが指定されていないときに小文字化する作業を行う。 1046 @author Egtra 1047 @date 2008/03/06 1048 @param[in,out] sb 書式化した文字列を格納しているバッファ。 1049 @param[in] flags フラグ。 1050 @param[in] offset 書式変換した部分の開始位置。 1051 */ 1052 Sub AdjustAlphabet(sb As System.Text.StringBuilder, flags As FormatFlags, offset As Long) 894 1053 If (flags And Cap) = 0 Then 895 1054 Dim len = sb.Length 896 1055 Dim i As Long 897 For i = lastLengthTo ELM(len)1056 For i = offset To ELM(len) 898 1057 sb[i] = CType.ToLower(sb[i]) 899 1058 Next 900 1059 End If 901 1060 End Sub 902 903 /*!904 @brief QWordの最大値18446744073709551615の文字数 - 1。FormatIntegerLU内で使用。905 @author Egtra906 @date 2007/09/18907 */908 Const MaxSizeLU = 19909 1061 910 1062 /*! … … 953 1105 */ 954 1106 Function FormatString(x As String, d As DWord, field As DWord, flags As FormatFlags) As String 1107 Imports System 955 1108 Dim sb = New System.Text.StringBuilder( 956 x, 0, System.Math.Min(x.Length As DWord, d) As Long, field) 1109 Math.Max(Math.Min(x.Length As DWord, d), field) As Long + 1) 1110 FormatString(sb, x, d, field, flags) 957 1111 AdjustFieldWidth(sb, field, flags And LeftSide) 958 1112 FormatString = sb.ToString() 959 1113 End Function 1114 1115 /*! 1116 @brief 文字列をprintfの%s相当の変換で書式化する関数。 1117 @author Egtra 1118 @date 2008/03/07 1119 @param[in,out] sb 書式化した文字列を追加するバッファ。 1120 @param[in] x 文字列。 1121 @param[in] d 精度、最大の文字数。 1122 @param[in] field フィールド幅。 1123 @param[in] flags 書式フラグ。 1124 @return 書式化された文字列。 1125 */ 1126 Sub FormatString(sb As System.Text.StringBuilder, x As String, d As DWord, field As DWord, flags As FormatFlags) 1127 Dim len = sb.Length 1128 sb.Append(x, 0, System.Math.Min(x.Length As DWord, d) As Long) 1129 AdjustFieldWidth(sb, field, flags And LeftSide, 0, len) 1130 End Sub 960 1131 961 1132 /*! … … 969 1140 @return 書式化された文字列。 970 1141 */ 971 Function FormatCharacter(x As StrChar, d As DWord, field As DWord, flags As FormatFlags) As String 972 Dim sb = New System.Text.StringBuilder(field + 1) 1142 Function FormatCharacter(x As Char, d As DWord, field As DWord, flags As FormatFlags) As String 1143 Dim sb = New System.Text.StringBuilder(field + 2) 1144 FormatCharacter(sb, x, d, field, flags) 1145 FormatCharacter = sb.ToString() 1146 End Function 1147 1148 /*! 1149 @brief 文字列をprintfの%s相当の変換で書式化する関数。 1150 @author Egtra 1151 @date 2008/03/07 1152 @param[in,out] sb 書式化した文字列を追加するバッファ。 1153 @param[in] x 文字。 1154 @param[in] d 精度、最大の文字数。 1155 @param[in] field フィールド幅。 1156 @param[in] flags 書式フラグ。 1157 @return 書式化された文字列。 1158 */ 1159 Sub FormatCharacter(sb As System.Text.StringBuilder, x As Char, d As DWord, field As DWord, flags As FormatFlags) 1160 Dim len = sb.Length 973 1161 sb.Append(x) 974 AdjustFieldWidth(sb, field, flags And LeftSide) 975 FormatCharacter = sb.ToString() 976 End Function 1162 AdjustFieldWidth(sb, field, flags And LeftSide, 0, len) 1163 End Sub 977 1164 978 1165 /*! … … 980 1167 @date 2007/10/28 981 1168 */ 982 TypeDef FormatFloatProc = * Function(x As Double, precision As DWord, fieldWidth As DWord, flags As FormatFlags) As String1169 TypeDef FormatFloatProc = *Sub(sb As System.Text.StringBuilder, x As Double, precision As DWord, fieldWidth As DWord, ByRef flags As FormatFlags) 983 1170 984 1171 /*! … … 997 1184 x = param As System.Single 998 1185 End If 999 s.Append(formatProc(x, precision, field, flags))1186 FormatFloatEx(s, formatProc, x, precision, field, flags) 1000 1187 End Sub 1001 1188 … … 1050 1237 End If 1051 1238 End If 1052 1053 ' s.Append(FormatIntegerEx(ByVal traits, x, precision, field, flags))1054 1239 FormatIntegerEx(s, ByVal traits, x, precision, field, flags) 1055 1240 End Sub … … 1066 1251 @return 変換して得られた数値。変換できなければ0。 1067 1252 */ 1068 Function StrToLong(s As * StrChar, ByRef p As *StrChar) As Long1253 Function StrToLong(s As *Char, ByRef p As *Char) As Long 1069 1254 Dim negative As Boolean 1070 1255 Dim i = 0 As Long … … 1099 1284 そうでなく、fmtに数字(先頭に-符号があっても可)が並んでいれば、それを読み取る。 1100 1285 */ 1101 Function ReadInt(ByRef fmt As * StrChar, params As *Object, ByRef paramsCount As SIZE_T, ByRef ret As Long) As Boolean1286 Function ReadInt(ByRef fmt As *Char, params As *Object, ByRef paramsCount As SIZE_T, ByRef ret As Long) As Boolean 1102 1287 If fmt[0] = &h2a Then '* 1103 1288 fmt = VarPtr(fmt[1]) 'po … … 1106 1291 ReadInt = True 1107 1292 Else 1108 Dim p As * StrChar1293 Dim p As *Char 1109 1294 ret = StrToLong(fmt, p) 1110 1295 If fmt <> p Then … … 1126 1311 @retval False 読み取り中に文字列が終了した(ヌル文字が現れた)。 1127 1312 */ 1128 Function ReadFlags(ByRef fmt As * StrChar, ByRef flags As FormatFlags) As Boolean1313 Function ReadFlags(ByRef fmt As *Char, ByRef flags As FormatFlags) As Boolean 1129 1314 ReadFlags = False 1130 1315 Do … … 1162 1347 @param[in, out] flags 1163 1348 */ 1164 Sub ReadFieldWidth(ByRef fmt As * StrChar, params As *Object, ByRef paramsCount As SIZE_T,1349 Sub ReadFieldWidth(ByRef fmt As *Char, params As *Object, ByRef paramsCount As SIZE_T, 1165 1350 ByRef fieldWidth As DWord, ByRef flags As FormatFlags) 1166 1351 Dim t As Long … … 1186 1371 @return 読み取った精度。指定がなかったときには、DWORD_MAX。 1187 1372 */ 1188 Function ReadPrecision(ByRef fmt As * StrChar,1373 Function ReadPrecision(ByRef fmt As *Char, 1189 1374 params As *Object, ByRef paramsCount As SIZE_T) As DWord 1190 1375 … … 1216 1401 @param[out] lengthSpec 1217 1402 */ 1218 Sub ReadLength(ByRef fmt As * StrChar, ByRef lengthSpec As Long)1403 Sub ReadLength(ByRef fmt As *Char, ByRef lengthSpec As Long) 1219 1404 Do 1220 1405 Select Case fmt[0] … … 1240 1425 1241 1426 /*! 1427 @brief efg変換用に、精度が指定されていないときに既定の精度を設定する。 1428 @auther Egtra 1429 @date 2008/03/07 1430 */ 1431 Sub AdjustPrecision(ByRef precision As DWord) 1432 If precision = DWORD_MAX Then 1433 precision = 6 1434 End If 1435 End Sub 1436 1437 /*! 1242 1438 @biref Cのsprintfのような書式文字列出力関数 1243 1439 @author Egtra … … 1255 1451 Dim s = New System.Text.StringBuilder 1256 1452 Do 1257 Dim last = format.Length - (((fmt - StrPtr(format)) \ SizeOf ( StrChar)) As LONG_PTR) As Long 'po1258 Dim pos = ActiveBasic.Strings.ChrFind(fmt, last, &h25 As StrChar) As Long '&h25 = %1453 Dim last = format.Length - (((fmt - StrPtr(format)) \ SizeOf (Char)) As LONG_PTR) As Long 'po 1454 Dim pos = ChrFind(fmt, last, &h25 As Char) As Long '&h25 = % 1259 1455 If pos = -1 Then 1260 1456 s.Append(fmt, 0, last) … … 1285 1481 Case &h75 'u 1286 1482 FormatInteger(s, TraitsIntegerU, params[i], False, typeWidth, precision, fieldWidth, flags) 1483 Case &h4f 'O 1484 flags Or= Cap 1485 Goto *O 1287 1486 Case &h6f 'o 1487 *O 1288 1488 FormatInteger(s, TraitsIntegerO, params[i], False, typeWidth, precision, fieldWidth, flags) 1289 Case &h4f 'O 1290 FormatInteger(s, TraitsIntegerO, params[i], False, typeWidth, precision, fieldWidth, flags Or Cap) 1489 Case &h58 'X 1490 flags Or= Cap 1491 Goto *X 1291 1492 Case &h78 'x 1493 *X 1292 1494 FormatInteger(s, TraitsIntegerX, params[i], False, typeWidth, precision, fieldWidth, flags) 1293 Case &h58 'X1294 FormatInteger(s, TraitsIntegerX, params[i], False, typeWidth, precision, fieldWidth, flags Or Cap)1295 1495 '現状ではVoidPtrを引数にする手段は無いはず 1296 1496 ' Case &h58 'p 1297 1497 ' FormatInteger(s, TraitsIntegerX, params[i], False, typeWidth, precision, fieldWidth, flags Or Cap) 1498 Case &h45 'E 1499 flags Or= Cap 1500 Goto *E 1298 1501 Case &h65 'e 1299 FormatFloat(s, AddressOf(FormatFloatE), params[i], precision, fieldWidth, flags) 1300 Case &h45 'E 1301 FormatFloat(s, AddressOf(FormatFloatE), params[i], precision, fieldWidth, flags Or Cap) 1502 *E 1503 AdjustPrecision(precision) 1504 FormatFloat(s, AddressOf(FormatFloatE_Convert), params[i], precision, fieldWidth, flags) 1505 Case &h46 'F 1506 flags Or= Cap 1507 Goto *F 1302 1508 Case &h66 'f 1303 FormatFloat(s, AddressOf(FormatFloatF), params[i], precision, fieldWidth, flags) 1304 Case &h46 'F 1305 FormatFloat(s, AddressOf(FormatFloatF), params[i], precision, fieldWidth, flags Or Cap) 1509 *F 1510 AdjustPrecision(precision) 1511 FormatFloat(s, AddressOf(FormatFloatF_Convert), params[i], precision, fieldWidth, flags) 1512 Case &h47 'G 1513 flags Or= Cap 1514 Goto *G 1306 1515 Case &h67 'g 1307 FormatFloat(s, AddressOf(FormatFloatG), params[i], precision, fieldWidth, flags) 1308 Case &h47 'G 1309 FormatFloat(s, AddressOf(FormatFloatG), params[i], precision, fieldWidth, flags Or Cap) 1516 *G 1517 AdjustPrecision(precision) 1518 FormatFloat(s, AddressOf(FormatFloatG_Convert), params[i], precision, fieldWidth, flags) 1519 Case &h41 'A 1520 flags Or= Cap 1521 Goto *A 1310 1522 Case &h61 'a 1523 *A 1311 1524 FormatFloat(s, AddressOf(FormatFloatA), params[i], precision, fieldWidth, flags) 1312 Case &h41 'A1313 FormatFloat(s, AddressOf(FormatFloatA), params[i], precision, fieldWidth, flags Or Cap)1314 1525 Case &h73 's 1315 s.Append(FormatString(params[i] As String, precision, fieldWidth, flags))1526 FormatString(s, params[i] As String, precision, fieldWidth, flags) 1316 1527 Case &h63 'c 1317 s.Append(FormatCharacter(params[i] As BoxedStrChar, precision, fieldWidth, flags))1528 FormatCharacter(s, params[i] As BoxedStrChar, precision, fieldWidth, flags) 1318 1529 ' Case &h6e 'n 1319 1530 Case &h25 '% 1320 s.Append(&h25 As StrChar)1531 s.Append(&h25 As Char) 1321 1532 i-- 1322 1533 Case 0
Note:
See TracChangeset
for help on using the changeset viewer.