2013-08-07 22:28:45 +02:00
|
|
|
/* Constructs a new Dict object.
|
2018-02-05 19:16:09 +01:00
|
|
|
*
|
|
|
|
* This module primarily exists to support the fold_case option,
|
|
|
|
* because so many string keys in Zulip are case-insensitive (emails,
|
|
|
|
* stream names, topics, etc.).
|
2013-08-07 22:28:45 +02:00
|
|
|
*
|
2013-08-19 20:58:31 +02:00
|
|
|
* Dict(opt) -> the new Dict will be empty
|
|
|
|
*
|
|
|
|
* Available options:
|
|
|
|
* fold_case - Make has() and get() case-insensitive. keys() and
|
|
|
|
* other methods that implicitly return keys return the
|
|
|
|
* casing used for the most recent set()
|
|
|
|
*
|
2013-08-07 22:28:45 +02:00
|
|
|
*/
|
2013-08-19 20:58:31 +02:00
|
|
|
function Dict(opts) {
|
2013-08-07 22:28:45 +02:00
|
|
|
this._items = {};
|
2013-08-19 20:58:31 +02:00
|
|
|
this._opts = _.extend({}, {fold_case: false}, opts);
|
2013-08-19 20:46:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Constructs a new Dict object from another object.
|
|
|
|
*
|
2013-08-19 20:58:31 +02:00
|
|
|
* Dict.from(jsobj, opts) -> create a Dict with keys corresponding to the
|
|
|
|
* properties of jsobj and values corresponding to
|
|
|
|
* the value of the appropriate property. `opts` is
|
|
|
|
* passed to the Dict constructor.
|
2013-08-19 20:46:27 +02:00
|
|
|
*/
|
2013-08-19 20:58:31 +02:00
|
|
|
Dict.from = function Dict_from(obj, opts) {
|
2013-08-20 21:32:55 +02:00
|
|
|
if (typeof obj !== "object" || obj === null) {
|
2013-08-19 20:46:27 +02:00
|
|
|
throw new TypeError("Cannot convert argument to Dict");
|
2013-08-07 22:28:45 +02:00
|
|
|
}
|
2013-08-19 20:46:27 +02:00
|
|
|
|
2013-08-20 21:32:55 +02:00
|
|
|
var ret = new Dict(opts);
|
|
|
|
_.each(obj, function (val, key) {
|
|
|
|
ret.set(key, val);
|
|
|
|
});
|
2013-08-19 20:46:27 +02:00
|
|
|
return ret;
|
|
|
|
};
|
2013-08-07 22:28:45 +02:00
|
|
|
|
2013-09-07 02:44:42 +02:00
|
|
|
/* Like above, but constructs a Dict object from an array, setting the value of
|
|
|
|
* each element to `true`. Intended for use as a set. As above, `opts` is
|
|
|
|
* passed to the Dict constructor.
|
|
|
|
*/
|
|
|
|
Dict.from_array = function Dict_from_array(xs, opts) {
|
2018-06-04 21:09:11 +02:00
|
|
|
if (!(xs instanceof Array)) {
|
2013-09-07 02:44:42 +02:00
|
|
|
throw new TypeError("Argument is not an array");
|
|
|
|
}
|
|
|
|
|
|
|
|
var ret = new Dict(opts);
|
|
|
|
_.each(xs, function (x) {
|
|
|
|
ret.set(x, true);
|
|
|
|
});
|
|
|
|
return ret;
|
|
|
|
};
|
|
|
|
|
2013-08-07 22:28:45 +02:00
|
|
|
(function () {
|
2013-08-28 18:29:11 +02:00
|
|
|
Dict.prototype = {
|
2013-08-19 20:58:31 +02:00
|
|
|
_munge: function Dict__munge(k) {
|
2013-09-10 23:06:56 +02:00
|
|
|
if (k === undefined) {
|
2013-09-10 23:33:46 +02:00
|
|
|
blueslip.error("Tried to call a Dict method with an undefined key.");
|
2018-03-13 13:04:16 +01:00
|
|
|
return;
|
2013-09-10 23:06:56 +02:00
|
|
|
}
|
2013-08-19 20:58:31 +02:00
|
|
|
if (this._opts.fold_case) {
|
|
|
|
k = k.toLowerCase();
|
|
|
|
}
|
|
|
|
return ':' + k;
|
|
|
|
},
|
|
|
|
|
2013-08-20 21:32:55 +02:00
|
|
|
clone: function Dict_clone() {
|
|
|
|
var ret = new Dict(this._opts);
|
|
|
|
ret._items = _.clone(this._items);
|
|
|
|
return ret;
|
|
|
|
},
|
|
|
|
|
2013-08-07 22:28:45 +02:00
|
|
|
get: function Dict_get(key) {
|
2013-08-19 20:58:31 +02:00
|
|
|
var mapping = this._items[this._munge(key)];
|
2013-08-19 20:33:18 +02:00
|
|
|
if (mapping === undefined) {
|
2018-03-13 13:04:16 +01:00
|
|
|
return;
|
2013-08-19 20:33:18 +02:00
|
|
|
}
|
|
|
|
return mapping.v;
|
2013-08-07 22:28:45 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
set: function Dict_set(key, value) {
|
2013-08-20 22:34:36 +02:00
|
|
|
this._items[this._munge(key)] = {k: key, v: value};
|
|
|
|
return value;
|
2013-08-07 22:28:45 +02:00
|
|
|
},
|
|
|
|
|
2013-08-20 22:48:07 +02:00
|
|
|
// If `key` exists in the Dict, return its value. Otherwise
|
|
|
|
// insert `key` with a value of `value` and return `value`.
|
|
|
|
setdefault: function Dict_setdefault(key, value) {
|
|
|
|
var mapping = this._items[this._munge(key)];
|
|
|
|
if (mapping === undefined) {
|
|
|
|
return this.set(key, value);
|
|
|
|
}
|
|
|
|
return mapping.v;
|
|
|
|
},
|
|
|
|
|
2013-08-07 22:28:45 +02:00
|
|
|
has: function Dict_has(key) {
|
2013-08-19 20:58:31 +02:00
|
|
|
return _.has(this._items, this._munge(key));
|
2013-08-07 22:28:45 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
del: function Dict_del(key) {
|
2013-08-19 20:58:31 +02:00
|
|
|
return delete this._items[this._munge(key)];
|
2013-08-07 22:28:45 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
keys: function Dict_keys() {
|
2013-08-19 20:33:18 +02:00
|
|
|
return _.pluck(_.values(this._items), 'k');
|
2013-08-07 22:28:45 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
values: function Dict_values() {
|
2013-08-19 20:33:18 +02:00
|
|
|
return _.pluck(_.values(this._items), 'v');
|
2013-08-07 22:28:45 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
items: function Dict_items() {
|
2013-08-19 20:33:18 +02:00
|
|
|
return _.map(_.values(this._items), function (mapping) {
|
|
|
|
return [mapping.k, mapping.v];
|
2013-08-07 22:28:45 +02:00
|
|
|
});
|
2013-08-14 19:08:03 +02:00
|
|
|
},
|
|
|
|
|
2013-08-23 02:54:47 +02:00
|
|
|
num_items: function Dict_num_items() {
|
|
|
|
return _.keys(this._items).length;
|
|
|
|
},
|
|
|
|
|
2017-04-21 18:05:50 +02:00
|
|
|
is_empty: function Dict_is_empty() {
|
|
|
|
return _.isEmpty(this._items);
|
|
|
|
},
|
|
|
|
|
2013-08-14 19:08:03 +02:00
|
|
|
// Iterates through the Dict calling f(value, key) for each (key, value) pair in the Dict
|
|
|
|
each: function Dict_each(f) {
|
2013-08-19 20:33:18 +02:00
|
|
|
return _.each(this._items, function (mapping) {
|
|
|
|
f(mapping.v, mapping.k);
|
2013-08-14 19:08:03 +02:00
|
|
|
});
|
2017-01-12 00:17:43 +01:00
|
|
|
},
|
2017-04-07 00:37:32 +02:00
|
|
|
|
|
|
|
clear: function Dict_clear() {
|
|
|
|
this._items = {};
|
|
|
|
},
|
2013-08-28 18:29:11 +02:00
|
|
|
};
|
2013-08-07 22:28:45 +02:00
|
|
|
|
|
|
|
}());
|
|
|
|
|
|
|
|
if (typeof module !== 'undefined') {
|
|
|
|
module.exports = Dict;
|
|
|
|
}
|