@@ -22,10 +22,10 @@ import Foundation
2222 //=------------------------------------------------------------------------=
2323
2424 @usableFromInline let id : ID
25- @usableFromInline let label : Label
2625 @usableFromInline let lexicon : Lexicon
2726 @usableFromInline let preferences : Preferences
28-
27+ @usableFromInline let instruction : Instruction ?
28+
2929 //=------------------------------------------------------------------------=
3030 // MARK: Initializers
3131 //=------------------------------------------------------------------------=
@@ -36,19 +36,16 @@ import Foundation
3636 formatter. currencyCode = id. code
3737 assert ( formatter. numberStyle == . none)
3838 //=--------------------------------------=
39- // MARK: Instantiate
40- //=--------------------------------------=
41- self . id = id
42- //=--------------------------------------=
4339 // MARK: Instantiate - None
4440 //=--------------------------------------=
41+ self . id = id
4542 self . lexicon = . currency( formatter)
46- self . label = . currency( id, lexicon)
4743 //=--------------------------------------=
4844 // MARK: Instantiate - Currency
4945 //=--------------------------------------=
5046 formatter. numberStyle = . currency
5147 self . preferences = Preferences ( formatter)
48+ self . instruction = Instruction ( id, lexicon)
5249 }
5350
5451 //=------------------------------------------------------------------------=
@@ -102,29 +99,101 @@ import Foundation
10299 formatter. maximumFractionDigits
103100 }
104101 }
102+
103+ //*========================================================================*
104+ // MARK: * Instruction
105+ //*========================================================================*
106+
107+ /// A model for marking currency labels as virtual.
108+ ///
109+ /// The characters used to express currencies are usually disjoint
110+ /// from the characters used to express their amounts, but sometimes they include fraction separators.
111+ /// This instruction is used to efficiently mark faux fraction separators, when they exist.
112+ ///
113+ @usableFromInline struct Instruction {
114+
115+ //=--------------------------------------------------------------------=
116+ // MARK: State
117+ //=--------------------------------------------------------------------=
118+
119+ @usableFromInline let occurances : Int
120+ @usableFromInline let character : Character
121+ @usableFromInline let direction : Direction
122+
123+ //=--------------------------------------------------------------------=
124+ // MARK: Initializers
125+ //=--------------------------------------------------------------------=
126+
127+ @inlinable init ? < S> ( _ label: S , _ character: Character ,
128+ _ direction: Direction ) where S: Sequence , S. Element == Character {
129+ self . occurances = label. count ( where: { $0 == character } )
130+ //=--------------------------------------=
131+ // MARK: Validate
132+ //=--------------------------------------=
133+ guard occurances > 0 else { return nil }
134+ //=--------------------------------------=
135+ // MARK: Instantiate
136+ //=--------------------------------------=
137+ self . character = character
138+ self . direction = direction
139+ }
140+
141+ @inlinable init ? ( _ id: ID , _ lexicon: Lexicon ) {
142+ let separator = lexicon. separators [ . fraction]
143+ let labels = IntegerFormatStyle < Int >
144+ . Currency ( code: id. code, locale: id. locale)
145+ . precision ( . fractionLength( 0 ) ) . format ( 0 ) . split (
146+ separator: lexicon. digits [ . zero] ,
147+ omittingEmptySubsequences: false )
148+ //=----------------------------------=
149+ // MARK: Instantiate
150+ //=----------------------------------=
151+ if let instance = Self ( labels [ 0 ] , separator, . forwards) { self = instance }
152+ else if let instance = Self ( labels [ 1 ] , separator, . backwards) { self = instance }
153+ else { return nil }
154+ }
155+
156+ //=------------------------------------------------------------------------=
157+ // MARK: Utilities
158+ //=------------------------------------------------------------------------=
159+
160+ @inlinable func autocorrect( _ snapshot: inout Snapshot ) {
161+ switch direction {
162+ case . forwards: autocorrect ( & snapshot, indices: snapshot. indices)
163+ case . backwards: autocorrect ( & snapshot, indices: snapshot. indices. reversed ( ) )
164+ }
165+ }
166+
167+ @inlinable func autocorrect< S> ( _ snapshot: inout Snapshot ,
168+ indices: S ) where S: Sequence , S. Element == Snapshot . Index {
169+ var count = 0 ; for index in indices where
170+ snapshot [ index] . character == character {
171+ snapshot. update ( attributes: index) { $0 = . phantom }
172+ count += 1 ; guard count < occurances else { return }
173+ }
174+ }
175+ }
105176}
106177
107178//=----------------------------------------------------------------------------=
108- // MARK: + Specialization
179+ // MARK: + Scheme
109180//=----------------------------------------------------------------------------=
110181
111182extension NumericTextSchemeXCurrency {
112183
113184 //=------------------------------------------------------------------------=
114- // MARK: Preferences
185+ // MARK: Autocorrect
115186 //=------------------------------------------------------------------------=
116187
117- @inlinable func precision < T > ( _ value : T . Type ) -> Precision < T > where T : Value {
118- Precision ( fraction : preferences . fraction )
188+ @inlinable func autocorrect ( _ snapshot : inout Snapshot ) {
189+ instruction ? . autocorrect ( & snapshot )
119190 }
120191
121192 //=------------------------------------------------------------------------=
122- // MARK: Autocorrect
193+ // MARK: Preferences
123194 //=------------------------------------------------------------------------=
124195
125- @inlinable func autocorrect( _ snapshot: inout Snapshot ) {
126- guard !label. characters. isEmpty else { return }
127- guard let indices = label. indices ( in: snapshot) else { return }
128- snapshot. update ( attributes: indices) { attribute in attribute = . phantom }
196+ @inlinable func precision< T> ( _ value: T . Type ) -> Precision < T > where T: Value {
197+ Precision ( fraction: preferences. fraction)
129198 }
130199}
0 commit comments