strokedb 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CONTRIBUTORS +7 -0
 - data/CREDITS +13 -0
 - data/README +44 -0
 - data/bin/sdbc +2 -0
 - data/lib/config/config.rb +161 -0
 - data/lib/data_structures/inverted_list.rb +297 -0
 - data/lib/data_structures/point_query.rb +24 -0
 - data/lib/data_structures/skiplist.rb +302 -0
 - data/lib/document/associations.rb +107 -0
 - data/lib/document/callback.rb +11 -0
 - data/lib/document/coercions.rb +57 -0
 - data/lib/document/delete.rb +28 -0
 - data/lib/document/document.rb +684 -0
 - data/lib/document/meta.rb +261 -0
 - data/lib/document/slot.rb +199 -0
 - data/lib/document/util.rb +27 -0
 - data/lib/document/validations.rb +704 -0
 - data/lib/document/versions.rb +106 -0
 - data/lib/document/virtualize.rb +82 -0
 - data/lib/init.rb +57 -0
 - data/lib/stores/chainable_storage.rb +57 -0
 - data/lib/stores/inverted_list_index/inverted_list_file_storage.rb +56 -0
 - data/lib/stores/inverted_list_index/inverted_list_index.rb +49 -0
 - data/lib/stores/remote_store.rb +172 -0
 - data/lib/stores/skiplist_store/chunk.rb +119 -0
 - data/lib/stores/skiplist_store/chunk_storage.rb +21 -0
 - data/lib/stores/skiplist_store/file_chunk_storage.rb +44 -0
 - data/lib/stores/skiplist_store/memory_chunk_storage.rb +37 -0
 - data/lib/stores/skiplist_store/skiplist_store.rb +217 -0
 - data/lib/stores/store.rb +5 -0
 - data/lib/sync/chain_sync.rb +38 -0
 - data/lib/sync/diff.rb +126 -0
 - data/lib/sync/lamport_timestamp.rb +81 -0
 - data/lib/sync/store_sync.rb +79 -0
 - data/lib/sync/stroke_diff/array.rb +102 -0
 - data/lib/sync/stroke_diff/default.rb +21 -0
 - data/lib/sync/stroke_diff/hash.rb +186 -0
 - data/lib/sync/stroke_diff/string.rb +116 -0
 - data/lib/sync/stroke_diff/stroke_diff.rb +9 -0
 - data/lib/util/blankslate.rb +42 -0
 - data/lib/util/ext/blank.rb +50 -0
 - data/lib/util/ext/enumerable.rb +36 -0
 - data/lib/util/ext/fixnum.rb +16 -0
 - data/lib/util/ext/hash.rb +22 -0
 - data/lib/util/ext/object.rb +8 -0
 - data/lib/util/ext/string.rb +35 -0
 - data/lib/util/inflect.rb +217 -0
 - data/lib/util/java_util.rb +9 -0
 - data/lib/util/lazy_array.rb +54 -0
 - data/lib/util/lazy_mapping_array.rb +64 -0
 - data/lib/util/lazy_mapping_hash.rb +46 -0
 - data/lib/util/serialization.rb +29 -0
 - data/lib/util/trigger_partition.rb +136 -0
 - data/lib/util/util.rb +38 -0
 - data/lib/util/xml.rb +6 -0
 - data/lib/view/view.rb +55 -0
 - data/script/console +70 -0
 - data/strokedb.rb +75 -0
 - metadata +148 -0
 
    
        data/lib/util/inflect.rb
    ADDED
    
    | 
         @@ -0,0 +1,217 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # from the English gem (http://english.rubyforge.org/)
         
     | 
| 
      
 2 
     | 
    
         
            +
            # http://english.rubyforge.org/rdoc/classes/English/Inflect.html
         
     | 
| 
      
 3 
     | 
    
         
            +
            #
         
     | 
| 
      
 4 
     | 
    
         
            +
            # last updated from http://english.rubyforge.org/svn/trunk/lib/english/inflect.rb on 3-31-2008
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            module English
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
              # = English Nouns Number Inflection.
         
     | 
| 
      
 9 
     | 
    
         
            +
              #
         
     | 
| 
      
 10 
     | 
    
         
            +
              # This module provides english singular <-> plural noun inflections.
         
     | 
| 
      
 11 
     | 
    
         
            +
              module Inflect
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                @singular_of = {}
         
     | 
| 
      
 14 
     | 
    
         
            +
                @plural_of = {}
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                @singular_rules = []
         
     | 
| 
      
 17 
     | 
    
         
            +
                @plural_rules = []
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                class << self
         
     | 
| 
      
 20 
     | 
    
         
            +
                  # Define a general exception.
         
     | 
| 
      
 21 
     | 
    
         
            +
                  def word(singular, plural=nil)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    plural = singular unless plural
         
     | 
| 
      
 23 
     | 
    
         
            +
                    singular_word(singular, plural)
         
     | 
| 
      
 24 
     | 
    
         
            +
                    plural_word(singular, plural)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  # Define a singularization exception.
         
     | 
| 
      
 28 
     | 
    
         
            +
                  def singular_word(singular, plural)
         
     | 
| 
      
 29 
     | 
    
         
            +
                    @singular_of[plural] = singular
         
     | 
| 
      
 30 
     | 
    
         
            +
                  end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                  # Define a pluralization exception.
         
     | 
| 
      
 33 
     | 
    
         
            +
                  def plural_word(singular, plural)
         
     | 
| 
      
 34 
     | 
    
         
            +
                    @plural_of[singular] = plural
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  # Define a general rule.
         
     | 
| 
      
 38 
     | 
    
         
            +
                  def rule(singular, plural)
         
     | 
| 
      
 39 
     | 
    
         
            +
                    singular_rule(singular, plural)
         
     | 
| 
      
 40 
     | 
    
         
            +
                    plural_rule(singular, plural)
         
     | 
| 
      
 41 
     | 
    
         
            +
                  end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                  # Define a singularization rule.
         
     | 
| 
      
 44 
     | 
    
         
            +
                  def singular_rule(singular, plural)
         
     | 
| 
      
 45 
     | 
    
         
            +
                    @singular_rules << [singular, plural]
         
     | 
| 
      
 46 
     | 
    
         
            +
                  end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                  # Define a plurualization rule.
         
     | 
