testing/mochitest/tests/MochiKit-1.4.2/MochiKit/Iter.js

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial