linked 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fefa402916a5d9db25add5e34a0d95cfbfe1440f
4
- data.tar.gz: 3f17115bffeb8777ba904292f98c8fffbed1b34b
3
+ metadata.gz: 128756e7bd9d7a135b08f43d8318d94960aa109a
4
+ data.tar.gz: 1ab7cd3ac051d2beffb1ef345ba45784b0396310
5
5
  SHA512:
6
- metadata.gz: 6dbf54c87e2ca417d725e40f12eff566439fc9212c5f13c12bd2c089c0018a09cf671de635c2aa800151e3d6474de793e6b3991ab51c7e7fa3f224903ad34cb2
7
- data.tar.gz: 83a352fb6f3f00e5bb7245075d47609521dbeb7c508a1ea066acb2fb120e6affdbc2ed9c54cbcc15c881353b7c716653976eec02e138f7b8131e51c6699ac7c9
6
+ metadata.gz: e7cdc70d3062ec1e70cb854bb5e52f05f7621e6a8225a9c6a3816ae2b57ad0fdfd9d165dd61d48bf9c0f1ad15f27f5d0027ff7a67b09f91673ce56cf064f3a01
7
+ data.tar.gz: b7439ec77d5db6122b2fc0f230a7eea8ac9d0043fec80674d392e192977354a5f2ea7338284916b720249dd251f0f125f44ceef7c609e1ea21147dba0f6a4f55
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # TODO: Think about moving some of basic functionallity of Item into Item::Base.
4
+
3
5
  module Linked
4
6
  # Item
5
7
  #
@@ -84,33 +86,33 @@ module Linked
84
86
  end
85
87
  super
86
88
  end
87
-
89
+
88
90
  # Identity method that simply return the item. This method mirrors List#item
89
91
  # and allows other methods that work on Item objects to easily and
90
92
  # interchangebly accept both lists and items as arguments.
91
93
  #
92
94
  # Returns the item itself.
93
-
95
+
94
96
  def item
95
97
  self
96
98
  end
97
-
99
+
98
100
  # Access the list that the item is part of. If the item is not in a list a
99
101
  # NoMethodError will be raised. This mirrors the behaviour of List#list and
100
102
  # allows other methods that work on List objects to easily and
101
103
  # interchangeably accept both lists and items as arguments.
102
104
  #
103
105
  # Returns the list that the item is part of.
104
-
106
+
105
107
  def list
106
108
  raise NoMethodError unless @list
107
109
  @list
108
110
  end
109
-
111
+
110
112
  # Check it the item is part of a list.
111
113
  #
112
114
  # Returns true if the item is in a list.
113
-
115
+
114
116
  def in_list?
115
117
  @list ? true : false
116
118
  end
@@ -132,7 +134,7 @@ module Linked
132
134
  def last?
133
135
  @next.nil?
134
136
  end
135
-
137
+
136
138
  # Check if the item is in the given list.
137
139
  #
138
140
  # list - any object.
@@ -196,66 +198,6 @@ module Linked
196
198
 
197
199
  alias previous! prev!
198
200
 
199
- # Split the chain of items in two. If the chain belongs to a list this item
200
- # and all that stay connected to it will continue to belong to it, while the
201
- # rest are removed from it.
202
- #
203
- # By default all items followng this one will be kept together, but if given
204
- # the argument after: true, the split will instead happen after this item
205
- # and it will instead be kept with those before it.
206
- #
207
- # Example for the chain (A <> B <> C)
208
- #
209
- # B.split(after: false) => (A), (B <> C)
210
- # B.split(after: true) => (A <> B), (C)
211
- #
212
- # after - determine wheter to split the chain before or after this item.
213
- #
214
- # Returns self.
215
-
216
- def split after: false
217
- warn '[DEPRECATION] this method will be removed in the next major update. Please use #delete_before and #delete_after instead'
218
- if after
219
- unless last?
220
- if @list
221
- item = self
222
- count = 1 + loop.count do
223
- item = item.next
224
- item.list = nil
225
- end
226
-
227
- tail = @list.tail
228
- tail.prev = self
229
- @next = tail
230
- @list.shrink count
231
- else
232
- @next.prev = nil
233
- @next = nil
234
- end
235
- end
236
- else
237
- unless first?
238
- if @list
239
- item = self
240
- count = 1 + loop.count do
241
- item = item.prev
242
- item.list = nil
243
- end
244
-
245
- head = @list.head
246
- head.next = self
247
- @prev = head
248
- @list.shrink count
249
- else
250
- @prev.next = nil
251
- @prev = nil
252
- end
253
- end
254
- end
255
-
256
- self
257
- end
258
-
259
201
  # Inserts the given item between this one and the one after it (if any). If
260
202
  # the given item is part of a chain, all items following it will be moved to
261
203
  # this one, and added to the list if one is set.
@@ -271,8 +213,9 @@ module Linked
271
213
  # number of added items as an argument. Should it also be the last item
272
214
  # #prev= will be called on the list tail.
273
215
  #
274
- # sibling - the item to append, or an arbitrary object to be wraped in a new
275
- # item.
216
+ # object - the item to append, or an arbitrary object to be wraped in a new
217
+ # item. If in a list it will be asked to create the new item via
218
+ # List#create_item.
276
219
  #
277
220
  # Returns the last item that was appended.
278
221
 
@@ -281,15 +224,19 @@ module Linked
281
224
  first_item = object.item
282
225
  last_item = first_item.send :extract_beginning_with, @list
283
226
  else
284
- first_item = last_item = self.class.new object
285
- first_item.list = @list
286
- @list.send :grow if @list
227
+ if @list
228
+ first_item = last_item = @list.send :create_item, object
229
+ first_item.list = @list
230
+ @list.send :grow
231
+ else
232
+ first_item = last_item = self.class.new object
233
+ end
287
234
  end
288
-
235
+
289
236
  first_item.prev = self
290
237
  @next.prev = last_item if @next
291
238
  @next, last_item.next = first_item, @next
292
-
239
+
293
240
  last_item
294
241
  end
295
242
 
@@ -308,8 +255,9 @@ module Linked
308
255
  # number of added items as an argument. Should it also be the first item
309
256
  # #next= will be called on the list head.
310
257
  #
311
- # sibling - the item to prepend. or an arbitrary object to be wraped in a
312
- # new item.
258
+ # object - the item to prepend. or an arbitrary object to be wraped in a
259
+ # new item. If in a list it will be asked to create the new item
260
+ # via List#create_item.
313
261
  #
314
262
  # Returns the last item that was prepended.
315
263
 
@@ -318,18 +266,22 @@ module Linked
318
266
  last_item = object.item
319
267
  first_item = last_item.send :extract_ending_with, @list
320
268
  else
321
- first_item = last_item = self.class.new object
322
- first_item.list = @list
323
- @list.send :grow, 1 if @list
269
+ if @list
270
+ first_item = last_item = @list.send :create_item, object
271
+ first_item.list = @list
272
+ @list.send :grow
273
+ else
274
+ first_item = last_item = self.class.new object
275
+ end
324
276
  end
325
-
277
+
326
278
  last_item.next = self
327
279
  @prev.next = first_item if @prev
328
280
  @prev, first_item.prev = last_item, @prev
329
-
281
+
330
282
  first_item
331
283
  end
332
-
284
+
333
285
  # Remove an item from the chain. If this item is part of a list and is
334
286
  # either first, last or both in that list, #next= and #prev= will be called
335
287
  # on the list head and tail respectivly.
@@ -346,23 +298,23 @@ module Linked
346
298
  @next = @prev = @list = nil
347
299
  self
348
300
  end
349
-
301
+
350
302
  # Remove all items before this one in the chain. If the items are part of a
351
303
  # list they will be removed from it.
352
304
  #
353
305
  # Returns the last item in the chain that was just deleted, or nil if this
354
306
  # is the first item.
