properties.go 20 KB

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