/vendor/github.com/magiconair/properties/properties.go

https://gitlab.com/rolfzhang/kanban · Go · 746 lines · 487 code · 105 blank · 154 comment · 124 complexity · a10eba65297a3d5193b28c18bc62466e MD5 · raw file

  1. // Copyright 2013-2014 Frank Schroeder. 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 properties
  5. // BUG(frank): Set() does not check for invalid unicode literals since this is currently handled by the lexer.
  6. // BUG(frank): Write() does not allow to configure the newline character. Therefore, on Windows LF is used.
  7. import (
  8. "fmt"
  9. "io"
  10. "log"
  11. "os"
  12. "regexp"
  13. "strconv"
  14. "strings"
  15. "time"
  16. "unicode/utf8"
  17. )
  18. // ErrorHandlerFunc defines the type of function which handles failures
  19. // of the MustXXX() functions. An error handler function must exit
  20. // the application after handling the error.
  21. type ErrorHandlerFunc func(error)
  22. // ErrorHandler is the function which handles failures of the MustXXX()
  23. // functions. The default is LogFatalHandler.
  24. var ErrorHandler = LogFatalHandler
  25. // LogFatalHandler handles the error by logging a fatal error and exiting.
  26. func LogFatalHandler(err error) {
  27. log.Fatal(err)
  28. }
  29. // PanicHandler handles the error by panicking.
  30. func PanicHandler(err error) {
  31. panic(err)
  32. }
  33. // -----------------------------------------------------------------------------
  34. // A Properties contains the key/value pairs from the properties input.
  35. // All values are stored in unexpanded form and are expanded at runtime
  36. type Properties struct {
  37. // Pre-/Postfix for property expansion.
  38. Prefix string
  39. Postfix string
  40. // DisableExpansion controls the expansion of properties on Get()
  41. // and the check for circular references on Set(). When set to
  42. // true Properties behaves like a simple key/value store and does
  43. // not check for circular references on Get() or on Set().
  44. DisableExpansion bool
  45. // Stores the key/value pairs
  46. m map[string]string
  47. // Stores the comments per key.
  48. c map[string][]string
  49. // Stores the keys in order of appearance.
  50. k []string
  51. }
  52. // NewProperties creates a new Properties struct with the default
  53. // configuration for "${key}" expressions.
  54. func NewProperties() *Properties {
  55. return &Properties{
  56. Prefix: "${",
  57. Postfix: "}",
  58. m: map[string]string{},
  59. c: map[string][]string{},
  60. k: []string{},
  61. }
  62. }
  63. // Get returns the expanded value for the given key if exists.
  64. // Otherwise, ok is false.
  65. func (p *Properties) Get(key string) (value string, ok bool) {
  66. v, ok := p.m[key]
  67. if p.DisableExpansion {
  68. return v, ok
  69. }
  70. if !ok {
  71. return "", false
  72. }
  73. expanded, err := p.expand(v)
  74. // we guarantee that the expanded value is free of
  75. // circular references and malformed expressions
  76. // so we panic if we still get an error here.
  77. if err != nil {
  78. ErrorHandler(fmt.Errorf("%s in %q", err, key+" = "+v))
  79. }
  80. return expanded, true
  81. }
  82. // MustGet returns the expanded value for the given key if exists.
  83. // Otherwise, it panics.
  84. func (p *Properties) MustGet(key string) string {
  85. if v, ok := p.Get(key); ok {
  86. return v
  87. }
  88. ErrorHandler(invalidKeyError(key))
  89. panic("ErrorHandler should exit")
  90. }
  91. // ----------------------------------------------------------------------------
  92. // ClearComments removes the comments for all keys.
  93. func (p *Properties) ClearComments() {
  94. p.c = map[string][]string{}
  95. }
  96. // ----------------------------------------------------------------------------
  97. // GetComment returns the last comment before the given key or an empty string.
  98. func (p *Properties) GetComment(key string) string {
  99. comments, ok := p.c[key]
  100. if !ok || len(comments) == 0 {
  101. return ""
  102. }
  103. return comments[len(comments)-1]
  104. }
  105. // ----------------------------------------------------------------------------
  106. // GetComments returns all comments that appeared before the given key or nil.
  107. func (p *Properties) GetComments(key string) []string {
  108. if comments, ok := p.c[key]; ok {
  109. return comments
  110. }
  111. return nil
  112. }
  113. // ----------------------------------------------------------------------------
  114. // SetComment sets the comment for the key.
  115. func (p *Properties) SetComment(key, comment string) {
  116. p.c[key] = []string{comment}
  117. }
  118. // ----------------------------------------------------------------------------
  119. // SetComments sets the comments for the key. If the comments are nil then
  120. // all comments for this key are deleted.
  121. func (p *Properties) SetComments(key string, comments []string) {
  122. if comments == nil {
  123. delete(p.c, key)
  124. return
  125. }
  126. p.c[key] = comments
  127. }
  128. // ----------------------------------------------------------------------------
  129. // GetBool checks if the expanded value is one of '1', 'yes',
  130. // 'true' or 'on' if the key exists. The comparison is case-insensitive.
  131. // If the key does not exist the default value is returned.
  132. func (p *Properties) GetBool(key string, def bool) bool {
  133. v, err := p.getBool(key)
  134. if err != nil {
  135. return def
  136. }
  137. return v
  138. }
  139. // MustGetBool checks if the expanded value is one of '1', 'yes',
  140. // 'true' or 'on' if the key exists. The comparison is case-insensitive.
  141. // If the key does not exist the function panics.
  142. func (p *Properties) MustGetBool(key string) bool {
  143. v, err := p.getBool(key)
  144. if err != nil {
  145. ErrorHandler(err)
  146. }
  147. return v
  148. }
  149. func (p *Properties) getBool(key string) (value bool, err error) {
  150. if v, ok := p.Get(key); ok {
  151. return boolVal(v), nil
  152. }
  153. return false, invalidKeyError(key)
  154. }
  155. func boolVal(v string) bool {
  156. v = strings.ToLower(v)
  157. return v == "1" || v == "true" || v == "yes" || v == "on"
  158. }
  159. // ----------------------------------------------------------------------------
  160. // GetDuration parses the expanded value as an time.Duration (in ns) if the
  161. // key exists. If key does not exist or the value cannot be parsed the default
  162. // value is returned. In almost all cases you want to use GetParsedDuration().
  163. func (p *Properties) GetDuration(key string, def time.Duration) time.Duration {
  164. v, err := p.getInt64(key)
  165. if err != nil {
  166. return def
  167. }
  168. return time.Duration(v)
  169. }
  170. // MustGetDuration parses the expanded value as an time.Duration (in ns) if
  171. // the key exists. If key does not exist or the value cannot be parsed the
  172. // function panics. In almost all cases you want to use MustGetParsedDuration().
  173. func (p *Properties) MustGetDuration(key string) time.Duration {
  174. v, err := p.getInt64(key)
  175. if err != nil {
  176. ErrorHandler(err)
  177. }
  178. return time.Duration(v)
  179. }
  180. // ----------------------------------------------------------------------------
  181. // GetParsedDuration parses the expanded value with time.ParseDuration() if the key exists.
  182. // If key does not exist or the value cannot be parsed the default
  183. // value is returned.
  184. func (p *Properties) GetParsedDuration(key string, def time.Duration) time.Duration {
  185. s, ok := p.Get(key)
  186. if !ok {
  187. return def
  188. }
  189. v, err := time.ParseDuration(s)
  190. if err != nil {
  191. return def
  192. }
  193. return v
  194. }
  195. // MustGetParsedDuration parses the expanded value with time.ParseDuration() if the key exists.
  196. // If key does not exist or the value cannot be parsed the function panics.
  197. func (p *Properties) MustGetParsedDuration(key string) time.Duration {
  198. s, ok := p.Get(key)
  199. if !ok {
  200. ErrorHandler(invalidKeyError(key))
  201. }
  202. v, err := time.ParseDuration(s)
  203. if err != nil {
  204. ErrorHandler(err)
  205. }
  206. return v
  207. }
  208. // ----------------------------------------------------------------------------
  209. // GetFloat64 parses the expanded value as a float64 if the key exists.
  210. // If key does not exist or the value cannot be parsed the default
  211. // value is returned.
  212. func (p *Properties) GetFloat64(key string, def float64) float64 {
  213. v, err := p.getFloat64(key)
  214. if err != nil {
  215. return def
  216. }
  217. return v
  218. }
  219. // MustGetFloat64 parses the expanded value as a float64 if the key exists.
  220. // If key does not exist or the value cannot be parsed the function panics.
  221. func (p *Properties) MustGetFloat64(key string) float64 {
  222. v, err := p.getFloat64(key)
  223. if err != nil {
  224. ErrorHandler(err)
  225. }
  226. return v
  227. }
  228. func (p *Properties) getFloat64(key string) (value float64, err error) {
  229. if v, ok := p.Get(key); ok {
  230. value, err = strconv.ParseFloat(v, 64)
  231. if err != nil {
  232. return 0, err
  233. }
  234. return value, nil
  235. }
  236. return 0, invalidKeyError(key)
  237. }
  238. // ----------------------------------------------------------------------------
  239. // GetInt parses the expanded value as an int if the key exists.
  240. // If key does not exist or the value cannot be parsed the default
  241. // value is returned. If the value does not fit into an int the
  242. // function panics with an out of range error.
  243. func (p *Properties) GetInt(key string, def int) int {
  244. v, err := p.getInt64(key)
  245. if err != nil {
  246. return def
  247. }
  248. return intRangeCheck(key, v)
  249. }
  250. // MustGetInt parses the expanded value as an int if the key exists.
  251. // If key does not exist or the value cannot be parsed the function panics.
  252. // If the value does not fit into an int the function panics with
  253. // an out of range error.
  254. func (p *Properties) MustGetInt(key string) int {
  255. v, err := p.getInt64(key)
  256. if err != nil {
  257. ErrorHandler(err)
  258. }
  259. return intRangeCheck(key, v)
  260. }
  261. // ----------------------------------------------------------------------------
  262. // GetInt64 parses the expanded value as an int64 if the key exists.
  263. // If key does not exist or the value cannot be parsed the default
  264. // value is returned.
  265. func (p *Properties) GetInt64(key string, def int64) int64 {
  266. v, err := p.getInt64(key)
  267. if err != nil {
  268. return def
  269. }
  270. return v
  271. }
  272. // MustGetInt64 parses the expanded value as an int if the key exists.
  273. // If key does not exist or the value cannot be parsed the function panics.
  274. func (p *Properties) MustGetInt64(key string) int64 {
  275. v, err := p.getInt64(key)
  276. if err != nil {
  277. ErrorHandler(err)
  278. }
  279. return v
  280. }
  281. func (p *Properties) getInt64(key string) (value int64, err error) {
  282. if v, ok := p.Get(key); ok {
  283. value, err = strconv.ParseInt(v, 10, 64)
  284. if err != nil {
  285. return 0, err
  286. }
  287. return value, nil
  288. }
  289. return 0, invalidKeyError(key)
  290. }
  291. // ----------------------------------------------------------------------------
  292. // GetUint parses the expanded value as an uint if the key exists.
  293. // If key does not exist or the value cannot be parsed the default
  294. // value is returned. If the value does not fit into an int the
  295. // function panics with an out of range error.
  296. func (p *Properties) GetUint(key string, def uint) uint {
  297. v, err := p.getUint64(key)
  298. if err != nil {
  299. return def
  300. }
  301. return uintRangeCheck(key, v)
  302. }
  303. // MustGetUint parses the expanded value as an int if the key exists.
  304. // If key does not exist or the value cannot be parsed the function panics.
  305. // If the value does not fit into an int the function panics with
  306. // an out of range error.
  307. func (p *Properties) MustGetUint(key string) uint {
  308. v, err := p.getUint64(key)
  309. if err != nil {
  310. ErrorHandler(err)
  311. }
  312. return uintRangeCheck(key, v)
  313. }
  314. // ----------------------------------------------------------------------------
  315. // GetUint64 parses the expanded value as an uint64 if the key exists.
  316. // If key does not exist or the value cannot be parsed the default
  317. // value is returned.
  318. func (p *Properties) GetUint64(key string, def uint64) uint64 {
  319. v, err := p.getUint64(key)
  320. if err != nil {
  321. return def
  322. }
  323. return v
  324. }
  325. // MustGetUint64 parses the expanded value as an int if the key exists.
  326. // If key does not exist or the value cannot be parsed the function panics.
  327. func (p *Properties) MustGetUint64(key string) uint64 {
  328. v, err := p.getUint64(key)
  329. if err != nil {
  330. ErrorHandler(err)
  331. }
  332. return v
  333. }
  334. func (p *Properties) getUint64(key string) (value uint64, err error) {
  335. if v, ok := p.Get(key); ok {
  336. value, err = strconv.ParseUint(v, 10, 64)
  337. if err != nil {
  338. return 0, err
  339. }
  340. return value, nil
  341. }
  342. return 0, invalidKeyError(key)
  343. }
  344. // ----------------------------------------------------------------------------
  345. // GetString returns the expanded value for the given key if exists or
  346. // the default value otherwise.
  347. func (p *Properties) GetString(key, def string) string {
  348. if v, ok := p.Get(key); ok {
  349. return v
  350. }
  351. return def
  352. }
  353. // MustGetString returns the expanded value for the given key if exists or
  354. // panics otherwise.
  355. func (p *Properties) MustGetString(key string) string {
  356. if v, ok := p.Get(key); ok {
  357. return v
  358. }
  359. ErrorHandler(invalidKeyError(key))
  360. panic("ErrorHandler should exit")
  361. }
  362. // ----------------------------------------------------------------------------
  363. // Filter returns a new properties object which contains all properties
  364. // for which the key matches the pattern.
  365. func (p *Properties) Filter(pattern string) (*Properties, error) {
  366. re, err := regexp.Compile(pattern)
  367. if err != nil {
  368. return nil, err
  369. }
  370. return p.FilterRegexp(re), nil
  371. }
  372. // FilterRegexp returns a new properties object which contains all properties
  373. // for which the key matches the regular expression.
  374. func (p *Properties) FilterRegexp(re *regexp.Regexp) *Properties {
  375. pp := NewProperties()
  376. for _, k := range p.k {
  377. if re.MatchString(k) {
  378. pp.Set(k, p.m[k])
  379. }
  380. }
  381. return pp
  382. }
  383. // FilterPrefix returns a new properties object with a subset of all keys
  384. // with the given prefix.
  385. func (p *Properties) FilterPrefix(prefix string) *Properties {
  386. pp := NewProperties()
  387. for _, k := range p.k {
  388. if strings.HasPrefix(k, prefix) {
  389. pp.Set(k, p.m[k])
  390. }
  391. }
  392. return pp
  393. }
  394. // FilterStripPrefix returns a new properties object with a subset of all keys
  395. // with the given prefix and the prefix removed from the keys.
  396. func (p *Properties) FilterStripPrefix(prefix string) *Properties {
  397. pp := NewProperties()
  398. n := len(prefix)
  399. for _, k := range p.k {
  400. if len(k) > len(prefix) && strings.HasPrefix(k, prefix) {
  401. pp.Set(k[n:], p.m[k])
  402. }
  403. }
  404. return pp
  405. }
  406. // Len returns the number of keys.
  407. func (p *Properties) Len() int {
  408. return len(p.m)
  409. }
  410. // Keys returns all keys in the same order as in the input.
  411. func (p *Properties) Keys() []string {
  412. keys := make([]string, len(p.k))
  413. for i, k := range p.k {
  414. keys[i] = k
  415. }
  416. return keys
  417. }
  418. // Set sets the property key to the corresponding value.
  419. // If a value for key existed before then ok is true and prev
  420. // contains the previous value. If the value contains a
  421. // circular reference or a malformed expression then
  422. // an error is returned.
  423. // An empty key is silently ignored.
  424. func (p *Properties) Set(key, value string) (prev string, ok bool, err error) {
  425. if key == "" {
  426. return "", false, nil
  427. }
  428. // if expansion is disabled we allow circular references
  429. if p.DisableExpansion {
  430. prev, ok = p.Get(key)
  431. p.m[key] = value
  432. return prev, ok, nil
  433. }
  434. // to check for a circular reference we temporarily need
  435. // to set the new value. If there is an error then revert
  436. // to the previous state. Only if all tests are successful
  437. // then we add the key to the p.k list.
  438. prev, ok = p.Get(key)
  439. p.m[key] = value
  440. // now check for a circular reference
  441. _, err = p.expand(value)
  442. if err != nil {
  443. // revert to the previous state
  444. if ok {
  445. p.m[key] = prev
  446. } else {
  447. delete(p.m, key)
  448. }
  449. return "", false, err
  450. }
  451. if !ok {
  452. p.k = append(p.k, key)
  453. }
  454. return prev, ok, nil
  455. }
  456. // MustSet sets the property key to the corresponding value.
  457. // If a value for key existed before then ok is true and prev
  458. // contains the previous value. An empty key is silently ignored.
  459. func (p *Properties) MustSet(key, value string) (prev string, ok bool) {
  460. prev, ok, err := p.Set(key, value)
  461. if err != nil {
  462. ErrorHandler(err)
  463. }
  464. return prev, ok
  465. }
  466. // String returns a string of all expanded 'key = value' pairs.
  467. func (p *Properties) String() string {
  468. var s string
  469. for _, key := range p.k {
  470. value, _ := p.Get(key)
  471. s = fmt.Sprintf("%s%s = %s\n", s, key, value)
  472. }
  473. return s
  474. }
  475. // Write writes all unexpanded 'key = value' pairs to the given writer.
  476. // Write returns the number of bytes written and any write error encountered.
  477. func (p *Properties) Write(w io.Writer, enc Encoding) (n int, err error) {
  478. return p.WriteComment(w, "", enc)
  479. }
  480. // WriteComment writes all unexpanced 'key = value' pairs to the given writer.
  481. // If prefix is not empty then comments are written with a blank line and the
  482. // given prefix. The prefix should be either "# " or "! " to be compatible with
  483. // the properties file format. Otherwise, the properties parser will not be
  484. // able to read the file back in. It returns the number of bytes written and
  485. // any write error encountered.
  486. func (p *Properties) WriteComment(w io.Writer, prefix string, enc Encoding) (n int, err error) {
  487. var x int
  488. for _, key := range p.k {
  489. value := p.m[key]
  490. if prefix != "" {
  491. if comments, ok := p.c[key]; ok {
  492. // don't print comments if they are all empty
  493. allEmpty := true
  494. for _, c := range comments {
  495. if c != "" {
  496. allEmpty = false
  497. break
  498. }
  499. }
  500. if !allEmpty {
  501. // add a blank line between entries but not at the top
  502. if len(comments) > 0 && n > 0 {
  503. x, err = fmt.Fprintln(w)
  504. if err != nil {
  505. return
  506. }
  507. n += x
  508. }
  509. for _, c := range comments {
  510. x, err = fmt.Fprintf(w, "%s%s\n", prefix, encode(c, "", enc))
  511. if err != nil {
  512. return
  513. }
  514. n += x
  515. }
  516. }
  517. }
  518. }
  519. x, err = fmt.Fprintf(w, "%s = %s\n", encode(key, " :", enc), encode(value, "", enc))
  520. if err != nil {
  521. return
  522. }
  523. n += x
  524. }
  525. return
  526. }
  527. // ----------------------------------------------------------------------------
  528. // Delete removes the key and its comments.
  529. func (p *Properties) Delete(key string) {
  530. delete(p.m, key)
  531. delete(p.c, key)
  532. newKeys := []string{}
  533. for _, k := range p.k {
  534. if k != key {
  535. newKeys = append(newKeys, key)
  536. }
  537. }
  538. p.k = newKeys
  539. }
  540. // ----------------------------------------------------------------------------
  541. // check expands all values and returns an error if a circular reference or
  542. // a malformed expression was found.
  543. func (p *Properties) check() error {
  544. for _, value := range p.m {
  545. if _, err := p.expand(value); err != nil {
  546. return err
  547. }
  548. }
  549. return nil
  550. }
  551. func (p *Properties) expand(input string) (string, error) {
  552. // no pre/postfix -> nothing to expand
  553. if p.Prefix == "" && p.Postfix == "" {
  554. return input, nil
  555. }
  556. return expand(input, make(map[string]bool), p.Prefix, p.Postfix, p.m)
  557. }
  558. // expand recursively expands expressions of '(prefix)key(postfix)' to their corresponding values.
  559. // The function keeps track of the keys that were already expanded and stops if it
  560. // detects a circular reference or a malformed expression of the form '(prefix)key'.
  561. func expand(s string, keys map[string]bool, prefix, postfix string, values map[string]string) (string, error) {
  562. start := strings.Index(s, prefix)
  563. if start == -1 {
  564. return s, nil
  565. }
  566. keyStart := start + len(prefix)
  567. keyLen := strings.Index(s[keyStart:], postfix)
  568. if keyLen == -1 {
  569. return "", fmt.Errorf("malformed expression")
  570. }
  571. end := keyStart + keyLen + len(postfix) - 1
  572. key := s[keyStart : keyStart+keyLen]
  573. // fmt.Printf("s:%q pp:%q start:%d end:%d keyStart:%d keyLen:%d key:%q\n", s, prefix + "..." + postfix, start, end, keyStart, keyLen, key)
  574. if _, ok := keys[key]; ok {
  575. return "", fmt.Errorf("circular reference")
  576. }
  577. val, ok := values[key]
  578. if !ok {
  579. val = os.Getenv(key)
  580. }
  581. // remember that we've seen the key
  582. keys[key] = true
  583. return expand(s[:start]+val+s[end+1:], keys, prefix, postfix, values)
  584. }
  585. // encode encodes a UTF-8 string to ISO-8859-1 and escapes some characters.
  586. func encode(s string, special string, enc Encoding) string {
  587. switch enc {
  588. case UTF8:
  589. return encodeUtf8(s, special)
  590. case ISO_8859_1:
  591. return encodeIso(s, special)
  592. default:
  593. panic(fmt.Sprintf("unsupported encoding %v", enc))
  594. }
  595. }
  596. func encodeUtf8(s string, special string) string {
  597. v := ""
  598. for pos := 0; pos < len(s); {
  599. r, w := utf8.DecodeRuneInString(s[pos:])
  600. pos += w
  601. v += escape(r, special)
  602. }
  603. return v
  604. }
  605. func encodeIso(s string, special string) string {
  606. var r rune
  607. var w int
  608. var v string
  609. for pos := 0; pos < len(s); {
  610. switch r, w = utf8.DecodeRuneInString(s[pos:]); {
  611. case r < 1<<8: // single byte rune -> escape special chars only
  612. v += escape(r, special)
  613. case r < 1<<16: // two byte rune -> unicode literal
  614. v += fmt.Sprintf("\\u%04x", r)
  615. default: // more than two bytes per rune -> can't encode
  616. v += "?"
  617. }
  618. pos += w
  619. }
  620. return v
  621. }
  622. func escape(r rune, special string) string {
  623. switch r {
  624. case '\f':
  625. return "\\f"
  626. case '\n':
  627. return "\\n"
  628. case '\r':
  629. return "\\r"
  630. case '\t':
  631. return "\\t"
  632. default:
  633. if strings.ContainsRune(special, r) {
  634. return "\\" + string(r)
  635. }
  636. return string(r)
  637. }
  638. }
  639. func invalidKeyError(key string) error {
  640. return fmt.Errorf("unknown property: %s", key)
  641. }