355
-
307
+
356
308
  def delete_before
357
309
  @prev.send :extract_ending_with unless first?
358
310
  end
359
-
311
+
360
312
  # Remove all items after this one in the chain. If the items are part of a
361
313
  # list they will be removed from it.
362
314
  #
363
315
  # Returns the last item in the chain that was just deleted, or nil if this
364
316
  # is the first item.
365
-
317
+
366
318
  def delete_after
367
319
  @next.send :extract_beginning_with unless last?
368
320
  end
@@ -420,7 +372,7 @@ module Linked
420
372
  output = format '%s:0x%0x', self.class.name, object_id
421
373
  value ? output + " value=#{value.inspect}" : output
422
374
  end
423
-
375
+
424
376
  # PRIVATE DANGEROUS METHOD. This method should never be called directly
425
377
  # since it may leave the extracted item chain in an invalid state.
426
378
  #
@@ -439,7 +391,7 @@ module Linked
439
391
  # be left in an invalid state.
440
392
  #
441
393
  # Returns the last item of the chain.
442
-
394
+
443
395
  private def extract_beginning_with(new_list = nil)
444
396
  old_list = @list
445
397
  # Count items and move them to the new list
@@ -448,7 +400,7 @@ module Linked
448
400
  last_item.list = new_list
449
401
  last_item = last_item.next
450
402
  end
451
-
403
+
452
404
  # Make sure the old list is in a valid state
453
405
  if old_list
454
406
  if first?
@@ -463,16 +415,16 @@ module Linked
463
415
  # Disconnect the item directly after the chain
464
416
  @prev.next = nil unless first?
465
417
  end
466
-
418
+
467
419
  # Disconnect the chain from the list
468
420
  @prev = last_item.next = nil
469
-
421
+
470
422
  # Preemptivly tell the new list to grow
471
423
  new_list.send :grow, count if new_list
472
-
424
+
473
425
  last_item
474
426
  end
475
-
427
+
476
428
  # PRIVATE DANGEROUS METHOD. This method should never be called directly
477
429
  # since it may leave the extracted item chain in an invalid state.
478
430
  #
@@ -482,7 +434,7 @@ module Linked
482
434
  # effects from calling this method.
483
435
  #
484
436
  # Returns the first item in the chain.
485
-
437
+
486
438
  private def extract_ending_with(new_list = nil)
487
439
  old_list = @list
488
440
  # Count items and move them to the new list
@@ -491,7 +443,7 @@ module Linked
491
443
  first_item.list = new_list
492
444
  first_item = first_item.prev
493
445
  end
494
-
446
+
495
447
  # Make sure the old list is in a valid state
496
448
  if old_list
497
449
  if last?
@@ -506,13 +458,13 @@ module Linked
506
458
  # Disconnect the item directly after the chain
507
459
  @next.prev = nil unless last?
508
460
  end
509
-
461
+
510
462
  # Disconnect the chain from the list
511
463
  first_item.prev = @next = nil
512
-
464
+
513
465
  # Preemptivly tell the new list to grow
514
466
  new_list.send :grow, count if new_list
515
-
467
+
516
468
  first_item
517
469
  end
518
470
  end
@@ -62,24 +62,24 @@ module Linked
62
62
 
63
63
  super
64
64
  end
65
-
65
+
66
66
  # Identity method that simply return the list. This method mirrors Item#list
67
67
  # and allows other methods that work on List objects to easily and
68
68
  # interchangebly accept both lists and items as arguments.
69
69
  #
70
70
  # Returns the list itself.
71
-
71
+
72
72
  def list
73
73
  self
74
74
  end
75
-
75
+
76
76
  # Access the first item in the list. If the list is empty a NoMethodError
77
77
  # will be raised. This mirrors the behaviour of Item#item and allows other
78
78
  # methods that work on List objects to easily and interchangeably accept
79
79
  # both lists and items as arguments.
80
80
  #
81
81
  # Returns the first item in the list.
82
-
82
+
83
83
  def item
