decode_meta.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  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. }
  72. return k[i]
  73. }
  74. func (k Key) add(piece string) Key {
  75. newKey := make(Key, len(k)+1)
  76. copy(newKey, k)
  77. newKey[len(k)] = piece
  78. return newKey
  79. }
  80. // Keys returns a slice of every key in the TOML data, including key groups.
  81. // Each key is itself a slice, where the first element is the top of the
  82. // hierarchy and the last is the most specific.
  83. //
  84. // The list will have the same order as the keys appeared in the TOML data.
  85. //
  86. // All keys returned are non-empty.
  87. func (md *MetaData) Keys() []Key {
  88. return md.keys
  89. }
  90. // Undecoded returns all keys that have not been decoded in the order in which
  91. // they appear in the original TOML document.
  92. //
  93. // This includes keys that haven't been decoded because of a Primitive value.
  94. // Once the Primitive value is decoded, the keys will be considered decoded.
  95. //
  96. // Also note that decoding into an empty interface will result in no decoding,
  97. // and so no keys will be considered decoded.
  98. //
  99. // In this sense, the Undecoded keys correspond to keys in the TOML document
  100. // that do not have a concrete type in your representation.
  101. func (md *MetaData) Undecoded() []Key {
  102. undecoded := make([]Key, 0, len(md.keys))
  103. for _, key := range md.keys {
  104. if !md.decoded[key.String()] {
  105. undecoded = append(undecoded, key)
  106. }
  107. }
  108. return undecoded
  109. }