source: uKadecot/trunk/tools/EcnlControllerUI/EcnlCtrlUI/js/linq.js@ 101

Last change on this file since 101 was 101, checked in by coas-nagasima, 9 years ago

TOPPERS/uKadecotのソースコードを追加

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/plain
File size: 96.8 KB
Line 
1/*--------------------------------------------------------------------------
2 * linq.js - LINQ for JavaScript
3 * ver 3.0.3-Beta4 (Oct. 9th, 2012)
4 *
5 * created and maintained by neuecc <ils@neue.cc>
6 * licensed under MIT License
7 * http://linqjs.codeplex.com/
8 *------------------------------------------------------------------------*/
9
10(function (root, undefined) {
11 // ReadOnly Function
12 var Functions = {
13 Identity: function (x) { return x; },
14 True: function () { return true; },
15 Blank: function () { }
16 };
17
18 // const Type
19 var Types = {
20 Boolean: typeof true,
21 Number: typeof 0,
22 String: typeof "",
23 Object: typeof {},
24 Undefined: typeof undefined,
25 Function: typeof function () { }
26 };
27
28 // private utility methods
29 var Utils = {
30 // Create anonymous function from lambda expression string
31 createLambda: function (expression) {
32 if (expression == null) return Functions.Identity;
33 if (typeof expression == Types.String) {
34 if (expression == "") {
35 return Functions.Identity;
36 }
37 else if (expression.indexOf("=>") == -1) {
38 var regexp = new RegExp("[$]+", "g");
39
40 var maxLength = 0;
41 var match;
42 while (match = regexp.exec(expression)) {
43 var paramNumber = match[0].length;
44 if (paramNumber > maxLength) {
45 maxLength = paramNumber;
46 }
47 }
48
49 var argArray = [];
50 for (var i = 1; i <= maxLength; i++) {
51 var dollar = "";
52 for (var j = 0; j < i; j++) {
53 dollar += "$";
54 }
55 argArray.push(dollar);
56 }
57
58 var args = Array.prototype.join.call(argArray, ",");
59
60 return new Function(args, "return " + expression);
61 }
62 else {
63 var expr = expression.match(/^[(\s]*([^()]*?)[)\s]*=>(.*)/);
64 return new Function(expr[1], "return " + expr[2]);
65 }
66 }
67 return expression;
68 },
69
70 isIEnumerable: function (obj) {
71 if (typeof Enumerator !== Types.Undefined) {
72 try {
73 new Enumerator(obj); // check JScript(IE)'s Enumerator
74 return true;
75 }
76 catch (e) { }
77 }
78
79 return false;
80 },
81
82 // IE8's defineProperty is defined but cannot use, therefore check defineProperties
83 defineProperty: (Object.defineProperties != null)
84 ? function (target, methodName, value) {
85 Object.defineProperty(target, methodName, {
86 enumerable: false,
87 configurable: true,
88 writable: true,
89 value: value
90 })
91 }
92 : function (target, methodName, value) {
93 target[methodName] = value;
94 },
95
96 compare: function (a, b) {
97 return (a === b) ? 0
98 : (a > b) ? 1
99 : -1;
100 },
101
102 dispose: function (obj) {
103 if (obj != null) obj.dispose();
104 }
105 };
106
107 // IEnumerator State
108 var State = { Before: 0, Running: 1, After: 2 };
109
110 // "Enumerator" is conflict JScript's "Enumerator"
111 var IEnumerator = function (initialize, tryGetNext, dispose) {
112 var yielder = new Yielder();
113 var state = State.Before;
114
115 this.current = yielder.current;
116 this.reset = function () { throw new Error('Reset is not supported'); };
117
118 this.moveNext = function () {
119 try {
120 switch (state) {
121 case State.Before:
122 state = State.Running;
123 initialize();
124 // fall through
125 case State.Running:
126 if (tryGetNext.apply(yielder)) {
127 return true;
128 }
129 else {
130 this.dispose();
131 return false;
132 }
133 case State.After:
134 return false;
135 }
136 }
137 catch (e) {
138 this.dispose();
139 throw e;
140 }
141 };
142
143 this.dispose = function () {
144 if (state != State.Running) return;
145
146 try {
147 dispose();
148 }
149 finally {
150 state = State.After;
151 }
152 };
153 };
154 var $asm = {};
155 ss.initAssembly($asm, 'linq');
156 ss.initClass(IEnumerator, $asm, {}, null, [ss.IDisposable]);
157
158 // for tryGetNext
159 var Yielder = function () {
160 var current = null;
161 this.current = function () { return current; };
162 this.yieldReturn = function (value) {
163 current = value;
164 return true;
165 };
166 this.yieldBreak = function () {
167 return false;
168 };
169 };
170
171 // Enumerable constuctor
172 var Enumerable = function (getEnumerator) {
173 this.getEnumerator = getEnumerator;
174 };
175 ss.initClass(Enumerable, $asm, {}, null, [ss.IEnumerable]);
176
177 // Utility
178
179 Enumerable.Utils = {}; // container
180
181 Enumerable.Utils.createLambda = function (expression) {
182 return Utils.createLambda(expression);
183 };
184
185 Enumerable.Utils.createEnumerable = function (getEnumerator) {
186 return new Enumerable(getEnumerator);
187 };
188
189 Enumerable.Utils.createEnumerator = function (initialize, tryGetNext, dispose) {
190 return new IEnumerator(initialize, tryGetNext, dispose);
191 };
192
193 Enumerable.Utils.extendTo = function (type) {
194 var typeProto = type.prototype;
195 var enumerableProto;
196
197 if (type === Array) {
198 enumerableProto = ArrayEnumerable.prototype;
199 Utils.defineProperty(typeProto, "getSource", function () {
200 return this;
201 });
202 }
203 else {
204 enumerableProto = Enumerable.prototype;
205 Utils.defineProperty(typeProto, "getEnumerator", function () {
206 return Enumerable.from(this).getEnumerator();
207 });
208 }
209
210 for (var methodName in enumerableProto) {
211 var func = enumerableProto[methodName];
212
213 // already extended
214 if (typeProto[methodName] == func) continue;
215
216 // already defined(example Array#reverse/join/forEach...)
217 if (typeProto[methodName] != null) {
218 methodName = methodName + "ByLinq";
219 if (typeProto[methodName] == func) continue; // recheck
220 }
221
222 if (func instanceof Function) {
223 Utils.defineProperty(typeProto, methodName, func);
224 }
225 }
226 };
227
228 // Generator
229
230 Enumerable.choice = function () // variable argument
231 {
232 var args = arguments;
233
234 return new Enumerable(function () {
235 return new IEnumerator(
236 function () {
237 args = (args[0] instanceof Array) ? args[0]
238 : (args[0].getEnumerator != null) ? args[0].toArray()
239 : args;
240 },
241 function () {
242 return this.yieldReturn(args[Math.floor(Math.random() * args.length)]);
243 },
244 Functions.Blank);
245 });
246 };
247
248 Enumerable.cycle = function () // variable argument
249 {
250 var args = arguments;
251
252 return new Enumerable(function () {
253 var index = 0;
254 return new IEnumerator(
255 function () {
256 args = (args[0] instanceof Array) ? args[0]
257 : (args[0].getEnumerator != null) ? args[0].toArray()
258 : args;
259 },
260 function () {
261 if (index >= args.length) index = 0;
262 return this.yieldReturn(args[index++]);
263 },
264 Functions.Blank);
265 });
266 };
267
268 Enumerable.empty = function () {
269 return new Enumerable(function () {
270 return new IEnumerator(
271 Functions.Blank,
272 function () { return false; },
273 Functions.Blank);
274 });
275 };
276
277 Enumerable.from = function (obj) {
278 if (obj == null) {
279 return Enumerable.empty();
280 }
281 if (obj instanceof Enumerable) {
282 return obj;
283 }
284 if (typeof obj == Types.Number || typeof obj == Types.Boolean) {
285 return Enumerable.repeat(obj, 1);
286 }
287 if (typeof obj == Types.String) {
288 return new Enumerable(function () {
289 var index = 0;
290 return new IEnumerator(
291 Functions.Blank,
292 function () {
293 return (index < obj.length) ? this.yieldReturn(obj.charAt(index++)) : false;
294 },
295 Functions.Blank);
296 });
297 }
298 var ienum = ss.safeCast(obj, ss.IEnumerable);
299 if (ienum) {
300 var enumerator;
301 return new Enumerable(function () {
302 return new IEnumerator(
303 function () { enumerator = ss.getEnumerator(ienum); },
304 function () {
305 var ok = enumerator.moveNext();
306 return ok ? this.yieldReturn(enumerator.current()) : false;
307 },
308 function () {
309 var disposable = ss.safeCast(enumerator, ss.IDisposable);
310 if (disposable) {
311 disposable.dispose();
312 }
313 }
314 );
315 });
316 }
317
318 if (typeof obj != Types.Function) {
319 // array or array like object
320 if (typeof obj.length == Types.Number) {
321 return new ArrayEnumerable(obj);
322 }
323
324 // JScript's IEnumerable
325 if (!(obj instanceof Object) && Utils.isIEnumerable(obj)) {
326 return new Enumerable(function () {
327 var isFirst = true;
328 var enumerator;
329 return new IEnumerator(
330 function () { enumerator = new Enumerator(obj); },
331 function () {
332 if (isFirst) isFirst = false;
333 else enumerator.moveNext();
334
335 return (enumerator.atEnd()) ? false : this.yieldReturn(enumerator.item());
336 },
337 Functions.Blank);
338 });
339 }
340
341 // WinMD IIterable<T>
342 if (typeof Windows === Types.Object && typeof obj.first === Types.Function) {
343 return new Enumerable(function () {
344 var isFirst = true;
345 var enumerator;
346 return new IEnumerator(
347 function () { enumerator = obj.first(); },
348 function () {
349 if (isFirst) isFirst = false;
350 else enumerator.moveNext();
351
352 return (enumerator.hasCurrent) ? this.yieldReturn(enumerator.current) : this.yieldBreak();
353 },
354 Functions.Blank);
355 });
356 }
357 }
358
359 // case function/object : Create keyValuePair[]
360 return new Enumerable(function () {
361 var array = [];
362 var index = 0;
363
364 return new IEnumerator(
365 function () {
366 for (var key in obj) {
367 var value = obj[key];
368 if (!(value instanceof Function) && Object.prototype.hasOwnProperty.call(obj, key)) {
369 array.push({ key: key, value: value });
370 }
371 }
372 },
373 function () {
374 return (index < array.length)
375 ? this.yieldReturn(array[index++])
376 : false;
377 },
378 Functions.Blank);
379 });
380 },
381
382 Enumerable.make = function (element) {
383 return Enumerable.repeat(element, 1);
384 };
385
386 // Overload:function(input, pattern)
387 // Overload:function(input, pattern, flags)
388 Enumerable.matches = function (input, pattern, flags) {
389 if (flags == null) flags = "";
390 if (pattern instanceof RegExp) {
391 flags += (pattern.ignoreCase) ? "i" : "";
392 flags += (pattern.multiline) ? "m" : "";
393 pattern = pattern.source;
394 }
395 if (flags.indexOf("g") === -1) flags += "g";
396
397 return new Enumerable(function () {
398 var regex;
399 return new IEnumerator(
400 function () { regex = new RegExp(pattern, flags); },
401 function () {
402 var match = regex.exec(input);
403 return (match) ? this.yieldReturn(match) : false;
404 },
405 Functions.Blank);
406 });
407 };
408
409 // Overload:function(start, count)
410 // Overload:function(start, count, step)
411 Enumerable.range = function (start, count, step) {
412 if (step == null) step = 1;
413
414 return new Enumerable(function () {
415 var value;
416 var index = 0;
417
418 return new IEnumerator(
419 function () { value = start - step; },
420 function () {
421 return (index++ < count)
422 ? this.yieldReturn(value += step)
423 : this.yieldBreak();
424 },
425 Functions.Blank);
426 });
427 };
428
429 // Overload:function(start, count)
430 // Overload:function(start, count, step)
431 Enumerable.rangeDown = function (start, count, step) {
432 if (step == null) step = 1;
433
434 return new Enumerable(function () {
435 var value;
436 var index = 0;
437
438 return new IEnumerator(
439 function () { value = start + step; },
440 function () {
441 return (index++ < count)
442 ? this.yieldReturn(value -= step)
443 : this.yieldBreak();
444 },
445 Functions.Blank);
446 });
447 };
448
449 // Overload:function(start, to)
450 // Overload:function(start, to, step)
451 Enumerable.rangeTo = function (start, to, step) {
452 if (step == null) step = 1;
453
454 if (start < to) {
455 return new Enumerable(function () {
456 var value;
457
458 return new IEnumerator(
459 function () { value = start - step; },
460 function () {
461 var next = value += step;
462 return (next <= to)
463 ? this.yieldReturn(next)
464 : this.yieldBreak();
465 },
466 Functions.Blank);
467 });
468 }
469 else {
470 return new Enumerable(function () {
471 var value;
472
473 return new IEnumerator(
474 function () { value = start + step; },
475 function () {
476 var next = value -= step;
477 return (next >= to)
478 ? this.yieldReturn(next)
479 : this.yieldBreak();
480 },
481 Functions.Blank);
482 });
483 }
484 };
485
486 // Overload:function(element)
487 // Overload:function(element, count)
488 Enumerable.repeat = function (element, count) {
489 if (count != null) return Enumerable.repeat(element).take(count);
490
491 return new Enumerable(function () {
492 return new IEnumerator(
493 Functions.Blank,
494 function () { return this.yieldReturn(element); },
495 Functions.Blank);
496 });
497 };
498
499 Enumerable.repeatWithFinalize = function (initializer, finalizer) {
500 initializer = Utils.createLambda(initializer);
501 finalizer = Utils.createLambda(finalizer);
502
503 return new Enumerable(function () {
504 var element;
505 return new IEnumerator(
506 function () { element = initializer(); },
507 function () { return this.yieldReturn(element); },
508 function () {
509 if (element != null) {
510 finalizer(element);
511 element = null;
512 }
513 });
514 });
515 };
516
517 // Overload:function(func)
518 // Overload:function(func, count)
519 Enumerable.generate = function (func, count) {
520 if (count != null) return Enumerable.generate(func).take(count);
521 func = Utils.createLambda(func);
522
523 return new Enumerable(function () {
524 return new IEnumerator(
525 Functions.Blank,
526 function () { return this.yieldReturn(func()); },
527 Functions.Blank);
528 });
529 };
530
531 // Overload:function()
532 // Overload:function(start)
533 // Overload:function(start, step)
534 Enumerable.toInfinity = function (start, step) {
535 if (start == null) start = 0;
536 if (step == null) step = 1;
537
538 return new Enumerable(function () {
539 var value;
540 return new IEnumerator(
541 function () { value = start - step; },
542 function () { return this.yieldReturn(value += step); },
543 Functions.Blank);
544 });
545 };
546
547 // Overload:function()
548 // Overload:function(start)
549 // Overload:function(start, step)
550 Enumerable.toNegativeInfinity = function (start, step) {
551 if (start == null) start = 0;
552 if (step == null) step = 1;
553
554 return new Enumerable(function () {
555 var value;
556 return new IEnumerator(
557 function () { value = start + step; },
558 function () { return this.yieldReturn(value -= step); },
559 Functions.Blank);
560 });
561 };
562
563 Enumerable.unfold = function (seed, func) {
564 func = Utils.createLambda(func);
565
566 return new Enumerable(function () {
567 var isFirst = true;
568 var value;
569 return new IEnumerator(
570 Functions.Blank,
571 function () {
572 if (isFirst) {
573 isFirst = false;
574 value = seed;
575 return this.yieldReturn(value);
576 }
577 value = func(value);
578 return this.yieldReturn(value);
579 },
580 Functions.Blank);
581 });
582 };
583
584 Enumerable.defer = function (enumerableFactory) {
585
586 return new Enumerable(function () {
587 var enumerator;
588
589 return new IEnumerator(
590 function () { enumerator = Enumerable.from(enumerableFactory()).getEnumerator(); },
591 function () {
592 return (enumerator.moveNext())
593 ? this.yieldReturn(enumerator.current())
594 : this.yieldBreak();
595 },
596 function () {
597 Utils.dispose(enumerator);
598 });
599 });
600 };
601
602 // Extension Methods
603
604 /* Projection and Filtering Methods */
605
606 // Overload:function(func)
607 // Overload:function(func, resultSelector<element>)
608 // Overload:function(func, resultSelector<element, nestLevel>)
609 Enumerable.prototype.traverseBreadthFirst = function (func, resultSelector) {
610 var source = this;
611 func = Utils.createLambda(func);
612 resultSelector = Utils.createLambda(resultSelector);
613
614 return new Enumerable(function () {
615 var enumerator;
616 var nestLevel = 0;
617 var buffer = [];
618
619 return new IEnumerator(
620 function () { enumerator = source.getEnumerator(); },
621 function () {
622 while (true) {
623 if (enumerator.moveNext()) {
624 buffer.push(enumerator.current());
625 return this.yieldReturn(resultSelector(enumerator.current(), nestLevel));
626 }
627
628 var next = Enumerable.from(buffer).selectMany(function (x) { return func(x); });
629 if (!next.any()) {
630 return false;
631 }
632 else {
633 nestLevel++;
634 buffer = [];
635 Utils.dispose(enumerator);
636 enumerator = next.getEnumerator();
637 }
638 }
639 },
640 function () { Utils.dispose(enumerator); });
641 });
642 };
643
644 // Overload:function(func)
645 // Overload:function(func, resultSelector<element>)
646 // Overload:function(func, resultSelector<element, nestLevel>)
647 Enumerable.prototype.traverseDepthFirst = function (func, resultSelector) {
648 var source = this;
649 func = Utils.createLambda(func);
650 resultSelector = Utils.createLambda(resultSelector);
651
652 return new Enumerable(function () {
653 var enumeratorStack = [];
654 var enumerator;
655
656 return new IEnumerator(
657 function () { enumerator = source.getEnumerator(); },
658 function () {
659 while (true) {
660 if (enumerator.moveNext()) {
661 var value = resultSelector(enumerator.current(), enumeratorStack.length);
662 enumeratorStack.push(enumerator);
663 enumerator = Enumerable.from(func(enumerator.current())).getEnumerator();
664 return this.yieldReturn(value);
665 }
666
667 if (enumeratorStack.length <= 0) return false;
668 Utils.dispose(enumerator);
669 enumerator = enumeratorStack.pop();
670 }
671 },
672 function () {
673 try {
674 Utils.dispose(enumerator);
675 }
676 finally {
677 Enumerable.from(enumeratorStack).forEach(function (s) { s.dispose(); });
678 }
679 });
680 });
681 };
682
683 Enumerable.prototype.flatten = function () {
684 var source = this;
685
686 return new Enumerable(function () {
687 var enumerator;
688 var middleEnumerator = null;
689
690 return new IEnumerator(
691 function () { enumerator = source.getEnumerator(); },
692 function () {
693 while (true) {
694 if (middleEnumerator != null) {
695 if (middleEnumerator.moveNext()) {
696 return this.yieldReturn(middleEnumerator.current());
697 }
698 else {
699 middleEnumerator = null;
700 }
701 }
702
703 if (enumerator.moveNext()) {
704 if (enumerator.current() instanceof Array) {
705 Utils.dispose(middleEnumerator);
706 middleEnumerator = Enumerable.from(enumerator.current())
707 .selectMany(Functions.Identity)
708 .flatten()
709 .getEnumerator();
710 continue;
711 }
712 else {
713 return this.yieldReturn(enumerator.current());
714 }
715 }
716
717 return false;
718 }
719 },
720 function () {
721 try {
722 Utils.dispose(enumerator);
723 }
724 finally {
725 Utils.dispose(middleEnumerator);
726 }
727 });
728 });
729 };
730
731 Enumerable.prototype.pairwise = function (selector) {
732 var source = this;
733 selector = Utils.createLambda(selector);
734
735 return new Enumerable(function () {
736 var enumerator;
737
738 return new IEnumerator(
739 function () {
740 enumerator = source.getEnumerator();
741 enumerator.moveNext();
742 },
743 function () {
744 var prev = enumerator.current();
745 return (enumerator.moveNext())
746 ? this.yieldReturn(selector(prev, enumerator.current()))
747 : false;
748 },
749 function () { Utils.dispose(enumerator); });
750 });
751 };
752
753 // Overload:function(func)
754 // Overload:function(seed,func<value,element>)
755 Enumerable.prototype.scan = function (seed, func) {
756 var isUseSeed;
757 if (func == null) {
758 func = Utils.createLambda(seed); // arguments[0]
759 isUseSeed = false;
760 } else {
761 func = Utils.createLambda(func);
762 isUseSeed = true;
763 }
764 var source = this;
765
766 return new Enumerable(function () {
767 var enumerator;
768 var value;
769 var isFirst = true;
770
771 return new IEnumerator(
772 function () { enumerator = source.getEnumerator(); },
773 function () {
774 if (isFirst) {
775 isFirst = false;
776 if (!isUseSeed) {
777 if (enumerator.moveNext()) {
778 return this.yieldReturn(value = enumerator.current());
779 }
780 }
781 else {
782 return this.yieldReturn(value = seed);
783 }
784 }
785
786 return (enumerator.moveNext())
787 ? this.yieldReturn(value = func(value, enumerator.current()))
788 : false;
789 },
790 function () { Utils.dispose(enumerator); });
791 });
792 };
793
794 // Overload:function(selector<element>)
795 // Overload:function(selector<element,index>)
796 Enumerable.prototype.select = function (selector) {
797 selector = Utils.createLambda(selector);
798
799 if (selector.length <= 1) {
800 return new WhereSelectEnumerable(this, null, selector);
801 }
802 else {
803 var source = this;
804
805 return new Enumerable(function () {
806 var enumerator;
807 var index = 0;
808
809 return new IEnumerator(
810 function () { enumerator = source.getEnumerator(); },
811 function () {
812 return (enumerator.moveNext())
813 ? this.yieldReturn(selector(enumerator.current(), index++))
814 : false;
815 },
816 function () { Utils.dispose(enumerator); });
817 });
818 }
819 };
820
821 // Overload:function(collectionSelector<element>)
822 // Overload:function(collectionSelector<element,index>)
823 // Overload:function(collectionSelector<element>,resultSelector)
824 // Overload:function(collectionSelector<element,index>,resultSelector)
825 Enumerable.prototype.selectMany = function (collectionSelector, resultSelector) {
826 var source = this;
827 collectionSelector = Utils.createLambda(collectionSelector);
828 if (resultSelector == null) resultSelector = function (a, b) { return b; };
829 resultSelector = Utils.createLambda(resultSelector);
830
831 return new Enumerable(function () {
832 var enumerator;
833 var middleEnumerator = undefined;
834 var index = 0;
835
836 return new IEnumerator(
837 function () { enumerator = source.getEnumerator(); },
838 function () {
839 if (middleEnumerator === undefined) {
840 if (!enumerator.moveNext()) return false;
841 }
842 do {
843 if (middleEnumerator == null) {
844 var middleSeq = collectionSelector(enumerator.current(), index++);
845 middleEnumerator = Enumerable.from(middleSeq).getEnumerator();
846 }
847 if (middleEnumerator.moveNext()) {
848 return this.yieldReturn(resultSelector(enumerator.current(), middleEnumerator.current()));
849 }
850 Utils.dispose(middleEnumerator);
851 middleEnumerator = null;
852 } while (enumerator.moveNext());
853 return false;
854 },
855 function () {
856 try {
857 Utils.dispose(enumerator);
858 }
859 finally {
860 Utils.dispose(middleEnumerator);
861 }
862 });
863 });
864 };
865
866 // Overload:function(predicate<element>)
867 // Overload:function(predicate<element,index>)
868 Enumerable.prototype.where = function (predicate) {
869 predicate = Utils.createLambda(predicate);
870
871 if (predicate.length <= 1) {
872 return new WhereEnumerable(this, predicate);
873 }
874 else {
875 var source = this;
876
877 return new Enumerable(function () {
878 var enumerator;
879 var index = 0;
880
881 return new IEnumerator(
882 function () { enumerator = source.getEnumerator(); },
883 function () {
884 while (enumerator.moveNext()) {
885 if (predicate(enumerator.current(), index++)) {
886 return this.yieldReturn(enumerator.current());
887 }
888 }
889 return false;
890 },
891 function () { Utils.dispose(enumerator); });
892 });
893 }
894 };
895
896
897 // Overload:function(selector<element>)
898 // Overload:function(selector<element,index>)
899 Enumerable.prototype.choose = function (selector) {
900 selector = Utils.createLambda(selector);
901 var source = this;
902
903 return new Enumerable(function () {
904 var enumerator;
905 var index = 0;
906
907 return new IEnumerator(
908 function () { enumerator = source.getEnumerator(); },
909 function () {
910 while (enumerator.moveNext()) {
911 var result = selector(enumerator.current(), index++);
912 if (result != null) {
913 return this.yieldReturn(result);
914 }
915 }
916 return this.yieldBreak();
917 },
918 function () { Utils.dispose(enumerator); });
919 });
920 };
921
922 Enumerable.prototype.ofType = function (type) {
923 var source = this;
924
925 return new Enumerable(function () {
926 var enumerator;
927
928 return new IEnumerator(
929 function () { enumerator = ss.getEnumerator(source); },
930 function () {
931 while (enumerator.moveNext()) {
932 var v = ss.safeCast(enumerator.current(), type);
933 if (ss.isValue(v)) {
934 return this.yieldReturn(v);
935 }
936 }
937 return false;
938 },
939 function () { Utils.dispose(enumerator); });
940 });
941 };
942
943 // mutiple arguments, last one is selector, others are enumerable
944 Enumerable.prototype.zip = function () {
945 var args = arguments;
946 var selector = Utils.createLambda(arguments[arguments.length - 1]);
947
948 var source = this;
949 // optimized case:argument is 2
950 if (arguments.length == 2) {
951 var second = arguments[0];
952
953 return new Enumerable(function () {
954 var firstEnumerator;
955 var secondEnumerator;
956 var index = 0;
957
958 return new IEnumerator(
959 function () {
960 firstEnumerator = source.getEnumerator();
961 secondEnumerator = Enumerable.from(second).getEnumerator();
962 },
963 function () {
964 if (firstEnumerator.moveNext() && secondEnumerator.moveNext()) {
965 return this.yieldReturn(selector(firstEnumerator.current(), secondEnumerator.current(), index++));
966 }
967 return false;
968 },
969 function () {
970 try {
971 Utils.dispose(firstEnumerator);
972 } finally {
973 Utils.dispose(secondEnumerator);
974 }
975 });
976 });
977 }
978 else {
979 return new Enumerable(function () {
980 var enumerators;
981 var index = 0;
982
983 return new IEnumerator(
984 function () {
985 var array = Enumerable.make(source)
986 .concat(Enumerable.from(args).takeExceptLast().select(Enumerable.from))
987 .select(function (x) { return x.getEnumerator() })
988 .toArray();
989 enumerators = Enumerable.from(array);
990 },
991 function () {
992 if (enumerators.all(function (x) { return x.moveNext() })) {
993 var array = enumerators
994 .select(function (x) { return x.current() })
995 .toArray();
996 array.push(index++);
997 return this.yieldReturn(selector.apply(null, array));
998 }
999 else {
1000 return this.yieldBreak();
1001 }
1002 },
1003 function () {
1004 Enumerable.from(enumerators).forEach(Utils.dispose);
1005 });
1006 });
1007 }
1008 };
1009
1010 // mutiple arguments
1011 Enumerable.prototype.merge = function () {
1012 var args = arguments;
1013 var source = this;
1014
1015 return new Enumerable(function () {
1016 var enumerators;
1017 var index = -1;
1018
1019 return new IEnumerator(
1020 function () {
1021 enumerators = Enumerable.make(source)
1022 .concat(Enumerable.from(args).select(Enumerable.from))
1023 .select(function (x) { return x.getEnumerator() })
1024 .toArray();
1025 },
1026 function () {
1027 while (enumerators.length > 0) {
1028 index = (index >= enumerators.length - 1) ? 0 : index + 1;
1029 var enumerator = enumerators[index];
1030
1031 if (enumerator.moveNext()) {
1032 return this.yieldReturn(enumerator.current());
1033 }
1034 else {
1035 enumerator.dispose();
1036 enumerators.splice(index--, 1);
1037 }
1038 }
1039 return this.yieldBreak();
1040 },
1041 function () {
1042 Enumerable.from(enumerators).forEach(Utils.dispose);
1043 });
1044 });
1045 };
1046
1047 /* Join Methods */
1048
1049 // Overload:function (inner, outerKeySelector, innerKeySelector, resultSelector)
1050 // Overload:function (inner, outerKeySelector, innerKeySelector, resultSelector, comparer)
1051 Enumerable.prototype.join = function (inner, outerKeySelector, innerKeySelector, resultSelector, comparer) {
1052 outerKeySelector = Utils.createLambda(outerKeySelector);
1053 innerKeySelector = Utils.createLambda(innerKeySelector);
1054 resultSelector = Utils.createLambda(resultSelector);
1055 var source = this;
1056
1057 return new Enumerable(function () {
1058 var outerEnumerator;
1059 var lookup;
1060 var innerElements = null;
1061 var innerCount = 0;
1062
1063 return new IEnumerator(
1064 function () {
1065 outerEnumerator = source.getEnumerator();
1066 lookup = Enumerable.from(inner).toLookup(innerKeySelector, Functions.Identity, comparer);
1067 },
1068 function () {
1069 while (true) {
1070 if (innerElements != null) {
1071 var innerElement = innerElements[innerCount++];
1072 if (innerElement !== undefined) {
1073 return this.yieldReturn(resultSelector(outerEnumerator.current(), innerElement));
1074 }
1075
1076 innerElement = null;
1077 innerCount = 0;
1078 }
1079
1080 if (outerEnumerator.moveNext()) {
1081 var key = outerKeySelector(outerEnumerator.current());
1082 innerElements = lookup.get(key).toArray();
1083 } else {
1084 return false;
1085 }
1086 }
1087 },
1088 function () { Utils.dispose(outerEnumerator); });
1089 });
1090 };
1091
1092 // Overload:function (inner, outerKeySelector, innerKeySelector, resultSelector)
1093 // Overload:function (inner, outerKeySelector, innerKeySelector, resultSelector, comparer)
1094 Enumerable.prototype.groupJoin = function (inner, outerKeySelector, innerKeySelector, resultSelector, comparer) {
1095 outerKeySelector = Utils.createLambda(outerKeySelector);
1096 innerKeySelector = Utils.createLambda(innerKeySelector);
1097 resultSelector = Utils.createLambda(resultSelector);
1098 var source = this;
1099
1100 return new Enumerable(function () {
1101 var enumerator = source.getEnumerator();
1102 var lookup = null;
1103
1104 return new IEnumerator(
1105 function () {
1106 enumerator = source.getEnumerator();
1107 lookup = Enumerable.from(inner).toLookup(innerKeySelector, Functions.Identity, comparer);
1108 },
1109 function () {
1110 if (enumerator.moveNext()) {
1111 var innerElement = lookup.get(outerKeySelector(enumerator.current()));
1112 return this.yieldReturn(resultSelector(enumerator.current(), innerElement));
1113 }
1114 return false;
1115 },
1116 function () { Utils.dispose(enumerator); });
1117 });
1118 };
1119
1120 /* Set Methods */
1121
1122 Enumerable.prototype.all = function (predicate) {
1123 predicate = Utils.createLambda(predicate);
1124
1125 var result = true;
1126 this.forEach(function (x) {
1127 if (!predicate(x)) {
1128 result = false;
1129 return false; // break
1130 }
1131 });
1132 return result;
1133 };
1134
1135 // Overload:function()
1136 // Overload:function(predicate)
1137 Enumerable.prototype.any = function (predicate) {
1138 predicate = Utils.createLambda(predicate);
1139
1140 var enumerator = this.getEnumerator();
1141 try {
1142 if (arguments.length == 0) return enumerator.moveNext(); // case:function()
1143
1144 while (enumerator.moveNext()) // case:function(predicate)
1145 {
1146 if (predicate(enumerator.current())) return true;
1147 }
1148 return false;
1149 }
1150 finally {
1151 Utils.dispose(enumerator);
1152 }
1153 };
1154
1155 Enumerable.prototype.isEmpty = function () {
1156 return !this.any();
1157 };
1158
1159 // multiple arguments
1160 Enumerable.prototype.concat = function () {
1161 var source = this;
1162
1163 if (arguments.length == 1) {
1164 var second = arguments[0];
1165
1166 return new Enumerable(function () {
1167 var firstEnumerator;
1168 var secondEnumerator;
1169
1170 return new IEnumerator(
1171 function () { firstEnumerator = source.getEnumerator(); },
1172 function () {
1173 if (secondEnumerator == null) {
1174 if (firstEnumerator.moveNext()) return this.yieldReturn(firstEnumerator.current());
1175 secondEnumerator = Enumerable.from(second).getEnumerator();
1176 }
1177 if (secondEnumerator.moveNext()) return this.yieldReturn(secondEnumerator.current());
1178 return false;
1179 },
1180 function () {
1181 try {
1182 Utils.dispose(firstEnumerator);
1183 }
1184 finally {
1185 Utils.dispose(secondEnumerator);
1186 }
1187 });
1188 });
1189 }
1190 else {
1191 var args = arguments;
1192
1193 return new Enumerable(function () {
1194 var enumerators;
1195
1196 return new IEnumerator(
1197 function () {
1198 enumerators = Enumerable.make(source)
1199 .concat(Enumerable.from(args).select(Enumerable.from))
1200 .select(function (x) { return x.getEnumerator() })
1201 .toArray();
1202 },
1203 function () {
1204 while (enumerators.length > 0) {
1205 var enumerator = enumerators[0];
1206
1207 if (enumerator.moveNext()) {
1208 return this.yieldReturn(enumerator.current());
1209 }
1210 else {
1211 enumerator.dispose();
1212 enumerators.splice(0, 1);
1213 }
1214 }
1215 return this.yieldBreak();
1216 },
1217 function () {
1218 Enumerable.from(enumerators).forEach(Utils.dispose);
1219 });
1220 });
1221 }
1222 };
1223
1224 Enumerable.prototype.insert = function (index, second) {
1225 var source = this;
1226
1227 return new Enumerable(function () {
1228 var firstEnumerator;
1229 var secondEnumerator;
1230 var count = 0;
1231 var isEnumerated = false;
1232
1233 return new IEnumerator(
1234 function () {
1235 firstEnumerator = source.getEnumerator();
1236 secondEnumerator = Enumerable.from(second).getEnumerator();
1237 },
1238 function () {
1239 if (count == index && secondEnumerator.moveNext()) {
1240 isEnumerated = true;
1241 return this.yieldReturn(secondEnumerator.current());
1242 }
1243 if (firstEnumerator.moveNext()) {
1244 count++;
1245 return this.yieldReturn(firstEnumerator.current());
1246 }
1247 if (!isEnumerated && secondEnumerator.moveNext()) {
1248 return this.yieldReturn(secondEnumerator.current());
1249 }
1250 return false;
1251 },
1252 function () {
1253 try {
1254 Utils.dispose(firstEnumerator);
1255 }
1256 finally {
1257 Utils.dispose(secondEnumerator);
1258 }
1259 });
1260 });
1261 };
1262
1263 Enumerable.prototype.alternate = function (alternateValueOrSequence) {
1264 var source = this;
1265
1266 return new Enumerable(function () {
1267 var buffer;
1268 var enumerator;
1269 var alternateSequence;
1270 var alternateEnumerator;
1271
1272 return new IEnumerator(
1273 function () {
1274 if (alternateValueOrSequence instanceof Array || alternateValueOrSequence.getEnumerator != null) {
1275 alternateSequence = Enumerable.from(Enumerable.from(alternateValueOrSequence).toArray()); // freeze
1276 }
1277 else {
1278 alternateSequence = Enumerable.make(alternateValueOrSequence);
1279 }
1280 enumerator = source.getEnumerator();
1281 if (enumerator.moveNext()) buffer = enumerator.current();
1282 },
1283 function () {
1284 while (true) {
1285 if (alternateEnumerator != null) {
1286 if (alternateEnumerator.moveNext()) {
1287 return this.yieldReturn(alternateEnumerator.current());
1288 }
1289 else {
1290 alternateEnumerator = null;
1291 }
1292 }
1293
1294 if (buffer == null && enumerator.moveNext()) {
1295 buffer = enumerator.current(); // hasNext
1296 alternateEnumerator = alternateSequence.getEnumerator();
1297 continue; // GOTO
1298 }
1299 else if (buffer != null) {
1300 var retVal = buffer;
1301 buffer = null;
1302 return this.yieldReturn(retVal);
1303 }
1304
1305 return this.yieldBreak();
1306 }
1307 },
1308 function () {
1309 try {
1310 Utils.dispose(enumerator);
1311 }
1312 finally {
1313 Utils.dispose(alternateEnumerator);
1314 }
1315 });
1316 });
1317 };
1318
1319 // Overload:function(value)
1320 // Overload:function(value, comparer)
1321 Enumerable.prototype.contains = function (value, comparer) {
1322 comparer = comparer || ss.EqualityComparer.def;
1323 var enumerator = this.getEnumerator();
1324 try {
1325 while (enumerator.moveNext()) {
1326 if (comparer.areEqual(enumerator.current(), value)) return true;
1327 }
1328 return false;
1329 }
1330 finally {
1331 Utils.dispose(enumerator);
1332 }
1333 };
1334
1335 Enumerable.prototype.defaultIfEmpty = function (defaultValue) {
1336 var source = this;
1337 if (defaultValue === undefined) defaultValue = null;
1338
1339 return new Enumerable(function () {
1340 var enumerator;
1341 var isFirst = true;
1342
1343 return new IEnumerator(
1344 function () { enumerator = source.getEnumerator(); },
1345 function () {
1346 if (enumerator.moveNext()) {
1347 isFirst = false;
1348 return this.yieldReturn(enumerator.current());
1349 }
1350 else if (isFirst) {
1351 isFirst = false;
1352 return this.yieldReturn(defaultValue);
1353 }
1354 return false;
1355 },
1356 function () { Utils.dispose(enumerator); });
1357 });
1358 };
1359
1360 // Overload:function()
1361 // Overload:function(comparer)
1362 Enumerable.prototype.distinct = function (comparer) {
1363 return this.except(Enumerable.empty(), comparer);
1364 };
1365
1366 Enumerable.prototype.distinctUntilChanged = function (compareSelector) {
1367 compareSelector = Utils.createLambda(compareSelector);
1368 var source = this;
1369
1370 return new Enumerable(function () {
1371 var enumerator;
1372 var compareKey;
1373 var initial;
1374
1375 return new IEnumerator(
1376 function () {
1377 enumerator = source.getEnumerator();
1378 },
1379 function () {
1380 while (enumerator.moveNext()) {
1381 var key = compareSelector(enumerator.current());
1382
1383 if (initial) {
1384 initial = false;
1385 compareKey = key;
1386 return this.yieldReturn(enumerator.current());
1387 }
1388
1389 if (compareKey === key) {
1390 continue;
1391 }
1392
1393 compareKey = key;
1394 return this.yieldReturn(enumerator.current());
1395 }
1396 return this.yieldBreak();
1397 },
1398 function () { Utils.dispose(enumerator); });
1399 });
1400 };
1401
1402 // Overload:function(second)
1403 // Overload:function(second, comparer)
1404 Enumerable.prototype.except = function (second, comparer) {
1405 var source = this;
1406
1407 return new Enumerable(function () {
1408 var enumerator;
1409 var keys;
1410
1411 return new IEnumerator(
1412 function () {
1413 enumerator = source.getEnumerator();
1414 keys = new (ss.makeGenericType(ss.Dictionary$2, [Object, Object]))(null, comparer);
1415 Enumerable.from(second).forEach(function (key) { keys.add(key); });
1416 },
1417 function () {
1418 while (enumerator.moveNext()) {
1419 var current = enumerator.current();
1420 if (!keys.containsKey(current)) {
1421 keys.add(current);
1422 return this.yieldReturn(current);
1423 }
1424 }
1425 return false;
1426 },
1427 function () { Utils.dispose(enumerator); });
1428 });
1429 };
1430
1431 // Overload:function(second)
1432 // Overload:function(second, comparer)
1433 Enumerable.prototype.intersect = function (second, comparer) {
1434 var source = this;
1435
1436 return new Enumerable(function () {
1437 var enumerator;
1438 var keys;
1439 var outs;
1440
1441 return new IEnumerator(
1442 function () {
1443 enumerator = source.getEnumerator();
1444
1445 keys = new (ss.makeGenericType(ss.Dictionary$2, [Object, Object]))(null, comparer);
1446 Enumerable.from(second).forEach(function (key) { keys.add(key); });
1447 outs = new (ss.makeGenericType(ss.Dictionary$2, [Object, Object]))(null, comparer);
1448 },
1449 function () {
1450 while (enumerator.moveNext()) {
1451 var current = enumerator.current();
1452 if (!outs.containsKey(current) && keys.containsKey(current)) {
1453 outs.add(current);
1454 return this.yieldReturn(current);
1455 }
1456 }
1457 return false;
1458 },
1459 function () { Utils.dispose(enumerator); });
1460 });
1461 };
1462
1463 // Overload:function(second)
1464 // Overload:function(second, comparer)
1465 Enumerable.prototype.sequenceEqual = function (second, comparer) {
1466 comparer = comparer || ss.EqualityComparer.def;
1467
1468 var firstEnumerator = this.getEnumerator();
1469 try {
1470 var secondEnumerator = Enumerable.from(second).getEnumerator();
1471 try {
1472 while (firstEnumerator.moveNext()) {
1473 if (!secondEnumerator.moveNext()
1474 || !comparer.areEqual(firstEnumerator.current(), secondEnumerator.current())) {
1475 return false;
1476 }
1477 }
1478
1479 if (secondEnumerator.moveNext()) return false;
1480 return true;
1481 }
1482 finally {
1483 Utils.dispose(secondEnumerator);
1484 }
1485 }
1486 finally {
1487 Utils.dispose(firstEnumerator);
1488 }
1489 };
1490
1491 Enumerable.prototype.union = function (second, comparer) {
1492 var source = this;
1493
1494 return new Enumerable(function () {
1495 var firstEnumerator;
1496 var secondEnumerator;
1497 var keys;
1498
1499 return new IEnumerator(
1500 function () {
1501 firstEnumerator = source.getEnumerator();
1502 keys = new (ss.makeGenericType(ss.Dictionary$2, [Object, Object]))(null, comparer);
1503 },
1504 function () {
1505 var current;
1506 if (secondEnumerator === undefined) {
1507 while (firstEnumerator.moveNext()) {
1508 current = firstEnumerator.current();
1509 if (!keys.containsKey(current)) {
1510 keys.add(current);
1511 return this.yieldReturn(current);
1512 }
1513 }
1514 secondEnumerator = Enumerable.from(second).getEnumerator();
1515 }
1516 while (secondEnumerator.moveNext()) {
1517 current = secondEnumerator.current();
1518 if (!keys.containsKey(current)) {
1519 keys.add(current);
1520 return this.yieldReturn(current);
1521 }
1522 }
1523 return false;
1524 },
1525 function () {
1526 try {
1527 Utils.dispose(firstEnumerator);
1528 }
1529 finally {
1530 Utils.dispose(secondEnumerator);
1531 }
1532 });
1533 });
1534 };
1535
1536 /* Ordering Methods */
1537
1538 // Overload:function()
1539 // Overload:function(keySelector)
1540 // Overload:function(keySelector, comparer)
1541 Enumerable.prototype.orderBy = function (keySelector, comparer) {
1542 return new OrderedEnumerable(this, keySelector, comparer, false);
1543 };
1544
1545 // Overload:function()
1546 // Overload:function(keySelector)
1547 // Overload:function(keySelector, comparer)
1548 Enumerable.prototype.orderByDescending = function (keySelector, comparer) {
1549 return new OrderedEnumerable(this, keySelector, comparer, true);
1550 };
1551
1552 Enumerable.prototype.reverse = function () {
1553 var source = this;
1554
1555 return new Enumerable(function () {
1556 var buffer;
1557 var index;
1558
1559 return new IEnumerator(
1560 function () {
1561 buffer = source.toArray();
1562 index = buffer.length;
1563 },
1564 function () {
1565 return (index > 0)
1566 ? this.yieldReturn(buffer[--index])
1567 : false;
1568 },
1569 Functions.Blank);
1570 });
1571 };
1572
1573 Enumerable.prototype.shuffle = function () {
1574 var source = this;
1575
1576 return new Enumerable(function () {
1577 var buffer;
1578
1579 return new IEnumerator(
1580 function () { buffer = source.toArray(); },
1581 function () {
1582 if (buffer.length > 0) {
1583 var i = Math.floor(Math.random() * buffer.length);
1584 return this.yieldReturn(buffer.splice(i, 1)[0]);
1585 }
1586 return false;
1587 },
1588 Functions.Blank);
1589 });
1590 };
1591
1592 Enumerable.prototype.weightedSample = function (weightSelector) {
1593 weightSelector = Utils.createLambda(weightSelector);
1594 var source = this;
1595
1596 return new Enumerable(function () {
1597 var sortedByBound;
1598 var totalWeight = 0;
1599
1600 return new IEnumerator(
1601 function () {
1602 sortedByBound = source
1603 .choose(function (x) {
1604 var weight = weightSelector(x);
1605 if (weight <= 0) return null; // ignore 0
1606
1607 totalWeight += weight;
1608 return { value: x, bound: totalWeight };
1609 })
1610 .toArray();
1611 },
1612 function () {
1613 if (sortedByBound.length > 0) {
1614 var draw = Math.floor(Math.random() * totalWeight) + 1;
1615
1616 var lower = -1;
1617 var upper = sortedByBound.length;
1618 while (upper - lower > 1) {
1619 var index = Math.floor((lower + upper) / 2);
1620 if (sortedByBound[index].bound >= draw) {
1621 upper = index;
1622 }
1623 else {
1624 lower = index;
1625 }
1626 }
1627
1628 return this.yieldReturn(sortedByBound[upper].value);
1629 }
1630
1631 return this.yieldBreak();
1632 },
1633 Functions.Blank);
1634 });
1635 };
1636
1637 /* Grouping Methods */
1638
1639 // Overload:function(keySelector)
1640 // Overload:function(keySelector,elementSelector)
1641 // Overload:function(keySelector,elementSelector,resultSelector)
1642 // Overload:function(keySelector,elementSelector,resultSelector,comparer)
1643 Enumerable.prototype.groupBy = function (keySelector, elementSelector, resultSelector, comparer) {
1644 var source = this;
1645 keySelector = Utils.createLambda(keySelector);
1646 elementSelector = Utils.createLambda(elementSelector);
1647 if (resultSelector != null) resultSelector = Utils.createLambda(resultSelector);
1648
1649 return new Enumerable(function () {
1650 var enumerator;
1651
1652 return new IEnumerator(
1653 function () {
1654 enumerator = source.toLookup(keySelector, elementSelector, comparer)
1655 .toEnumerable()
1656 .getEnumerator();
1657 },
1658 function () {
1659 while (enumerator.moveNext()) {
1660 return (resultSelector == null)
1661 ? this.yieldReturn(enumerator.current())
1662 : this.yieldReturn(resultSelector(enumerator.current().key(), enumerator.current()));
1663 }
1664 return false;
1665 },
1666 function () { Utils.dispose(enumerator); });
1667 });
1668 };
1669
1670 // Overload:function(keySelector)
1671 // Overload:function(keySelector,elementSelector)
1672 // Overload:function(keySelector,elementSelector,resultSelector)
1673 // Overload:function(keySelector,elementSelector,resultSelector,comperer)
1674 Enumerable.prototype.partitionBy = function (keySelector, elementSelector, resultSelector, comparer) {
1675 var source = this;
1676 keySelector = Utils.createLambda(keySelector);
1677 elementSelector = Utils.createLambda(elementSelector);
1678 comparer = comparer || ss.EqualityComparer.def;
1679 var hasResultSelector;
1680 if (resultSelector == null) {
1681 hasResultSelector = false;
1682 resultSelector = function (key, group) { return new Grouping(key, group); };
1683 }
1684 else {
1685 hasResultSelector = true;
1686 resultSelector = Utils.createLambda(resultSelector);
1687 }
1688
1689 return new Enumerable(function () {
1690 var enumerator;
1691 var key;
1692 var group = [];
1693
1694 return new IEnumerator(
1695 function () {
1696 enumerator = source.getEnumerator();
1697 if (enumerator.moveNext()) {
1698 key = keySelector(enumerator.current());
1699 group.push(elementSelector(enumerator.current()));
1700 }
1701 },
1702 function () {
1703 var hasNext;
1704 while ((hasNext = enumerator.moveNext()) == true) {
1705 if (comparer.areEqual(key, keySelector(enumerator.current()))) {
1706 group.push(elementSelector(enumerator.current()));
1707 }
1708 else break;
1709 }
1710
1711 if (group.length > 0) {
1712 var result = (hasResultSelector)
1713 ? resultSelector(key, Enumerable.from(group))
1714 : resultSelector(key, group);
1715 if (hasNext) {
1716 key = keySelector(enumerator.current());
1717 group = [elementSelector(enumerator.current())];
1718 }
1719 else group = [];
1720
1721 return this.yieldReturn(result);
1722 }
1723
1724 return false;
1725 },
1726 function () { Utils.dispose(enumerator); });
1727 });
1728 };
1729
1730 Enumerable.prototype.buffer = function (count) {
1731 var source = this;
1732
1733 return new Enumerable(function () {
1734 var enumerator;
1735
1736 return new IEnumerator(
1737 function () { enumerator = source.getEnumerator(); },
1738 function () {
1739 var array = [];
1740 var index = 0;
1741 while (enumerator.moveNext()) {
1742 array.push(enumerator.current());
1743 if (++index >= count) return this.yieldReturn(array);
1744 }
1745 if (array.length > 0) return this.yieldReturn(array);
1746 return false;
1747 },
1748 function () { Utils.dispose(enumerator); });
1749 });
1750 };
1751
1752 /* Aggregate Methods */
1753
1754 // Overload:function(func)
1755 // Overload:function(seed,func)
1756 // Overload:function(seed,func,resultSelector)
1757 Enumerable.prototype.aggregate = function (seed, func, resultSelector) {
1758 resultSelector = Utils.createLambda(resultSelector);
1759 return resultSelector(this.scan(seed, func, resultSelector).last());
1760 };
1761
1762 // Overload:function()
1763 // Overload:function(selector)
1764 Enumerable.prototype.average = function (selector) {
1765 selector = Utils.createLambda(selector);
1766
1767 var sum = 0;
1768 var count = 0;
1769 this.forEach(function (x) {
1770 sum += selector(x);
1771 ++count;
1772 });
1773
1774 return sum / count;
1775 };
1776
1777 // Overload:function()
1778 // Overload:function(predicate)
1779 Enumerable.prototype.count = function (predicate) {
1780 predicate = (predicate == null) ? Functions.True : Utils.createLambda(predicate);
1781
1782 var count = 0;
1783 this.forEach(function (x, i) {
1784 if (predicate(x, i))++count;
1785 });
1786 return count;
1787 };
1788
1789 // Overload:function()
1790 // Overload:function(selector)
1791 Enumerable.prototype.max = function (selector) {
1792 if (selector == null) selector = Functions.Identity;
1793 return this.select(selector).aggregate(function (a, b) { return (a > b) ? a : b; });
1794 };
1795
1796 // Overload:function()
1797 // Overload:function(selector)
1798 Enumerable.prototype.min = function (selector) {
1799 if (selector == null) selector = Functions.Identity;
1800 return this.select(selector).aggregate(function (a, b) { return (a < b) ? a : b; });
1801 };
1802
1803 Enumerable.prototype.maxBy = function (keySelector) {
1804 keySelector = Utils.createLambda(keySelector);
1805 return this.aggregate(function (a, b) { return (keySelector(a) > keySelector(b)) ? a : b; });
1806 };
1807
1808 Enumerable.prototype.minBy = function (keySelector) {
1809 keySelector = Utils.createLambda(keySelector);
1810 return this.aggregate(function (a, b) { return (keySelector(a) < keySelector(b)) ? a : b; });
1811 };
1812
1813 // Overload:function()
1814 // Overload:function(selector)
1815 Enumerable.prototype.sum = function (selector) {
1816 if (selector == null) selector = Functions.Identity;
1817 return this.select(selector).aggregate(0, function (a, b) { return a + b; });
1818 };
1819
1820 /* Paging Methods */
1821
1822 Enumerable.prototype.elementAt = function (index) {
1823 var value;
1824 var found = false;
1825 this.forEach(function (x, i) {
1826 if (i == index) {
1827 value = x;
1828 found = true;
1829 return false;
1830 }
1831 });
1832
1833 if (!found) throw new Error("index is less than 0 or greater than or equal to the number of elements in source.");
1834 return value;
1835 };
1836
1837 Enumerable.prototype.elementAtOrDefault = function (index, defaultValue) {
1838 if (defaultValue === undefined) defaultValue = null;
1839 var value;
1840 var found = false;
1841 this.forEach(function (x, i) {
1842 if (i == index) {
1843 value = x;
1844 found = true;
1845 return false;
1846 }
1847 });
1848
1849 return (!found) ? defaultValue : value;
1850 };
1851
1852 // Overload:function()
1853 // Overload:function(predicate)
1854 Enumerable.prototype.first = function (predicate) {
1855 if (predicate != null) return this.where(predicate).first();
1856
1857 var value;
1858 var found = false;
1859 this.forEach(function (x) {
1860 value = x;
1861 found = true;
1862 return false;
1863 });
1864
1865 if (!found) throw new Error("first:No element satisfies the condition.");
1866 return value;
1867 };
1868
1869 Enumerable.prototype.firstOrDefault = function (predicate, defaultValue) {
1870 if (defaultValue === undefined) defaultValue = null;
1871 if (predicate != null) return this.where(predicate).firstOrDefault(null, defaultValue);
1872
1873 var value;
1874 var found = false;
1875 this.forEach(function (x) {
1876 value = x;
1877 found = true;
1878 return false;
1879 });
1880 return (!found) ? defaultValue : value;
1881 };
1882
1883 // Overload:function()
1884 // Overload:function(predicate)
1885 Enumerable.prototype.last = function (predicate) {
1886 if (predicate != null) return this.where(predicate).last();
1887
1888 var value;
1889 var found = false;
1890 this.forEach(function (x) {
1891 found = true;
1892 value = x;
1893 });
1894
1895 if (!found) throw new Error("last:No element satisfies the condition.");
1896 return value;
1897 };
1898
1899 // Overload:function(defaultValue)
1900 // Overload:function(defaultValue,predicate)
1901 Enumerable.prototype.lastOrDefault = function (predicate, defaultValue) {
1902 if (defaultValue === undefined) defaultValue = null;
1903 if (predicate != null) return this.where(predicate).lastOrDefault(null, defaultValue);
1904
1905 var value;
1906 var found = false;
1907 this.forEach(function (x) {
1908 found = true;
1909 value = x;
1910 });
1911 return (!found) ? defaultValue : value;
1912 };
1913
1914 // Overload:function()
1915 // Overload:function(predicate)
1916 Enumerable.prototype.single = function (predicate) {
1917 if (predicate != null) return this.where(predicate).single();
1918
1919 var value;
1920 var found = false;
1921 this.forEach(function (x) {
1922 if (!found) {
1923 found = true;
1924 value = x;
1925 } else throw new Error("single:sequence contains more than one element.");
1926 });
1927
1928 if (!found) throw new Error("single:No element satisfies the condition.");
1929 return value;
1930 };
1931
1932 // Overload:function(defaultValue)
1933 // Overload:function(defaultValue,predicate)
1934 Enumerable.prototype.singleOrDefault = function (predicate, defaultValue) {
1935 if (defaultValue === undefined) defaultValue = null;
1936 if (predicate != null) return this.where(predicate).singleOrDefault(null, defaultValue);
1937
1938 var value;
1939 var found = false;
1940 this.forEach(function (x) {
1941 if (!found) {
1942 found = true;
1943 value = x;
1944 } else throw new Error("single:sequence contains more than one element.");
1945 });
1946
1947 return (!found) ? defaultValue : value;
1948 };
1949
1950 Enumerable.prototype.skip = function (count) {
1951 var source = this;
1952
1953 return new Enumerable(function () {
1954 var enumerator;
1955 var index = 0;
1956
1957 return new IEnumerator(
1958 function () {
1959 enumerator = source.getEnumerator();
1960 while (index++ < count && enumerator.moveNext()) {
1961 }
1962 ;
1963 },
1964 function () {
1965 return (enumerator.moveNext())
1966 ? this.yieldReturn(enumerator.current())
1967 : false;
1968 },
1969 function () { Utils.dispose(enumerator); });
1970 });
1971 };
1972
1973 // Overload:function(predicate<element>)
1974 // Overload:function(predicate<element,index>)
1975 Enumerable.prototype.skipWhile = function (predicate) {
1976 predicate = Utils.createLambda(predicate);
1977 var source = this;
1978
1979 return new Enumerable(function () {
1980 var enumerator;
1981 var index = 0;
1982 var isSkipEnd = false;
1983
1984 return new IEnumerator(
1985 function () { enumerator = source.getEnumerator(); },
1986 function () {
1987 while (!isSkipEnd) {
1988 if (enumerator.moveNext()) {
1989 if (!predicate(enumerator.current(), index++)) {
1990 isSkipEnd = true;
1991 return this.yieldReturn(enumerator.current());
1992 }
1993 continue;
1994 } else return false;
1995 }
1996
1997 return (enumerator.moveNext())
1998 ? this.yieldReturn(enumerator.current())
1999 : false;
2000
2001 },
2002 function () { Utils.dispose(enumerator); });
2003 });
2004 };
2005
2006 Enumerable.prototype.take = function (count) {
2007 var source = this;
2008
2009 return new Enumerable(function () {
2010 var enumerator;
2011 var index = 0;
2012
2013 return new IEnumerator(
2014 function () { enumerator = source.getEnumerator(); },
2015 function () {
2016 return (index++ < count && enumerator.moveNext())
2017 ? this.yieldReturn(enumerator.current())
2018 : false;
2019 },
2020 function () { Utils.dispose(enumerator); }
2021 );
2022 });
2023 };
2024
2025 // Overload:function(predicate<element>)
2026 // Overload:function(predicate<element,index>)
2027 Enumerable.prototype.takeWhile = function (predicate) {
2028 predicate = Utils.createLambda(predicate);
2029 var source = this;
2030
2031 return new Enumerable(function () {
2032 var enumerator;
2033 var index = 0;
2034
2035 return new IEnumerator(
2036 function () { enumerator = source.getEnumerator(); },
2037 function () {
2038 return (enumerator.moveNext() && predicate(enumerator.current(), index++))
2039 ? this.yieldReturn(enumerator.current())
2040 : false;
2041 },
2042 function () { Utils.dispose(enumerator); });
2043 });
2044 };
2045
2046 // Overload:function()
2047 // Overload:function(count)
2048 Enumerable.prototype.takeExceptLast = function (count) {
2049 if (count == null) count = 1;
2050 var source = this;
2051
2052 return new Enumerable(function () {
2053 if (count <= 0) return source.getEnumerator(); // do nothing
2054
2055 var enumerator;
2056 var q = [];
2057
2058 return new IEnumerator(
2059 function () { enumerator = source.getEnumerator(); },
2060 function () {
2061 while (enumerator.moveNext()) {
2062 if (q.length == count) {
2063 q.push(enumerator.current());
2064 return this.yieldReturn(q.shift());
2065 }
2066 q.push(enumerator.current());
2067 }
2068 return false;
2069 },
2070 function () { Utils.dispose(enumerator); });
2071 });
2072 };
2073
2074 Enumerable.prototype.takeFromLast = function (count) {
2075 if (count <= 0 || count == null) return Enumerable.empty();
2076 var source = this;
2077
2078 return new Enumerable(function () {
2079 var sourceEnumerator;
2080 var enumerator;
2081 var q = [];
2082
2083 return new IEnumerator(
2084 function () { sourceEnumerator = source.getEnumerator(); },
2085 function () {
2086 while (sourceEnumerator.moveNext()) {
2087 if (q.length == count) q.shift();
2088 q.push(sourceEnumerator.current());
2089 }
2090 if (enumerator == null) {
2091 enumerator = Enumerable.from(q).getEnumerator();
2092 }
2093 return (enumerator.moveNext())
2094 ? this.yieldReturn(enumerator.current())
2095 : false;
2096 },
2097 function () { Utils.dispose(enumerator); });
2098 });
2099 };
2100
2101 // Overload:function(item)
2102 // Overload:function(item, comparer)
2103 // Overload:function(predicate)
2104 Enumerable.prototype.indexOf = function (item, comparer) {
2105 var found = null;
2106
2107 // item as predicate
2108 if (typeof (item) === Types.Function) {
2109 this.forEach(function (x, i) {
2110 if (item(x, i)) {
2111 found = i;
2112 return false;
2113 }
2114 });
2115 }
2116 else {
2117 comparer = comparer || ss.EqualityComparer.def;
2118 this.forEach(function (x, i) {
2119 if (comparer.areEqual(x, item)) {
2120 found = i;
2121 return false;
2122 }
2123 });
2124 }
2125
2126 return (found !== null) ? found : -1;
2127 };
2128
2129 // Overload:function(item)
2130 // Overload:function(item, comparer)
2131 // Overload:function(predicate)
2132 Enumerable.prototype.lastIndexOf = function (item, comparer) {
2133 var result = -1;
2134
2135 // item as predicate
2136 if (typeof (item) === Types.Function) {
2137 this.forEach(function (x, i) {
2138 if (item(x, i)) result = i;
2139 });
2140 }
2141 else {
2142 comparer = comparer || ss.EqualityComparer.def;
2143 this.forEach(function (x, i) {
2144 if (comparer.areEqual(x, item)) result = i;
2145 });
2146 }
2147
2148 return result;
2149 };
2150
2151 /* Convert Methods */
2152
2153 Enumerable.prototype.asEnumerable = function () {
2154 return Enumerable.from(this);
2155 };
2156
2157 Enumerable.prototype.toArray = function () {
2158 var array = [];
2159 this.forEach(function (x) { array.push(x); });
2160 return array;
2161 };
2162
2163 // Overload:function(keySelector)
2164 // Overload:function(keySelector, elementSelector)
2165 // Overload:function(keySelector, elementSelector, comparer)
2166 Enumerable.prototype.toLookup = function (keySelector, elementSelector, comparer) {
2167 keySelector = Utils.createLambda(keySelector);
2168 elementSelector = Utils.createLambda(elementSelector);
2169
2170 var dict = new (ss.makeGenericType(ss.Dictionary$2, [Object, Object]))(null, comparer);
2171 var order = [];
2172 this.forEach(function (x) {
2173 var key = keySelector(x);
2174 var element = elementSelector(x);
2175
2176 var array = { $: null };
2177 if (dict.tryGetValue(key, array)) {
2178 array.$.push(element);
2179 }
2180 else {
2181 order.push(key);
2182 dict.add(key, [element]);
2183 }
2184 });
2185 return new Lookup(dict, order);
2186 };
2187
2188 Enumerable.prototype.toObject = function (keySelector, elementSelector) {
2189 keySelector = Utils.createLambda(keySelector);
2190 elementSelector = Utils.createLambda(elementSelector);
2191
2192 var obj = {};
2193 this.forEach(function (x) {
2194 obj[keySelector(x)] = elementSelector(x);
2195 });
2196 return obj;
2197 };
2198
2199 // Overload:function(keySelector, elementSelector, keyType, valueType)
2200 // Overload:function(keySelector, elementSelector, keyType, valueType, comparer)
2201 Enumerable.prototype.toDictionary = function (keySelector, elementSelector, keyType, valueType, comparer) {
2202 keySelector = Utils.createLambda(keySelector);
2203 elementSelector = Utils.createLambda(elementSelector);
2204
2205 var dict = new (ss.makeGenericType(ss.Dictionary$2, [keyType, valueType]))(null, comparer);
2206 this.forEach(function (x) {
2207 dict.add(keySelector(x), elementSelector(x));
2208 });
2209 return dict;
2210 };
2211
2212 // Overload:function()
2213 // Overload:function(replacer)
2214 // Overload:function(replacer, space)
2215 Enumerable.prototype.toJSONString = function (replacer, space) {
2216 if (typeof JSON === Types.Undefined || JSON.stringify == null) {
2217 throw new Error("toJSONString can't find JSON.stringify. This works native JSON support Browser or include json2.js");
2218 }
2219 return JSON.stringify(this.toArray(), replacer, space);
2220 };
2221
2222 // Overload:function()
2223 // Overload:function(separator)
2224 // Overload:function(separator,selector)
2225 Enumerable.prototype.toJoinedString = function (separator, selector) {
2226 if (separator == null) separator = "";
2227 if (selector == null) selector = Functions.Identity;
2228
2229 return this.select(selector).toArray().join(separator);
2230 };
2231
2232
2233 /* Action Methods */
2234
2235 // Overload:function(action<element>)
2236 // Overload:function(action<element,index>)
2237 Enumerable.prototype.doAction = function (action) {
2238 var source = this;
2239 action = Utils.createLambda(action);
2240
2241 return new Enumerable(function () {
2242 var enumerator;
2243 var index = 0;
2244
2245 return new IEnumerator(
2246 function () { enumerator = source.getEnumerator(); },
2247 function () {
2248 if (enumerator.moveNext()) {
2249 action(enumerator.current(), index++);
2250 return this.yieldReturn(enumerator.current());
2251 }
2252 return false;
2253 },
2254 function () { Utils.dispose(enumerator); });
2255 });
2256 };
2257
2258 // Overload:function(action<element>)
2259 // Overload:function(action<element,index>)
2260 // Overload:function(func<element,bool>)
2261 // Overload:function(func<element,index,bool>)
2262 Enumerable.prototype.forEach = function (action) {
2263 action = Utils.createLambda(action);
2264
2265 var index = 0;
2266 var enumerator = this.getEnumerator();
2267 try {
2268 while (enumerator.moveNext()) {
2269 if (action(enumerator.current(), index++) === false) break;
2270 }
2271 } finally {
2272 Utils.dispose(enumerator);
2273 }
2274 };
2275
2276 // Overload:function()
2277 // Overload:function(separator)
2278 // Overload:function(separator,selector)
2279 Enumerable.prototype.write = function (separator, selector) {
2280 if (separator == null) separator = "";
2281 selector = Utils.createLambda(selector);
2282
2283 var isFirst = true;
2284 this.forEach(function (item) {
2285 if (isFirst) isFirst = false;
2286 else document.write(separator);
2287 document.write(selector(item));
2288 });
2289 };
2290
2291 // Overload:function()
2292 // Overload:function(selector)
2293 Enumerable.prototype.writeLine = function (selector) {
2294 selector = Utils.createLambda(selector);
2295
2296 this.forEach(function (item) {
2297 document.writeln(selector(item) + "<br />");
2298 });
2299 };
2300
2301 Enumerable.prototype.force = function () {
2302 var enumerator = this.getEnumerator();
2303
2304 try {
2305 while (enumerator.moveNext()) {
2306 }
2307 }
2308 finally {
2309 Utils.dispose(enumerator);
2310 }
2311 };
2312
2313 /* Functional Methods */
2314
2315 Enumerable.prototype.letBind = function (func) {
2316 func = Utils.createLambda(func);
2317 var source = this;
2318
2319 return new Enumerable(function () {
2320 var enumerator;
2321
2322 return new IEnumerator(
2323 function () {
2324 enumerator = Enumerable.from(func(source)).getEnumerator();
2325 },
2326 function () {
2327 return (enumerator.moveNext())
2328 ? this.yieldReturn(enumerator.current())
2329 : false;
2330 },
2331 function () { Utils.dispose(enumerator); });
2332 });
2333 };
2334
2335 Enumerable.prototype.share = function () {
2336 var source = this;
2337 var sharedEnumerator;
2338 var disposed = false;
2339
2340 return new DisposableEnumerable(function () {
2341 return new IEnumerator(
2342 function () {
2343 if (sharedEnumerator == null) {
2344 sharedEnumerator = source.getEnumerator();
2345 }
2346 },
2347 function () {
2348 if (disposed) throw new Error("enumerator is disposed");
2349
2350 return (sharedEnumerator.moveNext())
2351 ? this.yieldReturn(sharedEnumerator.current())
2352 : false;
2353 },
2354 Functions.Blank
2355 );
2356 }, function () {
2357 disposed = true;
2358 Utils.dispose(sharedEnumerator);
2359 });
2360 };
2361
2362 Enumerable.prototype.memoize = function () {
2363 var source = this;
2364 var cache;
2365 var enumerator;
2366 var disposed = false;
2367
2368 return new DisposableEnumerable(function () {
2369 var index = -1;
2370
2371 return new IEnumerator(
2372 function () {
2373 if (enumerator == null) {
2374 enumerator = source.getEnumerator();
2375 cache = [];
2376 }
2377 },
2378 function () {
2379 if (disposed) throw new Error("enumerator is disposed");
2380
2381 index++;
2382 if (cache.length <= index) {
2383 return (enumerator.moveNext())
2384 ? this.yieldReturn(cache[index] = enumerator.current())
2385 : false;
2386 }
2387
2388 return this.yieldReturn(cache[index]);
2389 },
2390 Functions.Blank
2391 );
2392 }, function () {
2393 disposed = true;
2394 Utils.dispose(enumerator);
2395 cache = null;
2396 });
2397 };
2398
2399 /* Error Handling Methods */
2400
2401 Enumerable.prototype.catchError = function (handler) {
2402 handler = Utils.createLambda(handler);
2403 var source = this;
2404
2405 return new Enumerable(function () {
2406 var enumerator;
2407
2408 return new IEnumerator(
2409 function () { enumerator = source.getEnumerator(); },
2410 function () {
2411 try {
2412 return (enumerator.moveNext())
2413 ? this.yieldReturn(enumerator.current())
2414 : false;
2415 } catch (e) {
2416 handler(e);
2417 return false;
2418 }
2419 },
2420 function () { Utils.dispose(enumerator); });
2421 });
2422 };
2423
2424 Enumerable.prototype.finallyAction = function (finallyAction) {
2425 finallyAction = Utils.createLambda(finallyAction);
2426 var source = this;
2427
2428 return new Enumerable(function () {
2429 var enumerator;
2430
2431 return new IEnumerator(
2432 function () { enumerator = source.getEnumerator(); },
2433 function () {
2434 return (enumerator.moveNext())
2435 ? this.yieldReturn(enumerator.current())
2436 : false;
2437 },
2438 function () {
2439 try {
2440 Utils.dispose(enumerator);
2441 } finally {
2442 finallyAction();
2443 }
2444 });
2445 });
2446 };
2447
2448 /* For Debug Methods */
2449
2450 // Overload:function()
2451 // Overload:function(selector)
2452 Enumerable.prototype.log = function (selector) {
2453 selector = Utils.createLambda(selector);
2454
2455 return this.doAction(function (item) {
2456 if (typeof console !== Types.Undefined) {
2457 console.log(selector(item));
2458 }
2459 });
2460 };
2461
2462 // Overload:function()
2463 // Overload:function(message)
2464 // Overload:function(message,selector)
2465 Enumerable.prototype.trace = function (message, selector) {
2466 if (message == null) message = "Trace";
2467 selector = Utils.createLambda(selector);
2468
2469 return this.doAction(function (item) {
2470 if (typeof console !== Types.Undefined) {
2471 console.log(message, selector(item));
2472 }
2473 });
2474 };
2475
2476 // private
2477
2478 var OrderedEnumerable = function (source, keySelector, comparer, descending, parent) {
2479 this.source = source;
2480 this.keySelector = Utils.createLambda(keySelector);
2481 this.comparer = comparer || ss.Comparer.def;
2482 this.descending = descending;
2483 this.parent = parent;
2484 };
2485 OrderedEnumerable.prototype = new Enumerable();
2486
2487 OrderedEnumerable.prototype.createOrderedEnumerable = function (keySelector, comparer, descending) {
2488 return new OrderedEnumerable(this.source, keySelector, comparer, descending, this);
2489 };
2490 OrderedEnumerable.prototype.thenBy = function (keySelector, comparer) {
2491 return this.createOrderedEnumerable(keySelector, comparer, false);
2492 };
2493 OrderedEnumerable.prototype.thenByDescending = function (keySelector, comparer) {
2494 return this.createOrderedEnumerable(keySelector, comparer, true);
2495 };
2496 OrderedEnumerable.prototype.getEnumerator = function () {
2497 var self = this;
2498 var buffer;
2499 var indexes;
2500 var index = 0;
2501
2502 return new IEnumerator(
2503 function () {
2504 buffer = [];
2505 indexes = [];
2506 self.source.forEach(function (item, index) {
2507 buffer.push(item);
2508 indexes.push(index);
2509 });
2510 var sortContext = SortContext.create(self, null);
2511 sortContext.GenerateKeys(buffer);
2512
2513 indexes.sort(function (a, b) { return sortContext.compare(a, b); });
2514 },
2515 function () {
2516 return (index < indexes.length)
2517 ? this.yieldReturn(buffer[indexes[index++]])
2518 : false;
2519 },
2520 Functions.Blank
2521 );
2522 };
2523
2524 var SortContext = function (keySelector, comparer, descending, child) {
2525 this.keySelector = keySelector;
2526 this.comparer = comparer;
2527 this.descending = descending;
2528 this.child = child;
2529 this.keys = null;
2530 };
2531 SortContext.create = function (orderedEnumerable, currentContext) {
2532 var context = new SortContext(orderedEnumerable.keySelector, orderedEnumerable.comparer, orderedEnumerable.descending, currentContext);
2533 if (orderedEnumerable.parent != null) return SortContext.create(orderedEnumerable.parent, context);
2534 return context;
2535 };
2536 SortContext.prototype.GenerateKeys = function (source) {
2537 var len = source.length;
2538 var keySelector = this.keySelector;
2539 var keys = new Array(len);
2540 for (var i = 0; i < len; i++) keys[i] = keySelector(source[i]);
2541 this.keys = keys;
2542
2543 if (this.child != null) this.child.GenerateKeys(source);
2544 };
2545 SortContext.prototype.compare = function (index1, index2) {
2546 var comparison = this.comparer.compare(this.keys[index1], this.keys[index2]);
2547
2548 if (comparison == 0) {
2549 if (this.child != null) return this.child.compare(index1, index2);
2550 return Utils.compare(index1, index2);
2551 }
2552
2553 return (this.descending) ? -comparison : comparison;
2554 };
2555
2556 var DisposableEnumerable = function (getEnumerator, dispose) {
2557 this.dispose = dispose;
2558 Enumerable.call(this, getEnumerator);
2559 };
2560 DisposableEnumerable.prototype = new Enumerable();
2561
2562 // optimize array or arraylike object
2563
2564 var ArrayEnumerable = function (source) {
2565 this.getSource = function () { return source; };
2566 };
2567 ArrayEnumerable.prototype = new Enumerable();
2568
2569 ArrayEnumerable.prototype.any = function (predicate) {
2570 return (predicate == null)
2571 ? (this.getSource().length > 0)
2572 : Enumerable.prototype.any.apply(this, arguments);
2573 };
2574
2575 ArrayEnumerable.prototype.count = function (predicate) {
2576 return (predicate == null)
2577 ? this.getSource().length
2578 : Enumerable.prototype.count.apply(this, arguments);
2579 };
2580
2581 ArrayEnumerable.prototype.elementAt = function (index) {
2582 var source = this.getSource();
2583 return (0 <= index && index < source.length)
2584 ? source[index]
2585 : Enumerable.prototype.elementAt.apply(this, arguments);
2586 };
2587
2588 ArrayEnumerable.prototype.elementAtOrDefault = function (index, defaultValue) {
2589 if (defaultValue === undefined) defaultValue = null;
2590 var source = this.getSource();
2591 return (0 <= index && index < source.length)
2592 ? source[index]
2593 : defaultValue;
2594 };
2595
2596 ArrayEnumerable.prototype.first = function (predicate) {
2597 var source = this.getSource();
2598 return (predicate == null && source.length > 0)
2599 ? source[0]
2600 : Enumerable.prototype.first.apply(this, arguments);
2601 };
2602
2603 ArrayEnumerable.prototype.firstOrDefault = function (predicate, defaultValue) {
2604 if (defaultValue === undefined) defaultValue = null;
2605 if (predicate != null) {
2606 return Enumerable.prototype.firstOrDefault.apply(this, arguments);
2607 }
2608
2609 var source = this.getSource();
2610 return source.length > 0 ? source[0] : defaultValue;
2611 };
2612
2613 ArrayEnumerable.prototype.last = function (predicate) {
2614 var source = this.getSource();
2615 return (predicate == null && source.length > 0)
2616 ? source[source.length - 1]
2617 : Enumerable.prototype.last.apply(this, arguments);
2618 };
2619
2620 ArrayEnumerable.prototype.lastOrDefault = function (predicate, defaultValue) {
2621 if (defaultValue === undefined) defaultValue = null;
2622 if (predicate != null) {
2623 return Enumerable.prototype.lastOrDefault.apply(this, arguments);
2624 }
2625
2626 var source = this.getSource();
2627 return source.length > 0 ? source[source.length - 1] : defaultValue;
2628 };
2629
2630 ArrayEnumerable.prototype.skip = function (count) {
2631 var source = this.getSource();
2632
2633 return new Enumerable(function () {
2634 var index;
2635
2636 return new IEnumerator(
2637 function () { index = (count < 0) ? 0 : count; },
2638 function () {
2639 return (index < source.length)
2640 ? this.yieldReturn(source[index++])
2641 : false;
2642 },
2643 Functions.Blank);
2644 });
2645 };
2646
2647 ArrayEnumerable.prototype.takeExceptLast = function (count) {
2648 if (count == null) count = 1;
2649 return this.take(this.getSource().length - count);
2650 };
2651
2652 ArrayEnumerable.prototype.takeFromLast = function (count) {
2653 return this.skip(this.getSource().length - count);
2654 };
2655
2656 ArrayEnumerable.prototype.reverse = function () {
2657 var source = this.getSource();
2658
2659 return new Enumerable(function () {
2660 var index;
2661
2662 return new IEnumerator(
2663 function () {
2664 index = source.length;
2665 },
2666 function () {
2667 return (index > 0)
2668 ? this.yieldReturn(source[--index])
2669 : false;
2670 },
2671 Functions.Blank);
2672 });
2673 };
2674
2675 ArrayEnumerable.prototype.sequenceEqual = function (second, comparer) {
2676 if ((second instanceof ArrayEnumerable || second instanceof Array)
2677 && comparer == null
2678 && Enumerable.from(second).count() != this.count()) {
2679 return false;
2680 }
2681
2682 return Enumerable.prototype.sequenceEqual.apply(this, arguments);
2683 };
2684
2685 ArrayEnumerable.prototype.toJoinedString = function (separator, selector) {
2686 var source = this.getSource();
2687 if (selector != null || !(source instanceof Array)) {
2688 return Enumerable.prototype.toJoinedString.apply(this, arguments);
2689 }
2690
2691 if (separator == null) separator = "";
2692 return source.join(separator);
2693 };
2694
2695 ArrayEnumerable.prototype.getEnumerator = function () {
2696 return new ss.ArrayEnumerator(this.getSource());
2697 };
2698
2699 // optimization for multiple where and multiple select and whereselect
2700
2701 var WhereEnumerable = function (source, predicate) {
2702 this.prevSource = source;
2703 this.prevPredicate = predicate; // predicate.length always <= 1
2704 };
2705 WhereEnumerable.prototype = new Enumerable();
2706
2707 WhereEnumerable.prototype.where = function (predicate) {
2708 predicate = Utils.createLambda(predicate);
2709
2710 if (predicate.length <= 1) {
2711 var prevPredicate = this.prevPredicate;
2712 var composedPredicate = function (x) { return prevPredicate(x) && predicate(x); };
2713 return new WhereEnumerable(this.prevSource, composedPredicate);
2714 }
2715 else {
2716 // if predicate use index, can't compose
2717 return Enumerable.prototype.where.call(this, predicate);
2718 }
2719 };
2720
2721 WhereEnumerable.prototype.select = function (selector) {
2722 selector = Utils.createLambda(selector);
2723
2724 return (selector.length <= 1)
2725 ? new WhereSelectEnumerable(this.prevSource, this.prevPredicate, selector)
2726 : Enumerable.prototype.select.call(this, selector);
2727 };
2728
2729 WhereEnumerable.prototype.getEnumerator = function () {
2730 var predicate = this.prevPredicate;
2731 var source = this.prevSource;
2732 var enumerator;
2733
2734 return new IEnumerator(
2735 function () { enumerator = source.getEnumerator(); },
2736 function () {
2737 while (enumerator.moveNext()) {
2738 if (predicate(enumerator.current())) {
2739 return this.yieldReturn(enumerator.current());
2740 }
2741 }
2742 return false;
2743 },
2744 function () { Utils.dispose(enumerator); });
2745 };
2746
2747 var WhereSelectEnumerable = function (source, predicate, selector) {
2748 this.prevSource = source;
2749 this.prevPredicate = predicate; // predicate.length always <= 1 or null
2750 this.prevSelector = selector; // selector.length always <= 1
2751 };
2752 WhereSelectEnumerable.prototype = new Enumerable();
2753
2754 WhereSelectEnumerable.prototype.where = function (predicate) {
2755 predicate = Utils.createLambda(predicate);
2756
2757 return (predicate.length <= 1)
2758 ? new WhereEnumerable(this, predicate)
2759 : Enumerable.prototype.where.call(this, predicate);
2760 };
2761
2762 WhereSelectEnumerable.prototype.select = function (selector) {
2763 selector = Utils.createLambda(selector);
2764
2765 if (selector.length <= 1) {
2766 var prevSelector = this.prevSelector;
2767 var composedSelector = function (x) { return selector(prevSelector(x)); };
2768 return new WhereSelectEnumerable(this.prevSource, this.prevPredicate, composedSelector);
2769 }
2770 else {
2771 // if selector use index, can't compose
2772 return Enumerable.prototype.select.call(this, selector);
2773 }
2774 };
2775
2776 WhereSelectEnumerable.prototype.getEnumerator = function () {
2777 var predicate = this.prevPredicate;
2778 var selector = this.prevSelector;
2779 var source = this.prevSource;
2780 var enumerator;
2781
2782 return new IEnumerator(
2783 function () { enumerator = source.getEnumerator(); },
2784 function () {
2785 while (enumerator.moveNext()) {
2786 if (predicate == null || predicate(enumerator.current())) {
2787 return this.yieldReturn(selector(enumerator.current()));
2788 }
2789 }
2790 return false;
2791 },
2792 function () { Utils.dispose(enumerator); });
2793 };
2794
2795 // Collections
2796
2797 // dictionary = Dictionary<TKey, TValue[]>
2798 var Lookup = function (dictionary, order) {
2799 this.count = function () {
2800 return dictionary.get_count();
2801 };
2802 this.get = function (key) {
2803 var value = { $: null };
2804 var success = dictionary.tryGetValue(key, value);
2805 return Enumerable.from(success ? value.$ : []);
2806 };
2807 this.contains = function (key) {
2808 return dictionary.containsKey(key);
2809 };
2810 this.toEnumerable = function () {
2811 return Enumerable.from(order).select(function (key) {
2812 return new Grouping(key, dictionary.get_item(key));
2813 });
2814 };
2815 this.getEnumerator = function () {
2816 return this.toEnumerable().getEnumerator();
2817 };
2818 };
2819 ss.initClass(Lookup, $asm, {}, null, [ss.IEnumerable]);
2820
2821 var Grouping = function (groupKey, elements) {
2822 this.key = function () {
2823 return groupKey;
2824 };
2825 ArrayEnumerable.call(this, elements);
2826 };
2827 Grouping.prototype = new ArrayEnumerable();
2828
2829 // module export
2830 if (typeof define === Types.Function && define.amd) { // AMD
2831 define("linqjs", [], function () { return Enumerable; });
2832 root.Enumerable = Enumerable;
2833 }
2834 else if (typeof module !== Types.Undefined && module.exports) { // Node
2835 module.exports = Enumerable;
2836 global.Enumerable = Enumerable;
2837 }
2838 else {
2839 root.Enumerable = Enumerable;
2840 }
2841})(this);
Note: See TracBrowser for help on using the repository browser.