25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

536 lines
14 KiB

  1. // Copyright 2017 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package number
  5. import (
  6. "strconv"
  7. "unicode/utf8"
  8. "golang.org/x/text/language"
  9. )
  10. // TODO:
  11. // - grouping of fractions
  12. // - allow user-defined superscript notation (such as <sup>4</sup>)
  13. // - same for non-breaking spaces, like &nbsp;
  14. // A VisibleDigits computes digits, comma placement and trailing zeros as they
  15. // will be shown to the user.
  16. type VisibleDigits interface {
  17. Digits(buf []byte, t language.Tag, scale int) Digits
  18. // TODO: Do we also need to add the verb or pass a format.State?
  19. }
  20. // Formatting proceeds along the following lines:
  21. // 0) Compose rounding information from format and context.
  22. // 1) Convert a number into a Decimal.
  23. // 2) Sanitize Decimal by adding trailing zeros, removing leading digits, and
  24. // (non-increment) rounding. The Decimal that results from this is suitable
  25. // for determining the plural form.
  26. // 3) Render the Decimal in the localized form.
  27. // Formatter contains all the information needed to render a number.
  28. type Formatter struct {
  29. Pattern
  30. Info
  31. }
  32. func (f *Formatter) init(t language.Tag, index []uint8) {
  33. f.Info = InfoFromTag(t)
  34. f.Pattern = formats[index[tagToID(t)]]
  35. }
  36. // InitPattern initializes a Formatter for the given Pattern.
  37. func (f *Formatter) InitPattern(t language.Tag, pat *Pattern) {
  38. f.Info = InfoFromTag(t)
  39. f.Pattern = *pat
  40. }
  41. // InitDecimal initializes a Formatter using the default Pattern for the given
  42. // language.
  43. func (f *Formatter) InitDecimal(t language.Tag) {
  44. f.init(t, tagToDecimal)
  45. }
  46. // InitScientific initializes a Formatter using the default Pattern for the
  47. // given language.
  48. func (f *Formatter) InitScientific(t language.Tag) {
  49. f.init(t, tagToScientific)
  50. f.Pattern.MinFractionDigits = 0
  51. f.Pattern.MaxFractionDigits = -1
  52. }
  53. // InitEngineering initializes a Formatter using the default Pattern for the
  54. // given language.
  55. func (f *Formatter) InitEngineering(t language.Tag) {
  56. f.init(t, tagToScientific)
  57. f.Pattern.MinFractionDigits = 0
  58. f.Pattern.MaxFractionDigits = -1
  59. f.Pattern.MaxIntegerDigits = 3
  60. f.Pattern.MinIntegerDigits = 1
  61. }
  62. // InitPercent initializes a Formatter using the default Pattern for the given
  63. // language.
  64. func (f *Formatter) InitPercent(t language.Tag) {
  65. f.init(t, tagToPercent)
  66. }
  67. // InitPerMille initializes a Formatter using the default Pattern for the given
  68. // language.
  69. func (f *Formatter) InitPerMille(t language.Tag) {
  70. f.init(t, tagToPercent)
  71. f.Pattern.DigitShift = 3
  72. }
  73. func (f *Formatter) Append(dst []byte, x interface{}) []byte {
  74. var d Decimal
  75. r := f.RoundingContext
  76. d.Convert(r, x)
  77. return f.Render(dst, FormatDigits(&d, r))
  78. }
  79. func FormatDigits(d *Decimal, r RoundingContext) Digits {
  80. if r.isScientific() {
  81. return scientificVisibleDigits(r, d)
  82. }
  83. return decimalVisibleDigits(r, d)
  84. }
  85. func (f *Formatter) Format(dst []byte, d *Decimal) []byte {
  86. return f.Render(dst, FormatDigits(d, f.RoundingContext))
  87. }
  88. func (f *Formatter) Render(dst []byte, d Digits) []byte {
  89. var result []byte
  90. var postPrefix, preSuffix int
  91. if d.IsScientific {
  92. result, postPrefix, preSuffix = appendScientific(dst, f, &d)
  93. } else {
  94. result, postPrefix, preSuffix = appendDecimal(dst, f, &d)
  95. }
  96. if f.PadRune == 0 {
  97. return result
  98. }
  99. width := int(f.FormatWidth)
  100. if count := utf8.RuneCount(result); count < width {
  101. insertPos := 0
  102. switch f.Flags & PadMask {
  103. case PadAfterPrefix:
  104. insertPos = postPrefix
  105. case PadBeforeSuffix:
  106. insertPos = preSuffix
  107. case PadAfterSuffix:
  108. insertPos = len(result)
  109. }
  110. num := width - count
  111. pad := [utf8.UTFMax]byte{' '}
  112. sz := 1
  113. if r := f.PadRune; r != 0 {
  114. sz = utf8.EncodeRune(pad[:], r)
  115. }
  116. extra := sz * num
  117. if n := len(result) + extra; n < cap(result) {
  118. result = result[:n]
  119. copy(result[insertPos+extra:], result[insertPos:])
  120. } else {
  121. buf := make([]byte, n)
  122. copy(buf, result[:insertPos])
  123. copy(buf[insertPos+extra:], result[insertPos:])
  124. result = buf
  125. }
  126. for ; num > 0; num-- {
  127. insertPos += copy(result[insertPos:], pad[:sz])
  128. }
  129. }
  130. return result
  131. }
  132. // decimalVisibleDigits converts d according to the RoundingContext. Note that
  133. // the exponent may change as a result of this operation.
  134. func decimalVisibleDigits(r RoundingContext, d *Decimal) Digits {
  135. if d.NaN || d.Inf {
  136. return Digits{digits: digits{Neg: d.Neg, NaN: d.NaN, Inf: d.Inf}}
  137. }
  138. n := Digits{digits: d.normalize().digits}
  139. exp := n.Exp
  140. exp += int32(r.DigitShift)
  141. // Cap integer digits. Remove *most-significant* digits.
  142. if r.MaxIntegerDigits > 0 {
  143. if p := int(exp) - int(r.MaxIntegerDigits); p > 0 {
  144. if p > len(n.Digits) {
  145. p = len(n.Digits)
  146. }
  147. if n.Digits = n.Digits[p:]; len(n.Digits) == 0 {
  148. exp = 0
  149. } else {
  150. exp -= int32(p)
  151. }
  152. // Strip leading zeros.
  153. for len(n.Digits) > 0 && n.Digits[0] == 0 {
  154. n.Digits = n.Digits[1:]
  155. exp--
  156. }
  157. }
  158. }
  159. // Rounding if not already done by Convert.
  160. p := len(n.Digits)
  161. if maxSig := int(r.MaxSignificantDigits); maxSig > 0 {
  162. p = maxSig
  163. }
  164. if maxFrac := int(r.MaxFractionDigits); maxFrac >= 0 {
  165. if cap := int(exp) + maxFrac; cap < p {
  166. p = int(exp) + maxFrac
  167. }
  168. if p < 0 {
  169. p = 0
  170. }
  171. }
  172. n.round(r.Mode, p)
  173. // set End (trailing zeros)
  174. n.End = int32(len(n.Digits))
  175. if n.End == 0 {
  176. exp = 0
  177. if r.MinFractionDigits > 0 {
  178. n.End = int32(r.MinFractionDigits)
  179. }
  180. if p := int32(r.MinSignificantDigits) - 1; p > n.End {
  181. n.End = p
  182. }
  183. } else {
  184. if end := exp + int32(r.MinFractionDigits); end > n.End {
  185. n.End = end
  186. }
  187. if n.End < int32(r.MinSignificantDigits) {
  188. n.End = int32(r.MinSignificantDigits)
  189. }
  190. }
  191. n.Exp = exp
  192. return n
  193. }
  194. // appendDecimal appends a formatted number to dst. It returns two possible
  195. // insertion points for padding.
  196. func appendDecimal(dst []byte, f *Formatter, n *Digits) (b []byte, postPre, preSuf int) {
  197. if dst, ok := f.renderSpecial(dst, n); ok {
  198. return dst, 0, len(dst)
  199. }
  200. digits := n.Digits
  201. exp := n.Exp
  202. // Split in integer and fraction part.
  203. var intDigits, fracDigits []byte
  204. numInt := 0
  205. numFrac := int(n.End - n.Exp)
  206. if exp > 0 {
  207. numInt = int(exp)
  208. if int(exp) >= len(digits) { // ddddd | ddddd00
  209. intDigits = digits
  210. } else { // ddd.dd
  211. intDigits = digits[:exp]
  212. fracDigits = digits[exp:]
  213. }
  214. } else {
  215. fracDigits = digits
  216. }
  217. neg := n.Neg
  218. affix, suffix := f.getAffixes(neg)
  219. dst = appendAffix(dst, f, affix, neg)
  220. savedLen := len(dst)
  221. minInt := int(f.MinIntegerDigits)
  222. if minInt == 0 && f.MinSignificantDigits > 0 {
  223. minInt = 1
  224. }
  225. // add leading zeros
  226. for i := minInt; i > numInt; i-- {
  227. dst = f.AppendDigit(dst, 0)
  228. if f.needsSep(i) {
  229. dst = append(dst, f.Symbol(SymGroup)...)
  230. }
  231. }
  232. i := 0
  233. for ; i < len(intDigits); i++ {
  234. dst = f.AppendDigit(dst, intDigits[i])
  235. if f.needsSep(numInt - i) {
  236. dst = append(dst, f.Symbol(SymGroup)...)
  237. }
  238. }
  239. for ; i < numInt; i++ {
  240. dst = f.AppendDigit(dst, 0)
  241. if f.needsSep(numInt - i) {
  242. dst = append(dst, f.Symbol(SymGroup)...)
  243. }
  244. }
  245. if numFrac > 0 || f.Flags&AlwaysDecimalSeparator != 0 {
  246. dst = append(dst, f.Symbol(SymDecimal)...)
  247. }
  248. // Add trailing zeros
  249. i = 0
  250. for n := -int(n.Exp); i < n; i++ {
  251. dst = f.AppendDigit(dst, 0)
  252. }
  253. for _, d := range fracDigits {
  254. i++
  255. dst = f.AppendDigit(dst, d)
  256. }
  257. for ; i < numFrac; i++ {
  258. dst = f.AppendDigit(dst, 0)
  259. }
  260. return appendAffix(dst, f, suffix, neg), savedLen, len(dst)
  261. }
  262. func scientificVisibleDigits(r RoundingContext, d *Decimal) Digits {
  263. if d.NaN || d.Inf {
  264. return Digits{digits: digits{Neg: d.Neg, NaN: d.NaN, Inf: d.Inf}}
  265. }
  266. n := Digits{digits: d.normalize().digits, IsScientific: true}
  267. // Normalize to have at least one digit. This simplifies engineering
  268. // notation.
  269. if len(n.Digits) == 0 {
  270. n.Digits = append(n.Digits, 0)
  271. n.Exp = 1
  272. }
  273. // Significant digits are transformed by the parser for scientific notation
  274. // and do not need to be handled here.
  275. maxInt, numInt := int(r.MaxIntegerDigits), int(r.MinIntegerDigits)
  276. if numInt == 0 {
  277. numInt = 1
  278. }
  279. // If a maximum number of integers is specified, the minimum must be 1
  280. // and the exponent is grouped by this number (e.g. for engineering)
  281. if maxInt > numInt {
  282. // Correct the exponent to reflect a single integer digit.
  283. numInt = 1
  284. // engineering
  285. // 0.01234 ([12345]e-1) -> 1.2345e-2 12.345e-3
  286. // 12345 ([12345]e+5) -> 1.2345e4 12.345e3
  287. d := int(n.Exp-1) % maxInt
  288. if d < 0 {
  289. d += maxInt
  290. }
  291. numInt += d
  292. }
  293. p := len(n.Digits)
  294. if maxSig := int(r.MaxSignificantDigits); maxSig > 0 {
  295. p = maxSig
  296. }
  297. if maxFrac := int(r.MaxFractionDigits); maxFrac >= 0 && numInt+maxFrac < p {
  298. p = numInt + maxFrac
  299. }
  300. n.round(r.Mode, p)
  301. n.Comma = uint8(numInt)
  302. n.End = int32(len(n.Digits))
  303. if minSig := int32(r.MinFractionDigits) + int32(numInt); n.End < minSig {
  304. n.End = minSig
  305. }
  306. return n
  307. }
  308. // appendScientific appends a formatted number to dst. It returns two possible
  309. // insertion points for padding.
  310. func appendScientific(dst []byte, f *Formatter, n *Digits) (b []byte, postPre, preSuf int) {
  311. if dst, ok := f.renderSpecial(dst, n); ok {
  312. return dst, 0, 0
  313. }
  314. digits := n.Digits
  315. numInt := int(n.Comma)
  316. numFrac := int(n.End) - int(n.Comma)
  317. var intDigits, fracDigits []byte
  318. if numInt <= len(digits) {
  319. intDigits = digits[:numInt]
  320. fracDigits = digits[numInt:]
  321. } else {
  322. intDigits = digits
  323. }
  324. neg := n.Neg
  325. affix, suffix := f.getAffixes(neg)
  326. dst = appendAffix(dst, f, affix, neg)
  327. savedLen := len(dst)
  328. i := 0
  329. for ; i < len(intDigits); i++ {
  330. dst = f.AppendDigit(dst, intDigits[i])
  331. if f.needsSep(numInt - i) {
  332. dst = append(dst, f.Symbol(SymGroup)...)
  333. }
  334. }
  335. for ; i < numInt; i++ {
  336. dst = f.AppendDigit(dst, 0)
  337. if f.needsSep(numInt - i) {
  338. dst = append(dst, f.Symbol(SymGroup)...)
  339. }
  340. }
  341. if numFrac > 0 || f.Flags&AlwaysDecimalSeparator != 0 {
  342. dst = append(dst, f.Symbol(SymDecimal)...)
  343. }
  344. i = 0
  345. for ; i < len(fracDigits); i++ {
  346. dst = f.AppendDigit(dst, fracDigits[i])
  347. }
  348. for ; i < numFrac; i++ {
  349. dst = f.AppendDigit(dst, 0)
  350. }
  351. // exp
  352. buf := [12]byte{}
  353. // TODO: use exponential if superscripting is not available (no Latin
  354. // numbers or no tags) and use exponential in all other cases.
  355. exp := n.Exp - int32(n.Comma)
  356. exponential := f.Symbol(SymExponential)
  357. if exponential == "E" {
  358. dst = append(dst, "\u202f"...) // NARROW NO-BREAK SPACE
  359. dst = append(dst, f.Symbol(SymSuperscriptingExponent)...)
  360. dst = append(dst, "\u202f"...) // NARROW NO-BREAK SPACE
  361. dst = f.AppendDigit(dst, 1)
  362. dst = f.AppendDigit(dst, 0)
  363. switch {
  364. case exp < 0:
  365. dst = append(dst, superMinus...)
  366. exp = -exp
  367. case f.Flags&AlwaysExpSign != 0:
  368. dst = append(dst, superPlus...)
  369. }
  370. b = strconv.AppendUint(buf[:0], uint64(exp), 10)
  371. for i := len(b); i < int(f.MinExponentDigits); i++ {
  372. dst = append(dst, superDigits[0]...)
  373. }
  374. for _, c := range b {
  375. dst = append(dst, superDigits[c-'0']...)
  376. }
  377. } else {
  378. dst = append(dst, exponential...)
  379. switch {
  380. case exp < 0:
  381. dst = append(dst, f.Symbol(SymMinusSign)...)
  382. exp = -exp
  383. case f.Flags&AlwaysExpSign != 0:
  384. dst = append(dst, f.Symbol(SymPlusSign)...)
  385. }
  386. b = strconv.AppendUint(buf[:0], uint64(exp), 10)
  387. for i := len(b); i < int(f.MinExponentDigits); i++ {
  388. dst = f.AppendDigit(dst, 0)
  389. }
  390. for _, c := range b {
  391. dst = f.AppendDigit(dst, c-'0')
  392. }
  393. }
  394. return appendAffix(dst, f, suffix, neg), savedLen, len(dst)
  395. }
  396. const (
  397. superMinus = "\u207B" // SUPERSCRIPT HYPHEN-MINUS
  398. superPlus = "\u207A" // SUPERSCRIPT PLUS SIGN
  399. )
  400. var (
  401. // Note: the digits are not sequential!!!
  402. superDigits = []string{
  403. "\u2070", // SUPERSCRIPT DIGIT ZERO
  404. "\u00B9", // SUPERSCRIPT DIGIT ONE
  405. "\u00B2", // SUPERSCRIPT DIGIT TWO
  406. "\u00B3", // SUPERSCRIPT DIGIT THREE
  407. "\u2074", // SUPERSCRIPT DIGIT FOUR
  408. "\u2075", // SUPERSCRIPT DIGIT FIVE
  409. "\u2076", // SUPERSCRIPT DIGIT SIX
  410. "\u2077", // SUPERSCRIPT DIGIT SEVEN
  411. "\u2078", // SUPERSCRIPT DIGIT EIGHT
  412. "\u2079", // SUPERSCRIPT DIGIT NINE
  413. }
  414. )
  415. func (f *Formatter) getAffixes(neg bool) (affix, suffix string) {
  416. str := f.Affix
  417. if str != "" {
  418. if f.NegOffset > 0 {
  419. if neg {
  420. str = str[f.NegOffset:]
  421. } else {
  422. str = str[:f.NegOffset]
  423. }
  424. }
  425. sufStart := 1 + str[0]
  426. affix = str[1:sufStart]
  427. suffix = str[sufStart+1:]
  428. }
  429. // TODO: introduce a NeedNeg sign to indicate if the left pattern already
  430. // has a sign marked?
  431. if f.NegOffset == 0 && (neg || f.Flags&AlwaysSign != 0) {
  432. affix = "-" + affix
  433. }
  434. return affix, suffix
  435. }
  436. func (f *Formatter) renderSpecial(dst []byte, d *Digits) (b []byte, ok bool) {
  437. if d.NaN {
  438. return fmtNaN(dst, f), true
  439. }
  440. if d.Inf {
  441. return fmtInfinite(dst, f, d), true
  442. }
  443. return dst, false
  444. }
  445. func fmtNaN(dst []byte, f *Formatter) []byte {
  446. return append(dst, f.Symbol(SymNan)...)
  447. }
  448. func fmtInfinite(dst []byte, f *Formatter, d *Digits) []byte {
  449. affix, suffix := f.getAffixes(d.Neg)
  450. dst = appendAffix(dst, f, affix, d.Neg)
  451. dst = append(dst, f.Symbol(SymInfinity)...)
  452. dst = appendAffix(dst, f, suffix, d.Neg)
  453. return dst
  454. }
  455. func appendAffix(dst []byte, f *Formatter, affix string, neg bool) []byte {
  456. quoting := false
  457. escaping := false
  458. for _, r := range affix {
  459. switch {
  460. case escaping:
  461. // escaping occurs both inside and outside of quotes
  462. dst = append(dst, string(r)...)
  463. escaping = false
  464. case r == '\\':
  465. escaping = true
  466. case r == '\'':
  467. quoting = !quoting
  468. case quoting:
  469. dst = append(dst, string(r)...)
  470. case r == '%':
  471. if f.DigitShift == 3 {
  472. dst = append(dst, f.Symbol(SymPerMille)...)
  473. } else {
  474. dst = append(dst, f.Symbol(SymPercentSign)...)
  475. }
  476. case r == '-' || r == '+':
  477. if neg {
  478. dst = append(dst, f.Symbol(SymMinusSign)...)
  479. } else if f.Flags&ElideSign == 0 {
  480. dst = append(dst, f.Symbol(SymPlusSign)...)
  481. } else {
  482. dst = append(dst, ' ')
  483. }
  484. default:
  485. dst = append(dst, string(r)...)
  486. }
  487. }
  488. return dst
  489. }