2018-09-09 17:12:50 +00:00
|
|
|
"use strict";
|
2018-11-01 14:55:45 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
// @syndicate-lang/core, an implementation of Syndicate dataspaces for JS.
|
|
|
|
// Copyright (C) 2016-2018 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
|
|
|
|
//
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2018-09-09 17:12:50 +00:00
|
|
|
// Bags and Deltas (which are Bags where item-counts can be negative).
|
|
|
|
|
2019-06-14 14:33:02 +00:00
|
|
|
if (require('preserves/src/singletonmodule.js')('syndicate-lang.org/syndicate-js',
|
|
|
|
require('../package.json').version,
|
2019-06-14 15:08:31 +00:00
|
|
|
'bag.js',
|
2019-06-14 14:33:02 +00:00
|
|
|
module)) return;
|
|
|
|
|
2018-09-09 17:12:50 +00:00
|
|
|
const Immutable = require("immutable");
|
2018-11-15 23:24:58 +00:00
|
|
|
const { fromJS } = require("preserves");
|
2018-09-09 17:12:50 +00:00
|
|
|
|
|
|
|
const PRESENT_TO_ABSENT = -1;
|
|
|
|
const ABSENT_TO_ABSENT = 0;
|
|
|
|
const ABSENT_TO_PRESENT = 1;
|
|
|
|
const PRESENT_TO_PRESENT = 2;
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
function MutableBag(s) {
|
|
|
|
this._items = s ? fromSet(s) : Immutable.Map();
|
|
|
|
}
|
|
|
|
|
2018-11-04 19:30:23 +00:00
|
|
|
MutableBag.prototype.change = function (key, delta, clamp) {
|
2018-09-09 17:12:50 +00:00
|
|
|
var net;
|
2018-11-04 19:30:23 +00:00
|
|
|
({bag: this._items, net: net} = change(this._items, key, delta, clamp));
|
2018-09-09 17:12:50 +00:00
|
|
|
return net;
|
|
|
|
};
|
|
|
|
|
|
|
|
MutableBag.prototype.get = function (key) {
|
|
|
|
return get(this._items, key);
|
|
|
|
};
|
|
|
|
|
|
|
|
MutableBag.prototype.clear = function () {
|
|
|
|
this._items = Immutable.Map();
|
|
|
|
};
|
|
|
|
|
|
|
|
MutableBag.prototype.includes = function (key) {
|
|
|
|
return includes(this._items, key);
|
|
|
|
};
|
|
|
|
|
|
|
|
MutableBag.prototype.isEmpty = function () {
|
|
|
|
return this._items.isEmpty();
|
|
|
|
};
|
|
|
|
|
|
|
|
MutableBag.prototype.count = function () {
|
|
|
|
return this._items.count();
|
|
|
|
};
|
|
|
|
|
|
|
|
MutableBag.prototype.keys = function () {
|
|
|
|
return this._items.keys();
|
|
|
|
};
|
|
|
|
|
|
|
|
MutableBag.prototype.entries = function () {
|
|
|
|
return this._items.entries();
|
|
|
|
};
|
|
|
|
|
2018-10-27 19:32:12 +00:00
|
|
|
MutableBag.prototype.snapshot = function () {
|
|
|
|
return this._items;
|
|
|
|
};
|
|
|
|
|
2018-09-09 17:12:50 +00:00
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
const Bag = Immutable.Map;
|
|
|
|
|
|
|
|
function fromSet(s) {
|
|
|
|
return Bag().withMutations(function (b) {
|
|
|
|
for (let v of Immutable.Set(s)) {
|
2018-11-15 23:24:58 +00:00
|
|
|
b = b.set(fromJS(v), 1);
|
2018-09-09 17:12:50 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function change(bag, key, delta, clamp) {
|
|
|
|
let oldCount = get(bag, key);
|
|
|
|
let newCount = oldCount + delta;
|
|
|
|
if (clamp) {
|
|
|
|
newCount = Math.max(0, newCount);
|
|
|
|
}
|
|
|
|
if (newCount === 0) {
|
|
|
|
return {
|
|
|
|
bag: bag.remove(key),
|
|
|
|
net: (oldCount === 0) ? ABSENT_TO_ABSENT : PRESENT_TO_ABSENT
|
|
|
|
};
|
|
|
|
} else {
|
|
|
|
return {
|
|
|
|
bag: bag.set(key, newCount),
|
|
|
|
net: (oldCount === 0) ? ABSENT_TO_PRESENT : PRESENT_TO_PRESENT
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function get(bag, key) {
|
|
|
|
return bag.get(key, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
function includes(bag, key) {
|
|
|
|
return get(bag, key) > 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
module.exports.PRESENT_TO_ABSENT = PRESENT_TO_ABSENT;
|
|
|
|
module.exports.ABSENT_TO_ABSENT = ABSENT_TO_ABSENT;
|
|
|
|
module.exports.ABSENT_TO_PRESENT = ABSENT_TO_PRESENT;
|
|
|
|
module.exports.PRESENT_TO_PRESENT = PRESENT_TO_PRESENT;
|
|
|
|
module.exports.MutableBag = MutableBag;
|
|
|
|
module.exports.Bag = Bag;
|
|
|
|
module.exports.fromSet = fromSet;
|
|
|
|
module.exports.change = change;
|
|
|
|
module.exports.get = get;
|
|
|
|
module.exports.includes = includes;
|