Issues (81)

src/ub.strings.find.index.js (2 issues)

1
/** global: UB */
2
3
var stringFuncs = {
4
	
5
	
6
	// primary search functions
7
	indexOf: function(search, startAt = null){
8
		return this.smartIndexOf(search, true, true, startAt);
9
	},
10
	indexOfCI: function(search, startAt = null){
11
		return this.smartIndexOf(search, false, true, startAt);
12
	},
13
	smartIndexOf: function(search, caseSensitive = true, first = true, startAt = null, substringIsLower = false, wholeWords = false){
14
		var text = this;
15
		
16
		// temps
17
		var sl = search.length;
18
		var ml = (text.length - sl);
19
		
20
		// quick checks
21
		if (ml < sl) {
22
			return -1;
23
		}
24
		
25
		// only check equality of both strings of equal length
26
		if (ml == sl) {
27
			if (caseSensitive && !wholeWords) {
28
				return (text == search) ? 0 : -1;
29
			}
30
			return text.isEqual(search, caseSensitive, false, substringIsLower) ? 0 : -1;
31
		}
32
		
33
		
34
		// default start at
35
		if (first) {
36
			if (startAt == null) {
37
				startAt = 0;
38
			}
39
		} else {
40
			if (startAt == null) {
41
				startAt = ml - sl;
42
			}
43
		}
44
		
45
		
46
		// if using whole words, slower version is used
47
		if (wholeWords) {
48
			var regex = UB.regex.New(search, wholeWords, caseSensitive, true);
49
			if (first) {
50
				var i = startAt === 0 ? text.search(regex) : text.substring(startAt).search(regex);
51
			} else {
52
				/*var i:int = startAt == (ml - sl) ? text.search(regex) : text.substring(startAt).search(regex);*/
53
				/// unsupported
54
				i = -1;
55
			}
56
			return i;
57
		}
58
		
59
		
60
		
61
		if (first) {
62
			
63
			// FIRST INDEX
64
			
65
			// CASE INSENSITIVE
66
			if (!caseSensitive) {
67
				
68
				// very fast CI comparison
69
				return text._indexOfCI(search, startAt, substringIsLower, sl, ml);
70
				
71
				// much faster than this:
72
				//return text.toUpperCase().indexOf(search.toUpperCase(), startAt);
73
			}
74
			
75
			// CASE SENSITIVE
76
			return text.indexOf(search, startAt);
77
			
78
		}
79
		
80
		
81
		// LAST INDEX
82
		
83
		// CASE INSENSITIVE
84
		if (!caseSensitive) {
85
			
86
			// very fast CI comparison
87
			return text._lastIndexOfCI(search, startAt, substringIsLower, sl);
88
			
89
			// much faster than this:
90
			//return text.toUpperCase().lastIndexOf(search.toUpperCase(), startAt);
91
		}
92
		
93
		// CASE SENSITIVE
94
		return text.lastIndexOf(search, startAt);
95
	},
96
97 View Code Duplication
	_indexOfCI: function(search, startAt, substringIsLower, sl, ml){
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
98
		var text = this;
99
100
		// init casing tables
101
		if (UB.UTF_lowerToUpper == null){
102
			UB.initCasing();
103
		}
104
		
105
		// per main char
106
		for (var m = startAt;m <= ml;m++){
107
							
108
							
109
			// per substring char
110
			var match = true;
111
			for (var s = 0;s<sl;s++){
112
				
113
				var c1 = text.charCodeAt(m + s);
114
				var c2 = search.charCodeAt(s);
115
				
116
				// CI
117
				if (c1 <= UB.UTF_casingTablesMax){ /// CI
118
					c1 = UB.UTF_upperToLower[c1];
119
				}
120
				if (!substringIsLower){
121
					if (c2 <= UB.UTF_casingTablesMax){ /// CI
122
						c2 = UB.UTF_upperToLower[c2];
123
					}
124
				}
125
				
126
				if (c1 != c2) {
127
					match = false;
128
					break;
129
				}
130
				
131
			}
132
			
133
			if (match){
134
				return m;
135
			}
136
			
137
		}
138
139
		return -1;
140
	},
141
142 View Code Duplication
	_lastIndexOfCI: function(search, startAt, substringIsLower, sl){
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
143
		var text = this;
144
		
145
		// init casing tables
146
		if (UB.UTF_lowerToUpper == null){
147
			UB.initCasing();
148
		}
149
		
150
		// per main char
151
		for (var m = startAt;m >= 0;m--){
152
			
153
			
154
			// per substring char
155
			match = true;
156
			for (var s = 0;s<sl;s++){
157
				
158
				c1 = text.charCodeAt(m + s);
159
				c2 = search.charCodeAt(s);
160
				
161
				// CI
162
				if (c1 <= UB.UTF_casingTablesMax){ /// CI
163
					c1 = UB.UTF_upperToLower[c1];
164
				}
165
				if (!substringIsLower){
166
					if (c2 <= UB.UTF_casingTablesMax){ /// CI
167
						c2 = UB.UTF_upperToLower[c2];
168
					}
169
				}
170
				
171
				if (c1 != c2) {
172
					match = false;
173
					break;
174
				}
175
				
176
			}
177
			
178
			if (match){
179
				return m;
180
			}
181
			
182
		}
183
		
184
		return -1;
185
	},
186
187
	countOf: function(find, caseSensitive = true){
188
		var text = this;
189
		
190
		// use regex method for case insensitive comparison
191
		if (!caseSensitive){
192
			var char = UB.regex.Escape(find);
193
			var flags = 'ig';
194
			return parseInt(text.match(new RegExp(char, flags)).length);
195
		}
196
		
197
		// use faster method for case sensitive comparison
198
		var count = 0;
199
		var index = 0;
200
		var len = find.length;
201
		while ((index = text.indexOf(find, index)) > -1) {
202
			count++;
203
			index += len;
204
		}
205
		return count;
206
	},
207
	
208
	/** searches for all the given terms, collects their char indexes (S.IndexOf), and returns the smallest/largest index (depending on `first`) */
209
	indexOfAny: function(searchFor, first = true, caseSensitive = true, startAt = null){
210
		var str = this;
211
212
		// index of first
213
		if (first) {
214
			return str.indexOfFirstAny(searchFor, caseSensitive, startAt);
215
		}
216
217
		// index of last
218
		if (startAt == null) {
219
			startAt = 0;
220
		}
221
		return str.indexOfLastAny(searchFor, caseSensitive, startAt);
222
	},
223
	/** searches for all the given terms, collects their char indexes (S.IndexOf), and returns the largest index */
224
	indexOfLastAny: function(searchFor, caseSensitive = true, startAt = null){
225
		var str = this;
226
		
227
		// case insensitive if wanted
228
		if (!caseSensitive){
229
			str = str.toLowerCase();
230
		}
231
		
232
		// per search term
233
		var indices = [];
234
		for (var s = 0, sl = searchFor.length;s<sl;s++){
235
			var sWord = searchFor[s];
236
			
237
			// case insensitive if wanted
238
			if (!caseSensitive){
239
				sWord = sWord.toLowerCase();
240
			}
241
			
242
			// check where found
243
			indices[s] = str.lastIndexOf(sWord, startAt);
244
		}
245
		
246
		// return last found term
247
		return indices.max();
248
	},
249
	/** searches for all the given terms, collects their char indexes (S.IndexOf), and returns the smallest index */
250
	indexOfFirstAny: function(searchFor, caseSensitive = true, startAt = 0){
251
		var str = this;
252
		
253
		// case insensitive if wanted
254
		if (!caseSensitive){
255
			str = str.toLowerCase();
256
		}
257
		
258
		// per search term
259
		var indices = [];
260
		for (var s = 0, sl = searchFor.length;s<sl;s++){
261
			var sWord = searchFor[s];
262
			
263
			// case insensitive if wanted
264
			if (!caseSensitive){
265
				sWord = sWord.toLowerCase();
266
			}
267
			
268
			// check where found
269
			indices[s] = str.indexOf(sWord, startAt);
270
			
271
			// change -1 otherwise looks like first found term
272
			if (indices[s] === -1) {
273
				indices[s] = UB.intMaxValue;
274
			}
275
		}
276
		
277
		// return first found term
278
		return indices.min();
279
	},
280
	endIndexOfLastAny: function(searchFor, caseSensitive = true){
281
		var str = this;
282
		
283
		// case insensitive if wanted
284
		if (!caseSensitive){
285
			str = str.toLowerCase();
286
		}
287
		
288
		// per search term
289
		var indices = [];
290
		for (var s = 0, sl = searchFor.length;s<sl;s++){
291
			var sWord = searchFor[s];
292
			
293
			// case insensitive if wanted
294
			if (!caseSensitive){
295
				sWord = sWord.toLowerCase();
296
			}
297
			
298
			// check where found
299
			indices[s] = str.endIndexOfLast(sWord);
300
		}
301
		
302
		// return last found term
303
		return indices.max();
304
	},
305
	endIndexOfFirstAny: function(searchFor, caseSensitive = true){
306
		var str = this;
307
		
308
		// case insensitive if wanted
309
		if (!caseSensitive){
310
			str = str.toLowerCase();
311
		}
312
		
313
		// per search term
314
		var indices = [];
315
		for (var s = 0, sl = searchFor.length;s<sl;s++){
316
			var sWord = searchFor[s];
317
			
318
			// case insensitive if wanted
319
			if (!caseSensitive){
320
				sWord = sWord.toLowerCase();
321
			}
322
			
323
			// check where found
324
			indices[s] = str.endIndexOfFirst(sWord);
325
			
326
			// change -1 otherwise looks like first found term
327
			if (indices[s] === -1) {
328
				indices[s] = UB.intMaxValue;
329
			}
330
		}
331
		
332
		// return first found term
333
		return indices.min();
334
	},
335
	endIndexOfFirst: function(find){
336
		var str = this;
337
		var pos = str.indexOf(find);
338
		if (pos === -1) return -1;
339
		return pos + find.length;
340
	},
341
	endIndexOfLast: function(find){
342
		var str = this;
343
		var pos = str.lastIndexOf(find);
344
		if (pos === -1) return -1;
345
		return pos + find.length;
346
	},
347
	indexOfNumber: function(startAt = 0, not = false, lenIfNotFound = false){
348
		var str = this;
349
		for (var c = (startAt>0?startAt:0), cl = str.length;c<cl;c++){
350
			var char = str.charAt(c);
351
			if (char.isNumber() != not) {
352
				return c;
353
			}
354
		}
355
		return lenIfNotFound ? str.length : -1;
356
	},
357
	indexOfAlphaNumeric: function(startAt = 0, not = false, lenIfNotFound = false){
358
		var str = this;
359
		for (var c = (startAt>0?startAt:0), cl = str.length;c<cl;c++){
360
			var char = str.charAt(c);
361
			if (char.isAlphaNumeric() != not) {
362
				return c;
363
			}
364
		}
365
		return lenIfNotFound ? str.length : -1;
366
	},
367
	
368
	indexOfMany: function(find, startAt = 0){
369
		var str = this;
370
		
371
		// returns the index, of the FIRST FOUND item in the string
372
		
373
		var found = -1;
374
		for (var f = 0, fl = find.length;f<fl;f++){
375
			var at = str.indexOf(find[f], startAt);
376
			if (at != -1 && (at < found || found === -1)) {
377
				found = at;
378
			}
379
		}
380
		return found;
381
	},
382
	
383
	
384
	indexOfAll: function(find, caseSensitive = true, startAt = 0, wholeWords = false){
385
		var str = this;
386
		var indices = [];
387
		
388
		var len = str.length;
389
		var c = startAt;
390
		while (c < len) {
391
			c = str.smartIndexOf(find, caseSensitive, true, c, false, wholeWords);
392
			if (c === -1) {
393
				break;
394
			}
395
			indices.push(c);
396
			c += find.length;
397
		}
398
		
399
		return indices;
400
	},
401
402
	findAll: function(find){
403
		var str = this.toString();
404
		var matches = [];
405
406
		// if regex return all matches
407
		if (find.isRegex()){
408
			do {
409
				var match = find.exec(str);
410
				if (match) {
411
					matches.push(match);
412
				}
413
			} while (match);
414
		}
415
416
		// if string find and return all matches
417
		if (find.isString()){
418
			var indices = str.indexOfAll();
419
			for (var i=0; i<indices.length; i++){
420
				var index = indices[i];
421
				var match = {startIndex:index, endIndex:index+find.length, text:find};
422
			}
423
		}
424
425
		return matches;
426
	},
427
428
	indexOfNth(search, nth, wholeWords = false, matchCase = true) {
429
		var text = this.toString();
430
431
		// quickly test if text contains wanted var
432
		if (!matchCase || text.contains(search)) {
433
434
			// create regex to find
435
			var regex = UB.regex.New(search, wholeWords, matchCase);
436
			
437
438
			// find and return index if found
439
			var match = null;
440
			for (var n = 0; n < nth; n++) {
441
				match = regex.exec(text);
442
				if (match == null || match < 0) {
443
					return -1;
444
				} else {
445
					//startAt = match + 1;
446
				}
447
			}
448
			return match == null ? -1 : match;
449
		}
450
451
		return -1;
452
	},
453
454
	
455
	none:null
456
};
457
458
// register funcs
459
UB.registerFuncs(String.prototype, stringFuncs);