gentest.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. // Copyright 2013 The Go Authors. 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. // +build ignore
  5. // This program generates internet protocol constants by reading IANA
  6. // protocol registries.
  7. //
  8. // Usage:
  9. // go run gentest.go > iana_test.go
  10. package main
  11. import (
  12. "bytes"
  13. "encoding/xml"
  14. "fmt"
  15. "go/format"
  16. "io"
  17. "net/http"
  18. "os"
  19. "strconv"
  20. "strings"
  21. )
  22. var registries = []struct {
  23. url string
  24. parse func(io.Writer, io.Reader) error
  25. }{
  26. {
  27. "http://www.iana.org/assignments/dscp-registry/dscp-registry.xml",
  28. parseDSCPRegistry,
  29. },
  30. {
  31. "http://www.iana.org/assignments/ipv4-tos-byte/ipv4-tos-byte.xml",
  32. parseTOSTCByte,
  33. },
  34. }
  35. func main() {
  36. var bb bytes.Buffer
  37. fmt.Fprintf(&bb, "// go run gentv.go\n")
  38. fmt.Fprintf(&bb, "// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n\n")
  39. fmt.Fprintf(&bb, "package ipv4_test\n\n")
  40. for _, r := range registries {
  41. resp, err := http.Get(r.url)
  42. if err != nil {
  43. fmt.Fprintln(os.Stderr, err)
  44. os.Exit(1)
  45. }
  46. defer resp.Body.Close()
  47. if resp.StatusCode != http.StatusOK {
  48. fmt.Fprintf(os.Stderr, "got HTTP status code %v for %v\n", resp.StatusCode, r.url)
  49. os.Exit(1)
  50. }
  51. if err := r.parse(&bb, resp.Body); err != nil {
  52. fmt.Fprintln(os.Stderr, err)
  53. os.Exit(1)
  54. }
  55. fmt.Fprintf(&bb, "\n")
  56. }
  57. b, err := format.Source(bb.Bytes())
  58. if err != nil {
  59. fmt.Fprintln(os.Stderr, err)
  60. os.Exit(1)
  61. }
  62. os.Stdout.Write(b)
  63. }
  64. func parseDSCPRegistry(w io.Writer, r io.Reader) error {
  65. dec := xml.NewDecoder(r)
  66. var dr dscpRegistry
  67. if err := dec.Decode(&dr); err != nil {
  68. return err
  69. }
  70. drs := dr.escape()
  71. fmt.Fprintf(w, "// %s, Updated: %s\n", dr.Title, dr.Updated)
  72. fmt.Fprintf(w, "const (\n")
  73. for _, dr := range drs {
  74. fmt.Fprintf(w, "DiffServ%s = %#x", dr.Name, dr.Value)
  75. fmt.Fprintf(w, "// %s\n", dr.OrigName)
  76. }
  77. fmt.Fprintf(w, ")\n")
  78. return nil
  79. }
  80. type dscpRegistry struct {
  81. XMLName xml.Name `xml:"registry"`
  82. Title string `xml:"title"`
  83. Updated string `xml:"updated"`
  84. Note string `xml:"note"`
  85. RegTitle string `xml:"registry>title"`
  86. PoolRecords []dscpRecord `xml:"registry>record"`
  87. Records []dscpRecord `xml:"registry>registry>record"`
  88. }
  89. type dscpRecord struct {
  90. Name string `xml:"name"`
  91. Space string `xml:"space"`
  92. }
  93. type canonDSCPRecord struct {
  94. OrigName string
  95. Name string
  96. Value int
  97. }
  98. func (drr *dscpRegistry) escape() []canonDSCPRecord {
  99. drs := make([]canonDSCPRecord, len(drr.Records))
  100. sr := strings.NewReplacer(
  101. "+", "",
  102. "-", "",
  103. "/", "",
  104. ".", "",
  105. " ", "",
  106. )
  107. for i, dr := range drr.Records {
  108. s := strings.TrimSpace(dr.Name)
  109. drs[i].OrigName = s
  110. drs[i].Name = sr.Replace(s)
  111. n, err := strconv.ParseUint(dr.Space, 2, 8)
  112. if err != nil {
  113. continue
  114. }
  115. drs[i].Value = int(n) << 2
  116. }
  117. return drs
  118. }
  119. func parseTOSTCByte(w io.Writer, r io.Reader) error {
  120. dec := xml.NewDecoder(r)
  121. var ttb tosTCByte
  122. if err := dec.Decode(&ttb); err != nil {
  123. return err
  124. }
  125. trs := ttb.escape()
  126. fmt.Fprintf(w, "// %s, Updated: %s\n", ttb.Title, ttb.Updated)
  127. fmt.Fprintf(w, "const (\n")
  128. for _, tr := range trs {
  129. fmt.Fprintf(w, "%s = %#x", tr.Keyword, tr.Value)
  130. fmt.Fprintf(w, "// %s\n", tr.OrigKeyword)
  131. }
  132. fmt.Fprintf(w, ")\n")
  133. return nil
  134. }
  135. type tosTCByte struct {
  136. XMLName xml.Name `xml:"registry"`
  137. Title string `xml:"title"`
  138. Updated string `xml:"updated"`
  139. Note string `xml:"note"`
  140. RegTitle string `xml:"registry>title"`
  141. Records []tosTCByteRecord `xml:"registry>record"`
  142. }
  143. type tosTCByteRecord struct {
  144. Binary string `xml:"binary"`
  145. Keyword string `xml:"keyword"`
  146. }
  147. type canonTOSTCByteRecord struct {
  148. OrigKeyword string
  149. Keyword string
  150. Value int
  151. }
  152. func (ttb *tosTCByte) escape() []canonTOSTCByteRecord {
  153. trs := make([]canonTOSTCByteRecord, len(ttb.Records))
  154. sr := strings.NewReplacer(
  155. "Capable", "",
  156. "(", "",
  157. ")", "",
  158. "+", "",
  159. "-", "",
  160. "/", "",
  161. ".", "",
  162. " ", "",
  163. )
  164. for i, tr := range ttb.Records {
  165. s := strings.TrimSpace(tr.Keyword)
  166. trs[i].OrigKeyword = s
  167. ss := strings.Split(s, " ")
  168. if len(ss) > 1 {
  169. trs[i].Keyword = strings.Join(ss[1:], " ")
  170. } else {
  171. trs[i].Keyword = ss[0]
  172. }
  173. trs[i].Keyword = sr.Replace(trs[i].Keyword)
  174. n, err := strconv.ParseUint(tr.Binary, 2, 8)
  175. if err != nil {
  176. continue
  177. }
  178. trs[i].Value = int(n)
  179. }
  180. return trs
  181. }