Changeset 365


Ignore:
Timestamp:
Oct 27, 2007, 12:58:11 AM (17 years ago)
Author:
イグトランス (egtra)
Message:

QWord, Int64用書式化関数群を実装

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Include/Classes/ActiveBasic/Strings/SPrintF.ab

    r364 r365  
    3939        x = -x
    4040    Else
    41 
    4241        sign = False
    4342    End If
     
    6564    e = d
    6665
    67     FloatToChars = Str$(x As QWord)
     66    FloatToChars = FormatIntegerLU((x As Int64) As QWord, 17, 0, None)
    6867End Function
    6968
     
    102101    '! 大文字。使用するアルファベットを大文字にする。[aefgx]を[AEFGX]化する。
    103102    Cap = &h20
     103
     104    /*!
     105    内部処理用に予約。
     106    @note   Minusとして使用されている。
     107    */
     108    Reserved = &h80000000
    104109End Enum
    105110
     
    108113@author Egtra
    109114@date   2007/09/18
    110 @param[in]  x   文字列化する浮動小数点数値。
    111 @param[in]  d   精度。小数点以下の桁数。DWORD_MAXのとき、指定なしとして既定値6となる。
    112 @param[in]  field   フィールド幅。
    113 @param[in]  flags   書式フラグ。
    114 @return xの文字列表現
    115 
    116 @todo 他の実装での末尾桁の扱いを調べる(このコードでは何もしていないので切捨となっている)。
     115@param[in] x    文字列化する浮動小数点数値。
     116@param[in] d    精度。小数点以下の桁数。DWORD_MAXのとき、指定なしとして既定値6となる。
     117@param[in] field    フィールド幅。
     118@param[in] flags    書式フラグ。
     119@return xの文字列表現
     120
     121@todo   他の実装での末尾桁の扱いを調べる(このコードでは何もしていないので切捨となっている)。
    117122*/
    118123Function FormatFloatE(x As Double, d As DWord, field As DWord, flags As FormatFlags) As String
     
    156161
    157162/*!
    158 @brief  浮動小数点数をprintfの%f(小数点数形式、十進法)相当の変換で文字列化する関数。
     163@brief  浮動小数点数をprintfの%f(小数形式、十進法)相当の変換で文字列化する関数。
    159164@author Egtra
    160165@date   2007/10/23
     
    238243End Sub
    239244
    240 '! DWordの最大値4294967295の文字数 - 1。FormatIntegerU内で使用。
     245/*!
     246@brief  DWordの最大値4294967295の文字数 - 1。FormatIntegerU内で使用。
     247@author Egtra
     248@date   2007/09/18
     249*/
    241250Const MaxSizeU = 9
    242251
     
    252261*/
    253262Function FormatIntegerU(x As DWord, d As DWord, field As DWord, flags As FormatFlags) As String
    254     FormatIntegerU = FormatInteger(x, d, field, flags And (Not (Sign Or Blank)), 0)
    255 End Function
    256 
    257 /*!
    258 DWordの最大値4294967295やLongの最大値2147483647、最小値-2147483648
    259 (全て十進法)の符号部を除いた文字数 - 1。FormatIntegerU内で使用。
    260 */
    261 Const MaxSizeD = 9
     263    Return FormatIntegerEx(TraitsIntegerDU, x, d, field, flags And (Not (Sign Or Blank)))
     264End Function
     265
     266/*!
     267@brief  FormatIntegerUのQWord版
     268@author Egtra
     269@date   2007/10/26
     270*/
     271Function FormatIntegerLU(x As QWord, d As DWord, field As DWord, flags As FormatFlags) As String
     272    Return FormatIntegerEx(TraitsIntegerLDU, x, d, field, flags And (Not (Sign Or Blank)))
     273End Function
    262274
    263275/*!
     
    272284*/
    273285Function FormatIntegerD(x As Long, d As DWord, field As DWord, flags As FormatFlags) As String
    274     Dim dwX As DWord
    275 
    276     Dim signChar As StrChar
     286    Dim unsignedX As DWord
    277287    If x < 0 Then
    278         dwX = (-x) As DWord
    279         signChar = Asc("-")
    280         flags Or= Sign
     288        unsignedX = (-x) As DWord
     289        flags Or= Minus
    281290    Else
    282         dwX = x As DWord
    283         If flags And Sign Then
    284             signChar = Asc("+")
    285         ElseIf flags And Blank Then
    286             signChar = Asc(" ")
    287         End If
    288     End If
    289 
    290     FormatIntegerD = FormatInteger(dwX, d, field, flags, signChar)
    291 End Function
    292 
    293 /*!
    294 @brief  整数をprintfの%d, %u相当の変換で文字列化する関数。
    295 @author Egtra
    296 @date   2007/09/18
    297 @param[in]  x   文字列化する整数値。
    298 @param[in]  d   精度、最小限表示される桁数。DWORD_MAXのとき、指定なしとして、既定値1となる。
    299 @param[in]  field   フィールド幅。
    300 @param[in]  flags   書式フラグ。
    301 @param[in]  signChar    符号部分の文字。\0なら存在しないとして扱われる。
    302 @return xの文字列表現
    303 
    304 signCharに何らかの値を指定するときには、必ずflagsにSignまたはBlankを指定すること。
    305 さもないと、フィールド幅を指定したときに正しく整形されなくなる。
    306 */
    307 Function FormatInteger(x As DWord, d As DWord, field As DWord, flags As FormatFlags, signChar As StrChar) As String
    308     PreProcessFormatInteger(d, flags)
    309 
    310     Dim sb = New System.Text.StringBuilder
    311     With sb
    312         If signChar <> 0 Then
    313             .Append(signChar)
    314         End If
    315 
    316         Dim buf[MaxSizeU] As StrChar
    317         Dim i = MaxSizeU
    318         While x <> 0
    319             buf[i] = (x As Int64 Mod 10 + &h30) As StrChar 'Int64への型変換は#117対策
    320             x \= 10
    321             i--
    322         Wend
    323        
    324         Dim len = (MaxSizeU - i) As Long
    325         If len < d Then
    326             .Append(&h30 As StrChar, d - len)
    327         End If
    328 
    329         .Append(buf, i + 1, len)
    330 
    331         AdjustFieldWidth(sb, field, flags)
    332     End With
    333     FormatInteger = sb.ToString()
    334 End Function
    335 
    336 /*!
    337 DWordの最大値の八進法表現37777777777の文字数 - 1 + 1。FormatIntegerO内で使用。
     291        unsignedX = x As DWord
     292    End If
     293
     294    Return FormatIntegerEx(TraitsIntegerDU, unsignedX, d, field, flags)
     295End Function
     296
     297/*!
     298@brief  FormatIntegerDのInt64版
     299@author Egtra
     300@date   2007/10/26
     301*/
     302Function FormatIntegerLD(x As Int64, d As DWord, field As DWord, flags As FormatFlags) As String
     303    Dim unsignedX As QWord
     304    If x < 0 Then
     305        unsignedX = (-x) As QWord
     306        flags Or= Minus
     307    Else
     308        unsignedX = x As QWord
     309    End If
     310
     311    Return FormatIntegerEx(TraitsIntegerLDU, unsignedX, d, field, flags)
     312End Function
     313
     314/*!
     315@author Egtra
     316@date   2007/10/26
     317*/
     318Dim TraitsIntegerDU As IntegerConvertTraits
     319With TraitsIntegerDU
     320    .Convert = AddressOf(IntegerDU_Convert)
     321    .Prefix = AddressOf(IntegerDU_Prefix)
     322    .MaxSize = MaxSizeU
     323End With
     324
     325/*!
     326@author Egtra
     327@date   2007/10/26
     328*/
     329Dim TraitsIntegerLDU As IntegerConvertTraits
     330With TraitsIntegerLDU
     331    .Convert = AddressOf(IntegerLDU_Convert)
     332    .Prefix = AddressOf(IntegerDU_Prefix)
     333    .MaxSize = MaxSizeLU
     334End With
     335
     336/*!
     337@brief  負数を表すフラグ。FormatIntegerD, LDからIntegerDU_Prefixまでの内部処理用。
     338@author Egtra
     339@date   2007/10/26
     340*/
     341Const Minus = Reserved
     342
     343/*!
     344@author Egtra
     345@date   2007/10/26
     346*/
     347Function IntegerDU_Convert(buf As *StrChar, xq As QWord, flags As FormatFlags) As DWord
     348    Dim x = xq As DWord
     349    Dim i = MaxSizeU
     350    While x <> 0
     351        buf[i] = (x As Int64 Mod 10 + &h30) As StrChar 'Int64への型変換は#117対策
     352        x \= 10
     353        i--
     354    Wend
     355    Return i
     356End Function
     357
     358/*!
     359@brief  IntegerDU_ConvertのQWord版
     360@author Egtra
     361@date   2007/10/26
     362@bug    #117のため、現在Int64の最大値を超える値を正しく処理できない。
     363*/
     364Function IntegerLDU_Convert(buf As *StrChar, x As QWord, flags As FormatFlags) As DWord
     365    Dim i = MaxSizeLU
     366    While x <> 0
     367        buf[i] = (x As Int64 Mod 10 + &h30) As StrChar 'Int64への型変換は#117対策
     368        x \= 10
     369        i--
     370    Wend
     371    Return i
     372End Function
     373
     374/*!
     375@author Egtra
     376@date   2007/10/26
     377*/
     378Function IntegerDU_Prefix(x As QWord, flags As FormatFlags) As String
     379    If flags And Minus Then
     380        IntegerDU_Prefix = "-"
     381    ElseIf flags And Sign Then
     382        IntegerDU_Prefix = "+"
     383    ElseIf flags And Blank Then
     384        IntegerDU_Prefix = " "
     385    End If
     386End Function
     387
     388/*!
     389@brief  DWordの最大値の八進法表現37777777777の文字数 - 1 + 1。IntegerO_Convert内で使用。
     390@author Egtra
     391@date   2007/10/19
    338392上の式で1を加えているのは、八進接頭辞の分。
    339393*/
    340394Const MaxSizeO = 11
    341395
     396/*!
     397@brief  QWordの最大値の八進法表現1777777777777777777777の文字数 - 1 + 1。IntegerO_Convert内で使用。
     398@author Egtra
     399@date   2007/10/26
     400上の式で1を加えているのは、八進接頭辞の分。
     401*/
     402Const MaxSizeLO = 22
     403
     404/*!
     405@author Egtra
     406@date   2007/10/22
     407*/
    342408Dim TraitsIntegerO As IntegerConvertTraits
    343409With TraitsIntegerO
     
    348414
    349415/*!
     416@author Egtra
     417@date   2007/10/26
     418*/
     419Dim TraitsIntegerLO As IntegerConvertTraits
     420With TraitsIntegerLO
     421    .Convert = AddressOf(IntegerLO_Convert)
     422    .Prefix = AddressOf(IntegerO_Prefix)
     423    .MaxSize = MaxSizeLO
     424End With
     425
     426/*!
    350427@brief  符号無し整数をprintfの%o(八進法表現)相当の変換で文字列化する関数。
    351428@author Egtra
     
    358435*/
    359436Function FormatIntegerO(x As DWord, d As DWord, field As DWord, flags As FormatFlags) As String
    360     FormatIntegerO = FormatIntegerEx(TraitsIntegerO, x, d, field, flags)
    361 End Function
    362 
     437    Return FormatIntegerEx(TraitsIntegerO, x, d, field, flags)
     438End Function
     439
     440/*!
     441@brief  FormatIntegerOのQWord版。
     442@author Egtra
     443@date   2007/10/26
     444*/
     445Function FormatIntegerLO(x As QWord, d As DWord, field As DWord, flags As FormatFlags) As String
     446    Return FormatIntegerEx(TraitsIntegerLO, x, d, field, flags)
     447End Function
     448
     449/*!
     450@author Egtra
     451@date   2007/10/22
     452*/
    363453Function IntegerO_Convert(buf As *StrChar, xq As QWord, flags As FormatFlags) As DWord
    364454    Dim x = xq As DWord
     
    373463        i--
    374464    End If
    375     IntegerO_Convert = i
    376 End Function
    377 
     465    Return i
     466End Function
     467
     468/*!
     469@brief  IntegerO_ConvertのQWord版。
     470@author Egtra
     471@date   2007/10/26
     472*/
     473Function IntegerLO_Convert(buf As *StrChar, x As QWord, flags As FormatFlags) As DWord
     474    Dim i = MaxSizeLO
     475    While x <> 0
     476        buf[i] = ((x And &o7) + &h30) As StrChar
     477        x >>= 3
     478        i--
     479    Wend
     480    If flags And Alt Then
     481        buf[i] = &h30
     482        i--
     483    End If
     484    Return i
     485End Function
     486
     487/*!
     488@author Egtra
     489@date   2007/10/22
     490@note   #フラグ (Alt)の処理は、IntegerO/LO_Convert内で行うので、ここで処理することはない。
     491*/
    378492Function IntegerO_Prefix(x As QWord, flags As FormatFlags) As String
    379493End Function
    380494
    381495/*!
    382 DWordの最大値の十六進法表現ffffffffの文字数 - 1。FormatIntegerO内で使用。
     496@brief  DWordの最大値の十六進法表現ffffffffの文字数 - 1。FormatIntegerO内で使用。
     497@author Egtra
     498@date   2007/10/24
    383499*/
    384500Const MaxSizeX = 7
    385501
     502/*!
     503@brief  QWordの最大値の十六進法表現ffffffffffffffffの文字数 - 1。FormatIntegerO内で使用。
     504@author Egtra
     505@date   2007/10/26
     506*/
     507Const MaxSizeLX = 15
     508
     509/*!
     510@author Egtra
     511@date   2007/10/24
     512*/
    386513Dim TraitsIntegerX As IntegerConvertTraits
    387514With TraitsIntegerX
     
    392519
    393520/*!
     521@author Egtra
     522@date   2007/10/26
     523*/
     524Dim TraitsIntegerLX As IntegerConvertTraits
     525With TraitsIntegerLX
     526    .Convert = AddressOf(IntegerLX_Convert)
     527    .Prefix = AddressOf(IntegerX_Prefix)
     528    .MaxSize = MaxSizeLX
     529End With
     530
     531/*!
    394532@brief  整数をprintfの%x, %X(十六進法)相当の変換で文字列化する関数。
    395533@author Egtra
     
    402540*/
    403541Function FormatIntegerX(x As DWord, d As DWord, field As DWord, flags As FormatFlags) As String
    404     FormatIntegerX = FormatIntegerEx(TraitsIntegerX, x, d, field, flags)
    405 End Function
    406 
     542    Return FormatIntegerEx(TraitsIntegerX, x, d, field, flags)
     543End Function
     544
     545/*!
     546@brief  FormatIntegerXのQWord版。
     547@author Egtra
     548@date   2007/10/22
     549*/
     550Function FormatIntegerLX(x As QWord, d As DWord, field As DWord, flags As FormatFlags) As String
     551    Return FormatIntegerEx(TraitsIntegerLX, x, d, field, flags)
     552End Function
     553
     554/*!
     555@author Egtra
     556@date   2007/10/22
     557*/
    407558Function IntegerX_Convert(buf As *StrChar, xq As QWord, flags As FormatFlags) As DWord
    408559    Dim i = MaxSizeX
     
    413564        i--
    414565    Wend
    415     IntegerX_Convert = i
    416 End Function
    417 
     566    Return i
     567End Function
     568
     569/*!
     570@brief  IntegerX_ConvertのQWord版。
     571@author Egtra
     572@date   2007/10/22
     573*/
     574Function IntegerLX_Convert(buf As *StrChar, x As QWord, flags As FormatFlags) As DWord
     575    Dim i = MaxSizeLX
     576    While x <> 0
     577        buf[i] = _System_HexadecimalTable[x And &h0f]
     578        x >>= 4
     579        i--
     580    Wend
     581    Return i
     582End Function
     583
     584/*!
     585@author Egtra
     586@date   2007/10/24
     587*/
    418588Function IntegerX_Prefix(x As QWord, flags As FormatFlags) As String
    419589    If flags And Alt Then
     
    424594End Function
    425595
     596/*!
     597@brief  FormatIntegerExへ渡す変換特性を表す構造体型。
     598@author Egtra
     599@date   2007/10/22
     600*/
    426601Type IntegerConvertTraits
     602    '!変換を行う関数へのポインタ。
    427603    Convert As *Function(buf As *StrChar, x As QWord, flags As FormatFlags) As DWord
     604    '!接頭辞を取得する関数へのポインタ。
    428605    Prefix As *Function(x As QWord, flags As FormatFlags) As String
     606    '!必要なバッファの大きさ。
    429607    MaxSize As DWord
    430608End Type
     
    441619*/
    442620Function FormatIntegerEx(ByRef tr As IntegerConvertTraits, x As QWord, d As DWord, field As DWord, flags As FormatFlags) As String
    443     PreProcessFormatInteger(d, flags)
     621    If d = DWORD_MAX Then
     622        d = 1
     623    Else
     624        '精度が指定されているとき、ゼロフラグは無視される。
     625        '仕様上、左揃えのときも無視されるが、それはAdjustFieldWidthが行ってくれる。
     626        flags And= Not Zero
     627    End If
    444628
    445629    Dim sb = New System.Text.StringBuilder
     
    459643
    460644        Dim len = (tr.MaxSize - bufStartPos) As Long
     645        If len < 0 Then
     646            Debug
     647        End If
    461648        If len < d Then
    462649            .Append(&h30 As StrChar, d - len)
     
    474661End Function
    475662
    476 '! QWordの最大値18446744073709551615の文字数 - 1。FormatIntegerLU内で使用。
     663/*!
     664@brief  QWordの最大値18446744073709551615の文字数 - 1。FormatIntegerLU内で使用。
     665@author Egtra
     666@date   2007/09/18
     667*/
    477668Const MaxSizeLU = 19
    478669
    479670/*!
    480 @brief 整数変換共通の前処理
    481 @author Egtra
    482 @date   2007/10/19
    483 @param[in, out] d   精度。DWORD_MAXで省略とみなされ、精度1になる。
    484 @param[in, out] flags   フラグ。精度が指定されたとき、Zeroを消す。
    485 */
    486 Sub PreProcessFormatInteger(ByRef d As DWord, ByRef flags As FormatFlags)
    487     If d = DWORD_MAX Then
    488         d = 1
    489     Else
    490         '精度が指定されているとき、ゼロフラグは無視される。
    491         '仕様上、左揃えのときも無視されるが、それはAdjustFieldWidthが行ってくれる。
    492         flags And= Not Zero
    493     End If
    494 End Sub
    495 
    496 /*!
    497 @brief 文字列をフィールド幅まで満たされるように空白などを挿入する。
    498 @param [in,out] sb  対象文字列
    499 @param [in] field   フィールド幅
    500 @param [in] hasSign 符号を持っている(負の値か)か否か
    501 @param [in] flags   フラグ
    502 @param [in] prefixLen   (あれば)接頭辞の文字数。ゼロ埋めする際、この数だけ挿入位置を後ろにする。
     671@brief  文字列をフィールド幅まで満たされるように空白などを挿入する。
     672@author Egtra
     673@date   2007/10/13
     674@param[in,out] sb   対象文字列
     675@param[in] field    フィールド幅
     676@param[in] hasSign  符号を持っている(負の値か)か否か
     677@param[in] flags    フラグ
     678@param[in] prefixLen    (あれば)接頭辞の文字数。ゼロ埋めする際、この数だけ挿入位置を後ろにする。
    503679sbが"-1"のように負符号を持っている場合は、呼出元でSignフラグ(またはBlank)を立てること。
    504680*/
  • trunk/TestCase/SimpleTestCase/SPrintFTest.ab

    r364 r365  
    9696    UnitTest("FormatFloatF(1.00, precision = 2)", Right$(s, 6) = "000.00")
    9797
    98 '   s = FormatIntegerLU(8589934590, DWORD_MAX, 0, None)
    99 '   UnitTest("FormatIntegerLU(8589934590)", s = "8589934590")
     98    s = FormatIntegerLO(&hFFFFFFFFFFFFFFFF, 0, 0, Alt)
     99    UnitTest("FormatIntegerLO(&hFFFFFFFFFFFFFFFF, Alt) = 01777777777777777777777", s = "01777777777777777777777")
     100    s = FormatIntegerLX(&h123456789abcdef0, 0, 0, None)
     101    UnitTest("FormatIntegerLX(&h123456789abcdef0)", s = "123456789abcdef0")
     102    s = FormatIntegerLU(8589934590 As QWord, DWORD_MAX, 0, None)
     103    UnitTest("FormatIntegerLU(8589934590)", s = "8589934590")
     104    s = FormatIntegerLD(-8589934590, DWORD_MAX, 0, None)
     105    UnitTest("FormatIntegerLD(-8589934590)", s = "-8589934590")
    100106End Sub
    101107
Note: See TracChangeset for help on using the changeset viewer.