resolver.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. /*
  2. Licensed under the Apache License, Version 2.0 (the "License");
  3. you may not use this file except in compliance with the License.
  4. You may obtain a copy of the License at
  5. http://www.apache.org/licenses/LICENSE-2.0
  6. Unless required by applicable law or agreed to in writing, software
  7. distributed under the License is distributed on an "AS IS" BASIS,
  8. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  9. See the License for the specific language governing permissions and
  10. limitations under the License.
  11. */
  12. package candiedyaml
  13. import (
  14. "bytes"
  15. "encoding/base64"
  16. "fmt"
  17. "math"
  18. "reflect"
  19. "regexp"
  20. "strconv"
  21. "strings"
  22. "time"
  23. )
  24. var byteSliceType = reflect.TypeOf([]byte(nil))
  25. var binary_tags = [][]byte{[]byte("!binary"), []byte(yaml_BINARY_TAG)}
  26. var bool_values map[string]bool
  27. var null_values map[string]bool
  28. var signs = []byte{'-', '+'}
  29. var nulls = []byte{'~', 'n', 'N'}
  30. var bools = []byte{'t', 'T', 'f', 'F', 'y', 'Y', 'n', 'N', 'o', 'O'}
  31. var timestamp_regexp *regexp.Regexp
  32. var ymd_regexp *regexp.Regexp
  33. func init() {
  34. bool_values = make(map[string]bool)
  35. bool_values["y"] = true
  36. bool_values["yes"] = true
  37. bool_values["n"] = false
  38. bool_values["no"] = false
  39. bool_values["true"] = true
  40. bool_values["false"] = false
  41. bool_values["on"] = true
  42. bool_values["off"] = false
  43. null_values = make(map[string]bool)
  44. null_values["~"] = true
  45. null_values["null"] = true
  46. null_values["Null"] = true
  47. null_values["NULL"] = true
  48. timestamp_regexp = regexp.MustCompile("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:(?:[Tt]|[ \t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \t]*(?:Z|([-+][0-9][0-9]?)(?::([0-9][0-9])?)?))?)?$")
  49. ymd_regexp = regexp.MustCompile("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)$")
  50. }
  51. func resolve(event yaml_event_t, v reflect.Value, useNumber bool) (string, error) {
  52. val := string(event.value)
  53. if null_values[val] {
  54. v.Set(reflect.Zero(v.Type()))
  55. return yaml_NULL_TAG, nil
  56. }
  57. switch v.Kind() {
  58. case reflect.String:
  59. if useNumber && v.Type() == numberType {
  60. tag, i := resolveInterface(event, useNumber)
  61. if n, ok := i.(Number); ok {
  62. v.Set(reflect.ValueOf(n))
  63. return tag, nil
  64. }
  65. return "", fmt.Errorf("Not a number: '%s' at %s", event.value, event.start_mark)
  66. }
  67. return resolve_string(val, v, event)
  68. case reflect.Bool:
  69. return resolve_bool(val, v, event)
  70. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  71. return resolve_int(val, v, useNumber, event)
  72. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  73. return resolve_uint(val, v, useNumber, event)
  74. case reflect.Float32, reflect.Float64:
  75. return resolve_float(val, v, useNumber, event)
  76. case reflect.Interface:
  77. _, i := resolveInterface(event, useNumber)
  78. if i != nil {
  79. v.Set(reflect.ValueOf(i))
  80. } else {
  81. v.Set(reflect.Zero(v.Type()))
  82. }
  83. case reflect.Struct:
  84. return resolve_time(val, v, event)
  85. case reflect.Slice:
  86. if v.Type() != byteSliceType {
  87. return "", fmt.Errorf("Cannot resolve %s into %s at %s", val, v.String(), event.start_mark)
  88. }
  89. b, err := decode_binary(event.value, event)
  90. if err != nil {
  91. return "", err
  92. }
  93. v.Set(reflect.ValueOf(b))
  94. default:
  95. return "", fmt.Errorf("Unknown resolution for '%s' using %s at %s", val, v.String(), event.start_mark)
  96. }
  97. return yaml_STR_TAG, nil
  98. }
  99. func hasBinaryTag(event yaml_event_t) bool {
  100. for _, tag := range binary_tags {
  101. if bytes.Equal(event.tag, tag) {
  102. return true
  103. }
  104. }
  105. return false
  106. }
  107. func decode_binary(value []byte, event yaml_event_t) ([]byte, error) {
  108. b := make([]byte, base64.StdEncoding.DecodedLen(len(value)))
  109. n, err := base64.StdEncoding.Decode(b, value)
  110. if err != nil {
  111. return nil, fmt.Errorf("Invalid base64 text: '%s' at %s", string(b), event.start_mark)
  112. }
  113. return b[:n], nil
  114. }
  115. func resolve_string(val string, v reflect.Value, event yaml_event_t) (string, error) {
  116. if len(event.tag) > 0 {
  117. if hasBinaryTag(event) {
  118. b, err := decode_binary(event.value, event)
  119. if err != nil {
  120. return "", err
  121. }
  122. val = string(b)
  123. }
  124. }
  125. v.SetString(val)
  126. return yaml_STR_TAG, nil
  127. }
  128. func resolve_bool(val string, v reflect.Value, event yaml_event_t) (string, error) {
  129. b, found := bool_values[strings.ToLower(val)]
  130. if !found {
  131. return "", fmt.Errorf("Invalid boolean: '%s' at %s", val, event.start_mark)
  132. }
  133. v.SetBool(b)
  134. return yaml_BOOL_TAG, nil
  135. }
  136. func resolve_int(val string, v reflect.Value, useNumber bool, event yaml_event_t) (string, error) {
  137. original := val
  138. val = strings.Replace(val, "_", "", -1)
  139. var value uint64
  140. isNumberValue := v.Type() == numberType
  141. sign := int64(1)
  142. if val[0] == '-' {
  143. sign = -1
  144. val = val[1:]
  145. } else if val[0] == '+' {
  146. val = val[1:]
  147. }
  148. base := 0
  149. if val == "0" {
  150. if isNumberValue {
  151. v.SetString("0")
  152. } else {
  153. v.Set(reflect.Zero(v.Type()))
  154. }
  155. return yaml_INT_TAG, nil
  156. }
  157. if strings.HasPrefix(val, "0o") {
  158. base = 8
  159. val = val[2:]
  160. }
  161. value, err := strconv.ParseUint(val, base, 64)
  162. if err != nil {
  163. return "", fmt.Errorf("Invalid integer: '%s' at %s", original, event.start_mark)
  164. }
  165. var val64 int64
  166. if value <= math.MaxInt64 {
  167. val64 = int64(value)
  168. if sign == -1 {
  169. val64 = -val64
  170. }
  171. } else if sign == -1 && value == uint64(math.MaxInt64)+1 {
  172. val64 = math.MinInt64
  173. } else {
  174. return "", fmt.Errorf("Invalid integer: '%s' at %s", original, event.start_mark)
  175. }
  176. if isNumberValue {
  177. v.SetString(strconv.FormatInt(val64, 10))
  178. } else {
  179. if v.OverflowInt(val64) {
  180. return "", fmt.Errorf("Invalid integer: '%s' at %s", original, event.start_mark)
  181. }
  182. v.SetInt(val64)
  183. }
  184. return yaml_INT_TAG, nil
  185. }
  186. func resolve_uint(val string, v reflect.Value, useNumber bool, event yaml_event_t) (string, error) {
  187. original := val
  188. val = strings.Replace(val, "_", "", -1)
  189. var value uint64
  190. isNumberValue := v.Type() == numberType
  191. if val[0] == '-' {
  192. return "", fmt.Errorf("Unsigned int with negative value: '%s' at %s", original, event.start_mark)
  193. }
  194. if val[0] == '+' {
  195. val = val[1:]
  196. }
  197. base := 0
  198. if val == "0" {
  199. if isNumberValue {
  200. v.SetString("0")
  201. } else {
  202. v.Set(reflect.Zero(v.Type()))
  203. }
  204. return yaml_INT_TAG, nil
  205. }
  206. if strings.HasPrefix(val, "0o") {
  207. base = 8
  208. val = val[2:]
  209. }
  210. value, err := strconv.ParseUint(val, base, 64)
  211. if err != nil {
  212. return "", fmt.Errorf("Invalid unsigned integer: '%s' at %s", val, event.start_mark)
  213. }
  214. if isNumberValue {
  215. v.SetString(strconv.FormatUint(value, 10))
  216. } else {
  217. if v.OverflowUint(value) {
  218. return "", fmt.Errorf("Invalid unsigned integer: '%s' at %s", val, event.start_mark)
  219. }
  220. v.SetUint(value)
  221. }
  222. return yaml_INT_TAG, nil
  223. }
  224. func resolve_float(val string, v reflect.Value, useNumber bool, event yaml_event_t) (string, error) {
  225. val = strings.Replace(val, "_", "", -1)
  226. var value float64
  227. isNumberValue := v.Type() == numberType
  228. typeBits := 64
  229. if !isNumberValue {
  230. typeBits = v.Type().Bits()
  231. }
  232. sign := 1
  233. if val[0] == '-' {
  234. sign = -1
  235. val = val[1:]
  236. } else if val[0] == '+' {
  237. val = val[1:]
  238. }
  239. valLower := strings.ToLower(val)
  240. if valLower == ".inf" {
  241. value = math.Inf(sign)
  242. } else if valLower == ".nan" {
  243. value = math.NaN()
  244. } else {
  245. var err error
  246. value, err = strconv.ParseFloat(val, typeBits)
  247. value *= float64(sign)
  248. if err != nil {
  249. return "", fmt.Errorf("Invalid float: '%s' at %s", val, event.start_mark)
  250. }
  251. }
  252. if isNumberValue {
  253. v.SetString(strconv.FormatFloat(value, 'g', -1, typeBits))
  254. } else {
  255. if v.OverflowFloat(value) {
  256. return "", fmt.Errorf("Invalid float: '%s' at %s", val, event.start_mark)
  257. }
  258. v.SetFloat(value)
  259. }
  260. return yaml_FLOAT_TAG, nil
  261. }
  262. func resolve_time(val string, v reflect.Value, event yaml_event_t) (string, error) {
  263. var parsedTime time.Time
  264. matches := ymd_regexp.FindStringSubmatch(val)
  265. if len(matches) > 0 {
  266. year, _ := strconv.Atoi(matches[1])
  267. month, _ := strconv.Atoi(matches[2])
  268. day, _ := strconv.Atoi(matches[3])
  269. parsedTime = time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC)
  270. } else {
  271. matches = timestamp_regexp.FindStringSubmatch(val)
  272. if len(matches) == 0 {
  273. return "", fmt.Errorf("Invalid timestamp: '%s' at %s", val, event.start_mark)
  274. }
  275. year, _ := strconv.Atoi(matches[1])
  276. month, _ := strconv.Atoi(matches[2])
  277. day, _ := strconv.Atoi(matches[3])
  278. hour, _ := strconv.Atoi(matches[4])
  279. min, _ := strconv.Atoi(matches[5])
  280. sec, _ := strconv.Atoi(matches[6])
  281. nsec := 0
  282. if matches[7] != "" {
  283. millis, _ := strconv.Atoi(matches[7])
  284. nsec = int(time.Duration(millis) * time.Millisecond)
  285. }
  286. loc := time.UTC
  287. if matches[8] != "" {
  288. sign := matches[8][0]
  289. hr, _ := strconv.Atoi(matches[8][1:])
  290. min := 0
  291. if matches[9] != "" {
  292. min, _ = strconv.Atoi(matches[9])
  293. }
  294. zoneOffset := (hr*60 + min) * 60
  295. if sign == '-' {
  296. zoneOffset = -zoneOffset
  297. }
  298. loc = time.FixedZone("", zoneOffset)
  299. }
  300. parsedTime = time.Date(year, time.Month(month), day, hour, min, sec, nsec, loc)
  301. }
  302. v.Set(reflect.ValueOf(parsedTime))
  303. return "", nil
  304. }
  305. func resolveInterface(event yaml_event_t, useNumber bool) (string, interface{}) {
  306. val := string(event.value)
  307. if len(event.tag) == 0 && !event.implicit {
  308. return "", val
  309. }
  310. if len(val) == 0 {
  311. return yaml_NULL_TAG, nil
  312. }
  313. var result interface{}
  314. sign := false
  315. c := val[0]
  316. switch {
  317. case bytes.IndexByte(signs, c) != -1:
  318. sign = true
  319. fallthrough
  320. case c >= '0' && c <= '9':
  321. i := int64(0)
  322. result = &i
  323. if useNumber {
  324. var n Number
  325. result = &n
  326. }
  327. v := reflect.ValueOf(result).Elem()
  328. if _, err := resolve_int(val, v, useNumber, event); err == nil {
  329. return yaml_INT_TAG, v.Interface()
  330. }
  331. f := float64(0)
  332. result = &f
  333. if useNumber {
  334. var n Number
  335. result = &n
  336. }
  337. v = reflect.ValueOf(result).Elem()
  338. if _, err := resolve_float(val, v, useNumber, event); err == nil {
  339. return yaml_FLOAT_TAG, v.Interface()
  340. }
  341. if !sign {
  342. t := time.Time{}
  343. if _, err := resolve_time(val, reflect.ValueOf(&t).Elem(), event); err == nil {
  344. return "", t
  345. }
  346. }
  347. case bytes.IndexByte(nulls, c) != -1:
  348. if null_values[val] {
  349. return yaml_NULL_TAG, nil
  350. }
  351. b := false
  352. if _, err := resolve_bool(val, reflect.ValueOf(&b).Elem(), event); err == nil {
  353. return yaml_BOOL_TAG, b
  354. }
  355. case c == '.':
  356. f := float64(0)
  357. result = &f
  358. if useNumber {
  359. var n Number
  360. result = &n
  361. }
  362. v := reflect.ValueOf(result).Elem()
  363. if _, err := resolve_float(val, v, useNumber, event); err == nil {
  364. return yaml_FLOAT_TAG, v.Interface()
  365. }
  366. case bytes.IndexByte(bools, c) != -1:
  367. b := false
  368. if _, err := resolve_bool(val, reflect.ValueOf(&b).Elem(), event); err == nil {
  369. return yaml_BOOL_TAG, b
  370. }
  371. }
  372. if hasBinaryTag(event) {
  373. bytes, err := decode_binary(event.value, event)
  374. if err == nil {
  375. return yaml_BINARY_TAG, bytes
  376. }
  377. }
  378. return yaml_STR_TAG, val
  379. }