/* Constructs a new Dict object. * * 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.). * * 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() * */ function Dict(opts) { this._items = {}; this._opts = _.extend({}, {fold_case: false}, opts); } /* Constructs a new Dict object from another object. * * 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. */ Dict.from = function Dict_from(obj, opts) { if (typeof obj !== "object" || obj === null) { throw new TypeError("Cannot convert argument to Dict"); } var ret = new Dict(opts); _.each(obj, function (val, key) { ret.set(key, val); }); return ret; }; /* 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) { if (! (xs instanceof Array)) { throw new TypeError("Argument is not an array"); } var ret = new Dict(opts); _.each(xs, function (x) { ret.set(x, true); }); return ret; }; (function () { Dict.prototype = { _munge: function Dict__munge(k) { if (k === undefined) { blueslip.error("Tried to call a Dict method with an undefined key."); return undefined; } if (this._opts.fold_case) { k = k.toLowerCase(); } return ':' + k; }, clone: function Dict_clone() { var ret = new Dict(this._opts); ret._items = _.clone(this._items); return ret; }, get: function Dict_get(key) { var mapping = this._items[this._munge(key)]; if (mapping === undefined) { return undefined; } return mapping.v; }, set: function Dict_set(key, value) { this._items[this._munge(key)] = {k: key, v: value}; return value; }, // 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; }, has: function Dict_has(key) { return _.has(this._items, this._munge(key)); }, del: function Dict_del(key) { return delete this._items[this._munge(key)]; }, keys: function Dict_keys() { return _.pluck(_.values(this._items), 'k'); }, values: function Dict_values() { return _.pluck(_.values(this._items), 'v'); }, items: function Dict_items() { return _.map(_.values(this._items), function (mapping) { return [mapping.k, mapping.v]; }); }, num_items: function Dict_num_items() { return _.keys(this._items).length; }, is_empty: function Dict_is_empty() { return _.isEmpty(this._items); }, // Iterates through the Dict calling f(value, key) for each (key, value) pair in the Dict each: function Dict_each(f) { return _.each(this._items, function (mapping) { f(mapping.v, mapping.k); }); }, clear: function Dict_clear() { this._items = {}; }, }; }()); if (typeof module !== 'undefined') { module.exports = Dict; }