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