diff --git a/src/enum.js b/src/enum.js index 9eaec4ea5..59a6ef7f0 100644 --- a/src/enum.js +++ b/src/enum.js @@ -5,7 +5,8 @@ module.exports = Enum; var ReflectionObject = require("./object"); ((Enum.prototype = Object.create(ReflectionObject.prototype)).constructor = Enum).className = "Enum"; -var util = require("./util"); +var Namespace = require("./namespace"), + util = require("./util"); /** * Constructs a new enum instance. @@ -84,7 +85,7 @@ Enum.prototype.toJSON = function toJSON() { return util.toObject([ "options" , this.options, "values" , this.values, - "reserved" , this.reserved + "reserved" , this.reserved && this.reserved.length ? this.reserved : undefined ]); }; @@ -97,7 +98,7 @@ Enum.prototype.toJSON = function toJSON() { * @throws {TypeError} If arguments are invalid * @throws {Error} If there is already a value with this name or id */ -Enum.prototype.add = function(name, id, comment) { +Enum.prototype.add = function add(name, id, comment) { // utilized by the parser but not by .fromJSON if (!util.isString(name)) @@ -107,11 +108,17 @@ Enum.prototype.add = function(name, id, comment) { throw TypeError("id must be an integer"); if (this.values[name] !== undefined) - throw Error("duplicate name"); + throw Error("duplicate name '" + name + "' in " + this); + + if (this.isReservedId(id)) + throw Error("id " + id + " is reserved in " + this); + + if (this.isReservedName(name)) + throw Error("name '" + name + "' is reserved in " + this); if (this.valuesById[id] !== undefined) { if (!(this.options && this.options.allow_alias)) - throw Error("duplicate id"); + throw Error("duplicate id " + id + " in " + this); this.values[name] = id; } else this.valuesById[this.values[name] = id] = name; @@ -127,14 +134,14 @@ Enum.prototype.add = function(name, id, comment) { * @throws {TypeError} If arguments are invalid * @throws {Error} If `name` is not a name of this enum */ -Enum.prototype.remove = function(name) { +Enum.prototype.remove = function remove(name) { if (!util.isString(name)) throw TypeError("name must be a string"); var val = this.values[name]; - if (val === undefined) - throw Error("name does not exist"); + if (val == null) + throw Error("name '" + name + "' does not exist in " + this); delete this.valuesById[val]; delete this.values[name]; @@ -142,3 +149,21 @@ Enum.prototype.remove = function(name) { return this; }; + +/** + * Tests if the specified id is reserved. + * @param {number} id Id to test + * @returns {boolean} `true` if reserved, otherwise `false` + */ +Enum.prototype.isReservedId = function isReservedId(id) { + return Namespace.isReservedId(this.reserved, id); +}; + +/** + * Tests if the specified name is reserved. + * @param {string} name Name to test + * @returns {boolean} `true` if reserved, otherwise `false` + */ +Enum.prototype.isReservedName = function isReservedName(name) { + return Namespace.isReservedName(this.reserved, name); +}; diff --git a/src/namespace.js b/src/namespace.js index 7d6bd6d1c..ff96aada1 100644 --- a/src/namespace.js +++ b/src/namespace.js @@ -52,6 +52,34 @@ function arrayToJSON(array) { Namespace.arrayToJSON = arrayToJSON; +/** + * Tests if the specified id is reserved. + * @param {Array.|undefined} reserved Array of reserved ranges and names + * @param {number} id Id to test + * @returns {boolean} `true` if reserved, otherwise `false` + */ +Namespace.isReservedId = function isReservedId(reserved, id) { + if (reserved) + for (var i = 0; i < reserved.length; ++i) + if (typeof reserved[i] !== "string" && reserved[i][0] <= id && reserved[i][1] >= id) + return true; + return false; +}; + +/** + * Tests if the specified name is reserved. + * @param {Array.|undefined} reserved Array of reserved ranges and names + * @param {string} name Name to test + * @returns {boolean} `true` if reserved, otherwise `false` + */ +Namespace.isReservedName = function isReservedName(reserved, name) { + if (reserved) + for (var i = 0; i < reserved.length; ++i) + if (reserved[i] === name) + return true; + return false; +}; + /** * Not an actual constructor. Use {@link Namespace} instead. * @classdesc Base class of all reflection objects containing nested objects. This is not an actual class but here for the sake of having consistent type definitions. diff --git a/src/type.js b/src/type.js index cc61a03ad..e22b65113 100644 --- a/src/type.js +++ b/src/type.js @@ -395,11 +395,7 @@ Type.prototype.remove = function remove(object) { * @returns {boolean} `true` if reserved, otherwise `false` */ Type.prototype.isReservedId = function isReservedId(id) { - if (this.reserved) - for (var i = 0; i < this.reserved.length; ++i) - if (typeof this.reserved[i] !== "string" && this.reserved[i][0] <= id && this.reserved[i][1] >= id) - return true; - return false; + return Namespace.isReservedId(this.reserved, id); }; /** @@ -408,11 +404,7 @@ Type.prototype.isReservedId = function isReservedId(id) { * @returns {boolean} `true` if reserved, otherwise `false` */ Type.prototype.isReservedName = function isReservedName(name) { - if (this.reserved) - for (var i = 0; i < this.reserved.length; ++i) - if (this.reserved[i] === name) - return true; - return false; + return Namespace.isReservedName(this.reserved, name); }; /**