-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
179 additions
and
156 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
const BackingStoreKey = 'backingStore'; | ||
const ChunkWidthKey = 'chunkWidth'; | ||
const KeyPrefixKey = 'keyPrefix'; | ||
|
||
module.exports = { | ||
BackingStoreKey, | ||
ChunkWidthKey, | ||
KeyPrefixKey | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
const { | ||
BackingStoreKey, | ||
ChunkWidthKey, | ||
KeyPrefixKey | ||
} = require('./constants'); | ||
|
||
module.exports = class { | ||
constructor(parentFacade) { | ||
this.parent = parentFacade; | ||
} | ||
|
||
chunkCoords(x, y) { | ||
const cWidth = this.parent[ChunkWidthKey]; | ||
return [Math.floor(Number(x) / cWidth), Math.floor(Number(y) / cWidth)]; | ||
} | ||
|
||
bitPosition(chunkXY, x, y) { | ||
const cWidth = this.parent[ChunkWidthKey]; | ||
return (Number(x) - (chunkXY[0] * cWidth)) + ((Number(y) - (chunkXY[1] * cWidth)) * cWidth); | ||
} | ||
|
||
key(bmType, cX, cY) { | ||
return `${this.parent[KeyPrefixKey]}:${bmType}:${cX}:${cY}`; | ||
} | ||
|
||
async getSet(bmType, x, y, setVal = undefined) { | ||
const chunk = this.chunkCoords(x, y); | ||
const bitPos = this.bitPosition(chunk, x, y); | ||
const [cX, cY] = chunk; | ||
|
||
if (setVal === undefined) { | ||
return this.parent[BackingStoreKey].getbit(this.key(bmType, cX, cY), bitPos); | ||
} else { | ||
return this.parent[BackingStoreKey].setbit(this.key(bmType, cX, cY), bitPos, setVal == true ? 1 : 0); | ||
} | ||
} | ||
|
||
async allSetInBounds(bmType, fromX, fromY, toX, toY, strict = false) { | ||
const rowWidth = this.parent[ChunkWidthKey]; | ||
const [fcX, fcY] = this.chunkCoords(fromX, fromY); | ||
const [tcX, tcY] = this.chunkCoords(toX, toY); | ||
|
||
let retList = []; | ||
let bufferGetter = async (bgX, bgY) => this.parent[BackingStoreKey].getBuffer(this.key(bmType, bgX, bgY)); | ||
|
||
if (this.parent.isPipelineCapable) { | ||
const plBuffer = {}; | ||
|
||
bufferGetter = async (bgX, bgY) => { | ||
if (bgX in plBuffer) { | ||
if (bgY in plBuffer[bgX]) { | ||
return plBuffer[bgX][bgY]; | ||
} | ||
} | ||
}; | ||
|
||
const pipeline = this.parent[BackingStoreKey].pipeline(); | ||
for (let wcX = fcX; wcX <= tcX; wcX++) { | ||
if (!(wcX in plBuffer)) { | ||
plBuffer[wcX] = {}; | ||
} | ||
|
||
for (let wcY = fcY; wcY <= tcY; wcY++) { | ||
pipeline.getBuffer(this.key(bmType, wcX, wcY), function (err, result) { | ||
if (err) { | ||
throw new Error(`pipeline.getBuffer: shouldn't happen! ${err}`); | ||
} | ||
|
||
plBuffer[wcX][wcY] = result; | ||
}); | ||
} | ||
} | ||
|
||
await pipeline.exec(); | ||
bufferGetter = async (bgX, bgY) => plBuffer[bgX][bgY]; | ||
} | ||
|
||
for (let wcX = fcX; wcX <= tcX; wcX++) { | ||
for (let wcY = fcY; wcY <= tcY; wcY++) { | ||
const chunkBytes = await bufferGetter(wcX, wcY); | ||
|
||
if (!chunkBytes || chunkBytes.length < 1) { | ||
continue; | ||
} | ||
|
||
for (let cByte = 0; cByte < chunkBytes.length; cByte++) { | ||
for (let bit = 0; bit < 8; bit++) { | ||
if (chunkBytes[cByte] & (1 << bit)) { | ||
let ix = (wcX * rowWidth) + (7 - bit) + ((cByte % (rowWidth / 8)) * 8); | ||
let iy = ((((7 - bit) + (cByte * 8)) - ix + (wcX * rowWidth)) / rowWidth) + (wcY * rowWidth); | ||
retList.push([ix, iy]); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
// strict includes *only* coordinates within the specified bounding box, otherwise all coordinates | ||
// within the *chunks* intersected by the specified bounding box are returned | ||
if (strict) { | ||
retList = retList.filter(x => x[0] >= fromX && x[1] >= fromY && x[0] <= toX && x[1] <= toY); | ||
} | ||
|
||
return retList; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
// a very simple, unoptimized store provided as an example implementation & last-chance default | ||
module.exports = class { | ||
constructor() { | ||
this.store = {}; | ||
} | ||
|
||
getbit(key, bitPosition) { | ||
if (key in this.store) { | ||
const byteIdx = Math.floor(bitPosition / 8); | ||
const innerPos = (bitPosition % 8); | ||
const bitMask = 0x80 >> innerPos; | ||
if (byteIdx in this.store[key]) { | ||
return (this.store[key][byteIdx] & bitMask) >> (7 - innerPos); | ||
} | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
setbit(key, bitPosition, value) { | ||
if (!(key in this.store)) { | ||
this.store[key] = []; | ||
} | ||
|
||
const byteIdx = Math.floor(bitPosition / 8); | ||
const bitMask = 0x80 >> (bitPosition % 8); | ||
|
||
// lazily initialize everything up to and including byteIdx, if it isn't already initialized | ||
if (!(byteIdx in this.store[key])) { | ||
for (let bi = 0; bi <= byteIdx; bi++) { | ||
if (!(bi in this.store[key])) { | ||
this.store[key][bi] = 0; | ||
} | ||
} | ||
} | ||
|
||
if (value == true) { | ||
this.store[key][byteIdx] |= bitMask; | ||
} else { | ||
this.store[key][byteIdx] &= ~bitMask; | ||
} | ||
} | ||
|
||
getBuffer(key) { | ||
if (!(key in this.store)) { | ||
this.store[key] = []; | ||
} | ||
|
||
return Buffer.from(this.store[key]); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
const InMemoryStore = require('./in-memory'); | ||
|
||
module.exports = { | ||
InMemoryStore | ||
} |