decode_meta.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. package toml
  2. import "strings"
  3. // MetaData allows access to meta information about TOML data that may not
  4. // be inferrable via reflection. In particular, whether a key has been defined
  5. // and the TOML type of a key.
  6. type MetaData struct {
  7. mapping map[string]interface{}
  8. types map[string]tomlType
  9. keys []Key
  10. decoded map[string]bool
  11. context Key // Used only during decoding.
  12. }
  13. // IsDefined returns true if the key given exists in the TOML data. The key
  14. // should be specified hierarchially. e.g.,
  15. //
  16. // // access the TOML key 'a.b.c'
  17. // IsDefined("a", "b", "c")
  18. //
  19. // IsDefined will return false if an empty key given. Keys are case sensitive.
  20. func (md *MetaData) IsDefined(key ...string) bool {
  21. if len(key) == 0 {
  22. return false
  23. }
  24. var hash map[string]interface{}
  25. var ok bool
  26. var hashOrVal interface{} = md.mapping
  27. for _, k := range key {
  28. if hash, ok = hashOrVal.(map[string]interface{}); !ok {
  29. return false
  30. }
  31. if hashOrVal, ok = hash[k]; !ok {
  32. return false
  33. }
  34. }
  35. return true
  36. }
  37. // Type returns a string representation of the type of the key specified.
  38. //
  39. // Type will return the empty string if given an empty key or a key that
  40. // does not exist. Keys are case sensitive.
  41. func (md *MetaData) Type(key ...string) string {
  42. fullkey := strings.Join(key, ".")
  43. if typ, ok := md.types[fullkey]; ok {
  44. return typ.typeString()
  45. }
  46. return ""
  47. }
  48. // Key is the type of any TOML key, including key groups. Use (MetaData).Keys
  49. // to get values of this type.
  50. type Key []string
  51. func (k Key) String() string {
  52. return strings.Join(k, ".")
  53. }
  54. func (k Key) maybeQuotedAll() string {
  55. var ss []string
  56. for i := range k {
  57. ss = append(ss, k.maybeQuoted(i))
  58. }
  59. return strings.Join(ss, ".")
  60. }
  61. func (k Key) maybeQuoted(i int) string {
  62. quote := false
  63. for _, c := range k[i] {
  64. if !isBareKeyChar(c) {
  65. quote = true
  66. break
  67. }
  68. }
  69. if quote {
  70. return "\"" + strings.Replace(k[i], "\"", "\\\"", -1) + "\""
  71. } else {
  72. return k[i]
  73. }
  74. }
  75. func (k Key) add(piece string) Key {
  76. newKey := make(Key, len(k)+1)
  77. copy(newKey, k)
  78. newKey[len(k)] = piece
  79. return newKey
  80. }
  81. // Keys returns a slice of every key in the TOML data, including key groups.
  82. // Each key is itself a slice, where the first element is the top of the
  83. // hierarchy and the last is the most specific.
  84. //
  85. // The list will have the same order as the keys appeared in the TOML data.
  86. //
  87. // All keys returned are non-empty.
  88. func (md *MetaData) Keys() []Key {
  89. return md.keys
  90. }
  91. // Undecoded returns all keys that have not been decoded in the order in which
  92. // they appear in the original TOML document.
  93. //
  94. // This includes keys that haven't been decoded because of a Primitive value.
  95. // Once the Primitive value is decoded, the keys will be considered decoded.
  96. //
  97. // Also note that decoding into an empty interface will result in no decoding,
  98. // and so no keys will be considered decoded.
  99. //
  100. // In this sense, the Undecoded keys correspond to keys in the TOML document
  101. // that do not have a concrete type in your representation.
  102. func (md *MetaData) Undecoded() []Key {
  103. undecoded := make([]Key, 0, len(md.keys))
  104. for _, key := range md.keys {
  105. if !md.decoded[key.String()] {
  106. undecoded = append(undecoded, key)
  107. }
  108. }
  109. return undecoded
  110. }