couch_potato 1.6.4 → 1.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ruby.yml +38 -0
  3. data/.gitignore +3 -0
  4. data/CHANGES.md +193 -122
  5. data/Gemfile +4 -0
  6. data/README.md +61 -85
  7. data/Rakefile +11 -10
  8. data/couch_potato-rspec.gemspec +3 -2
  9. data/couch_potato.gemspec +9 -7
  10. data/gemfiles/active_support_5_0 +7 -0
  11. data/gemfiles/active_support_5_1 +7 -0
  12. data/gemfiles/active_support_5_2 +7 -0
  13. data/gemfiles/active_support_6_0 +7 -0
  14. data/gemfiles/active_support_6_1 +7 -0
  15. data/lib/couch_potato/database.rb +168 -71
  16. data/lib/couch_potato/persistence/dirty_attributes.rb +3 -21
  17. data/lib/couch_potato/persistence/magic_timestamps.rb +3 -3
  18. data/lib/couch_potato/persistence/properties.rb +15 -10
  19. data/lib/couch_potato/persistence/revisions.rb +14 -0
  20. data/lib/couch_potato/persistence/simple_property.rb +0 -4
  21. data/lib/couch_potato/persistence/type_caster.rb +11 -6
  22. data/lib/couch_potato/persistence.rb +5 -3
  23. data/lib/couch_potato/railtie.rb +7 -12
  24. data/lib/couch_potato/validation.rb +8 -0
  25. data/lib/couch_potato/version.rb +2 -2
  26. data/lib/couch_potato/view/base_view_spec.rb +8 -32
  27. data/lib/couch_potato/view/custom_views.rb +4 -3
  28. data/lib/couch_potato/view/flex_view_spec.rb +121 -0
  29. data/lib/couch_potato/view/view_parameters.rb +34 -0
  30. data/lib/couch_potato.rb +37 -16
  31. data/spec/callbacks_spec.rb +45 -19
  32. data/spec/conflict_handling_spec.rb +1 -2
  33. data/spec/property_spec.rb +12 -3
  34. data/spec/railtie_spec.rb +17 -1
  35. data/spec/revisions_spec.rb +25 -0
  36. data/spec/spec_helper.rb +4 -3
  37. data/spec/unit/active_model_compliance_spec.rb +7 -3
  38. data/spec/unit/attributes_spec.rb +54 -1
  39. data/spec/unit/caching_spec.rb +105 -0
  40. data/spec/unit/couch_potato_spec.rb +70 -5
  41. data/spec/unit/create_spec.rb +5 -4
  42. data/spec/unit/database_spec.rb +235 -135
  43. data/spec/unit/dirty_attributes_spec.rb +5 -26
  44. data/spec/unit/flex_view_spec_spec.rb +17 -0
  45. data/spec/unit/model_view_spec_spec.rb +1 -1
  46. data/spec/unit/rspec_stub_db_spec.rb +31 -0
  47. data/spec/unit/validation_spec.rb +42 -2
  48. data/spec/views_spec.rb +214 -103
  49. data/vendor/pouchdb-collate/LICENSE +202 -0
  50. data/vendor/pouchdb-collate/pouchdb-collate.js +430 -0
  51. metadata +46 -33
  52. data/.ruby-version +0 -1
  53. data/.travis.yml +0 -20
  54. data/gemfiles/active_support_4_0 +0 -11
  55. data/gemfiles/active_support_4_1 +0 -11
  56. data/gemfiles/active_support_4_2 +0 -11
  57. data/lib/couch_potato/persistence/deep_dirty_attributes.rb +0 -180
  58. data/spec/unit/deep_dirty_attributes_spec.rb +0 -434
