UNPKG

@abaplint/runtime

Version:
201 lines • 6.69 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Structure = void 0; const field_symbol_1 = require("./field_symbol"); const table_1 = require("./table"); const _parse_1 = require("../operators/_parse"); const character_1 = require("./character"); const throw_error_1 = require("../throw_error"); const abap_object_1 = require("./abap_object"); // structures are typically instantiated repeatedly with the same literal names, // cache the uppercasing const upperCaseCache = new Map(); function cachedUpperCase(name) { let upper = upperCaseCache.get(name); if (upper === undefined) { upper = name.toUpperCase(); upperCaseCache.set(name, upper); } return upper; } class Structure { value; qualifiedName; ddicName; suffix; asInclude; // "cloning = true" is only used from clone(), the names are then already uppercased constructor(fields, qualifiedName, ddicName, suffix, asInclude, cloning = false) { this.value = fields; if (cloning === true) { this.qualifiedName = qualifiedName; this.ddicName = ddicName; } else { this.qualifiedName = qualifiedName === undefined ? undefined : cachedUpperCase(qualifiedName); this.ddicName = ddicName === undefined ? undefined : cachedUpperCase(ddicName); } this.suffix = suffix; this.asInclude = asInclude; if (asInclude !== undefined) { this.linkGroupFields(); } } linkGroupFields() { for (const as of Object.keys(this.asInclude || {})) { const suffix = this.suffix?.[as] || ""; for (const fieldName of Object.keys(this.value[as].get())) { this.value[fieldName + suffix] = this.value[as].get()[fieldName]; } } } clone() { const newValues = {}; for (const key in this.value) { newValues[key] = this.value[key].clone(); } // note: when includes are present, the constructor re-links the group // fields so they alias the cloned include's fields const n = new Structure(newValues, this.qualifiedName, this.ddicName, this.suffix, this.asInclude, true); return n; } clear() { for (const f in this.value) { this.value[f].clear(); } return this; } getDDICName() { return this.ddicName; } getRenamingSuffix() { return this.suffix; } getAsInclude() { return this.asInclude; } getQualifiedName() { return this.qualifiedName; } setField(name, value) { if (name.includes("->") || name.includes("=>")) { throw new Error("transpiler, structure setField todo, " + name); } if (name.includes("-")) { // hmm, todo const [base, field] = name.split("-"); if (field.includes("-")) { throw new Error("transpiler, structure setField todo"); } this.value[base].setField(field, value); } else { if (this.value[name] === undefined) { throw new Error("Structure, setField, field not found: " + name); } this.value[name].set(value); } return this; } set(input) { if (input === undefined) { return; } if (input instanceof field_symbol_1.FieldSymbol) { this.set(input.getPointer()); } else if (input instanceof table_1.Table) { throw new Error("Structure, input is a table"); } else if (input instanceof Structure) { if (input === this) { return this; } const obj = input.get(); const keys1 = Object.keys(obj); const keys2 = Object.keys(this.value); for (let i = 0; i < keys1.length; i++) { const key1 = keys1[i]; const key2 = keys2[i]; if (this.value[key2] === undefined) { break; } const val = obj[key1]; if (val instanceof Structure || val instanceof table_1.Table || val instanceof table_1.HashedTable) { // deep types are cloned so the target never shares references with the source this.value[key2].set(val.clone()); } else { // elementary types copy by value in set(), no clone needed this.value[key2].set(val); } } } else { this.setCharacter(input); } return this; } setCharacter(input) { this.clear(); let val = input; if (typeof val !== "string") { val = val.get() + ""; } for (const key of Object.keys(this.value)) { const targetLength = this.value[key].getLength(); this.value[key].set(val.substr(0, targetLength)); val = val.substr(targetLength); } } get() { return this.value; } getCharacter(allowObject = false) { let val = ""; for (const v in this.value) { const foo = this.value[v]; if (foo instanceof Structure) { val += foo.getCharacter(allowObject); } else if (foo instanceof abap_object_1.ABAPObject) { if (allowObject === false) { throw new Error("Structure getCharacter: unexpected ABAPObject"); } val += foo.getInternalID(); } else { val += foo.get(); } } return val; } getOffset(input) { let offset = input?.offset; if (offset) { offset = (0, _parse_1.parse)(offset); } let length = input?.length; if (length) { length = (0, _parse_1.parse)(length); } const val = this.getCharacter(); if ((offset && offset >= val.length) || (offset && offset < 0) || (length && length < 0)) { (0, throw_error_1.throwError)("CX_SY_RANGE_OUT_OF_BOUNDS"); } let ret = val; if (offset) { ret = ret.substr(offset); } if (length !== undefined) { ret = ret.substr(0, length); } const r = new character_1.Character(ret.length); r.set(ret); return r; } } exports.Structure = Structure; //# sourceMappingURL=structure.js.map