delphirtl
Version:
RTL functions from Delphi
376 lines • 20.3 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Output = exports.TextFile = exports.sLineBreak = exports.TObject = void 0;
exports.hasInstanceMethod = hasInstanceMethod;
exports.hasPrototypeMethodFromConstructor = hasPrototypeMethodFromConstructor;
exports.getParamCount = getParamCount;
exports.UNUSED = UNUSED;
exports.getLauncher = getLauncher;
exports.sleep = sleep;
exports.Sleep = sleep;
exports.ParamStr = ParamStr;
exports.getParamStr = ParamStr;
exports.AssignFile = AssignFile;
exports.Assign = AssignFile;
exports.Append = Append;
exports.CloseFile = CloseFile;
exports.Close = CloseFile;
exports.Rewrite = Rewrite;
exports.Write = Write;
exports.WriteLn = WriteLn;
exports.Halt = Halt;
const assert = require("assert");
require("./dateutils"); // Import all the prototypes into delphirtl
/**
* Implements Delphi TObject semantics where you have to call .Free() to destroy the object.
* Has AfterConstruction and BeforeDestruction methods, which can be overridden.
*
* @category RTL
*/
class TObject {
constructor() {
this._isDestroyed = false;
}
/**
* performs cleanup tasks and destroys the object
*/
destroy() {
if (this._isDestroyed)
return;
this.BeforeDestruction();
// place future destruction code below
// end destruction code above
this._isDestroyed = true;
}
Destroy() { this.destroy(); }
/**
* Calls destroy to perform any cleanup tasks. Call Free() to destroy the object, so as to retain Delphi-style AfterConstruction and BeforeDestruction semantics.
*/
free() {
this.destroy();
}
/**
* Destroys the object, maintaining Delphi-style AfterConstruction and BeforeDestruction semantics.
*/
Free() {
this.free();
}
/**
* Creates a new instance of the class. To create a new constructor, declare the constructor(args) method
* and call the super constructor. Then, to instantiate the class, call YourClass.Create(args) instead of new YourClass(args),
* so as to retain Delphi-style AfterConstruction and BeforeDestruction semantics.
*
* @param args
* @constructor
*/
static Create(...args) {
const instance = new this(...args);
if (instance.AfterConstruction && typeof instance.AfterConstruction === 'function') {
instance.AfterConstruction();
}
return instance;
}
/**
* Responds after the last constructor has executed.
*
* AfterConstruction is called automatically after the object's last constructor has executed. Do not call it explicitly in your applications.
*
* The AfterConstruction method implemented in TObject does nothing. Override this method when creating a class that performs an action after the object is created.
*/
AfterConstruction() { }
/**
* Responds before the first destructor executes.
*
* BeforeDestruction is called automatically before the object's first destructor executes. Do not call it explicitly in your applications.
*
* The BeforeDestruction method implemented in TObject does nothing. Override this method when creating a class that performs an action before the object is destroyed.
*/
BeforeDestruction() { }
}
exports.TObject = TObject;
const sLineBreak = process.platform === 'win32' ? '\r\n' : '\n';
exports.sLineBreak = sLineBreak;
/**
* Gets the process arguments
*
* @returns {string[]}
* @category RTL
*/
function getProcessArgs() {
const result = process.argv.slice(1);
return result;
}
/**
* Returns true if the named method exists as a function on the constructor's prototype
* or on the given instance.
*
* This helper is useful for checking prototype-augmented methods added at runtime.
*/
function hasPrototypeMethodFromConstructor(constructorFn, name) {
if (!constructorFn || typeof constructorFn !== 'function')
return false;
return typeof constructorFn.prototype?.[name] === 'function';
}
function hasInstanceMethod(instance, name) {
if (!instance || typeof instance !== 'object')
return false;
return typeof instance[name] === 'function';
}
/**
* Returns the number of parameters passed to the app
*
* @returns {number}
* @category RTL
*/
function getParamCount() {
const processArgs = getProcessArgs();
return processArgs.length - 1;
}
/**
* Returns the index'th argument passed to the app
*
* @param {number} index
* @returns {string}
* @category RTL
*/
function ParamStr(index) {
assert(index >= 0);
const processArgs = getProcessArgs();
if (index < 0) {
return "";
}
else {
return processArgs[index];
}
}
/**
*
* @returns the launcher, ie, node.exe or something that can run Javascript...
* @category RTL
*/
function getLauncher() {
const result = process.argv[0];
return result;
}
/**
* Sleeps for the specified number of millisecs.
*
* @async
* @param {number} ms number of ms to sleep
* @returns {unknown}
* @category RTL
*/
async function sleep(ms) {
// Ensure we do not resolve earlier than requested due to timer rounding
const delay = Math.max(0, Math.ceil(ms));
return new Promise(resolve => setTimeout(resolve, delay + 1));
}
/**
* Used for ignoring any unused types, variables, so that the compiler doesn't complain.
*
* @param {...*} x any number of parameters to ignore
* @category RTL
*/
function UNUSED(...x) { }
const fs = require('fs');
class TextFile {
constructor() {
this.filename = null;
this.stream = null;
this.mode = null;
}
open(mode = "w") {
if (!this.filename)
throw new Error("Filename not assigned");
this.mode = mode;
// Treat Delphi pseudo-filenames for console specially:
if (this.filename === 'CONOUT$') {
// use process.stdout as the stream
this.stream = process.stdout;
return;
}
if (mode === "w") {
fs.writeFileSync(this.filename, ""); // truncate/create
}
else {
// mode 'a': create if not exists
if (!fs.existsSync(this.filename))
fs.writeFileSync(this.filename, "");
}
}
write(text) {
if (!this.mode)
throw new Error("File not opened");
if (this.stream) {
// process.stdout (a Writable) accepts strings
this.stream.write(text);
return;
}
if (this.mode === "w") {
fs.appendFileSync(this.filename, text);
}
else if (this.mode === "a") {
fs.appendFileSync(this.filename, text);
}
}
writelnText(text) {
this.write(text + sLineBreak);
}
close() {
if (this.stream) {
// Do not end process.stdout, otherwise, future writes in the same process will fail
if (this.stream !== process.stdout) {
this.stream.end();
}
this.stream = null;
}
this.filename = null;
this.mode = null;
}
}
exports.TextFile = TextFile;
// Delphi-style functions
/**
* Associates the name of an external file with a file class
*
* @param {TextFile} outFile
* @param {string} filename
* @returns {void}
* @category RTL
*/
function AssignFile(outFile, filename) {
if (!(outFile instanceof TextFile))
throw new TypeError('First arg must be TextFile');
outFile.filename = filename;
}
/**
* Creates a new file and opens it.
*
* @param {TextFile} outFile
* @returns {void}
* @category RTL
*/
function Rewrite(outFile) {
if (!(outFile instanceof TextFile))
throw new TypeError('RewriteFile expects a TextFile');
outFile.open('w');
}
/**
* Prepares an existing file for adding text to the end.
*
* @param {TextFile} outFile
* @returns {void}
* @category RTL
*/
function Append(outFile) {
if (!(outFile instanceof TextFile))
throw new TypeError('Append expects a TextFile');
outFile.open('a');
}
/**
* Terminates the association between a file variable and an external disk file.
*
* @param {TextFile} outFile
* @returns {void}
* @category RTL
*/
function CloseFile(outFile) {
if (!(outFile instanceof TextFile))
throw new TypeError('CloseFile expects a TextFile');
outFile.close();
}
function concatArgs(args, startIndex = 0) {
return Array.prototype.slice.call(args, startIndex).map(x => {
if (x === null || x === undefined)
return '';
return typeof x === 'object' ? JSON.stringify(x) : String(x);
}).join('');
}
/**
*
* Writes to a text file.
*
* Writeln is an extension of the Write procedure, as it is defined for text files.
*
* The syntax shown here for the Writeln procedure is illustrates that WriteLn can take a variable number of arguments.
*
* After executing Write, Writeln writes an end-of-line marker (line feed or carriage return/line feed) to the file.
*
* If F is omitted, the global variable Output is used to access the processed standard input file.
*
* @param {TextFile} outFile optional output file, otherwise uses standard output
* @param {...*} arg any number of arguments to write
* @returns {void}
* @category RTL
*/
function Write(outFile, ...arg /* args */) {
const args = arguments;
if (args.length === 0)
return;
const first = args[0];
if (first instanceof TextFile) {
const text = concatArgs(args, 1);
if (text.length)
first.write(text);
}
else {
const text = concatArgs(args, 0);
process.stdout.write(text);
}
}
/**
*
* Writes to a text file and adds an end-of-line marker.
*
* Writeln is an extension of the Write procedure, as it is defined for text files.
*
* The syntax shown here for the Writeln procedure is illustrates that WriteLn can take a variable number of arguments.
*
* After executing Write, Writeln writes an end-of-line marker (line feed or carriage return/line feed) to the file.
*
* If F is omitted, the global variable Output is used to access the processed standard input file.
*
* @param {TextFile} outFile optional output file, otherwise uses standard output
* @param {...*} arg any number of arguments to write
* @returns {void}
* @category RTL
*/
function WriteLn(outFile, ...arg /* args */) {
const args = arguments;
if (args.length > 0 && args[0] instanceof TextFile) {
// Pass OutputFile + all args + newline as one string to Write
const file = args[0];
const text = concatArgs(args, 1) + sLineBreak;
Write(file, text);
}
else {
const text = concatArgs(args, 0) + sLineBreak;
Write(text);
}
}
/*
* Halts the program with the given code and returns control to the operating system.
*
* @returns {void}
* @category RTL
*/
function Halt(code) {
process.exit(code);
}
/*
* Specifies a write-only text file associated with the process's standard output file.
* @category RTL
*/
const Output = new TextFile();
exports.Output = Output;
AssignFile(Output, 'CONOUT$');
Rewrite(Output);
// Define ParamCount, and this is a run-time definition
Object.defineProperty(exports, 'ParamCount', {
get() {
const processArgs = getProcessArgs();
return processArgs.length - 1;
},
enumerable: true
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnRsLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3J0bC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFpWkksOENBQWlCO0FBQUUsOEVBQWlDO0FBQ3BELHNDQUFhO0FBRWIsd0JBQU07QUFBRSxrQ0FBVztBQUduQixzQkFBSztBQUFXLHNCQUFLO0FBQ3JCLDRCQUFRO0FBQWMsK0JBQVc7QUFDdkIsZ0NBQVU7QUFBZ0IsNEJBQU07QUFBRSx3QkFBTTtBQUNsRCw4QkFBUztBQUFlLDBCQUFLO0FBQVUsMEJBQU87QUFDOUMsc0JBQUs7QUFBRSwwQkFBTztBQUFFLG9CQUFJO0FBM1p4QixpQ0FBa0M7QUFDbEMsdUJBQXFCLENBQUMsMkNBQTJDO0FBRWpFOzs7OztHQUtHO0FBQ0gsTUFBTSxPQUFPO0lBQWI7UUFFWSxpQkFBWSxHQUFZLEtBQUssQ0FBQztJQWdFMUMsQ0FBQztJQTlERzs7T0FFRztJQUNJLE9BQU87UUFDVixJQUFJLElBQUksQ0FBQyxZQUFZO1lBQUUsT0FBTztRQUM5QixJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztRQUN6QixzQ0FBc0M7UUFFdEMsNkJBQTZCO1FBQzdCLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDO0lBQzdCLENBQUM7SUFDTSxPQUFPLEtBQVcsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQztJQUUxQzs7T0FFRztJQUNJLElBQUk7UUFDUCxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDbkIsQ0FBQztJQUVEOztPQUVHO0lBQ0ksSUFBSTtRQUNQLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUNoQixDQUFDO0lBRUQ7Ozs7Ozs7T0FPRztJQUNILE1BQU0sQ0FBQyxNQUFNLENBQXFELEdBQUcsSUFBVztRQUM1RSxNQUFNLFFBQVEsR0FBRyxJQUFJLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDO1FBRW5DLElBQUksUUFBUSxDQUFDLGlCQUFpQixJQUFJLE9B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