84
84
  raise NoMethodError if empty?
85
85
  eol.next
@@ -167,18 +167,18 @@ module Linked
167
167
  @item_count == 0
168
168
  end
169
169
 
170
- # Insert an item at the end of the list. If the given object is not an Item,
171
- # or a decendant of Item, it will be treated as a value. Depending on the
172
- # state of the list the value will be
173
- # a) wraped in a new instance of Item if the list is empty or
174
- # b) wraped in an object of the same class as the last item in the list.
170
+ # Insert an item at the end of the list. If the given object is not an
171
+ # object responding to #item it will be treated as a value. The value will
172
+ # be wraped in a new Item create by #create_item.
173
+ #
174
+ # See Item#append for more details.
175
175
  #
176
- # item - the item to insert, or an arbitrary value.
176
+ # object - the item to insert, or an arbitrary object.
177
177
  #
178
178
  # Returns self.
179
179
 
180
- def push(item)
181
- eol.append item
180
+ def push(object)
181
+ eol.append object
182
182
  self
183
183
  end
184
184
 
@@ -194,17 +194,17 @@ module Linked
194
194
  end
195
195
 
196
196
  # Insert an item at the beginning of the list. If the given object is not an
197
- # Item, or a decendant of Item, it will be treated as a value. Depending on
198
- # the state of the list the value will be
199
- # a) wraped in a new instance of Item if the list is empty or
200
- # b) wraped in an object of the same class as the last item in the list.
197
+ # object responding to #item it will be treated as a value. The value will
198
+ # be wraped in a new Item create by #create_item.
199
+ #
200
+ # See Item#prepend for more details.
201
201
  #
202
- # item - the item to insert, or an arbitrary value.
202
+ # object - the item to insert, or an arbitrary object.
203
203
  #
204
204
  # Returns self.
205
205
 
206
- def unshift(item)
207
- eol.prepend item
206
+ def unshift(object)
207
+ eol.prepend object
208
208
  self
209
209
  end
210
210
 
@@ -216,32 +216,24 @@ module Linked
216
216
  return nil if empty?
217
217
  first.delete
218
218
  end
219
-
219
+
220
220
  # Check if an item is in the list.
221
221
  #
222
222
  # item - Item, or any object that may be in the list.
223
223
  #
224
224
  # Returns true if the given item is in the list, otherwise false.
225
-
225
+
226
226
  def include?(item)
227
227
  item.in? self
228
228
  rescue NoMethodError
229
229
  false
230
230
  end
231
231
 
232
- # Iterates over each item in the list, either in normal or reverse order. If
233
- # a block is not given an enumerator is returned.
234
- #
235
- # reverse - flips the iteration order if true. Note that this option is
236
- # depricated and will be removed in the next major release.
232
+ # Iterates over each item in the list If a block is not given an enumerator
233
+ # is returned.
237
234
 
238
- def each_item(reverse: false, &block)
239
- if reverse
240
- warn '[DEPRECATION] the option `reverse: true` will be removed in a future release. Please call `reverse_each_item` instead.'
241
- eol.before(&block)
242
- else
243
- eol.after(&block)
244
- end
235
+ def each_item(&block)
236
+ eol.after(&block)
245
237
  end
246
238
 
247
239
  alias each each_item
@@ -285,6 +277,20 @@ module Linked
285
277
  res.join("\n")
286
278
  end
287
279
 
280
+ # Protected factory method for creating items compatible with the list. This
281
+ # method is called whenever an arbitrary object is pushed or unshifted onto
282
+ # the list and need to be wraped inside an Item.
283
+ #
284
+ # This method can be overridden to suport different Item types.
285
+ #
286
+ # args - any arguments will be passed on to Item.new.
287
+ #
288
+ # Returns a new Item.
289
+
290
+ protected def create_item(*args)
291
+ Item.new(*args)
292
+ end
293
+
288
294
  # Internal method to grow the list with n elements. Never call this method
289
295
  # without also inserting the n elements.
