本站源代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

453 lines
11KB

  1. // Package denco provides fast URL router.
  2. package denco
  3. import (
  4. "fmt"
  5. "sort"
  6. "strings"
  7. )
  8. const (
  9. // ParamCharacter is a special character for path parameter.
  10. ParamCharacter = ':'
  11. // WildcardCharacter is a special character for wildcard path parameter.
  12. WildcardCharacter = '*'
  13. // TerminationCharacter is a special character for end of path.
  14. TerminationCharacter = '#'
  15. // MaxSize is max size of records and internal slice.
  16. MaxSize = (1 << 22) - 1
  17. )
  18. // Router represents a URL router.
  19. type Router struct {
  20. // SizeHint expects the maximum number of path parameters in records to Build.
  21. // SizeHint will be used to determine the capacity of the memory to allocate.
  22. // By default, SizeHint will be determined from given records to Build.
  23. SizeHint int
  24. static map[string]interface{}
  25. param *doubleArray
  26. }
  27. // New returns a new Router.
  28. func New() *Router {
  29. return &Router{
  30. SizeHint: -1,
  31. static: make(map[string]interface{}),
  32. param: newDoubleArray(),
  33. }
  34. }
  35. // Lookup returns data and path parameters that associated with path.
  36. // params is a slice of the Param that arranged in the order in which parameters appeared.
  37. // e.g. when built routing path is "/path/to/:id/:name" and given path is "/path/to/1/alice". params order is [{"id": "1"}, {"name": "alice"}], not [{"name": "alice"}, {"id": "1"}].
  38. func (rt *Router) Lookup(path string) (data interface{}, params Params, found bool) {
  39. if data, found := rt.static[path]; found {
  40. return data, nil, true
  41. }
  42. if len(rt.param.node) == 1 {
  43. return nil, nil, false
  44. }
  45. nd, params, found := rt.param.lookup(path, make([]Param, 0, rt.SizeHint), 1)
  46. if !found {
  47. return nil, nil, false
  48. }
  49. for i := 0; i < len(params); i++ {
  50. params[i].Name = nd.paramNames[i]
  51. }
  52. return nd.data, params, true
  53. }
  54. // Build builds URL router from records.
  55. func (rt *Router) Build(records []Record) error {
  56. statics, params := makeRecords(records)
  57. if len(params) > MaxSize {
  58. return fmt.Errorf("denco: too many records")
  59. }
  60. if rt.SizeHint < 0 {
  61. rt.SizeHint = 0
  62. for _, p := range params {
  63. size := 0
  64. for _, k := range p.Key {
  65. if k == ParamCharacter || k == WildcardCharacter {
  66. size++
  67. }
  68. }
  69. if size > rt.SizeHint {
  70. rt.SizeHint = size
  71. }
  72. }
  73. }
  74. for _, r := range statics {
  75. rt.static[r.Key] = r.Value
  76. }
  77. if err := rt.param.build(params, 1, 0, make(map[int]struct{})); err != nil {
  78. return err
  79. }
  80. return nil
  81. }
  82. // Param represents name and value of path parameter.
  83. type Param struct {
  84. Name string
  85. Value string
  86. }
  87. // Params represents the name and value of path parameters.
  88. type Params []Param
  89. // Get gets the first value associated with the given name.
  90. // If there are no values associated with the key, Get returns "".
  91. func (ps Params) Get(name string) string {
  92. for _, p := range ps {
  93. if p.Name == name {
  94. return p.Value
  95. }
  96. }
  97. return ""
  98. }
  99. type doubleArray struct {
  100. bc []baseCheck
  101. node []*node
  102. }
  103. func newDoubleArray() *doubleArray {
  104. return &doubleArray{
  105. bc: []baseCheck{0},
  106. node: []*node{nil}, // A start index is adjusting to 1 because 0 will be used as a mark of non-existent node.
  107. }
  108. }
  109. // baseCheck contains BASE, CHECK and Extra flags.
  110. // From the top, 22bits of BASE, 2bits of Extra flags and 8bits of CHECK.
  111. //
  112. // BASE (22bit) | Extra flags (2bit) | CHECK (8bit)
  113. // |----------------------|--|--------|
  114. // 32 10 8 0
  115. type baseCheck uint32
  116. func (bc baseCheck) Base() int {
  117. return int(bc >> 10)
  118. }
  119. func (bc *baseCheck) SetBase(base int) {
  120. *bc |= baseCheck(base) << 10
  121. }
  122. func (bc baseCheck) Check() byte {
  123. return byte(bc)
  124. }
  125. func (bc *baseCheck) SetCheck(check byte) {
  126. *bc |= baseCheck(check)
  127. }
  128. func (bc baseCheck) IsEmpty() bool {
  129. return bc&0xfffffcff == 0
  130. }
  131. func (bc baseCheck) IsSingleParam() bool {
  132. return bc&paramTypeSingle == paramTypeSingle
  133. }
  134. func (bc baseCheck) IsWildcardParam() bool {
  135. return bc&paramTypeWildcard == paramTypeWildcard
  136. }
  137. func (bc baseCheck) IsAnyParam() bool {
  138. return bc&paramTypeAny != 0
  139. }
  140. func (bc *baseCheck) SetSingleParam() {
  141. *bc |= (1 << 8)
  142. }
  143. func (bc *baseCheck) SetWildcardParam() {
  144. *bc |= (1 << 9)
  145. }
  146. const (
  147. paramTypeSingle = 0x0100
  148. paramTypeWildcard = 0x0200
  149. paramTypeAny = 0x0300
  150. )
  151. func (da *doubleArray) lookup(path string, params []Param, idx int) (*node, []Param, bool) {
  152. indices := make([]uint64, 0, 1)
  153. for i := 0; i < len(path); i++ {
  154. if da.bc[idx].IsAnyParam() {
  155. indices = append(indices, (uint64(i)<<32)|(uint64(idx)&0xffffffff))
  156. }
  157. c := path[i]
  158. if idx = nextIndex(da.bc[idx].Base(), c); idx >= len(da.bc) || da.bc[idx].Check() != c {
  159. goto BACKTRACKING
  160. }
  161. }
  162. if next := nextIndex(da.bc[idx].Base(), TerminationCharacter); next < len(da.bc) && da.bc[next].Check() == TerminationCharacter {
  163. return da.node[da.bc[next].Base()], params, true
  164. }
  165. BACKTRACKING:
  166. for j := len(indices) - 1; j >= 0; j-- {
  167. i, idx := int(indices[j]>>32), int(indices[j]&0xffffffff)
  168. if da.bc[idx].IsSingleParam() {
  169. idx := nextIndex(da.bc[idx].Base(), ParamCharacter)
  170. if idx >= len(da.bc) {
  171. break
  172. }
  173. next := NextSeparator(path, i)
  174. params := append(params, Param{Value: path[i:next]})
  175. if nd, params, found := da.lookup(path[next:], params, idx); found {
  176. return nd, params, true
  177. }
  178. }
  179. if da.bc[idx].IsWildcardParam() {
  180. idx := nextIndex(da.bc[idx].Base(), WildcardCharacter)
  181. params := append(params, Param{Value: path[i:]})
  182. return da.node[da.bc[idx].Base()], params, true
  183. }
  184. }
  185. return nil, nil, false
  186. }
  187. // build builds double-array from records.
  188. func (da *doubleArray) build(srcs []*record, idx, depth int, usedBase map[int]struct{}) error {
  189. sort.Stable(recordSlice(srcs))
  190. base, siblings, leaf, err := da.arrange(srcs, idx, depth, usedBase)
  191. if err != nil {
  192. return err
  193. }
  194. if leaf != nil {
  195. nd, err := makeNode(leaf)
  196. if err != nil {
  197. return err
  198. }
  199. da.bc[idx].SetBase(len(da.node))
  200. da.node = append(da.node, nd)
  201. }
  202. for _, sib := range siblings {
  203. da.setCheck(nextIndex(base, sib.c), sib.c)
  204. }
  205. for _, sib := range siblings {
  206. records := srcs[sib.start:sib.end]
  207. switch sib.c {
  208. case ParamCharacter:
  209. for _, r := range records {
  210. next := NextSeparator(r.Key, depth+1)
  211. name := r.Key[depth+1 : next]
  212. r.paramNames = append(r.paramNames, name)
  213. r.Key = r.Key[next:]
  214. }
  215. da.bc[idx].SetSingleParam()
  216. if err := da.build(records, nextIndex(base, sib.c), 0, usedBase); err != nil {
  217. return err
  218. }
  219. case WildcardCharacter:
  220. r := records[0]
  221. name := r.Key[depth+1 : len(r.Key)-1]
  222. r.paramNames = append(r.paramNames, name)
  223. r.Key = ""
  224. da.bc[idx].SetWildcardParam()
  225. if err := da.build(records, nextIndex(base, sib.c), 0, usedBase); err != nil {
  226. return err
  227. }
  228. default:
  229. if err := da.build(records, nextIndex(base, sib.c), depth+1, usedBase); err != nil {
  230. return err
  231. }
  232. }
  233. }
  234. return nil
  235. }
  236. // setBase sets BASE.
  237. func (da *doubleArray) setBase(i, base int) {
  238. da.bc[i].SetBase(base)
  239. }
  240. // setCheck sets CHECK.
  241. func (da *doubleArray) setCheck(i int, check byte) {
  242. da.bc[i].SetCheck(check)
  243. }
  244. // findEmptyIndex returns an index of unused BASE/CHECK node.
  245. func (da *doubleArray) findEmptyIndex(start int) int {
  246. i := start
  247. for ; i < len(da.bc); i++ {
  248. if da.bc[i].IsEmpty() {
  249. break
  250. }
  251. }
  252. return i
  253. }
  254. // findBase returns good BASE.
  255. func (da *doubleArray) findBase(siblings []sibling, start int, usedBase map[int]struct{}) (base int) {
  256. for idx, firstChar := start+1, siblings[0].c; ; idx = da.findEmptyIndex(idx + 1) {
  257. base = nextIndex(idx, firstChar)
  258. if _, used := usedBase[base]; used {
  259. continue
  260. }
  261. i := 0
  262. for ; i < len(siblings); i++ {
  263. next := nextIndex(base, siblings[i].c)
  264. if len(da.bc) <= next {
  265. da.bc = append(da.bc, make([]baseCheck, next-len(da.bc)+1)...)
  266. }
  267. if !da.bc[next].IsEmpty() {
  268. break
  269. }
  270. }
  271. if i == len(siblings) {
  272. break
  273. }
  274. }
  275. usedBase[base] = struct{}{}
  276. return base
  277. }
  278. func (da *doubleArray) arrange(records []*record, idx, depth int, usedBase map[int]struct{}) (base int, siblings []sibling, leaf *record, err error) {
  279. siblings, leaf, err = makeSiblings(records, depth)
  280. if err != nil {
  281. return -1, nil, nil, err
  282. }
  283. if len(siblings) < 1 {
  284. return -1, nil, leaf, nil
  285. }
  286. base = da.findBase(siblings, idx, usedBase)
  287. if base > MaxSize {
  288. return -1, nil, nil, fmt.Errorf("denco: too many elements of internal slice")
  289. }
  290. da.setBase(idx, base)
  291. return base, siblings, leaf, err
  292. }
  293. // node represents a node of Double-Array.
  294. type node struct {
  295. data interface{}
  296. // Names of path parameters.
  297. paramNames []string
  298. }
  299. // makeNode returns a new node from record.
  300. func makeNode(r *record) (*node, error) {
  301. dups := make(map[string]bool)
  302. for _, name := range r.paramNames {
  303. if dups[name] {
  304. return nil, fmt.Errorf("denco: path parameter `%v' is duplicated in the key `%v'", name, r.Key)
  305. }
  306. dups[name] = true
  307. }
  308. return &node{data: r.Value, paramNames: r.paramNames}, nil
  309. }
  310. // sibling represents an intermediate data of build for Double-Array.
  311. type sibling struct {
  312. // An index of start of duplicated characters.
  313. start int
  314. // An index of end of duplicated characters.
  315. end int
  316. // A character of sibling.
  317. c byte
  318. }
  319. // nextIndex returns a next index of array of BASE/CHECK.
  320. func nextIndex(base int, c byte) int {
  321. return base ^ int(c)
  322. }
  323. // makeSiblings returns slice of sibling.
  324. func makeSiblings(records []*record, depth int) (sib []sibling, leaf *record, err error) {
  325. var (
  326. pc byte
  327. n int
  328. )
  329. for i, r := range records {
  330. if len(r.Key) <= depth {
  331. leaf = r
  332. continue
  333. }
  334. c := r.Key[depth]
  335. switch {
  336. case pc < c:
  337. sib = append(sib, sibling{start: i, c: c})
  338. case pc == c:
  339. continue
  340. default:
  341. return nil, nil, fmt.Errorf("denco: BUG: routing table hasn't been sorted")
  342. }
  343. if n > 0 {
  344. sib[n-1].end = i
  345. }
  346. pc = c
  347. n++
  348. }
  349. if n == 0 {
  350. return nil, leaf, nil
  351. }
  352. sib[n-1].end = len(records)
  353. return sib, leaf, nil
  354. }
  355. // Record represents a record data for router construction.
  356. type Record struct {
  357. // Key for router construction.
  358. Key string
  359. // Result value for Key.
  360. Value interface{}
  361. }
  362. // NewRecord returns a new Record.
  363. func NewRecord(key string, value interface{}) Record {
  364. return Record{
  365. Key: key,
  366. Value: value,
  367. }
  368. }
  369. // record represents a record that use to build the Double-Array.
  370. type record struct {
  371. Record
  372. paramNames []string
  373. }
  374. // makeRecords returns the records that use to build Double-Arrays.
  375. func makeRecords(srcs []Record) (statics, params []*record) {
  376. spChars := string([]byte{ParamCharacter, WildcardCharacter})
  377. termChar := string(TerminationCharacter)
  378. for _, r := range srcs {
  379. if strings.ContainsAny(r.Key, spChars) {
  380. r.Key += termChar
  381. params = append(params, &record{Record: r})
  382. } else {
  383. statics = append(statics, &record{Record: r})
  384. }
  385. }
  386. return statics, params
  387. }
  388. // recordSlice represents a slice of Record for sort and implements the sort.Interface.
  389. type recordSlice []*record
  390. // Len implements the sort.Interface.Len.
  391. func (rs recordSlice) Len() int {
  392. return len(rs)
  393. }
  394. // Less implements the sort.Interface.Less.
  395. func (rs recordSlice) Less(i, j int) bool {
  396. return rs[i].Key < rs[j].Key
  397. }
  398. // Swap implements the sort.Interface.Swap.
  399. func (rs recordSlice) Swap(i, j int) {
  400. rs[i], rs[j] = rs[j], rs[i]
  401. }
上海开阖软件有限公司 沪ICP备12045867号-1