author | Giulio Cesare Solaroli <giulio.cesare@clipperz.com> | 2013-08-30 15:56:53 (UTC) |
---|---|---|
committer | Giulio Cesare Solaroli <giulio.cesare@clipperz.com> | 2013-08-30 21:23:42 (UTC) |
commit | 20bea94ab6b91c85b171dcf86baba0a64169d508 (patch) (unidiff) | |
tree | 6e38e91498dcdb861620eba1e237d1026fe79cc5 /frontend/delta/js/MochiKit/Iter.js | |
parent | bde3c7b98523112ade9c5bbf7390c4ecb494cd2e (diff) | |
download | clipperz-20bea94ab6b91c85b171dcf86baba0a64169d508.zip clipperz-20bea94ab6b91c85b171dcf86baba0a64169d508.tar.gz clipperz-20bea94ab6b91c85b171dcf86baba0a64169d508.tar.bz2 |
First release of /delta version
Diffstat (limited to 'frontend/delta/js/MochiKit/Iter.js') (more/less context) (show whitespace changes)
-rw-r--r-- | frontend/delta/js/MochiKit/Iter.js | 811 |
1 files changed, 811 insertions, 0 deletions
diff --git a/frontend/delta/js/MochiKit/Iter.js b/frontend/delta/js/MochiKit/Iter.js new file mode 100644 index 0000000..8f7ea3d --- a/dev/null +++ b/frontend/delta/js/MochiKit/Iter.js | |||
@@ -0,0 +1,811 @@ | |||
1 | /* | ||
2 | |||
3 | Copyright 2008-2013 Clipperz Srl | ||
4 | |||
5 | This file is part of Clipperz, the online password manager. | ||
6 | For further information about its features and functionalities please | ||
7 | refer to http://www.clipperz.com. | ||
8 | |||
9 | * Clipperz is free software: you can redistribute it and/or modify it | ||
10 | under the terms of the GNU Affero General Public License as published | ||
11 | by the Free Software Foundation, either version 3 of the License, or | ||
12 | (at your option) any later version. | ||
13 | |||
14 | * Clipperz is distributed in the hope that it will be useful, but | ||
15 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
17 | See the GNU Affero General Public License for more details. | ||
18 | |||
19 | * You should have received a copy of the GNU Affero General Public | ||
20 | License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||
21 | |||
22 | */ | ||
23 | |||
24 | /*** | ||
25 | |||
26 | MochiKit.Iter 1.5 | ||
27 | |||
28 | See <http://mochikit.com/> for documentation, downloads, license, etc. | ||
29 | |||
30 | (c) 2005 Bob Ippolito. All rights Reserved. | ||
31 | |||
32 | ***/ | ||
33 | |||
34 | MochiKit.Base.module(MochiKit, 'Iter', '1.5', ['Base']); | ||
35 | |||
36 | MochiKit.Base.update(MochiKit.Iter, { | ||
37 | /** @id MochiKit.Iter.registerIteratorFactory */ | ||
38 | registerIteratorFactory: function (name, check, iterfactory, /* optional */ override) { | ||
39 | MochiKit.Iter.iteratorRegistry.register(name, check, iterfactory, override); | ||
40 | }, | ||
41 | |||
42 | /** @id MochiKit.Iter.isIterable */ | ||
43 | isIterable: function(o) { | ||
44 | return o != null && | ||
45 | (typeof(o.next) == "function" || typeof(o.iter) == "function"); | ||
46 | }, | ||
47 | |||
48 | /** @id MochiKit.Iter.iter */ | ||
49 | iter: function (iterable, /* optional */ sentinel) { | ||
50 | var self = MochiKit.Iter; | ||
51 | if (arguments.length == 2) { | ||
52 | return self.takewhile( | ||
53 | function (a) { return a != sentinel; }, | ||
54 | iterable | ||
55 | ); | ||
56 | } | ||
57 | if (typeof(iterable.next) == 'function') { | ||
58 | return iterable; | ||
59 | } else if (typeof(iterable.iter) == 'function') { | ||
60 | return iterable.iter(); | ||
61 | /* | ||
62 | } else if (typeof(iterable.__iterator__) == 'function') { | ||
63 | // | ||
64 | // XXX: We can't support JavaScript 1.7 __iterator__ directly | ||
65 | // because of Object.prototype.__iterator__ | ||
66 | // | ||
67 | return iterable.__iterator__(); | ||
68 | */ | ||
69 | } | ||
70 | |||
71 | try { | ||
72 | return self.iteratorRegistry.match(iterable); | ||
73 | } catch (e) { | ||
74 | var m = MochiKit.Base; | ||
75 | if (e == m.NotFound) { | ||
76 | e = new TypeError(typeof(iterable) + ": " + m.repr(iterable) + " is not iterable"); | ||
77 | } | ||
78 | throw e; | ||
79 | } | ||
80 | }, | ||
81 | |||
82 | /** @id MochiKit.Iter.count */ | ||
83 | count: function (n) { | ||
84 | if (!n) { | ||
85 | n = 0; | ||
86 | } | ||
87 | var m = MochiKit.Base; | ||
88 | return { | ||
89 | repr: function () { return "count(" + n + ")"; }, | ||
90 | toString: m.forwardCall("repr"), | ||
91 | next: m.counter(n) | ||
92 | }; | ||
93 | }, | ||
94 | |||
95 | /** @id MochiKit.Iter.cycle */ | ||
96 | cycle: function (p) { | ||
97 | var self = MochiKit.Iter; | ||
98 | var m = MochiKit.Base; | ||
99 | var lst = []; | ||
100 | var iterator = self.iter(p); | ||
101 | return { | ||
102 | repr: function () { return "cycle(...)"; }, | ||
103 | toString: m.forwardCall("repr"), | ||
104 | next: function () { | ||
105 | try { | ||
106 | var rval = iterator.next(); | ||
107 | lst.push(rval); | ||
108 | return rval; | ||
109 | } catch (e) { | ||
110 | if (e != self.StopIteration) { | ||
111 | throw e; | ||
112 | } | ||
113 | if (lst.length === 0) { | ||
114 | this.next = function () { | ||
115 | throw self.StopIteration; | ||
116 | }; | ||
117 | } else { | ||
118 | var i = -1; | ||
119 | this.next = function () { | ||
120 | i = (i + 1) % lst.length; | ||
121 | return lst[i]; | ||
122 | }; | ||
123 | } | ||
124 | return this.next(); | ||
125 | } | ||
126 | } | ||
127 | }; | ||
128 | }, | ||
129 | |||
130 | /** @id MochiKit.Iter.repeat */ | ||
131 | repeat: function (elem, /* optional */n) { | ||
132 | var m = MochiKit.Base; | ||
133 | if (typeof(n) == 'undefined') { | ||
134 | return { | ||
135 | repr: function () { | ||
136 | return "repeat(" + m.repr(elem) + ")"; | ||
137 | }, | ||
138 | toString: m.forwardCall("repr"), | ||
139 | next: function () { | ||
140 | return elem; | ||
141 | } | ||
142 | }; | ||
143 | } | ||
144 | return { | ||
145 | repr: function () { | ||
146 | return "repeat(" + m.repr(elem) + ", " + n + ")"; | ||
147 | }, | ||
148 | toString: m.forwardCall("repr"), | ||
149 | next: function () { | ||
150 | if (n <= 0) { | ||
151 | throw MochiKit.Iter.StopIteration; | ||
152 | } | ||
153 | n -= 1; | ||
154 | return elem; | ||
155 | } | ||
156 | }; | ||
157 | }, | ||
158 | |||
159 | /** @id MochiKit.Iter.next */ | ||
160 | next: function (iterator) { | ||
161 | return iterator.next(); | ||
162 | }, | ||
163 | |||
164 | /** @id MochiKit.Iter.izip */ | ||
165 | izip: function (p, q/*, ...*/) { | ||
166 | var m = MochiKit.Base; | ||
167 | var self = MochiKit.Iter; | ||
168 | var next = self.next; | ||
169 | var iterables = m.map(self.iter, arguments); | ||
170 | return { | ||
171 | repr: function () { return "izip(...)"; }, | ||
172 | toString: m.forwardCall("repr"), | ||
173 | next: function () { return m.map(next, iterables); } | ||
174 | }; | ||
175 | }, | ||
176 | |||
177 | /** @id MochiKit.Iter.ifilter */ | ||
178 | ifilter: function (pred, seq) { | ||
179 | var m = MochiKit.Base; | ||
180 | seq = MochiKit.Iter.iter(seq); | ||
181 | if (pred === null) { | ||
182 | pred = m.operator.truth; | ||
183 | } | ||
184 | return { | ||
185 | repr: function () { return "ifilter(...)"; }, | ||
186 | toString: m.forwardCall("repr"), | ||
187 | next: function () { | ||
188 | while (true) { | ||
189 | var rval = seq.next(); | ||
190 | if (pred(rval)) { | ||
191 | return rval; | ||
192 | } | ||
193 | } | ||
194 | // mozilla warnings aren't too bright | ||
195 | return undefined; | ||
196 | } | ||
197 | }; | ||
198 | }, | ||
199 | |||
200 | /** @id MochiKit.Iter.ifilterfalse */ | ||
201 | ifilterfalse: function (pred, seq) { | ||
202 | var m = MochiKit.Base; | ||
203 | seq = MochiKit.Iter.iter(seq); | ||
204 | if (pred === null) { | ||
205 | pred = m.operator.truth; | ||
206 | } | ||
207 | return { | ||
208 | repr: function () { return "ifilterfalse(...)"; }, | ||
209 | toString: m.forwardCall("repr"), | ||
210 | next: function () { | ||
211 | while (true) { | ||
212 | var rval = seq.next(); | ||
213 | if (!pred(rval)) { | ||
214 | return rval; | ||
215 | } | ||
216 | } | ||
217 | // mozilla warnings aren't too bright | ||
218 | return undefined; | ||
219 | } | ||
220 | }; | ||
221 | }, | ||
222 | |||
223 | /** @id MochiKit.Iter.islice */ | ||
224 | islice: function (seq/*, [start,] stop[, step] */) { | ||
225 | var self = MochiKit.Iter; | ||
226 | var m = MochiKit.Base; | ||
227 | seq = self.iter(seq); | ||
228 | var start = 0; | ||
229 | var stop = 0; | ||
230 | var step = 1; | ||
231 | var i = -1; | ||
232 | if (arguments.length == 2) { | ||
233 | stop = arguments[1]; | ||
234 | } else if (arguments.length == 3) { | ||
235 | start = arguments[1]; | ||
236 | stop = arguments[2]; | ||
237 | } else { | ||
238 | start = arguments[1]; | ||
239 | stop = arguments[2]; | ||
240 | step = arguments[3]; | ||
241 | } | ||
242 | return { | ||
243 | repr: function () { | ||
244 | return "islice(" + ["...", start, stop, step].join(", ") + ")"; | ||
245 | }, | ||
246 | toString: m.forwardCall("repr"), | ||
247 | next: function () { | ||
248 | if (start >= stop) { | ||
249 | throw self.StopIteration; | ||
250 | } | ||
251 | |||
252 | var rval; | ||
253 | while (i < start) { | ||
254 | rval = seq.next(); | ||
255 | i++; | ||
256 | } | ||
257 | start += step; | ||
258 | return rval; | ||
259 | } | ||
260 | }; | ||
261 | }, | ||
262 | |||
263 | /** @id MochiKit.Iter.imap */ | ||
264 | imap: function (fun, p, q/*, ...*/) { | ||
265 | var m = MochiKit.Base; | ||
266 | var self = MochiKit.Iter; | ||
267 | var iterables = m.map(self.iter, m.extend(null, arguments, 1)); | ||
268 | var map = m.map; | ||
269 | var next = self.next; | ||
270 | return { | ||
271 | repr: function () { return "imap(...)"; }, | ||
272 | toString: m.forwardCall("repr"), | ||
273 | next: function () { | ||
274 | return fun.apply(this, map(next, iterables)); | ||
275 | } | ||
276 | }; | ||
277 | }, | ||
278 | |||
279 | /** @id MochiKit.Iter.applymap */ | ||
280 | applymap: function (fun, seq, self) { | ||
281 | seq = MochiKit.Iter.iter(seq); | ||
282 | var m = MochiKit.Base; | ||
283 | return { | ||
284 | repr: function () { return "applymap(...)"; }, | ||
285 | toString: m.forwardCall("repr"), | ||
286 | next: function () { | ||
287 | return fun.apply(self, seq.next()); | ||
288 | } | ||
289 | }; | ||
290 | }, | ||
291 | |||
292 | /** @id MochiKit.Iter.chain */ | ||
293 | chain: function (p, q/*, ...*/) { | ||
294 | // dumb fast path | ||
295 | var self = MochiKit.Iter; | ||
296 | var m = MochiKit.Base; | ||
297 | if (arguments.length == 1) { | ||
298 | return self.iter(arguments[0]); | ||
299 | } | ||
300 | var argiter = m.map(self.iter, arguments); | ||
301 | return { | ||
302 | repr: function () { return "chain(...)"; }, | ||
303 | toString: m.forwardCall("repr"), | ||
304 | next: function () { | ||
305 | while (argiter.length > 1) { | ||
306 | try { | ||
307 | return argiter[0].next(); | ||
308 | } catch (e) { | ||
309 | if (e != self.StopIteration) { | ||
310 | throw e; | ||
311 | } | ||
312 | argiter.shift(); | ||
313 | } | ||
314 | } | ||
315 | if (argiter.length == 1) { | ||
316 | // optimize last element | ||
317 | var arg = argiter.shift(); | ||
318 | this.next = m.bind("next", arg); | ||
319 | return this.next(); | ||
320 | } | ||
321 | throw self.StopIteration; | ||
322 | } | ||
323 | }; | ||
324 | }, | ||
325 | |||
326 | /** @id MochiKit.Iter.takewhile */ | ||
327 | takewhile: function (pred, seq) { | ||
328 | var self = MochiKit.Iter; | ||
329 | seq = self.iter(seq); | ||
330 | return { | ||
331 | repr: function () { return "takewhile(...)"; }, | ||
332 | toString: MochiKit.Base.forwardCall("repr"), | ||
333 | next: function () { | ||
334 | var rval = seq.next(); | ||
335 | if (!pred(rval)) { | ||
336 | this.next = function () { | ||
337 | throw self.StopIteration; | ||
338 | }; | ||
339 | this.next(); | ||
340 | } | ||
341 | return rval; | ||
342 | } | ||
343 | }; | ||
344 | }, | ||
345 | |||
346 | /** @id MochiKit.Iter.dropwhile */ | ||
347 | dropwhile: function (pred, seq) { | ||
348 | seq = MochiKit.Iter.iter(seq); | ||
349 | var m = MochiKit.Base; | ||
350 | var bind = m.bind; | ||
351 | return { | ||
352 | "repr": function () { return "dropwhile(...)"; }, | ||
353 | "toString": m.forwardCall("repr"), | ||
354 | "next": function () { | ||
355 | while (true) { | ||
356 | var rval = seq.next(); | ||
357 | if (!pred(rval)) { | ||
358 | break; | ||
359 | } | ||
360 | } | ||
361 | this.next = bind("next", seq); | ||
362 | return rval; | ||
363 | } | ||
364 | }; | ||
365 | }, | ||
366 | |||
367 | _tee: function (ident, sync, iterable) { | ||
368 | sync.pos[ident] = -1; | ||
369 | var m = MochiKit.Base; | ||
370 | var listMin = m.listMin; | ||
371 | return { | ||
372 | repr: function () { return "tee(" + ident + ", ...)"; }, | ||
373 | toString: m.forwardCall("repr"), | ||
374 | next: function () { | ||
375 | var rval; | ||
376 | var i = sync.pos[ident]; | ||
377 | |||
378 | if (i == sync.max) { | ||
379 | rval = iterable.next(); | ||
380 | sync.deque.push(rval); | ||
381 | sync.max += 1; | ||
382 | sync.pos[ident] += 1; | ||
383 | } else { | ||
384 | rval = sync.deque[i - sync.min]; | ||
385 | sync.pos[ident] += 1; | ||
386 | if (i == sync.min && listMin(sync.pos) != sync.min) { | ||
387 | sync.min += 1; | ||
388 | sync.deque.shift(); | ||
389 | } | ||
390 | } | ||
391 | return rval; | ||
392 | } | ||
393 | }; | ||
394 | }, | ||
395 | |||
396 | /** @id MochiKit.Iter.tee */ | ||
397 | tee: function (iterable, n/* = 2 */) { | ||
398 | var rval = []; | ||
399 | var sync = { | ||
400 | "pos": [], | ||
401 | "deque": [], | ||
402 | "max": -1, | ||
403 | "min": -1 | ||
404 | }; | ||
405 | if (arguments.length == 1 || typeof(n) == "undefined" || n === null) { | ||
406 | n = 2; | ||
407 | } | ||
408 | var self = MochiKit.Iter; | ||
409 | iterable = self.iter(iterable); | ||
410 | var _tee = self._tee; | ||
411 | for (var i = 0; i < n; i++) { | ||
412 | rval.push(_tee(i, sync, iterable)); | ||
413 | } | ||
414 | return rval; | ||
415 | }, | ||
416 | |||
417 | /** @id MochiKit.Iter.list */ | ||
418 | list: function (iterable) { | ||
419 | // Fast-path for Array and Array-like | ||
420 | var rval; | ||
421 | if (iterable instanceof Array) { | ||
422 | return iterable.slice(); | ||
423 | } | ||
424 | // this is necessary to avoid a Safari crash | ||
425 | if (typeof(iterable) == "function" && | ||
426 | !(iterable instanceof Function) && | ||
427 | typeof(iterable.length) == 'number') { | ||
428 | rval = []; | ||
429 | for (var i = 0; i < iterable.length; i++) { | ||
430 | rval.push(iterable[i]); | ||
431 | } | ||
432 | return rval; | ||
433 | } | ||
434 | |||
435 | var self = MochiKit.Iter; | ||
436 | iterable = self.iter(iterable); | ||
437 | rval = []; | ||
438 | var a_val; | ||
439 | try { | ||
440 | while (true) { | ||
441 | a_val = iterable.next(); | ||
442 | rval.push(a_val); | ||
443 | } | ||
444 | } catch (e) { | ||
445 | if (e != self.StopIteration) { | ||
446 | throw e; | ||
447 | } | ||
448 | return rval; | ||
449 | } | ||
450 | // mozilla warnings aren't too bright | ||
451 | return undefined; | ||
452 | }, | ||
453 | |||
454 | |||
455 | /** @id MochiKit.Iter.reduce */ | ||
456 | reduce: function (fn, iterable, /* optional */initial) { | ||
457 | var i = 0; | ||
458 | var x = initial; | ||
459 | var self = MochiKit.Iter; | ||
460 | iterable = self.iter(iterable); | ||
461 | if (arguments.length < 3) { | ||
462 | try { | ||
463 | x = iterable.next(); | ||
464 | } catch (e) { | ||
465 | if (e == self.StopIteration) { | ||
466 | e = new TypeError("reduce() of empty sequence with no initial value"); | ||
467 | } | ||
468 | throw e; | ||
469 | } | ||
470 | i++; | ||
471 | } | ||
472 | try { | ||
473 | while (true) { | ||
474 | x = fn(x, iterable.next()); | ||
475 | } | ||
476 | } catch (e) { | ||
477 | if (e != self.StopIteration) { | ||
478 | throw e; | ||
479 | } | ||
480 | } | ||
481 | return x; | ||
482 | }, | ||
483 | |||
484 | /** @id MochiKit.Iter.range */ | ||
485 | range: function (/* [start,] stop[, step] */) { | ||
486 | var start = 0; | ||
487 | var stop = 0; | ||
488 | var step = 1; | ||
489 | if (arguments.length == 1) { | ||
490 | stop = arguments[0]; | ||
491 | } else if (arguments.length == 2) { | ||
492 | start = arguments[0]; | ||
493 | stop = arguments[1]; | ||
494 | } else if (arguments.length == 3) { | ||
495 | start = arguments[0]; | ||
496 | stop = arguments[1]; | ||
497 | step = arguments[2]; | ||
498 | } else { | ||
499 | throw new TypeError("range() takes 1, 2, or 3 arguments!"); | ||
500 | } | ||
501 | if (step === 0) { | ||
502 | throw new TypeError("range() step must not be 0"); | ||
503 | } | ||
504 | return { | ||
505 | next: function () { | ||
506 | if ((step > 0 && start >= stop) || (step < 0 && start <= stop)) { | ||
507 | throw MochiKit.Iter.StopIteration; | ||
508 | } | ||
509 | var rval = start; | ||
510 | start += step; | ||
511 | return rval; | ||
512 | }, | ||
513 | repr: function () { | ||
514 | return "range(" + [start, stop, step].join(", ") + ")"; | ||
515 | }, | ||
516 | toString: MochiKit.Base.forwardCall("repr") | ||
517 | }; | ||
518 | }, | ||
519 | |||
520 | /** @id MochiKit.Iter.sum */ | ||
521 | sum: function (iterable, start/* = 0 */) { | ||
522 | if (typeof(start) == "undefined" || start === null) { | ||
523 | start = 0; | ||
524 | } | ||
525 | var x = start; | ||
526 | var self = MochiKit.Iter; | ||
527 | iterable = self.iter(iterable); | ||
528 | try { | ||
529 | while (true) { | ||
530 | x += iterable.next(); | ||
531 | } | ||
532 | } catch (e) { | ||
533 | if (e != self.StopIteration) { | ||
534 | throw e; | ||
535 | } | ||
536 | } | ||
537 | return x; | ||
538 | }, | ||
539 | |||
540 | /** @id MochiKit.Iter.exhaust */ | ||
541 | exhaust: function (iterable) { | ||
542 | var self = MochiKit.Iter; | ||
543 | iterable = self.iter(iterable); | ||
544 | try { | ||
545 | while (true) { | ||
546 | iterable.next(); | ||
547 | } | ||
548 | } catch (e) { | ||
549 | if (e != self.StopIteration) { | ||
550 | throw e; | ||
551 | } | ||
552 | } | ||
553 | }, | ||
554 | |||
555 | /** @id MochiKit.Iter.forEach */ | ||
556 | forEach: function (iterable, func, /* optional */obj) { | ||
557 | var m = MochiKit.Base; | ||
558 | var self = MochiKit.Iter; | ||
559 | if (arguments.length > 2) { | ||
560 | func = m.bind(func, obj); | ||
561 | } | ||
562 | // fast path for array | ||
563 | if (m.isArrayLike(iterable) && !self.isIterable(iterable)) { | ||
564 | try { | ||
565 | for (var i = 0; i < iterable.length; i++) { | ||
566 | func(iterable[i]); | ||
567 | } | ||
568 | } catch (e) { | ||
569 | if (e != self.StopIteration) { | ||
570 | throw e; | ||
571 | } | ||
572 | } | ||
573 | } else { | ||
574 | self.exhaust(self.imap(func, iterable)); | ||
575 | } | ||
576 | }, | ||
577 | |||
578 | /** @id MochiKit.Iter.every */ | ||
579 | every: function (iterable, func) { | ||
580 | var self = MochiKit.Iter; | ||
581 | try { | ||
582 | self.ifilterfalse(func, iterable).next(); | ||
583 | return false; | ||
584 | } catch (e) { | ||
585 | if (e != self.StopIteration) { | ||
586 | throw e; | ||
587 | } | ||
588 | return true; | ||
589 | } | ||
590 | }, | ||
591 | |||
592 | /** @id MochiKit.Iter.sorted */ | ||
593 | sorted: function (iterable, /* optional */cmp) { | ||
594 | var rval = MochiKit.Iter.list(iterable); | ||
595 | if (arguments.length == 1) { | ||
596 | cmp = MochiKit.Base.compare; | ||
597 | } | ||
598 | rval.sort(cmp); | ||
599 | return rval; | ||
600 | }, | ||
601 | |||
602 | /** @id MochiKit.Iter.reversed */ | ||
603 | reversed: function (iterable) { | ||
604 | var rval = MochiKit.Iter.list(iterable); | ||
605 | rval.reverse(); | ||
606 | return rval; | ||
607 | }, | ||
608 | |||
609 | /** @id MochiKit.Iter.some */ | ||
610 | some: function (iterable, func) { | ||
611 | var self = MochiKit.Iter; | ||
612 | try { | ||
613 | self.ifilter(func, iterable).next(); | ||
614 | return true; | ||
615 | } catch (e) { | ||
616 | if (e != self.StopIteration) { | ||
617 | throw e; | ||
618 | } | ||
619 | return false; | ||
620 | } | ||
621 | }, | ||
622 | |||
623 | /** @id MochiKit.Iter.iextend */ | ||
624 | iextend: function (lst, iterable) { | ||
625 | var m = MochiKit.Base; | ||
626 | var self = MochiKit.Iter; | ||
627 | if (m.isArrayLike(iterable) && !self.isIterable(iterable)) { | ||
628 | // fast-path for array-like | ||
629 | for (var i = 0; i < iterable.length; i++) { | ||
630 | lst.push(iterable[i]); | ||
631 | } | ||
632 | } else { | ||
633 | iterable = self.iter(iterable); | ||
634 | try { | ||
635 | while (true) { | ||
636 | lst.push(iterable.next()); | ||
637 | } | ||
638 | } catch (e) { | ||
639 | if (e != self.StopIteration) { | ||
640 | throw e; | ||
641 | } | ||
642 | } | ||
643 | } | ||
644 | return lst; | ||
645 | }, | ||
646 | |||
647 | /** @id MochiKit.Iter.groupby */ | ||
648 | groupby: function(iterable, /* optional */ keyfunc) { | ||
649 | var m = MochiKit.Base; | ||
650 | var self = MochiKit.Iter; | ||
651 | if (arguments.length < 2) { | ||
652 | keyfunc = m.operator.identity; | ||
653 | } | ||
654 | iterable = self.iter(iterable); | ||
655 | |||
656 | // shared | ||
657 | var pk = undefined; | ||
658 | var k = undefined; | ||
659 | var v; | ||
660 | |||
661 | function fetch() { | ||
662 | v = iterable.next(); | ||
663 | k = keyfunc(v); | ||
664 | }; | ||
665 | |||
666 | function eat() { | ||
667 | var ret = v; | ||
668 | v = undefined; | ||
669 | return ret; | ||
670 | }; | ||
671 | |||
672 | var first = true; | ||
673 | var compare = m.compare; | ||
674 | return { | ||
675 | repr: function () { return "groupby(...)"; }, | ||
676 | next: function() { | ||
677 | // iterator-next | ||
678 | |||
679 | // iterate until meet next group | ||
680 | while (compare(k, pk) === 0) { | ||
681 | fetch(); | ||
682 | if (first) { | ||
683 | first = false; | ||
684 | break; | ||
685 | } | ||
686 | } | ||
687 | pk = k; | ||
688 | return [k, { | ||
689 | next: function() { | ||
690 | // subiterator-next | ||
691 | if (v == undefined) { // Is there something to eat? | ||
692 | fetch(); | ||
693 | } | ||
694 | if (compare(k, pk) !== 0) { | ||
695 | throw self.StopIteration; | ||
696 | } | ||
697 | return eat(); | ||
698 | } | ||
699 | }]; | ||
700 | } | ||
701 | }; | ||
702 | }, | ||
703 | |||
704 | /** @id MochiKit.Iter.groupby_as_array */ | ||
705 | groupby_as_array: function (iterable, /* optional */ keyfunc) { | ||
706 | var m = MochiKit.Base; | ||
707 | var self = MochiKit.Iter; | ||
708 | if (arguments.length < 2) { | ||
709 | keyfunc = m.operator.identity; | ||
710 | } | ||
711 | |||
712 | iterable = self.iter(iterable); | ||
713 | var result = []; | ||
714 | var first = true; | ||
715 | var prev_key; | ||
716 | var compare = m.compare; | ||
717 | while (true) { | ||
718 | try { | ||
719 | var value = iterable.next(); | ||
720 | var key = keyfunc(value); | ||
721 | } catch (e) { | ||
722 | if (e == self.StopIteration) { | ||
723 | break; | ||
724 | } | ||
725 | throw e; | ||
726 | } | ||
727 | if (first || compare(key, prev_key) !== 0) { | ||
728 | var values = []; | ||
729 | result.push([key, values]); | ||
730 | } | ||
731 | values.push(value); | ||
732 | first = false; | ||
733 | prev_key = key; | ||
734 | } | ||
735 | return result; | ||
736 | }, | ||
737 | |||
738 | /** @id MochiKit.Iter.arrayLikeIter */ | ||
739 | arrayLikeIter: function (iterable) { | ||
740 | var i = 0; | ||
741 | return { | ||
742 | repr: function () { return "arrayLikeIter(...)"; }, | ||
743 | toString: MochiKit.Base.forwardCall("repr"), | ||
744 | next: function () { | ||
745 | if (i >= iterable.length) { | ||
746 | throw MochiKit.Iter.StopIteration; | ||
747 | } | ||
748 | return iterable[i++]; | ||
749 | } | ||
750 | }; | ||
751 | }, | ||
752 | |||
753 | /** @id MochiKit.Iter.hasIterateNext */ | ||
754 | hasIterateNext: function (iterable) { | ||
755 | return (iterable && typeof(iterable.iterateNext) == "function"); | ||
756 | }, | ||
757 | |||
758 | /** @id MochiKit.Iter.iterateNextIter */ | ||
759 | iterateNextIter: function (iterable) { | ||
760 | return { | ||
761 | repr: function () { return "iterateNextIter(...)"; }, | ||
762 | toString: MochiKit.Base.forwardCall("repr"), | ||
763 | next: function () { | ||
764 | var rval = iterable.iterateNext(); | ||
765 | if (rval === null || rval === undefined) { | ||
766 | throw MochiKit.Iter.StopIteration; | ||
767 | } | ||
768 | return rval; | ||
769 | } | ||
770 | }; | ||
771 | } | ||
772 | }); | ||
773 | |||
774 | |||
775 | MochiKit.Iter.__new__ = function () { | ||
776 | var m = MochiKit.Base; | ||
777 | // Re-use StopIteration if exists (e.g. SpiderMonkey) | ||
778 | if (typeof(StopIteration) != "undefined") { | ||
779 | this.StopIteration = StopIteration; | ||
780 | } else { | ||
781 | /** @id MochiKit.Iter.StopIteration */ | ||
782 | this.StopIteration = new m.NamedError("StopIteration"); | ||
783 | } | ||
784 | this.iteratorRegistry = new m.AdapterRegistry(); | ||
785 | // Register the iterator factory for arrays | ||
786 | this.registerIteratorFactory( | ||
787 | "arrayLike", | ||
788 | m.isArrayLike, | ||
789 | this.arrayLikeIter | ||
790 | ); | ||
791 | |||
792 | this.registerIteratorFactory( | ||
793 | "iterateNext", | ||
794 | this.hasIterateNext, | ||
795 | this.iterateNextIter | ||
796 | ); | ||
797 | |||
798 | m.nameFunctions(this); | ||
799 | |||
800 | }; | ||
801 | |||
802 | MochiKit.Iter.__new__(); | ||
803 | |||
804 | // | ||
805 | // XXX: Internet Explorer blows | ||
806 | // | ||
807 | if (MochiKit.__export__) { | ||
808 | reduce = MochiKit.Iter.reduce; | ||
809 | } | ||
810 | |||
811 | MochiKit.Base._exportSymbols(this, MochiKit.Iter); | ||