290
296
  #
@@ -306,17 +312,17 @@ module Linked
306
312
  private def shrink(n = 1)
307
313
  @item_count -= n
308
314
  end
309
-
315
+
310
316
  # Private method to clear the list. Never call this method without also
311
317
  # modifying the items in the list, as this operation leavs them in an
312
318
  # inconsistant state. If the list items are kept, make sure to
313
319
  # a) clear the `prev` pointer of the first item and
314
320
  # b) clear the `next` pointer of the last item.
315
-
321
+
316
322
  private def clear
317
323
  head.send :next=, tail
318
324
  tail.send :prev=, head
319
-
325
+
320
326
  @item_count = 0
321
327
  end
322
328
 
@@ -342,7 +348,7 @@ module Linked
342
348
  return nil if n == 0
343
349
  return n > 1 ? [] : nil if item.next!.nil?
344
350
  return item.next if n == 1
345
-
351
+
346
352
  n = items_left if n > items_left
347
353
 
348
354
  arr = Array.new n
@@ -376,18 +382,18 @@ module Linked
376
382
  return item.prev if n == 1
377
383
 
378
384
  n = items_left if n > items_left
379
-
385
+
380
386
  arr = Array.new n
381
387
  (n - 1).downto(0) { |i| arr[i] = item = item.prev }
382
388
  arr
383
389
  rescue StopIteration
384
390
  arr.compact! || arr
385
391
  end
386
-
392
+
387
393
  # This method is called whenever the module is included somewhere. In the
388
394
  # special case when List is included in an Item the #item method must be
389
395
  # changed to return self.
390
-
396
+
391
397
  def self.included(klass)
392
398
  klass.send(:define_method, :item) { self } if klass < Item
393
399
  end
@@ -38,44 +38,28 @@ module Linked
38
38
  true
39
39
  end
40
40
 
41
- # Inserts one or more items at the end of the list. If the given object is
42
- # not an Item, or a decendant of Item, it will be treated as a value.
43
- # Depending on the state of the list the value will be
44
- # a) wraped in a new instance of Item if the list is empty or
45
- # b) wraped in an object of the same class as the last item in the list.
41
+ # Inserts one or more items at the end of the list.
46
42
  #
47
- # sibling - the item or value to be appended.
48
- #
49
- # Returns the item that was appended. In case of a string of items the
50
- # last one is returned.
43
+ # See Item#append for more details.
51
44
 
52
- def append(sibling)
53
- if @prev == self
54
- sibling = Item.new sibling unless sibling.is_a? Item
55
- super sibling
56
- else
57
- @prev.append sibling
58
- end
45
+ def append(object)
46
+ empty? ? super : @prev.append(object)
59
47
  end
60
48
 
61
- # Inserts one or more items at the beginning of the list. If the given
62
- # object is not an Item, or a decendant of Item, it will be treated as a
63
- # value. Depending on the state of the list the value will be
64
- # a) wraped in a new instance of Item if the list is empty or
65
- # b) wraped in an object of the same class as the last item in the list.
49
+ # Inserts one or more items at the beginning of the list.
66
50
  #
67
- # sibling - the item or value to be prepended.
51
+ # See Item#append for more details.
52
+
53
+ def prepend(object)
54
+ empty? ? super : @next.prepend(object)
55
+ end
56
+
57
+ # Private helper to check if the item chain is empty.
68
58
  #
69
- # Returns the item that was prepended. In case of a string of items the
70
- # first one is returned.
59
+ # Return true if the chain is empty, otherwise nil.
71
60
 
72
- def prepend(sibling)
73
- if @next == self
74
- sibling = Item.new sibling unless sibling.is_a? Item
75
- super sibling
76
- else
77
- @next.prepend sibling
78
- end
61
+ private def empty?
62
+ @prev == self
79
63
  end
80
64
  end
81
65
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Linked
4
- VERSION = '0.2.1'
4
+ VERSION = '0.3.0'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: linked
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sebastian Lindberg