1
0

entry_index.rb 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. require 'yajl/json_gem'
  2. module Docs
  3. class EntryIndex
  4. attr_reader :entries, :types
  5. def initialize
  6. @entries = []
  7. @index = Set.new
  8. @types = Hash.new { |hash, key| hash[key] = Type.new key }
  9. end
  10. def add(entry)
  11. if entry.is_a? Array
  12. entry.each(&method(:add))
  13. else
  14. add_entry(entry) unless entry.root?
  15. end
  16. end
  17. def empty?
  18. @entries.empty?
  19. end
  20. alias_method :blank?, :empty?
  21. def length
  22. @entries.length
  23. end
  24. def as_json
  25. { entries: entries_as_json, types: types_as_json }
  26. end
  27. def to_json
  28. JSON.generate(as_json)
  29. end
  30. private
  31. def add_entry(entry)
  32. if @index.add?(entry.as_json.to_s)
  33. @entries << entry.dup
  34. @types[entry.type].count += 1 if entry.type
  35. end
  36. end
  37. def entries_as_json
  38. @entries.sort! { |a, b| sort_fn(a.name, b.name) }.map(&:as_json)
  39. end
  40. def types_as_json
  41. @types.values.sort! { |a, b| sort_fn(a.name, b.name) }.map(&:as_json)
  42. end
  43. SPLIT_INTS = /(?<=\d)\.(?=[\s\d])/.freeze
  44. def sort_fn(a, b)
  45. if (a.getbyte(0) >= 49 && a.getbyte(0) <= 57) || (b.getbyte(0) >= 49 && b.getbyte(0) <= 57)
  46. a_split = a.split(SPLIT_INTS)
  47. b_split = b.split(SPLIT_INTS)
  48. a_length = a_split.length
  49. b_length = b_split.length
  50. return a.casecmp(b) if a_length == 1 && b_length == 1
  51. return 1 if a_length == 1
  52. return -1 if b_length == 1
  53. a_split.each_with_index { |s, i| a_split[i] = s.to_i unless i == a_length - 1 }
  54. b_split.each_with_index { |s, i| b_split[i] = s.to_i unless i == b_length - 1 }
  55. if b_length > a_length
  56. (b_length - a_length).times { a_split.insert(-2, 0) }
  57. elsif a_length > b_length
  58. (a_length - b_length).times { b_split.insert(-2, 0) }
  59. end
  60. a_split <=> b_split
  61. else
  62. a.casecmp(b)
  63. end
  64. end
  65. end
  66. end