| 
      
 49 
     | 
    
         
            +
                  def plural_rule(singular, plural)
         
     | 
| 
      
 50 
     | 
    
         
            +
                    @plural_rules << [singular, plural]
         
     | 
| 
      
 51 
     | 
    
         
            +
                  end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                  # Read prepared singularization rules.
         
     | 
| 
      
 54 
     | 
    
         
            +
                  def singularization_rules
         
     | 
| 
      
 55 
     | 
    
         
            +
                    return @singularization_rules if @singularization_rules
         
     | 
| 
      
 56 
     | 
    
         
            +
                    sorted = @singular_rules.sort_by{ |s, p| "#{p}".size }.reverse
         
     | 
| 
      
 57 
     | 
    
         
            +
                    @singularization_rules = sorted.collect do |s, p|
         
     | 
| 
      
 58 
     | 
    
         
            +
                      [ /#{p}$/, "#{s}" ]
         
     | 
| 
      
 59 
     | 
    
         
            +
                    end
         
     | 
| 
      
 60 
     | 
    
         
            +
                  end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                  # Read prepared pluralization rules.
         
     | 
| 
      
 63 
     | 
    
         
            +
                  def pluralization_rules
         
     | 
| 
      
 64 
     | 
    
         
            +
                    return @pluralization_rules if @pluralization_rules
         
     | 
| 
      
 65 
     | 
    
         
            +
                    sorted = @plural_rules.sort_by{ |s, p| "#{s}".size }.reverse
         
     | 
| 
      
 66 
     | 
    
         
            +
                    @pluralization_rules = sorted.collect do |s, p|
         
     | 
| 
      
 67 
     | 
    
         
            +
                      [ /#{s}$/, "#{p}" ]
         
     | 
| 
      
 68 
     | 
    
         
            +
                    end
         
     | 
| 
      
 69 
     | 
    
         
            +
                  end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                  #
         
     | 
| 
      
 72 
     | 
    
         
            +
                  def plural_of
         
     | 
| 
      
 73 
     | 
    
         
            +
                    @plural_of
         
     | 
| 
      
 74 
     | 
    
         
            +
                  end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                  #
         
     | 
| 
      
 77 
     | 
    
         
            +
                  def singular_of
         
     | 
| 
      
 78 
     | 
    
         
            +
                    @singular_of
         
     | 
| 
      
 79 
     | 
    
         
            +
                  end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                  # Convert an English word from plurel to singular.
         
     | 
| 
      
 82 
     | 
    
         
            +
                  #
         
     | 
| 
      
 83 
     | 
    
         
            +
                  #   "boys".singular      #=> boy
         
     | 
| 
      
 84 
     | 
    
         
            +
                  #   "tomatoes".singular  #=> tomato
         
     | 
| 
      
 85 
     | 
    
         
            +
                  #
         
     | 
| 
      
 86 
     | 
    
         
            +
                  def singular(word)
         
     | 
| 
      
 87 
     | 
    
         
            +
                    if result = singular_of[word]
         
     | 
| 
      
 88 
     | 
    
         
            +
                      return result.dup
         
     | 
| 
      
 89 
     | 
    
         
            +
                    end
         
     | 
| 
      
 90 
     | 
    
         
            +
                    result = word.dup
         
     | 
| 
      
 91 
     | 
    
         
            +
                    singularization_rules.each do |(match, replacement)|
         
     | 
| 
      
 92 
     | 
    
         
            +
                      break if result.gsub!(match, replacement)
         
     | 
| 
      
 93 
     | 
    
         
            +
                    end
         
     | 
| 
      
 94 
     | 
    
         
            +
                    return result
         
     | 
| 
      
 95 
     | 
    
         
            +
                  end
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                  # Alias for #singular (a Railism).
         
     | 
| 
      
 98 
     | 
    
         
            +
                  #
         
     | 
| 
      
 99 
     | 
    
         
            +
                  alias_method(:singularize, :singular)
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
                  # Convert an English word from singular to plurel.
         
     | 
| 
      
 102 
     | 
    
         
            +
                  #
         
     | 
| 
      
 103 
     | 
    
         
            +
                  #   "boy".plural     #=> boys
         
     | 
| 
      
 104 
     | 
    
         
            +
                  #   "tomato".plural  #=> tomatoes
         
     | 
| 
      
 105 
     | 
    
         
            +
                  #
         
     | 
| 
      
 106 
     | 
    
         
            +
                  def plural(word)
         
     | 
| 
      
 107 
     | 
    
         
            +
                    if result = plural_of[word]
         
     | 
| 
      
 108 
     | 
    
         
            +
                      return result.dup
         
     | 
| 
      
 109 
     | 
    
         
            +
                    end
         
     | 
| 
      
 110 
     | 
    
         
            +
                    #return self.dup if /s$/ =~ self # ???
         
     | 
| 
      
 111 
     | 
    
         
            +
                    result = word.dup
         
     | 
| 
      
 112 
     | 
    
         
            +
                    pluralization_rules.each do |(match, replacement)|
         
     | 
| 
      
 113 
     | 
    
         
            +
                      break if result.gsub!(match, replacement)
         
     | 
| 
      
 114 
     | 
    
         
            +
                    end
         
     | 
| 
      
 115 
     | 
    
         
            +
                    return result
         
     | 
| 
      
 116 
     | 
    
         
            +
                  end
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
                  # Alias for #plural (a Railism).
         
     | 
| 
      
 119 
     | 
    
         
            +
                  alias_method(:pluralize, :plural)
         
     | 
| 
      
 120 
     | 
    
         
            +
                end
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
                # One argument means singular and plural are the same.
         
     | 
| 
      
 123 
     | 
    
         
            +
             
     | 
| 
      
 124 
     | 
    
         
            +
                word 'equipment'
         
     | 
| 
      
 125 
     | 
    
         
            +
                word 'information'
         
     | 
| 
      
 126 
     | 
    
         
            +
                word 'money'
         
     | 
| 
      
 127 
     | 
    
         
            +
                word 'species'
         
     | 
| 
      
 128 
     | 
    
         
            +
                word 'series'
         
     | 
| 
      
 129 
     | 
    
         
            +
                word 'fish'
         
     | 
| 
      
 130 
     | 
    
         
            +
                word 'sheep'
         
     | 
| 
      
 131 
     | 
    
         
            +
                word 'moose'
         
     | 
| 
      
 132 
     | 
    
         
            +
                word 'hovercraft'
         
     | 
| 
      
 133 
     | 
    
         
            +
             
     | 
| 
      
 134 
     | 
    
         
            +
                # Two arguments defines a singular and plural exception.
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
                word 'Swiss'     , 'Swiss'
         
     | 
| 
      
 137 
     | 
    
         
            +
                word 'life'      , 'lives'
         
     | 
| 
      
 138 
     | 
    
         
            +
                word 'wife'      , 'wives'
         
     | 
| 
      
 139 
     | 
    
         
            +
                word 'virus'     , 'viri'
         
     | 
| 
      
 140 
     | 
    
         
            +
                word 'octopus'   , 'octopi'
         
     | 
| 
      
 141 
     | 
    
         
            +
                word 'goose'     , 'geese'
         
     | 
| 
      
 142 
     | 
    
         
            +
                word 'criterion' , 'criteria'
         
     | 
| 
      
 143 
     | 
    
         
            +
                word 'alias'     , 'aliases'
         
     | 
| 
      
 144 
     | 
    
         
            +
                word 'status'    , 'statuses'
         
     | 
| 
      
 145 
     | 
    
         
            +
                word 'axis'      , 'axes'
         
     | 
| 
      
 146 
     | 
    
         
            +
                word 'crisis'    , 'crises'
         
     | 
| 
      
 147 
     | 
    
         
            +
                word 'testis'    , 'testes'
         
     | 
| 
      
 148 
     | 
    
         
            +
                word 'child'     , 'children'
         
     | 
| 
      
 149 
     | 
    
         
            +
                word 'person'    , 'people'
         
     | 
| 
      
 150 
     | 
    
         
            +
                word 'potato'    , 'potatoes'
         
     | 
| 
      
 151 
     | 
    
         
            +
                word 'tomato'    , 'tomatoes'
         
     | 
| 
      
 152 
     | 
    
         
            +
                word 'buffalo'   , 'buffaloes'
         
     | 
| 
      
 153 
     | 
    
         
            +
                word 'torpedo'   , 'torpedoes'
         
     | 
| 
      
 154 
     | 
    
         
            +
                word 'quiz'      , 'quizes'
         
     | 
| 
      
 155 
     | 
    
         
            +
                word 'matrix'    , 'matrices'
         
     | 
| 
      
 156 
     | 
    
         
            +
                word 'vertex'    , 'vetices'
         
     | 
| 
      
 157 
     | 
    
         
            +
                word 'index'     , 'indices'
         
     | 
| 
      
 158 
     | 
    
         
            +
                word 'ox'        , 'oxen'
         
     | 
| 
      
 159 
     | 
    
         
            +
                word 'mouse'     , 'mice'
         
     | 
| 
      
 160 
     | 
    
         
            +
                word 'louse'     , 'lice'
         
     | 
| 
      
 161 
     | 
    
         
            +
                word 'thesis'    , 'theses'
         
     | 
| 
      
 162 
     | 
    
         
            +
                word 'thief'     , 'thieves'
         
     | 
| 
      
 163 
     | 
    
         
            +
                word 'analysis'  , 'analyses'
         
     | 
| 
      
 164 
     | 
    
         
            +
             
     | 
| 
      
 165 
     | 
    
         
            +
                # One-way singularization exception (convert plural to singular).
         
     | 
| 
      
 166 
     | 
    
         
            +
             
     | 
| 
      
 167 
     | 
    
         
            +
                singular_word 'cactus', 'cacti'
         
     | 
| 
      
 168 
     | 
    
         
            +
             
     | 
| 
      
 169 
     | 
    
         
            +
                # General rules.
         
     | 
| 
      
 170 
     | 
    
         
            +
             
     | 
| 
      
 171 
     | 
    
         
            +
                rule 'hive' , 'hives'
         
     | 
| 
      
 172 
     | 
    
         
            +
                rule 'rf'   , 'rves'
         
     | 
| 
      
 173 
     | 
    
         
            +
                rule 'af'   , 'aves'
         
     | 
| 
      
 174 
     | 
    
         
            +
                rule 'ero'  , 'eroes'
         
     | 
| 
      
 175 
     | 
    
         
            +
                rule 'man'  , 'men'
         
     | 
| 
      
 176 
     | 
    
         
            +
                rule 'ch'   , 'ches'
         
     | 
| 
      
 177 
     | 
    
         
            +
                rule 'sh'   , 'shes'
         
     | 
| 
      
 178 
     | 
    
         
            +
                rule 'ss'   , 'sses'
         
     | 
| 
      
 179 
     | 
    
         
            +
                rule 'ta'   , 'tum'
         
     | 
| 
      
 180 
     | 
    
         
            +
                rule 'ia'   , 'ium'
         
     | 
| 
      
 181 
     | 
    
         
            +
                rule 'ra'   , 'rum'
         
     | 
| 
      
 182 
     | 
    
         
            +
                rule 'ay'   , 'ays'
         
     | 
| 
      
 183 
     | 
    
         
            +
                rule 'ey'   , 'eys'
         
     | 
| 
      
 184 
     | 
    
         
            +
                rule 'oy'   , 'oys'
         
     | 
| 
      
 185 
     | 
    
         
            +
                rule 'uy'   , 'uys'
         
     | 
| 
      
 186 
     | 
    
         
            +
                rule 'y'    , 'ies'
         
     | 
| 
      
 187 
     | 
    
         
            +
                rule 'x'    , 'xes'
         
     | 
| 
      
 188 
     | 
    
         
            +
                rule 'lf'   , 'lves'
         
     | 
| 
      
 189 
     | 
    
         
            +
                rule 'us'   , 'uses'
         
     | 
| 
      
 190 
     | 
    
         
            +
                rule ''     , 's'
         
     | 
| 
      
 191 
     | 
    
         
            +
             
     | 
| 
      
 192 
     | 
    
         
            +
                # One-way singular rules.
         
     | 
| 
      
 193 
     | 
    
         
            +
             
     | 
| 
      
 194 
     | 
    
         
            +
                singular_rule 'of' , 'ofs' # proof
         
     | 
| 
      
 195 
     | 
    
         
            +
                singular_rule 'o'  , 'oes' # hero, heroes
         
     | 
| 
      
 196 
     | 
    
         
            +
                singular_rule 'f'  , 'ves'
         
     | 
| 
      
 197 
     | 
    
         
            +
             
     | 
| 
      
 198 
     | 
    
         
            +
                # One-way plural rules.
         
     | 
| 
      
 199 
     | 
    
         
            +
             
     | 
| 
      
 200 
     | 
    
         
            +
                plural_rule 'fe' , 'ves' # safe, wife
         
     | 
| 
      
 201 
     | 
    
         
            +
                plural_rule 's'  , 'ses'
         
     | 
| 
      
 202 
     | 
    
         
            +
             
     | 
| 
      
 203 
     | 
    
         
            +
              end
         
     | 
| 
      
 204 
     | 
    
         
            +
            end
         
     | 
| 
      
 205 
     | 
    
         
            +
             
     | 
| 
      
 206 
     | 
    
         
            +
             
     | 
| 
      
 207 
     | 
    
         
            +
            class String
         
     | 
| 
      
 208 
     | 
    
         
            +
              def singular
         
     | 
| 
      
 209 
     | 
    
         
            +
                English::Inflect.singular(self)
         
     | 
| 
      
 210 
     | 
    
         
            +
              end
         
     | 
| 
      
 211 
     | 
    
         
            +
              alias_method(:singularize, :singular)
         
     | 
| 
      
 212 
     | 
    
         
            +
             
     | 
| 
      
 213 
     | 
    
         
            +
              def plural
         
     | 
| 
      
 214 
     | 
    
         
            +
                English::Inflect.plural(self)
         
     | 
| 
      
 215 
     | 
    
         
            +
              end
         
     | 
| 
      
 216 
     | 
    
         
            +
              alias_method(:pluralize, :plural)
         
     | 
| 
      
 217 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,54 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module StrokeDB
         
     | 
| 
      
 2 
     | 
    
         
            +
              # Lazy loads items from array.
         
     | 
| 
      
 3 
     | 
    
         
            +
              #
         
     | 
| 
      
 4 
     | 
    
         
            +
              # Lazy arrays are backed by Proc returning regular array
         
     | 
| 
      
 5 
     | 
    
         
            +
              # on first call retrieving it from @load_with_proc.
         
     | 
| 
      
 6 
     | 
    
         
            +
              #
         
     | 
| 
      
 7 
     | 
    
         
            +
              # Example:
         
     | 
| 
      
 8 
     | 
    
         
            +
              #
         
     | 
| 
      
 9 
     | 
    
         
            +
              #   ary = LazyArray.new.load_with { Time.now.to_s.split(/\s/) }
         
     | 
| 
      
 10 
     | 
    
         
            +
              #
         
     | 
| 
      
 11 
     | 
    
         
            +
              # On first attempt to access <tt>ary</tt> (including <tt>inspect</tt>) it will
         
     | 
| 
      
 12 
     | 
    
         
            +
              # evaluate load_with's Proc and update own content with its result:
         
     | 
| 
      
 13 
     | 
    
         
            +
              #
         
     | 
| 
      
 14 
     | 
    
         
            +
              #   ary
         
     | 
| 
      
 15 
     | 
    
         
            +
              #     # ==> ["Mon", "Mar", "17", "10:35:52", "+0200", "2008"]
         
     | 
| 
      
 16 
     | 
    
         
            +
              #
         
     | 
| 
      
 17 
     | 
    
         
            +
              class LazyArray < BlankSlate
         
     | 
| 
      
 18 
     | 
    
         
            +
                def initialize(*args)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  @load_with_proc = proc {|v| v}
         
     | 
| 
      
 20 
     | 
    
         
            +
                  @array = Array.new(*args)
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                # Proc to execute lazy loading
         
     | 
| 
      
 24 
     | 
    
         
            +
                def load_with(&block)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  @load_with_proc = block
         
     | 
| 
      
 26 
     | 
    
         
            +
                  self
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                # Make it look like array for outer world
         
     | 
| 
      
 30 
     | 
    
         
            +
                def class
         
     | 
| 
      
 31 
     | 
    
         
            +
                  Array
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                def method_missing sym, *args, &blk
         
     | 
| 
      
 35 
     | 
    
         
            +
                  if @array.respond_to? sym
         
     | 
| 
      
 36 
     | 
    
         
            +
                    load!
         
     | 
| 
      
 37 
     | 
    
         
            +
                    @array.__send__ sym, *args, &blk
         
     | 
| 
      
 38 
     | 
    
         
            +
                  else
         
     | 
| 
      
 39 
     | 
    
         
            +
                    super
         
     | 
| 
      
 40 
     | 
    
         
            +
                  end
         
     | 
| 
      
 41 
     | 
    
         
            +
                end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                private
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                def load!
         
     | 
| 
      
 46 
     | 
    
         
            +
                  if @load_with_proc
         
     | 
| 
      
 47 
     | 
    
         
            +
                    @array.clear
         
     | 
| 
      
 48 
     | 
    
         
            +
                    @array.concat @load_with_proc.call(@array)
         
     | 
| 
      
 49 
     | 
    
         
            +
                    @load_with_proc = nil
         
     | 
| 
      
 50 
     | 
    
         
            +
                  end
         
     | 
| 
      
 51 
     | 
    
         
            +
                end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
              end
         
     | 
| 
      
 54 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,64 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module StrokeDB
         
     | 
| 
      
 2 
     | 
    
         
            +
              # Lazy loads items from array applying procs on each read and write.
         
     | 
| 
      
 3 
     | 
    
         
            +
              #
         
     | 
| 
      
 4 
     | 
    
         
            +
              # Example:
         
     | 
| 
      
 5 
     | 
    
         
            +
              #
         
     | 
| 
      
 6 
     | 
    
         
            +
              # @ary[i] = 10
         
     | 
| 
      
 7 
     | 
    
         
            +
              #
         
     | 
| 
      
 8 
     | 
    
         
            +
              # applies "unmap proc" to new item value.
         
     | 
| 
      
 9 
     | 
    
         
            +
              #
         
     | 
| 
      
 10 
     | 
    
         
            +
              # @ary.at(i)
         
     | 
| 
      
 11 
     | 
    
         
            +
              #
         
     | 
| 
      
 12 
     | 
    
         
            +
              # applies "map proc" to value just have been read.
         
     | 
| 
      
 13 
     | 
    
         
            +
              #
         
     | 
| 
      
 14 
     | 
    
         
            +
              # StrokeDB uses this class to "follow" links to other documents
         
     | 
| 
      
 15 
     | 
    
         
            +
              # found in slots in a lazy manner.
         
     | 
| 
      
 16 
     | 
    
         
            +
              #
         
     | 
| 
      
 17 
     | 
    
         
            +
              # player:
         
     | 
| 
      
 18 
     | 
    
         
            +
              #   model: [@#8b195509-f9c4-4fea-90c9-425b38bdda3e.ea5eda78-d410-44be-8b14-f4e33f6fa047]
         
     | 
| 
      
 19 
     | 
    
         
            +
              #   generation: 4
         
     | 
| 
      
 20 
     | 
    
         
            +
              #
         
     | 
| 
      
 21 
     | 
    
         
            +
              # when model collection item is fetched, reference followed and turned into document
         
     | 
| 
      
 22 
     | 
    
         
            +
              # instance with mapping proc of lazy mapping array.
         
     | 
| 
      
 23 
     | 
    
         
            +
              class LazyMappingArray < BlankSlate(Array)
         
     | 
| 
      
 24 
     | 
    
         
            +
                def initialize(*args)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  @map_proc = proc {|v| v}
         
     | 
| 
      
 26 
     | 
    
         
            +
                  @unmap_proc = proc {|v| v}
         
     | 
| 
      
 27 
     | 
    
         
            +
                  super(*args)
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                def map_with(&block)
         
     | 
| 
      
 31 
     | 
    
         
            +
                  @map_proc = block
         
     | 
| 
      
 32 
     | 
    
         
            +
                  self
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                def unmap_with(&block)
         
     | 
| 
      
 36 
     | 
    
         
            +
                  @unmap_proc = block
         
     | 
| 
      
 37 
     | 
    
         
            +
                  self
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                def class
         
     | 
| 
      
 41 
     | 
    
         
            +
                  Array
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                def method_missing sym, *args, &blk
         
     | 
| 
      
 45 
     | 
    
         
            +
                  super if sym.to_s =~ /^__/
         
     | 
| 
      
 46 
     | 
    
         
            +
                  mname = "__#{::BlankSlate::MethodMapping[sym.to_s] || sym}"
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                  case sym
         
     | 
| 
      
 49 
     | 
    
         
            +
                  when :push, :unshift, :<<, :[]=, :index, :-
         
     | 
| 
      
 50 
     | 
    
         
            +
                    last = args.pop
         
     | 
| 
      
 51 
     | 
    
         
            +
                    last = last.is_a?(Array) ? last.map{|v| @unmap_proc.call(v) } : @unmap_proc.call(last)
         
     | 
| 
      
 52 
     | 
    
         
            +
                    args.push last
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                    __send__(mname, *args, &blk)
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                  when :[], :slice, :at, :map, :shift, :pop, :include?, :last, :first, :zip, :each, :inject, :each_with_index
         
     | 
| 
      
 57 
     | 
    
         
            +
                    __map{|v| @map_proc.call(v) }.__send__(sym, *args, &blk)
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                  else
         
     | 
| 
      
 60 
     | 
    
         
            +
                    __send__(mname, *args, &blk)
         
     | 
| 
      
 61 
     | 
    
         
            +
                  end
         
     | 
| 
      
 62 
     | 
    
         
            +
                end
         
     | 
| 
      
 63 
     | 
    
         
            +
              end
         
     | 
| 
      
 64 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,46 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module StrokeDB
         
     | 
| 
      
 2 
     | 
    
         
            +
              class LazyMappingHash < BlankSlate(Hash)
         
     | 
| 
      
 3 
     | 
    
         
            +
                def initialize(original = {}, decoder = nil, encoder = nil)
         
     | 
| 
      
 4 
     | 
    
         
            +
                  @decoder = decoder || proc {|v| v}
         
     | 
| 
      
 5 
     | 
    
         
            +
                  @encoder = encoder || proc {|v| v}
         
     | 
| 
      
 6 
     | 
    
         
            +
                  super(default)
         
     | 
| 
      
 7 
     | 
    
         
            +
                  original.each {|k,v| self.__squarebracket_set(k,v) }
         
     | 
| 
      
 8 
     | 
    
         
            +
                end
         
     | 
| 
      
 9 
     | 
    
         
            +
                
         
     | 
| 
      
 10 
     | 
    
         
            +
                def map_with(&block)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @encoder = block
         
     | 
| 
      
 12 
     | 
    
         
            +
                  self
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                def unmap_with(&block)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  @decoder = block
         
     | 
| 
      
 17 
     | 
    
         
            +
                  self
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                def class
         
     | 
| 
      
 21 
     | 
    
         
            +
                  Hash
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                def method_missing sym, *args, &blk
         
     | 
| 
      
 25 
     | 
    
         
            +
                  super if sym.to_s =~ /^__/
         
     | 
| 
      
 26 
     | 
    
         
            +
                  mname = "__#{::BlankSlate::MethodMapping[sym.to_s] || sym}"
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                  case sym
         
     | 
| 
      
 29 
     | 
    
         
            +
                  when :keys, :values
         
     | 
| 
      
 30 
     | 
    
         
            +
                    __send__(mname, *args, &blk).map{|v| @encoder.call(v) }
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                  when :each
         
     | 
| 
      
 33 
     | 
    
         
            +
                    self.__each do |k,v|
         
     | 
| 
      
 34 
     | 
    
         
            +
                      yield @encoder.call(k), @encoder.call(v)
         
     | 
| 
      
 35 
     | 
    
         
            +
                    end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  when :[], :[]=
         
     | 
| 
      
 38 
     | 
    
         
            +
                    args.map!{|v| @decoder.call(v) }
         
     | 
| 
      
 39 
     | 
    
         
            +
                    @encoder.call __send__(mname, *args, &blk)
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                  else
         
     | 
| 
      
 42 
     | 
    
         
            +
                    __send__(mname, *args, &blk)
         
     | 
| 
      
 43 
     | 
    
         
            +
                  end
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
              end
         
     | 
| 
      
 46 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,29 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module StrokeDB
         
     | 
| 
      
 2 
     | 
    
         
            +
              module JsonSerializationMethod
         
     | 
| 
      
 3 
     | 
    
         
            +
                def serialize(x)
         
     | 
| 
      
 4 
     | 
    
         
            +
                  x.to_json
         
     | 
| 
      
 5 
     | 
    
         
            +
                end
         
     | 
| 
      
 6 
     | 
    
         
            +
                def deserialize(x)
         
     | 
| 
      
 7 
     | 
    
         
            +
                  JSON.parse(x)
         
     | 
| 
      
 8 
     | 
    
         
            +
                end
         
     | 
| 
      
 9 
     | 
    
         
            +
              end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              module MarshalSerializationMethod
         
     | 
| 
      
 12 
     | 
    
         
            +
                def serialize(x)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  x = x.to_raw if x.respond_to?(:to_raw)
         
     | 
| 
      
 14 
     | 
    
         
            +
                  Marshal.dump(x)
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
                def deserialize(x)
         
     | 
| 
      
 17 
     | 
    
         
            +
                 Marshal.load(x)
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              
         
     | 
| 
      
 22 
     | 
    
         
            +
              def self.serialization_method=(method_name)
         
     | 
| 
      
 23 
     | 
    
         
            +
                StrokeDB.extend StrokeDB.const_get("#{method_name.to_s.camelize}SerializationMethod")
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
              
         
     | 
| 
      
 26 
     | 
    
         
            +
              self.serialization_method = :marshal
         
     | 
| 
      
 27 
     | 
    
         
            +
              
         
     | 
| 
      
 28 
     | 
    
         
            +
              
         
     | 
| 
      
 29 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,136 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Enumerable
         
     | 
| 
      
 2 
     | 
    
         
            +
              class TriggerPartitionContext
         
     | 
| 
      
 3 
     | 
    
         
            +
                def initialize(enum, &block)
         
     | 
| 
      
 4 
     | 
    
         
            +
                  @enum = enum
         
     | 
| 
      
 5 
     | 
    
         
            +
                  @cont = block
         
     | 
| 
      
 6 
     | 
    
         
            +
                end
         
     | 
| 
      
 7 
     | 
    
         
            +
                def fill(&block)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  @fill = block
         
     | 
| 
      
 9 
     | 
    
         
            +
                  self
         
     | 
| 
      
 10 
     | 
    
         
            +
                end
         
     | 
| 
      
 11 
     | 
    
         
            +
                def emit
         
     | 
| 
      
 12 
     | 
    
         
            +
                  partitions = []
         
     | 
| 
      
 13 
     | 
    
         
            +
                  cont = @cont
         
     | 
| 
      
 14 
     | 
    
         
            +
                  fill = @fill
         
     | 
| 
      
 15 
     | 
    
         
            +
                  p = @enum.inject(nil) do |part, elem|
         
     | 
| 
      
 16 
     | 
    
         
            +
                    if part && cont.call(part, elem)
         
     | 
| 
      
 17 
     | 
    
         
            +
                      fill.call(part, elem)
         
     | 
| 
      
 18 
     | 
    
         
            +
                      part
         
     | 
| 
      
 19 
     | 
    
         
            +
                    else
         
     | 
| 
      
 20 
     | 
    
         
            +
                      partitions << part if part
         
     | 
| 
      
 21 
     | 
    
         
            +
                      yield(elem)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    end
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
                  partitions << p if p
         
     | 
| 
      
 25 
     | 
    
         
            +
                  partitions
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
              end
         
     | 
| 
      
 28 
     | 
    
         
            +
              def trigger_partition(&block)
         
     | 
| 
      
 29 
     | 
    
         
            +
                TriggerPartitionContext.new(self, &block)
         
     | 
| 
      
 30 
     | 
    
         
            +
              end
         
     | 
| 
      
 31 
     | 
    
         
            +
              
         
     | 
| 
      
 32 
     | 
    
         
            +
              class TriggerPartitions
         
     | 
| 
      
 33 
     | 
    
         
            +
                def self.partition(list)
         
     | 
| 
      
 34 
     | 
    
         
            +
                  partitions = []
         
     | 
| 
      
 35 
     | 
    
         
            +
                  p = list.inject(nil) do |part, elem|
         
     | 
| 
      
 36 
     | 
    
         
            +
                    if part && continue?(part, elem)
         
     | 
| 
      
 37 
     | 
    
         
            +
                      fill(part, elem)
         
     | 
| 
      
 38 
     | 
    
         
            +
                      part
         
     | 
| 
      
 39 
     | 
    
         
            +
                    else
         
     | 
| 
      
 40 
     | 
    
         
            +
                      partitions << part if part
         
     | 
| 
      
 41 
     | 
    
         
            +
                      emit(elem)
         
     | 
| 
      
 42 
     | 
    
         
            +
                    end
         
     | 
| 
      
 43 
     | 
    
         
            +
                  end
         
     | 
| 
      
 44 
     | 
    
         
            +
                  partitions << p if p
         
     | 
| 
      
 45 
     | 
    
         
            +
                  partitions
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
      
 47 
     | 
    
         
            +
                def self.continue?(p, e)
         
     | 
| 
      
 48 
     | 
    
         
            +
                  true
         
     | 
| 
      
 49 
     | 
    
         
            +
                end
         
     | 
| 
      
 50 
     | 
    
         
            +
                def self.emit(e)
         
     | 
| 
      
 51 
     | 
    
         
            +
                  [e]
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
                def self.fill(p, e)
         
     | 
| 
      
 54 
     | 
    
         
            +
                  p << e
         
     | 
| 
      
 55 
     | 
    
         
            +
                end
         
     | 
| 
      
 56 
     | 
    
         
            +
              end
         
     | 
| 
      
 57 
     | 
    
         
            +
            end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
            if __FILE__ == $0
         
     | 
| 
      
 60 
     | 
    
         
            +
              arr = [1,2,3,4,5, -1, -4, -3, 5, 6, 7, 8, -6, -7]
         
     | 
| 
      
 61 
     | 
    
         
            +
              parr = arr.trigger_partition do |partition, element|
         
     | 
| 
      
 62 
     | 
    
         
            +
                partition[0] > 0 && element > 0 || partition[0] < 0 && element < 0
         
     | 
| 
      
 63 
     | 
    
         
            +
              end.fill do |p, e|
         
     | 
| 
      
 64 
     | 
    
         
            +
                p << e
         
     | 
| 
      
 65 
     | 
    
         
            +
              end.emit do |e|
         
     | 
| 
      
 66 
     | 
    
         
            +
                [e]
         
     | 
| 
      
 67 
     | 
    
         
            +
              end
         
     | 
| 
      
 68 
     | 
    
         
            +
              
         
     | 
| 
      
 69 
     | 
    
         
            +
              p arr
         
     | 
| 
      
 70 
     | 
    
         
            +
              p parr
         
     | 
| 
      
 71 
     | 
    
         
            +
              
         
     | 
| 
      
 72 
     | 
    
         
            +
              # Class might be faster
         
     | 
| 
      
 73 
     | 
    
         
            +
              class SignPartitions < Enumerable::TriggerPartitions
         
     | 
| 
      
 74 
     | 
    
         
            +
                def self.continue?(partition, element)
         
     | 
| 
      
 75 
     | 
    
         
            +
                  partition[0] > 0 && element > 0 || partition[0] < 0 && element < 0
         
     | 
| 
      
 76 
     | 
    
         
            +
                end
         
     | 
| 
      
 77 
     | 
    
         
            +
              end
         
     | 
| 
      
 78 
     | 
    
         
            +
              
         
     | 
| 
      
 79 
     | 
    
         
            +
              p Enumerable::TriggerPartitions.partition(arr)
         
     | 
| 
      
 80 
     | 
    
         
            +
              p SignPartitions.partition(arr)
         
     | 
| 
      
 81 
     | 
    
         
            +
              
         
     | 
| 
      
 82 
     | 
    
         
            +
              require 'benchmark'
         
     | 
| 
      
 83 
     | 
    
         
            +
              include Benchmark
         
     | 
| 
      
 84 
     | 
    
         
            +
              n = 1000
         
     | 
| 
      
 85 
     | 
    
         
            +
              bm(32) do |x|
         
     | 
| 
      
 86 
     | 
    
         
            +
                x.report("#{n} times:" ) do
         
     | 
| 
      
 87 
     | 
    
         
            +
                  n.times do
         
     | 
| 
      
 88 
     | 
    
         
            +
                    arr.trigger_partition do |partition, element|
         
     | 
| 
      
 89 
     | 
    
         
            +
                      partition[0] > 0 && element > 0 || partition[0] < 0 && element < 0
         
     | 
| 
      
 90 
     | 
    
         
            +
                    end.fill do |p, e|
         
     | 
| 
      
 91 
     | 
    
         
            +
                      p << e
         
     | 
| 
      
 92 
     | 
    
         
            +
                    end.emit do |e|
         
     | 
| 
      
 93 
     | 
    
         
            +
                      [e]
         
     | 
| 
      
 94 
     | 
    
         
            +
                    end
         
     | 
| 
      
 95 
     | 
    
         
            +
                  end
         
     | 
| 
      
 96 
     | 
    
         
            +
                end
         
     | 
| 
      
 97 
     | 
    
         
            +
                arrL = arr*28
         
     | 
| 
      
 98 
     | 
    
         
            +
                x.report("#{n} times (x28 larger data):" ) do
         
     | 
| 
      
 99 
     | 
    
         
            +
                  n.times do
         
     | 
| 
      
 100 
     | 
    
         
            +
                    arrL.trigger_partition do |partition, element|
         
     | 
| 
      
 101 
     | 
    
         
            +
                      partition[0] > 0 && element > 0 || partition[0] < 0 && element < 0
         
     | 
| 
      
 102 
     | 
    
         
            +
                    end.fill do |p, e|
         
     | 
| 
      
 103 
     | 
    
         
            +
                      p << e
         
     | 
| 
      
 104 
     | 
    
         
            +
                    end.emit do |e|
         
     | 
| 
      
 105 
     | 
    
         
            +
                      [e]
         
     | 
| 
      
 106 
     | 
    
         
            +
                    end
         
     | 
| 
      
 107 
     | 
    
         
            +
                  end
         
     | 
| 
      
 108 
     | 
    
         
            +
                end
         
     | 
| 
      
 109 
     | 
    
         
            +
                # 35% faster
         
     | 
| 
      
 110 
     | 
    
         
            +
                x.report("#{n} times (SignPartitions):" ) do
         
     | 
| 
      
 111 
     | 
    
         
            +
                  (n/5).times do
         
     | 
| 
      
 112 
     | 
    
         
            +
                    SignPartitions.partition(arrL)
         
     | 
| 
      
 113 
     | 
    
         
            +
                    SignPartitions.partition(arrL)
         
     | 
| 
      
 114 
     | 
    
         
            +
                    SignPartitions.partition(arrL)
         
     | 
| 
      
 115 
     | 
    
         
            +
                    SignPartitions.partition(arrL)
         
     | 
| 
      
 116 
     | 
    
         
            +
                    SignPartitions.partition(arrL)
         
     | 
| 
      
 117 
     | 
    
         
            +
                  end
         
     | 
| 
      
 118 
     | 
    
         
            +
                end
         
     | 
| 
      
 119 
     | 
    
         
            +
                # + 17% faster (relative to SignPartitions)
         
     | 
| 
      
 120 
     | 
    
         
            +
                x.report("#{n} times (raw code):" ) do
         
     | 
| 
      
 121 
     | 
    
         
            +
                  n.times do
         
     | 
| 
      
 122 
     | 
    
         
            +
                    parts = []
         
     | 
| 
      
 123 
     | 
    
         
            +
                    p = arrL.inject(nil) do |partition, element|
         
     | 
| 
      
 124 
     | 
    
         
            +
                      if partition && (partition[0] > 0 && element > 0 || partition[0] < 0 && element < 0)
         
     | 
| 
      
 125 
     | 
    
         
            +
                        partition << element
         
     | 
| 
      
 126 
     | 
    
         
            +
                        partition
         
     | 
| 
      
 127 
     | 
    
         
            +
                      else
         
     | 
| 
      
 128 
     | 
    
         
            +
                        parts << partition if partition
         
     | 
| 
      
 129 
     | 
    
         
            +
                        [element]
         
     | 
| 
      
 130 
     | 
    
         
            +
                      end
         
     | 
| 
      
 131 
     | 
    
         
            +
                    end
         
     | 
| 
      
 132 
     | 
    
         
            +
                    parts << p if p
         
     | 
| 
      
 133 
     | 
    
         
            +
                  end
         
     | 
| 
      
 134 
     | 
    
         
            +
                end
         
     | 
| 
      
 135 
     | 
    
         
            +
              end
         
     | 
| 
      
 136 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/util/util.rb
    ADDED
    
    | 
         @@ -0,0 +1,38 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module StrokeDB
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Util
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
                class ::Object
         
     | 
| 
      
 5 
     | 
    
         
            +
                  # Uses references to documents (compared to to_raw using hashes instead)
         
     | 
| 
      
 6 
     | 
    
         
            +
                  def to_optimized_raw
         
     | 
| 
      
 7 
     | 
    
         
            +
                    case self
         
     | 
| 
      
 8 
     | 
    
         
            +
                    when Array
         
     | 
| 
      
 9 
     | 
    
         
            +
                      map{|v| v.to_optimized_raw }
         
     | 
| 
      
 10 
     | 
    
         
            +
                    when Hash
         
     | 
| 
      
 11 
     | 
    
         
            +
                      new_hash = {}
         
     | 
| 
      
 12 
     | 
    
         
            +
                      each_pair{|k,v| new_hash[k.to_optimized_raw] = v.to_optimized_raw}
         
     | 
| 
      
 13 
     | 
    
         
            +
                      new_hash
         
     | 
| 
      
 14 
     | 
    
         
            +
                    else
         
     | 
| 
      
 15 
     | 
    
         
            +
                      self
         
     | 
| 
      
 16 
     | 
    
         
            +
                    end
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                unless RUBY_PLATFORM =~ /java/
         
     | 
| 
      
 21 
     | 
    
         
            +
                  require 'uuidtools'
         
     | 
| 
      
 22 
     | 
    
         
            +
                  def self.random_uuid
         
     | 
| 
      
 23 
     | 
    
         
            +
                    ::UUID.random_create.to_s
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                class CircularReferenceCondition < Exception ; end
         
     | 
| 
      
 28 
     | 
    
         
            +
                class << self
         
     | 
| 
      
 29 
     | 
    
         
            +
                  def catch_circular_reference(value,name = 'StrokeDB.reference_stack')
         
     | 
| 
      
 30 
     | 
    
         
            +
                    stack = Thread.current[name] ||= []
         
     | 
| 
      
 31 
     | 
    
         
            +
                    raise CircularReferenceCondition if stack.find{|v| value == v}
         
     | 
| 
      
 32 
     | 
    
         
            +
                    stack << value
         
     | 
| 
      
 33 
     | 
    
         
            +
                    yield
         
     | 
| 
      
 34 
     | 
    
         
            +
                    stack.pop
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
              end
         
     | 
| 
      
 38 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/util/xml.rb
    ADDED
    
    
    
        data/lib/view/view.rb
    ADDED
    
    | 
         @@ -0,0 +1,55 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module StrokeDB
         
     | 
| 
      
 2 
     | 
    
         
            +
              View = Meta.new(:uuid => VIEW_UUID) do
         
     | 
| 
      
 3 
     | 
    
         
            +
                attr_accessor :map_with_proc
         
     | 
| 
      
 4 
     | 
    
         
            +
                attr_reader :reduce_with_proc
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                on_initialization do |view|
         
     | 
| 
      
 7 
     | 
    
         
            +
                  view.map_with_proc = proc {|doc, *args| doc } 
         
     | 
| 
      
 8 
     | 
    
         
            +
                end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                def reduce_with(&block)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @reduce_with_proc = block
         
     | 
| 
      
 12 
     | 
    
         
            +
                  self
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                def map_with(&block)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  @map_with_proc = block
         
     | 
| 
      
 17 
     | 
    
         
            +
                  self
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                def emit(*args) 
         
     | 
| 
      
 21 
     | 
    
         
            +
                  ViewCut.new(store, :view => self, :args => args, :timestamp_state => LTS.zero.counter).emit
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
              ViewCut = Meta.new(:uuid => VIEWCUT_UUID) do
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                on_new_document do |cut|
         
     | 
| 
      
 28 
     | 
    
         
            +
                  cut.instance_eval do
         
     | 
| 
      
 29 
     | 
    
         
            +
                    if view.is_a?(View)
         
     | 
| 
      
 30 
     | 
    
         
            +
                      @map_with_proc = view.map_with_proc
         
     | 
| 
      
 31 
     | 
    
         
            +
                      @reduce_with_proc = view.reduce_with_proc
         
     | 
| 
      
 32 
     | 
    
         
            +
                    end
         
     | 
| 
      
 33 
     | 
    
         
            +
                  end
         
     | 
| 
      
 34 
     | 
    
         
            +
                end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                before_save do |cut|
         
     | 
| 
      
 37 
     | 
    
         
            +
                  view = cut.view
         
     | 
| 
      
 38 
     | 
    
         
            +
                  view.last_cut = cut if view[:last_cut].nil? or (cut[:previous] && view.last_cut == cut.previous)
         
     | 
| 
      
 39 
     | 
    
         
            +
                  view.save!
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                def emit
         
     | 
| 
      
 44 
     | 
    
         
            +
                  mapped = []
         
     | 
| 
      
 45 
     | 
    
         
            +
                  store.each(:after_timestamp => timestamp_state, :include_versions => view[:include_versions]) do |doc| 
         
     | 
| 
      
 46 
     | 
    
         
            +
                    mapped << @map_with_proc.call(doc,*args) 
         
     | 
| 
      
 47 
     | 
    
         
            +
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
                  documents = (@reduce_with_proc ? mapped.select {|doc| @reduce_with_proc.call(doc,*args) } : mapped).map{|d| d.is_a?(Document) ? d.extend(VersionedDocument) : d}
         
     | 
| 
      
 49 
     | 
    
         
            +
                  ViewCut.new(store, :documents => documents, :view => view, :args => args, :timestamp_state => store.timestamp.counter, :previous => timestamp_state == 0 ? nil : self)
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
                def to_a
         
     | 
| 
      
 52 
     | 
    
         
            +
                  documents
         
     | 
| 
      
 53 
     | 
    
         
            +
                end
         
     | 
| 
      
 54 
     | 
    
         
            +
              end
         
     | 
| 
      
 55 
     | 
    
         
            +
            end
         
     |