Skip to content

Commit 4a0affc

Browse files
🚧 progress: First draft.
1 parent abe277c commit 4a0affc

File tree

10 files changed

+10207
-7
lines changed

10 files changed

+10207
-7
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
"@babel/preset-env": "7.14.0",
6666
"@babel/register": "7.13.16",
6767
"@commitlint/cli": "12.1.1",
68+
"@iterable-iterator/map": "^0.1.0",
6869
"@js-library/commitlint-config": "0.0.4",
6970
"ava": "3.15.0",
7071
"babel-plugin-transform-remove-console": "6.9.4",

src/Hit.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export default class Hit {
2+
constructor(si, pattern, pi) {
3+
this.si = si;
4+
this.p = pattern;
5+
this.pi = pi;
6+
}
7+
}

src/StringSlice.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export default class StringSlice {
2+
constructor(s, i, j) {
3+
this.s = s;
4+
this.i = i;
5+
this.j = j;
6+
}
7+
}

src/data.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
const data = [
2+
{
3+
string: 'abcd',
4+
patterns: [
5+
{
6+
pattern: 'abcde',
7+
hits: [],
8+
},
9+
{
10+
pattern: 'abcd',
11+
hits: [0],
12+
},
13+
{
14+
pattern: 'bc',
15+
hits: [1],
16+
},
17+
],
18+
},
19+
{
20+
string: 'abcdbdbc',
21+
patterns: [
22+
{
23+
pattern: 'bc',
24+
hits: [1, 6],
25+
},
26+
],
27+
},
28+
{
29+
string: 'abcdbdbcazertyuiopqsdfghjklmwxcvbn',
30+
patterns: [
31+
{
32+
pattern: 'bc',
33+
hits: [1, 6],
34+
},
35+
],
36+
},
37+
];
38+
39+
export default data;

src/index.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
1-
const answer = 42;
2-
export default answer;
1+
export {default as Hit} from './Hit.js';
2+
export {default as StringSlice} from './StringSlice.js';
3+
export {default as data} from './data.js';
4+
export {default as mock} from './mock.js';
5+
export {default as single} from './single.js';

src/mock.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import assert from 'assert';
2+
import StringSlice from './StringSlice.js';
3+
import Hit from './Hit.js';
4+
5+
/**
6+
* A brute-force string searching algorithm leveraging String#indexOf.
7+
*
8+
* @param {StringSlice} string
9+
* @param {Iterable<StringSlice>} patterns
10+
* @return {IterableIterator<Hit>}
11+
*/
12+
export default function* mock(string, patterns) {
13+
assert(string instanceof StringSlice);
14+
const s = string.s.slice(string.i, string.j);
15+
for (const pattern of patterns) {
16+
assert(pattern instanceof StringSlice);
17+
const p = pattern.s.slice(pattern.i, pattern.j);
18+
let fromIndex = 0;
19+
while (true) {
20+
const i = s.indexOf(p, fromIndex);
21+
if (i === -1) break;
22+
yield new Hit(i, pattern, pattern.i);
23+
fromIndex = i + 1;
24+
}
25+
}
26+
}

src/single.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
const single = ({test, algorithms, data}) => {
2+
for (const algorithm of algorithms) {
3+
for (const {string, patterns} of data) {
4+
for (const {pattern, hits} of patterns) {
5+
test(macro, algorithm, string, pattern, hits);
6+
}
7+
}
8+
}
9+
};
10+
11+
export default single;
12+
13+
const macro = (t, algorithm, s, p, hits) => {
14+
const name = algorithm.name;
15+
16+
const si = 0;
17+
const sj = s.length;
18+
const pi = 0;
19+
const pj = p.length;
20+
21+
let k = 0;
22+
for (const i of algorithm(s, si, sj, p, pi, pj)) {
23+
if (k < hits.length) {
24+
t.is(i, hits[k], `${name} > begin of '${p}' in '${s}'`);
25+
++k;
26+
} else {
27+
++k;
28+
t.fail(
29+
`"${name} > (${i}) callback called ${k} times for '${p}' in '${s}'`,
30+
);
31+
}
32+
}
33+
34+
t.is(k, hits.length, `${name} > check number of hits for '${p}' in '${s}'`);
35+
};
36+
37+
macro.title = (title, algorithm, string, pattern, hits) =>
38+
title ??
39+
`${algorithm.name}('${string}', '${pattern}') hits ${JSON.stringify(hits)}`;

test/src/api.js

Lines changed: 0 additions & 5 deletions
This file was deleted.

test/src/single.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import test from 'ava';
2+
3+
import {map} from '@iterable-iterator/map';
4+
5+
import {mock, single, data, StringSlice} from '../../src/index.js';
6+
7+
const mockedSingle = (s, si, sj, p, pi, pj) =>
8+
map(
9+
(hit) => hit.si,
10+
mock(new StringSlice(s, si, sj), [new StringSlice(p, pi, pj)]),
11+
);
12+
13+
single({
14+
test,
15+
algorithms: [mockedSingle],
16+
data,
17+
});

0 commit comments

Comments
 (0)