@@ -0,0 +1,202 @@
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright [yyyy] [name of copyright owner]
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
@@ -0,0 +1,430 @@
1
+ !function(e){"object"==typeof exports?module.exports=e():"function"==typeof define&&define.amd?define(e):"undefined"!=typeof window?window.pouchCollate=e():"undefined"!=typeof global?global.pouchCollate=e():"undefined"!=typeof self&&(self.pouchCollate=e())}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
2
+ 'use strict';
3
+
4
+ var MIN_MAGNITUDE = -324; // verified by -Number.MIN_VALUE
5
+ var MAGNITUDE_DIGITS = 3; // ditto
6
+ var SEP = ''; // set to '_' for easier debugging
7
+
8
+ var utils = require('./utils');
9
+
10
+ exports.collate = function (a, b) {
11
+
12
+ if (a === b) {
13
+ return 0;
14
+ }
15
+
16
+ a = exports.normalizeKey(a);
17
+ b = exports.normalizeKey(b);
18
+
19
+ var ai = collationIndex(a);
20
+ var bi = collationIndex(b);
21
+ if ((ai - bi) !== 0) {
22
+ return ai - bi;
23
+ }
24
+ if (a === null) {
25
+ return 0;
26
+ }
27
+ switch (typeof a) {
28
+ case 'number':
29
+ return a - b;
30
+ case 'boolean':
31
+ return a === b ? 0 : (a < b ? -1 : 1);
32
+ case 'string':
33
+ return stringCollate(a, b);
34
+ }
35
+ return Array.isArray(a) ? arrayCollate(a, b) : objectCollate(a, b);
36
+ };
37
+
38
+ // couch considers null/NaN/Infinity/-Infinity === undefined,
39
+ // for the purposes of mapreduce indexes. also, dates get stringified.
40
+ exports.normalizeKey = function (key) {
41
+ switch (typeof key) {
42
+ case 'undefined':
43
+ return null;
44
+ case 'number':
45
+ if (key === Infinity || key === -Infinity || isNaN(key)) {
46
+ return null;
47
+ }
48
+ return key;
49
+ case 'object':
50
+ var origKey = key;
51
+ if (Array.isArray(key)) {
52
+ var len = key.length;
53
+ key = new Array(len);
54
+ for (var i = 0; i < len; i++) {
55
+ key[i] = exports.normalizeKey(origKey[i]);
56
+ }
57
+ } else if (key instanceof Date) {
58
+ return key.toJSON();
59
+ } else if (key !== null) { // generic object
60
+ key = {};
61
+ for (var k in origKey) {
62
+ if (origKey.hasOwnProperty(k)) {
63
+ var val = origKey[k];
64
+ if (typeof val !== 'undefined') {
65
+ key[k] = exports.normalizeKey(val);
66
+ }
67
+ }
68
+ }
69
+ }
70
+ }
71
+ return key;
72
+ };
73
+
74
+ function indexify(key) {
75
+ if (key !== null) {
76
+ switch (typeof key) {
77
+ case 'boolean':
78
+ return key ? 1 : 0;
79
+ case 'number':
80
+ return numToIndexableString(key);
81
+ case 'string':
82
+ // We've to be sure that key does not contain \u0000
83
+ // Do order-preserving replacements:
84
+ // 0 -> 1, 1
85
+ // 1 -> 1, 2
86
+ // 2 -> 2, 2
87
+ return key
88
+ .replace(/\u0002/g, '\u0002\u0002')
89
+ .replace(/\u0001/g, '\u0001\u0002')
90
+ .replace(/\u0000/g, '\u0001\u0001');
91
+ case 'object':
92
+ var isArray = Array.isArray(key);
93
+ var arr = isArray ? key : Object.keys(key);
94
+ var i = -1;
95
+ var len = arr.length;
96
+ var result = '';
97
+ if (isArray) {
98
+ while (++i < len) {
99
+ result += exports.toIndexableString(arr[i]);
100
+ }
101
+ } else {
102
+ while (++i < len) {
103
+ var objKey = arr[i];
104
+ result += exports.toIndexableString(objKey) +
105
+ exports.toIndexableString(key[objKey]);
106
+ }
107
+ }
108
+ return result;
109
+ }
110
+ }
111
+ return '';
112
+ }
113
+
114
+ // convert the given key to a string that would be appropriate
115
+ // for lexical sorting, e.g. within a database, where the
116
+ // sorting is the same given by the collate() function.
117
+ exports.toIndexableString = function (key) {
118
+ var zero = '\u0000';
119
+ key = exports.normalizeKey(key);
120
+ return collationIndex(key) + SEP + indexify(key) + zero;
121
+ };
122
+
123
+ function parseNumber(str, i) {
124
+ var originalIdx = i;
125
+ var num;
126
+ var zero = str[i] === '1';
127
+ if (zero) {
128
+ num = 0;
129
+ i++;
130
+ } else {
131
+ var neg = str[i] === '0';
132
+ i++;
133
+ var numAsString = '';
134
+ var magAsString = str.substring(i, i + MAGNITUDE_DIGITS);
135
+ var magnitude = parseInt(magAsString, 10) + MIN_MAGNITUDE;
136
+ if (neg) {
137
+ magnitude = -magnitude;
138
+ }
139
+ i += MAGNITUDE_DIGITS;
140
+ while (true) {
141
+ var ch = str[i];
142
+ if (ch === '\u0000') {
143
+ break;
144
+ } else {
145
+ numAsString += ch;
146
+ }
147
+ i++;
148
+ }
149
+ numAsString = numAsString.split('.');
150
+ if (numAsString.length === 1) {
151
+ num = parseInt(numAsString, 10);
152
+ } else {
153
+ num = parseFloat(numAsString[0] + '.' + numAsString[1]);
154
+ }
155
+ if (neg) {
156
+ num = num - 10;
157
+ }
158
+ if (magnitude !== 0) {
159
+ // parseFloat is more reliable than pow due to rounding errors
160
+ // e.g. Number.MAX_VALUE would return Infinity if we did
161
+ // num * Math.pow(10, magnitude);
162
+ num = parseFloat(num + 'e' + magnitude);
163
+ }
164
+ }
165
+ return {num: num, length : i - originalIdx};
166
+ }
167
+
168
+ // move up the stack while parsing
169
+ // this function moved outside of parseIndexableString for performance
170
+ function pop(stack, metaStack) {
171
+ var obj = stack.pop();
172
+
173
+ if (metaStack.length) {
174
+ var lastMetaElement = metaStack[metaStack.length - 1];
175
+ if (obj === lastMetaElement.element) {
176
+ // popping a meta-element, e.g. an object whose value is another object
177
+ metaStack.pop();
178
+ lastMetaElement = metaStack[metaStack.length - 1];
179
+ }
180
+ var element = lastMetaElement.element;
181
+ var lastElementIndex = lastMetaElement.index;
182
+ if (Array.isArray(element)) {
183
+ element.push(obj);
184
+ } else if (lastElementIndex === stack.length - 2) { // obj with key+value
185
+ var key = stack.pop();
186
+ element[key] = obj;
187
+ } else {
188
+ stack.push(obj); // obj with key only
189
+ }
190
+ }
191
+ }
192
+
193
+ exports.parseIndexableString = function (str) {
194
+ var stack = [];
195
+ var metaStack = []; // stack for arrays and objects
196
+ var i = 0;
197
+
198
+ while (true) {
199
+ var collationIndex = str[i++];
200
+ if (collationIndex === '\u0000') {
201
+ if (stack.length === 1) {
202
+ return stack.pop();
203
+ } else {
204
+ pop(stack, metaStack);
205
+ continue;
206
+ }
207
+ }
208
+ switch (collationIndex) {
209
+ case '1':
210
+ stack.push(null);
211
+ break;
212
+ case '2':
213
+ stack.push(str[i] === '1');
214
+ i++;
215
+ break;
216
+ case '3':
217
+ var parsedNum = parseNumber(str, i);
218
+ stack.push(parsedNum.num);
219
+ i += parsedNum.length;
220
+ break;
221
+ case '4':
222
+ var parsedStr = '';
223
+ while (true) {
224
+ var ch = str[i];
225
+ if (ch === '\u0000') {
226
+ break;
227
+ }
228
+ parsedStr += ch;
229
+ i++;
230
+ }
231
+ // perform the reverse of the order-preserving replacement
232
+ // algorithm (see above)
233
+ parsedStr = parsedStr.replace(/\u0001\u0001/g, '\u0000')
234
+ .replace(/\u0001\u0002/g, '\u0001')
235
+ .replace(/\u0002\u0002/g, '\u0002');
236
+ stack.push(parsedStr);
237
+ break;
238
+ case '5':
239
+ var arrayElement = { element: [], index: stack.length };
240
+ stack.push(arrayElement.element);
241
+ metaStack.push(arrayElement);
242
+ break;
243
+ case '6':
244
+ var objElement = { element: {}, index: stack.length };
245
+ stack.push(objElement.element);
246
+ metaStack.push(objElement);
247
+ break;
248
+ default:
249
+ throw new Error(
250
+ 'bad collationIndex or unexpectedly reached end of input: ' + collationIndex);
251
+ }
252
+ }
253
+ };
254
+
255
+ function arrayCollate(a, b) {
256
+ var len = Math.min(a.length, b.length);
257
+ for (var i = 0; i < len; i++) {
258
+ var sort = exports.collate(a[i], b[i]);
259
+ if (sort !== 0) {
260
+ return sort;
261
+ }
262
+ }
263
+ return (a.length === b.length) ? 0 :
264
+ (a.length > b.length) ? 1 : -1;
265
+ }
266
+ function stringCollate(a, b) {
267
+ // See: https://github.com/daleharvey/pouchdb/issues/40
268
+ // This is incompatible with the CouchDB implementation, but its the
269
+ // best we can do for now
270
+ return (a === b) ? 0 : ((a > b) ? 1 : -1);
271
+ }
272
+ function objectCollate(a, b) {
273
+ var ak = Object.keys(a), bk = Object.keys(b);
274
+ var len = Math.min(ak.length, bk.length);
275
+ for (var i = 0; i < len; i++) {
276
+ // First sort the keys
277
+ var sort = exports.collate(ak[i], bk[i]);
278
+ if (sort !== 0) {
279
+ return sort;
280
+ }
281
+ // if the keys are equal sort the values
282
+ sort = exports.collate(a[ak[i]], b[bk[i]]);
283
+ if (sort !== 0) {
284
+ return sort;
285
+ }
286
+
287
+ }
288
+ return (ak.length === bk.length) ? 0 :
289
+ (ak.length > bk.length) ? 1 : -1;
290
+ }
291
+ // The collation is defined by erlangs ordered terms
292
+ // the atoms null, true, false come first, then numbers, strings,
293
+ // arrays, then objects
294
+ // null/undefined/NaN/Infinity/-Infinity are all considered null
295
+ function collationIndex(x) {
296
+ var id = ['boolean', 'number', 'string', 'object'];
297
+ var idx = id.indexOf(typeof x);
298
+ //false if -1 otherwise true, but fast!!!!1
299
+ if (~idx) {
300
+ if (x === null) {
301
+ return 1;
302
+ }
303
+ if (Array.isArray(x)) {
304
+ return 5;
305
+ }
306
+ return idx < 3 ? (idx + 2) : (idx + 3);
307
+ }
308
+ if (Array.isArray(x)) {
309
+ return 5;
310
+ }
311
+ }
312
+
313
+ // conversion:
314
+ // x yyy zz...zz
315
+ // x = 0 for negative, 1 for 0, 2 for positive
316
+ // y = exponent (for negative numbers negated) moved so that it's >= 0
317
+ // z = mantisse
318
+ function numToIndexableString(num) {
319
+
320
+ if (num === 0) {
321
+ return '1';
322
+ }
323
+
324
+ // convert number to exponential format for easier and
325
+ // more succinct string sorting
326
+ var expFormat = num.toExponential().split(/e\+?/);
327
+ var magnitude = parseInt(expFormat[1], 10);
328
+
329
+ var neg = num < 0;
330
+
331
+ var result = neg ? '0' : '2';
332
+
333
+ // first sort by magnitude
334
+ // it's easier if all magnitudes are positive
335
+ var magForComparison = ((neg ? -magnitude : magnitude) - MIN_MAGNITUDE);
336
+ var magString = utils.padLeft((magForComparison).toString(), '0', MAGNITUDE_DIGITS);
337
+
338
+ result += SEP + magString;
339
+
340
+ // then sort by the factor
341
+ var factor = Math.abs(parseFloat(expFormat[0])); // [1..10)
342
+ if (neg) { // for negative reverse ordering
343
+ factor = 10 - factor;
344
+ }
345
+
346
+ var factorStr = factor.toFixed(20);
347
+
348
+ // strip zeros from the end
349
+ factorStr = factorStr.replace(/\.?0+$/, '');
350
+
351
+ result += SEP + factorStr;
352
+
353
+ return result;
354
+ }
355
+
356
+ },{"./utils":2}],2:[function(require,module,exports){
357
+ 'use strict';
358
+
359
+ function pad(str, padWith, upToLength) {
360
+ var padding = '';
361
+ var targetLength = upToLength - str.length;
362
+ while (padding.length < targetLength) {
363
+ padding += padWith;
364
+ }
365
+ return padding;
366
+ }
367
+
368
+ exports.padLeft = function (str, padWith, upToLength) {
369
+ var padding = pad(str, padWith, upToLength);
370
+ return padding + str;
371
+ };
372
+
373
+ exports.padRight = function (str, padWith, upToLength) {
374
+ var padding = pad(str, padWith, upToLength);
375
+ return str + padding;
376
+ };
377
+
378
+ exports.stringLexCompare = function (a, b) {
379
+
380
+ var aLen = a.length;
381
+ var bLen = b.length;
382
+
383
+ var i;
384
+ for (i = 0; i < aLen; i++) {
385
+ if (i === bLen) {
386
+ // b is shorter substring of a
387
+ return 1;
388
+ }
389
+ var aChar = a.charAt(i);
390
+ var bChar = b.charAt(i);
391
+ if (aChar !== bChar) {
392
+ return aChar < bChar ? -1 : 1;
393
+ }
394
+ }
395
+
396
+ if (aLen < bLen) {
397
+ // a is shorter substring of b
398
+ return -1;
399
+ }
400
+
401
+ return 0;
402
+ };
403
+
404
+ /*
405
+ * returns the decimal form for the given integer, i.e. writes
406
+ * out all the digits (in base-10) instead of using scientific notation
407
+ */
408
+ exports.intToDecimalForm = function (int) {
409
+
410
+ var isNeg = int < 0;
411
+ var result = '';
412
+
413
+ do {
414
+ var remainder = isNeg ? -Math.ceil(int % 10) : Math.floor(int % 10);
415
+
416
+ result = remainder + result;
417
+ int = isNeg ? Math.ceil(int / 10) : Math.floor(int / 10);
418
+ } while (int);
419
+
420
+
421
+ if (isNeg && result !== '0') {
422
+ result = '-' + result;
423
+ }
424
+
425
+ return result;
426
+ };
427
+ },{}]},{},[1])
428
+ (1)
429
+ });
430
+ ;