dom/tests/mochitest/ajax/mochikit/MochiKit/Iter.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial