mirror of
https://github.com/BorysLevytskyi/BitwiseCmd.git
synced 2025-12-09 22:42:07 +01:00
Better support for 64 bit numbers (#44)
This commit is contained in:
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@@ -4,7 +4,7 @@
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
{
|
||||
"type": "pwa-chrome",
|
||||
"request": "launch",
|
||||
"name": "Launch Chrome against localhost",
|
||||
|
||||
@@ -1,26 +1,29 @@
|
||||
import calc from './calc';
|
||||
import { BitwiseOperationExpression, ScalarOperand, ExpressionOperand } from '../expression/expression';
|
||||
import { BitwiseOperationExpression, ScalarExpression, OperatorExpression } from '../expression/expression';
|
||||
import exp from 'constants';
|
||||
import { INT_MAX_VALUE } from './const';
|
||||
|
||||
describe("calc", () => {
|
||||
it('calculates number of bits', () => {
|
||||
expect(calc.numberOfBits(1)).toBe(1);
|
||||
expect(calc.numberOfBits(2)).toBe(2);
|
||||
expect(calc.numberOfBits(3)).toBe(2);
|
||||
expect(calc.numberOfBits(68719476735)).toBe(36);
|
||||
expect(calc.numberOfBitsDisplayed(1)).toBe(1);
|
||||
expect(calc.numberOfBitsDisplayed(2)).toBe(2);
|
||||
expect(calc.numberOfBitsDisplayed(3)).toBe(2);
|
||||
expect(calc.numberOfBitsDisplayed(68719476735)).toBe(36);
|
||||
expect(calc.numberOfBitsDisplayed(-INT_MAX_VALUE)).toBe(32);
|
||||
expect(calc.numberOfBitsDisplayed(-(INT_MAX_VALUE+1))).toBe(64);
|
||||
});
|
||||
|
||||
it('calculates max number of bits', () => {
|
||||
expect(calc.maxNumberOfBits([1, 2, 3, 10])).toBe(4);
|
||||
expect(calc.maxNumberOfBitsDisplayed([1, 2, 3, 10])).toBe(4);
|
||||
});
|
||||
|
||||
it('calculates expression', () => {
|
||||
var result = calc.calcExpression(new BitwiseOperationExpression(
|
||||
"1|2&3",
|
||||
[
|
||||
new ScalarOperand(1),
|
||||
new ExpressionOperand("|2", new ScalarOperand(2), "|"),
|
||||
new ExpressionOperand("&3", new ScalarOperand(3), "&"),
|
||||
new ScalarExpression(1),
|
||||
new OperatorExpression("|2", new ScalarExpression(2), "|"),
|
||||
new OperatorExpression("&3", new ScalarExpression(3), "&"),
|
||||
]
|
||||
));
|
||||
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
import { ExpressionInput } from "../expression/expression-interfaces";
|
||||
import { INT_MAX_VALUE } from "./const";
|
||||
|
||||
export default {
|
||||
numberOfBits: function (num: number) : number {
|
||||
numberOfBitsDisplayed: function (num: number) : number {
|
||||
if(num < 0) {
|
||||
return 32;
|
||||
return Math.abs(num) <= INT_MAX_VALUE ? 32 : 64;
|
||||
}
|
||||
|
||||
return Math.floor(Math.log(num) / Math.log(2)) + 1;
|
||||
},
|
||||
|
||||
maxNumberOfBits: function (arr: number[]) {
|
||||
maxNumberOfBitsDisplayed: function (arr: number[]) {
|
||||
|
||||
var counts = [], num;
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
num = arr[i];
|
||||
counts.push(this.numberOfBits(num));
|
||||
counts.push(this.numberOfBitsDisplayed(num));
|
||||
}
|
||||
|
||||
return Math.max.apply(null, counts);
|
||||
|
||||
4
src/core/const.ts
Normal file
4
src/core/const.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
const INT_MAX_VALUE = 2147483647;
|
||||
|
||||
export {INT_MAX_VALUE};
|
||||
@@ -2,18 +2,24 @@ import formatter from './formatter';
|
||||
|
||||
describe("formatter", () => {
|
||||
it('formats string', () => {
|
||||
expect(formatter.formatString(15, "dec")).toBe("15");
|
||||
expect(formatter.formatString(15, "hex")).toBe("f");
|
||||
expect(formatter.formatString(15, "bin")).toBe("1111");
|
||||
expect(formatter.numberToString(15, "dec")).toBe("15");
|
||||
expect(formatter.numberToString(15, "hex")).toBe("0xf");
|
||||
expect(formatter.numberToString(15, "bin")).toBe("1111");
|
||||
});
|
||||
|
||||
it('formats large binary number correctly', () => {
|
||||
var decimal = 68719476735;
|
||||
var binary = formatter.bin(68719476735);
|
||||
var hex = formatter.formatString(decimal, 'hex');
|
||||
var hex = formatter.numberToString(decimal, 'hex');
|
||||
expect(binary).toBe('111111111111111111111111111111111111');
|
||||
expect(hex).toBe('fffffffff');
|
||||
})
|
||||
expect(hex).toBe('0xfffffffff');
|
||||
});
|
||||
|
||||
it('formats negative binary numbers', () => {
|
||||
expect(formatter.numberToString(-1, 'bin')).toBe("11111111111111111111111111111111");
|
||||
expect(formatter.numberToString(-0, 'bin')).toBe("0");
|
||||
expect(formatter.numberToString(-2147483647, 'bin')).toBe("10000000000000000000000000000001");
|
||||
});
|
||||
|
||||
it('pads left', () => {
|
||||
expect(formatter.padLeft("1", 3, " ")).toBe(" 1");
|
||||
|
||||
@@ -1,6 +1,27 @@
|
||||
import { INT_MAX_VALUE } from "./const";
|
||||
export type NumberBase = 'dec' | 'hex' | 'bin';
|
||||
|
||||
const formatter = {
|
||||
formatString: function(num: number, kind: string) : string {
|
||||
return num.toString(getBase(kind || "bin"));
|
||||
numberToString: function(value: number, kind: NumberBase) : string {
|
||||
|
||||
switch(kind) {
|
||||
case 'hex':
|
||||
var hexVal = Math.abs(value).toString(16);
|
||||
return value >= 0 ? '0x' + hexVal : '-0x' + hexVal;
|
||||
case 'bin':
|
||||
if(value < 0) {
|
||||
const n = Math.abs(value);
|
||||
const padding = n > INT_MAX_VALUE ? 64 : 32;
|
||||
const pos = n.toString(2).padStart(padding, '0');
|
||||
return findTwosComplement(pos);
|
||||
}
|
||||
|
||||
return value.toString(getBase(kind || "bin"));
|
||||
case 'dec':
|
||||
return value.toString(10);
|
||||
default:
|
||||
throw new Error("Unexpected kind: " + kind)
|
||||
}
|
||||
},
|
||||
padLeft: function (str: string, length: number, symbol: string) : string {
|
||||
var sb = Array.prototype.slice.call(str), symbol = symbol || "0";
|
||||
@@ -16,7 +37,7 @@ const formatter = {
|
||||
return sb.join('');
|
||||
},
|
||||
bin(number: number) {
|
||||
return this.formatString(number, 'bin');
|
||||
return this.numberToString(number, 'bin');
|
||||
},
|
||||
emBin(number: number) {
|
||||
return this.padLeft(this.bin(number), 8, '0');
|
||||
@@ -49,6 +70,15 @@ const formatter = {
|
||||
if(tmp.length > 0) res.push(tmp.join(''));
|
||||
|
||||
return { vpc: res[0], subnet: res[1], hosts: res[2]};
|
||||
},
|
||||
getAlternativeBase: (base: NumberBase) : NumberBase => {
|
||||
switch(base) {
|
||||
case 'dec':
|
||||
case 'bin':
|
||||
return 'hex';
|
||||
case 'hex': return 'dec';
|
||||
default : throw new Error(base + " kind doesn't have opposite kind")
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -62,6 +92,43 @@ function getBase(kind:string) : number {
|
||||
throw new Error("Unsupported kind: " + kind);
|
||||
}
|
||||
|
||||
function flip(bit: string) : string {
|
||||
switch(bit) {
|
||||
case "1": return "0";
|
||||
case "0": return "1";
|
||||
default: throw new Error("unexpected bit value: " + bit);
|
||||
}
|
||||
}
|
||||
|
||||
function findTwosComplement(str:string):string {
|
||||
var n = str.length;
|
||||
|
||||
// Traverse the string to get first '1' from
|
||||
// the last of string
|
||||
var i;
|
||||
for (i = n - 1; i >= 0; i--)
|
||||
if (str.charAt(i) == '1')
|
||||
break;
|
||||
|
||||
// If there exists no '1' concat 1 at the
|
||||
// starting of string
|
||||
if (i == -1)
|
||||
return "1" + str;
|
||||
|
||||
// Continue traversal after the position of
|
||||
// first '1'
|
||||
for (var k = i - 1; k >= 0; k--) {
|
||||
// Just flip the values
|
||||
if (str.charAt(k) == '1')
|
||||
str = str.substring(0,k)+"0"+str.substring(k+1, str.length);
|
||||
else
|
||||
str = str.substring(0,k)+"1"+str.substring(k+1, str.length);
|
||||
}
|
||||
|
||||
// return the modified string
|
||||
return str.toString();
|
||||
}
|
||||
|
||||
const emBin = formatter.emBin.bind(formatter);
|
||||
const padLeft = formatter.padLeft.bind(formatter);
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { ExpressionInput, ExpressionInputItem } from "./expression-interfaces";
|
||||
import { ExpressionInput, Expression } from "./expression-interfaces";
|
||||
|
||||
export default class BitwiseOperationExpression implements ExpressionInput {
|
||||
|
||||
expressionString: string;
|
||||
expressionItems: ExpressionInputItem[];
|
||||
children: Expression[];
|
||||
|
||||
constructor(expressionString: string, expressions: ExpressionInputItem[]) {
|
||||
constructor(expressionString: string, children: Expression[]) {
|
||||
this.expressionString = expressionString;
|
||||
this.expressionItems = expressions;
|
||||
this.children = children;
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
import ScalarOperand from "./ScalarOperand";
|
||||
import ExpressionOperand from './ExpressionOperand';
|
||||
|
||||
it('can apply ~ operand', () => {
|
||||
var op = new ScalarOperand(10, 'dec');
|
||||
var expr = new ExpressionOperand("~10", op, "~");
|
||||
var result = expr.evaluate();
|
||||
expect(result.value).toBe(-11);
|
||||
expect(result.base).toBe('dec');
|
||||
});
|
||||
|
||||
it('can apply & operand', () => {
|
||||
var op1 = new ScalarOperand(3, 'dec');
|
||||
var op2 = new ScalarOperand(4, 'dec');
|
||||
var expr = new ExpressionOperand("|3", op1, "|");
|
||||
var result = expr.evaluate(op2);
|
||||
expect(result.value).toBe(7);
|
||||
expect(result.base).toBe('dec');
|
||||
});
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Expression, NumericLiteral } from "typescript";
|
||||
import ExpressionOperand from "./ExpressionOperand";
|
||||
import { ScalarOperand } from "./expression";
|
||||
import { ExpressionInputItem } from "./expression-interfaces";
|
||||
import OperatorExpression from "./OperatorExpression";
|
||||
import { ScalarExpression } from "./expression";
|
||||
import { Expression } from "./expression-interfaces";
|
||||
import { type } from "os";
|
||||
import { InputType } from "zlib";
|
||||
import exp from "constants";
|
||||
@@ -17,7 +16,6 @@ type TokenDef = {
|
||||
const decimalRegex = /^-?\d+/;
|
||||
const hexRegex = /^-?0x[0-9,a-f]+/i;
|
||||
const binRegex = /^-?0b[0-1]+/i;
|
||||
const operatorRegex = /^<<|>>|<<<|\&|\|\^|~/;
|
||||
|
||||
type Token = {
|
||||
value: string,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import ScalarOperand from "./ScalarOperand";
|
||||
import ScalarExpression from "./ScalarExpression";
|
||||
import ListOfNumbersExpression from "./ListOfNumbersExpression";
|
||||
|
||||
it('calculates max bits length', () => {
|
||||
var expr = new ListOfNumbersExpression("10 0xabef 0b01010", [ScalarOperand.parse("10"), ScalarOperand.parse("0xabef"), ScalarOperand.parse("0b01010")])
|
||||
var expr = new ListOfNumbersExpression("10 0xabef 0b01010", [ScalarExpression.parse("10"), ScalarExpression.parse("0xabef"), ScalarExpression.parse("0b01010")])
|
||||
expect(expr.maxBitsLength).toBe(16);
|
||||
});
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import ScalarOperand from "./ScalarOperand";
|
||||
import { ExpressionInput, ExpressionInputItem } from "./expression-interfaces";
|
||||
import calc from "../core/calc";
|
||||
import ScalarExpression from "./ScalarExpression";
|
||||
import { ExpressionInput, Expression } from "./expression-interfaces";
|
||||
|
||||
export default class ListOfNumbersExpression implements ExpressionInput {
|
||||
numbers: ScalarOperand[];
|
||||
numbers: ScalarExpression[];
|
||||
expressionString: string;
|
||||
maxBitsLength: number;
|
||||
|
||||
constructor(expressionString: string, numbers: ScalarOperand[]) {
|
||||
constructor(expressionString: string, numbers: ScalarExpression[]) {
|
||||
this.expressionString = expressionString;
|
||||
this.numbers = numbers;
|
||||
this.maxBitsLength = numbers.map(n => n.lengthInBits).reduce((n , c) => n >= c ? n : c, 0);
|
||||
this.maxBitsLength = numbers.map(n => calc.numberOfBitsDisplayed(n.value)).reduce((n , c) => n >= c ? n : c, 0);
|
||||
}
|
||||
|
||||
toString() {
|
||||
|
||||
19
src/expression/OperatorExpression.test.ts
Normal file
19
src/expression/OperatorExpression.test.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import ScalarExpression from "./ScalarExpression";
|
||||
import OperatorExpression from './OperatorExpression';
|
||||
|
||||
it('can apply ~ operand', () => {
|
||||
var op = new ScalarExpression(10, 'dec');
|
||||
var expr = new OperatorExpression("~10", op, "~");
|
||||
var result = expr.evaluate();
|
||||
expect(result.value).toBe(-11);
|
||||
expect(result.base).toBe('dec');
|
||||
});
|
||||
|
||||
it('can apply & operand', () => {
|
||||
var op1 = new ScalarExpression(3, 'dec');
|
||||
var op2 = new ScalarExpression(4, 'dec');
|
||||
var expr = new OperatorExpression("|3", op1, "|");
|
||||
var result = expr.evaluate(op2);
|
||||
expect(result.value).toBe(7);
|
||||
expect(result.base).toBe('dec');
|
||||
});
|
||||
@@ -1,25 +1,25 @@
|
||||
import ScalarOperand from './ScalarOperand';
|
||||
import { ExpressionInputItem } from './expression-interfaces';
|
||||
import ScalarExpression from './ScalarExpression';
|
||||
import { Expression } from './expression-interfaces';
|
||||
|
||||
export default class ExpressionOperand implements ExpressionInputItem {
|
||||
export default class OperatorExpression implements Expression {
|
||||
expressionString: string;
|
||||
operand: ExpressionInputItem;
|
||||
operand: Expression;
|
||||
sign: string;
|
||||
isExpression: boolean;
|
||||
isOperator: boolean;
|
||||
isShiftExpression: boolean;
|
||||
isNotExpression: boolean;
|
||||
|
||||
constructor(expressionString : string, operand : ExpressionInputItem, sign : string) {
|
||||
constructor(expressionString : string, operand : Expression, sign : string) {
|
||||
this.expressionString = expressionString;
|
||||
this.operand = operand;
|
||||
this.sign = sign;
|
||||
this.isExpression = true;
|
||||
this.isOperator = true;
|
||||
this.isShiftExpression = this.sign.indexOf('<') >= 0 || this.sign.indexOf('>')>= 0;
|
||||
this.isNotExpression = this.sign === '~';
|
||||
}
|
||||
|
||||
evaluate(operand?: ScalarOperand) : ScalarOperand {
|
||||
if (operand instanceof ExpressionOperand) {
|
||||
evaluate(operand?: ScalarExpression) : ScalarExpression {
|
||||
if (operand instanceof OperatorExpression) {
|
||||
throw new Error('value shouldnt be expression');
|
||||
}
|
||||
|
||||
@@ -35,11 +35,11 @@ export default class ExpressionOperand implements ExpressionInputItem {
|
||||
str = operand.value + this.sign + evaluatedOperand.value;
|
||||
}
|
||||
|
||||
return ScalarOperand.create(eval(str), evaluatedOperand.base);
|
||||
return ScalarExpression.create(eval(str), evaluatedOperand.base);
|
||||
}
|
||||
|
||||
getUnderlyingOperand() : ScalarOperand {
|
||||
return this.operand.getUnderlyingOperand();
|
||||
getUnderlyingScalarOperand() : ScalarExpression {
|
||||
return this.operand.getUnderlyingScalarOperand();
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
19
src/expression/ScalarExpression.test.ts
Normal file
19
src/expression/ScalarExpression.test.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import ScalarExpression from './ScalarExpression';
|
||||
|
||||
it('parsed from dec string', () => {
|
||||
var op = ScalarExpression.parse('123');
|
||||
expect(op.base).toBe('dec');
|
||||
expect(op.value).toBe(123);
|
||||
});
|
||||
|
||||
it('parsed from bin string', () => {
|
||||
var op = ScalarExpression.parse('0b10');
|
||||
expect(op.base).toBe('bin');
|
||||
expect(op.value).toBe(2);
|
||||
});
|
||||
|
||||
it('parsed from hex string', () => {
|
||||
var op = ScalarExpression.parse('0x10');
|
||||
expect(op.base).toBe('hex');
|
||||
expect(op.value).toBe(16);
|
||||
});
|
||||
61
src/expression/ScalarExpression.ts
Normal file
61
src/expression/ScalarExpression.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import {numberParser} from './numberParser';
|
||||
import { Expression as Expression } from './expression-interfaces';
|
||||
import { NumberBase } from '../core/formatter';
|
||||
|
||||
var globalId : number = 1;
|
||||
|
||||
|
||||
// Represents scalar numeric value
|
||||
export default class ScalarExpression implements Expression {
|
||||
id: number;
|
||||
value: number;
|
||||
base: NumberBase;
|
||||
isOperator: boolean;
|
||||
|
||||
constructor(value : number, base?: NumberBase) {
|
||||
|
||||
this.id = globalId++;
|
||||
this.value = value;
|
||||
this.base = base || "dec";
|
||||
this.isOperator = false;
|
||||
}
|
||||
|
||||
setValue(value : number) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
evaluate() : ScalarExpression {
|
||||
return this;
|
||||
}
|
||||
|
||||
getUnderlyingScalarOperand() : ScalarExpression {
|
||||
return this
|
||||
}
|
||||
|
||||
static create(value : number, base? : NumberBase) {
|
||||
return new ScalarExpression(value, base || "dec");
|
||||
};
|
||||
|
||||
static parse(input: string) : ScalarExpression {
|
||||
|
||||
var parsed = ScalarExpression.tryParse(input);
|
||||
|
||||
if(parsed == null) {
|
||||
throw new Error(input + " is not a valid number");
|
||||
}
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
static tryParse(input: string) : ScalarExpression | null {
|
||||
|
||||
var parsed = numberParser.parse(input);
|
||||
|
||||
if(!parsed) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new ScalarExpression(parsed.value, parsed.base);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
import ScalarOperand, { INT_MAX_VALUE } from './ScalarOperand';
|
||||
|
||||
it('parsed from string', () => {
|
||||
var op = ScalarOperand.parse('123');
|
||||
expect(op.base).toBe('dec');
|
||||
expect(op.value).toBe(123);
|
||||
});
|
||||
|
||||
it('can get other kind', () => {
|
||||
var op = new ScalarOperand(10, 'dec');
|
||||
expect(op.getOtherBase('hex')).toBe('dec');
|
||||
expect(op.getOtherBase('bin')).toBe('hex');
|
||||
});
|
||||
|
||||
it('negtive value binary string', () => {
|
||||
expect(ScalarOperand.toBaseString(-1, 'bin')).toBe('11111111111111111111111111111111');
|
||||
});
|
||||
|
||||
it('64 bit operand binary string', () => {
|
||||
expect(ScalarOperand.toBaseString(68719476735, 'bin')).toBe('111111111111111111111111111111111111');
|
||||
});
|
||||
|
||||
it('throws on negative 64 bit numbers', () => {
|
||||
var bigN = -(INT_MAX_VALUE+1);
|
||||
expect(() => new ScalarOperand(bigN)).toThrowError("BitwiseCmd currently doesn't support 64 bit negative numbers such as " + bigN);
|
||||
})
|
||||
@@ -1,141 +0,0 @@
|
||||
import {numberParser} from './numberParser';
|
||||
import { ExpressionInputItem, NumberBase } from './expression-interfaces';
|
||||
|
||||
var globalId : number = 1;
|
||||
|
||||
const INT_MAX_VALUE = 2147483647;
|
||||
|
||||
export {INT_MAX_VALUE};
|
||||
|
||||
// Represents scalar numeric value
|
||||
export default class ScalarOperand implements ExpressionInputItem {
|
||||
id: number;
|
||||
value: number;
|
||||
base: NumberBase;
|
||||
lengthInBits: number;
|
||||
isExpression: boolean;
|
||||
|
||||
constructor(value : number, base?: NumberBase) {
|
||||
this.id = globalId++;
|
||||
this.value = value;
|
||||
this.base = base || "dec";
|
||||
this.lengthInBits = ScalarOperand.getBitLength(this.value);
|
||||
this.isExpression = false;
|
||||
|
||||
if(value < 0 && !ScalarOperand.is32Bit(value))
|
||||
throw new Error("BitwiseCmd currently doesn't support 64 bit negative numbers such as " + value);
|
||||
}
|
||||
|
||||
getLengthInBits() {
|
||||
if(this.value < 0) {
|
||||
return 32;
|
||||
}
|
||||
return Math.floor(Math.log(this.value) / Math.log(2)) + 1;
|
||||
};
|
||||
|
||||
getOtherBase(kind?: NumberBase) : NumberBase {
|
||||
switch(kind || this.base) {
|
||||
case 'dec':
|
||||
case 'bin':
|
||||
return 'hex';
|
||||
case 'hex': return 'dec';
|
||||
default : throw new Error(kind + " kind doesn't have opposite kind")
|
||||
}
|
||||
};
|
||||
|
||||
toString(base?: NumberBase) : string {
|
||||
return ScalarOperand.toBaseString(this.value, base || this.base);
|
||||
}
|
||||
|
||||
toOtherKindString() : string {
|
||||
return this.toString(this.getOtherBase());
|
||||
}
|
||||
|
||||
toDecimalString() {
|
||||
return this.toString('dec');
|
||||
}
|
||||
|
||||
toHexString() {
|
||||
return this.toString('hex');
|
||||
}
|
||||
|
||||
toBinaryString() : string {
|
||||
return this.toString('bin');
|
||||
}
|
||||
|
||||
setValue(value : number) {
|
||||
this.value = value;
|
||||
this.lengthInBits = ScalarOperand.getBitLength(value);
|
||||
}
|
||||
|
||||
evaluate() : ScalarOperand {
|
||||
return this;
|
||||
}
|
||||
|
||||
getUnderlyingOperand() : ScalarOperand {
|
||||
return this
|
||||
}
|
||||
|
||||
static getBitLength(num : number) {
|
||||
return Math.floor(Math.log(num) / Math.log(2)) + 1;
|
||||
}
|
||||
|
||||
static getBase(kind : string){
|
||||
switch (kind){
|
||||
case 'bin': return 2;
|
||||
case 'hex': return 16;
|
||||
case 'dec': return 10;
|
||||
}
|
||||
};
|
||||
|
||||
static create(value : number, base? : NumberBase) {
|
||||
return new ScalarOperand(value, base || "dec");
|
||||
};
|
||||
|
||||
static parse(input: string) : ScalarOperand {
|
||||
|
||||
var parsed = ScalarOperand.tryParse(input);
|
||||
|
||||
if(parsed == null) {
|
||||
throw new Error(input + " is not a valid number");
|
||||
}
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
static tryParse(input: string) : ScalarOperand | null {
|
||||
|
||||
var parsed = numberParser.parse(input);
|
||||
|
||||
if(!parsed) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new ScalarOperand(parsed.value, parsed.base);
|
||||
}
|
||||
|
||||
static toBaseString(value : number, base : NumberBase) : string {
|
||||
switch(base) {
|
||||
case 'hex':
|
||||
var hexVal = Math.abs(value).toString(16);
|
||||
return value >= 0 ? '0x' + hexVal : '-0x' + hexVal;
|
||||
case 'bin':
|
||||
// >>> 0 is used to get an actual bit representation of the negative numbers
|
||||
// https://stackoverflow.com/questions/5747123/strange-javascript-operator-expr-0
|
||||
const is32Bit = ScalarOperand.is32Bit(value);
|
||||
return (is32Bit && value < 0 ? (value >>> 0) : value).toString(2);
|
||||
case 'dec':
|
||||
return value.toString(10);
|
||||
default:
|
||||
throw new Error("Unexpected kind: " + base)
|
||||
}
|
||||
};
|
||||
|
||||
static toHexString (hex : string) {
|
||||
return hex.indexOf('-') === 0 ? '-0x' + hex.substr(1) : '0x' + hex;
|
||||
};
|
||||
|
||||
static is32Bit(n: number) {
|
||||
return Math.abs(n) <= INT_MAX_VALUE
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
import { ScalarOperand, ListOfNumbersExpression, BitwiseOperationExpression, ExpressionOperand } from '../expression';
|
||||
import { ExpressionInputItem, ExpressionInput } from '../expression-interfaces';
|
||||
import { ScalarExpression, ListOfNumbersExpression, BitwiseOperationExpression, OperatorExpression } from '../expression';
|
||||
import { Expression, ExpressionInput } from '../expression-interfaces';
|
||||
import calc from '../../core/calc';
|
||||
import formatter from '../../core/formatter';
|
||||
|
||||
type Config = {
|
||||
emphasizeBytes: boolean;
|
||||
@@ -9,7 +11,7 @@ type Config = {
|
||||
type ExpressionItemModel = {
|
||||
sign: string;
|
||||
css: string;
|
||||
expressionItem: ExpressionInputItem;
|
||||
expression: Expression;
|
||||
allowFlipBits: boolean;
|
||||
label: string;
|
||||
}
|
||||
@@ -30,28 +32,28 @@ export default class BitwiseExpressionViewModel {
|
||||
|
||||
static buildListOfNumbers(expr : ListOfNumbersExpression, config : Config) {
|
||||
var model = new BitwiseExpressionViewModel(config);
|
||||
expr.numbers.forEach(op => model.addOperandRow(op));
|
||||
model.maxNumberOfBits = BitwiseExpressionViewModel.getNumberOfBits(model.maxNumberOfBits, model.emphasizeBytes);
|
||||
expr.numbers.forEach(op => model.addScalarRow(op));
|
||||
model.maxNumberOfBits = BitwiseExpressionViewModel.applyEmphasizeBytes(model.maxNumberOfBits, model.emphasizeBytes);
|
||||
return model;
|
||||
}
|
||||
|
||||
static buildMultiple (expr : BitwiseOperationExpression, config : Config) {
|
||||
|
||||
var op = expr.expressionItems[0],
|
||||
i = 0, len = expr.expressionItems.length,
|
||||
var op = expr.children[0],
|
||||
i = 0, len = expr.children.length,
|
||||
ex, m = new BitwiseExpressionViewModel(config);
|
||||
|
||||
var prev : ScalarOperand | null = null;
|
||||
var prev : ScalarExpression | null = null;
|
||||
|
||||
for (;i<len;i++) {
|
||||
ex = expr.expressionItems[i];
|
||||
if(ex instanceof ScalarOperand) {
|
||||
m.addOperandRow(ex);
|
||||
ex = expr.children[i];
|
||||
if(ex instanceof ScalarExpression) {
|
||||
m.addScalarRow(ex);
|
||||
prev = ex;
|
||||
continue;
|
||||
}
|
||||
|
||||
var eo = ex as ExpressionOperand;
|
||||
var eo = ex as OperatorExpression;
|
||||
|
||||
// If it a single NOT expression
|
||||
if(eo.isNotExpression) {
|
||||
@@ -61,86 +63,88 @@ export default class BitwiseExpressionViewModel {
|
||||
prev = notResult;
|
||||
}
|
||||
else if(eo.isShiftExpression){
|
||||
prev = eo.evaluate(prev as ScalarOperand);
|
||||
prev = eo.evaluate(prev as ScalarExpression);
|
||||
m.addShiftExpressionResultRow(eo, prev);
|
||||
} else {
|
||||
|
||||
prev = eo.evaluate(prev as ScalarOperand);
|
||||
prev = eo.evaluate(prev as ScalarExpression);
|
||||
m.addExpressionOperandRow(eo);
|
||||
m.addExpressionResultRow(prev);
|
||||
}
|
||||
}
|
||||
|
||||
m.maxNumberOfBits = BitwiseExpressionViewModel.getNumberOfBits(m.maxNumberOfBits, m.emphasizeBytes);
|
||||
m.maxNumberOfBits = BitwiseExpressionViewModel.applyEmphasizeBytes(m.maxNumberOfBits, m.emphasizeBytes);
|
||||
return m;
|
||||
};
|
||||
|
||||
static buildNot (expression: ExpressionOperand, config : Config) {
|
||||
static buildNot (expression: OperatorExpression, config : Config) {
|
||||
|
||||
var m = new BitwiseExpressionViewModel(config);
|
||||
m.addExpressionOperandRow(expression);
|
||||
m.addExpressionResultRow(expression.evaluate());
|
||||
m.maxNumberOfBits = BitwiseExpressionViewModel.getNumberOfBits(m.maxNumberOfBits, m.emphasizeBytes);
|
||||
m.maxNumberOfBits = BitwiseExpressionViewModel.applyEmphasizeBytes(m.maxNumberOfBits, m.emphasizeBytes);
|
||||
return m;
|
||||
};
|
||||
|
||||
addOperandRow(operand: ScalarOperand) {
|
||||
this.maxNumberOfBits = Math.max(operand.getLengthInBits(), this.maxNumberOfBits);
|
||||
addScalarRow(expr: ScalarExpression) {
|
||||
const bits = calc.numberOfBitsDisplayed(expr.value);
|
||||
this.maxNumberOfBits = Math.max(bits, this.maxNumberOfBits);
|
||||
this.items.push({
|
||||
sign:'',
|
||||
css: '',
|
||||
expressionItem: operand,
|
||||
expression: expr,
|
||||
allowFlipBits: this.allowFlipBits,
|
||||
label: ''
|
||||
});
|
||||
};
|
||||
|
||||
addExpressionOperandRow(expression: ExpressionOperand) {
|
||||
const resultNumber = expression.isNotExpression ? expression.evaluate() : expression.getUnderlyingOperand();
|
||||
this.maxNumberOfBits = Math.max(resultNumber.getLengthInBits(), this.maxNumberOfBits);
|
||||
addExpressionOperandRow(expr: OperatorExpression) {
|
||||
|
||||
const resultNumber = expr.isNotExpression ? expr.evaluate() : expr.getUnderlyingScalarOperand();
|
||||
const bits = calc.numberOfBitsDisplayed(resultNumber.value);
|
||||
this.maxNumberOfBits = Math.max(bits, this.maxNumberOfBits);
|
||||
|
||||
this.items.push({
|
||||
sign: expression.sign,
|
||||
sign: expr.sign,
|
||||
css: '',
|
||||
label: this.getLabel(resultNumber),
|
||||
expressionItem: expression.operand,
|
||||
expression: expr.operand,
|
||||
allowFlipBits: this.allowFlipBits
|
||||
});
|
||||
};
|
||||
|
||||
addShiftExpressionResultRow(expression : ExpressionOperand, resultOperand : ScalarOperand) {
|
||||
this.maxNumberOfBits = Math.max(resultOperand.getLengthInBits(), this.maxNumberOfBits);
|
||||
|
||||
addShiftExpressionResultRow(expr : OperatorExpression, resultExpr : ScalarExpression) {
|
||||
const bits = calc.numberOfBitsDisplayed(resultExpr.value);
|
||||
this.maxNumberOfBits = Math.max(bits, this.maxNumberOfBits);
|
||||
const child = expr.operand.getUnderlyingScalarOperand();
|
||||
this.items.push({
|
||||
sign: expression.sign + expression.operand.toString(),
|
||||
sign: expr.sign + formatter.numberToString(child.value, child.base),
|
||||
css: 'expression-result',
|
||||
expressionItem: resultOperand,
|
||||
expression: resultExpr,
|
||||
allowFlipBits: false,
|
||||
label: ''
|
||||
});
|
||||
};
|
||||
|
||||
addExpressionResultRow(operand : ScalarOperand) {
|
||||
this.maxNumberOfBits = Math.max(operand.getLengthInBits(), this.maxNumberOfBits);
|
||||
addExpressionResultRow(expr : ScalarExpression) {
|
||||
const bits = calc.numberOfBitsDisplayed(expr.value);
|
||||
this.maxNumberOfBits = Math.max(bits, this.maxNumberOfBits);
|
||||
this.items.push({
|
||||
sign:'=',
|
||||
css: 'expression-result',
|
||||
expressionItem: operand,
|
||||
expression: expr,
|
||||
allowFlipBits: false,
|
||||
label: '',
|
||||
});
|
||||
};
|
||||
|
||||
getLabel (op: ScalarOperand) : string {
|
||||
|
||||
if(op.base == 'bin') {
|
||||
return op.toString("dec");
|
||||
}
|
||||
getLabel (op: ScalarExpression) : string {
|
||||
|
||||
return op.toString();
|
||||
return formatter.numberToString(op.value, op.base === 'bin' ? 'dec' : op.base)
|
||||
}
|
||||
|
||||
// TODO: move this method elsewhere. It is also used in LisOfNumbersExpressionView.js
|
||||
static getNumberOfBits = function (bits : number, emphasizeBytes : boolean) : number {
|
||||
static applyEmphasizeBytes (bits : number, emphasizeBytes : boolean) : number {
|
||||
|
||||
if(emphasizeBytes && bits % 8 != 0) {
|
||||
if(bits < 8) {
|
||||
return 8;
|
||||
|
||||
@@ -2,8 +2,8 @@ import React from 'react';
|
||||
import formatter from '../../core/formatter';
|
||||
import BinaryStringView, { FlipBitEventArg } from '../../core/components/BinaryString';
|
||||
import BitwiseExpressionViewModel from './BitwiseExpressionModel';
|
||||
import { ExpressionInput, ExpressionInputItem } from '../expression-interfaces';
|
||||
import { ExpressionOperand, ScalarOperand } from '../expression';
|
||||
import { ExpressionInput, Expression } from '../expression-interfaces';
|
||||
import { OperatorExpression, ScalarExpression } from '../expression';
|
||||
|
||||
type BitwiseOperationExpressionViewProps = {
|
||||
expression: ExpressionInput;
|
||||
@@ -41,7 +41,7 @@ export default class BitwiseOperationExpressionView extends React.Component<Bitw
|
||||
sign={itm.sign}
|
||||
css={itm.css}
|
||||
allowFlipBits={itm.allowFlipBits}
|
||||
expressionItem={itm.expressionItem}
|
||||
expressionItem={itm.expression}
|
||||
emphasizeBytes={this.props.emphasizeBytes}
|
||||
maxNumberOfBits={model.maxNumberOfBits}
|
||||
onBitFlipped={() => this.onBitFlipped()} />);
|
||||
@@ -59,7 +59,7 @@ type ExpressionRowProps = {
|
||||
maxNumberOfBits: number,
|
||||
emphasizeBytes: boolean,
|
||||
allowFlipBits: boolean,
|
||||
expressionItem: ExpressionInputItem,
|
||||
expressionItem: Expression,
|
||||
onBitFlipped: any
|
||||
}
|
||||
|
||||
@@ -81,46 +81,48 @@ class ExpressionRow extends React.Component<ExpressionRowProps> {
|
||||
allowFlipBits={allowFlipBits}
|
||||
onFlipBit={args => this.flipBit(args)}/>
|
||||
</td>
|
||||
<td className="other">{this.getOther()}</td>
|
||||
<td className="other">{this.getAlternative()}</td>
|
||||
</tr>;;
|
||||
}
|
||||
|
||||
getBinaryString() : string {
|
||||
var binary = this.props.expressionItem.evaluate().toBinaryString();
|
||||
return binary;
|
||||
var v = this.props.expressionItem.evaluate();
|
||||
return formatter.numberToString(v.value, 'bin');
|
||||
}
|
||||
|
||||
getLabel(): string {
|
||||
|
||||
// For expressions like |~2
|
||||
// TODO: find a better way...
|
||||
if(this.props.expressionItem.isExpression) {
|
||||
const ex = this.props.expressionItem as ExpressionOperand;
|
||||
return ex.sign + this.getLabelString(ex.getUnderlyingOperand());
|
||||
if(this.props.expressionItem.isOperator) {
|
||||
const ex = this.props.expressionItem as OperatorExpression;
|
||||
return ex.sign + this.getLabelString(ex.getUnderlyingScalarOperand());
|
||||
}
|
||||
|
||||
return this.getLabelString(this.props.expressionItem.getUnderlyingOperand());
|
||||
return this.getLabelString(this.props.expressionItem.getUnderlyingScalarOperand());
|
||||
}
|
||||
|
||||
getOther() {
|
||||
getAlternative() {
|
||||
|
||||
if(this.props.expressionItem.isExpression) {
|
||||
const ex = this.props.expressionItem as ExpressionOperand;
|
||||
const op = ex.evaluate();
|
||||
if(this.props.expressionItem.isOperator) {
|
||||
const ex = this.props.expressionItem as OperatorExpression;
|
||||
const res = ex.evaluate();
|
||||
|
||||
return op.toString();
|
||||
return formatter.numberToString(res.value, res.base);
|
||||
}
|
||||
|
||||
return this.props.expressionItem.evaluate().toOtherKindString();
|
||||
const v = this.props.expressionItem.evaluate();
|
||||
const altBase = formatter.getAlternativeBase(v.base);
|
||||
return formatter.numberToString(v.value, altBase);
|
||||
}
|
||||
|
||||
getLabelString (op: ScalarOperand) : string {
|
||||
return op.toString(op.base == 'bin' ? 'dec' : op.base);
|
||||
getLabelString (op: ScalarExpression) : string {
|
||||
return formatter.numberToString(op.value, op.base == 'bin' ? 'dec' : op.base);
|
||||
}
|
||||
|
||||
flipBit(args: FlipBitEventArg) {
|
||||
|
||||
const op = this.props.expressionItem.getUnderlyingOperand();
|
||||
const op = this.props.expressionItem.getUnderlyingScalarOperand();
|
||||
const { index, binaryString } = args;
|
||||
|
||||
var arr = binaryString.split('');
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
import { ScalarOperand } from "./expression";
|
||||
import { ScalarExpression } from "./expression";
|
||||
|
||||
export interface ExpressionInput
|
||||
{
|
||||
expressionString: string;
|
||||
}
|
||||
|
||||
export interface ExpressionInputItem
|
||||
export interface Expression
|
||||
{
|
||||
isExpression: boolean;
|
||||
getUnderlyingOperand: () => ScalarOperand;
|
||||
evaluate(operand? : ScalarOperand): ScalarOperand;
|
||||
isOperator: boolean;
|
||||
getUnderlyingScalarOperand: () => ScalarExpression;
|
||||
evaluate(operand? : ScalarExpression): ScalarExpression;
|
||||
}
|
||||
|
||||
export type NumberBase = 'dec' | 'hex' | 'bin';
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { OperationCanceledException } from "typescript";
|
||||
import { parser, ListOfNumbersExpression, BitwiseOperationExpression, ScalarOperand, ExpressionOperand } from "./expression";
|
||||
import { parser, ListOfNumbersExpression, BitwiseOperationExpression, ScalarExpression, OperatorExpression } from "./expression";
|
||||
|
||||
describe("expression parser", () => {
|
||||
|
||||
@@ -26,32 +26,32 @@ describe("expression parser", () => {
|
||||
expect(actual).toBeInstanceOf(BitwiseOperationExpression);
|
||||
|
||||
const expr = actual as BitwiseOperationExpression;
|
||||
expect(expr.expressionItems[0].getUnderlyingOperand().value).toBe(305419896);
|
||||
expect(expr.expressionItems[1].getUnderlyingOperand().value).toBe(2863311360);
|
||||
expect(expr.children[0].getUnderlyingScalarOperand().value).toBe(305419896);
|
||||
expect(expr.children[1].getUnderlyingScalarOperand().value).toBe(2863311360);
|
||||
})
|
||||
|
||||
it("pares multiple operand expression", () => {
|
||||
const result = parser.parse("1^2") as BitwiseOperationExpression;
|
||||
expect(result.expressionItems.length).toBe(2);
|
||||
expect(result.children.length).toBe(2);
|
||||
|
||||
const first = result.expressionItems[0];
|
||||
const second = result.expressionItems[1];
|
||||
const first = result.children[0];
|
||||
const second = result.children[1];
|
||||
|
||||
expect(first).toBeInstanceOf(ScalarOperand);
|
||||
expect(first).toBeInstanceOf(ScalarExpression);
|
||||
|
||||
expect((first as ScalarOperand).value).toBe(1);
|
||||
expect((first as ScalarExpression).value).toBe(1);
|
||||
|
||||
expect(second).toBeInstanceOf(ExpressionOperand);
|
||||
var secondOp = second as ExpressionOperand;
|
||||
expect(second).toBeInstanceOf(OperatorExpression);
|
||||
var secondOp = second as OperatorExpression;
|
||||
expect(secondOp.sign).toBe("^");
|
||||
|
||||
expect(secondOp.operand).toBeInstanceOf(ScalarOperand);
|
||||
var childOp = secondOp.operand as ScalarOperand;
|
||||
expect(secondOp.operand).toBeInstanceOf(ScalarExpression);
|
||||
var childOp = secondOp.operand as ScalarExpression;
|
||||
expect(childOp.value).toBe(2);
|
||||
});
|
||||
|
||||
it("bug", () => {
|
||||
var result = parser.parse("1|~2") as BitwiseOperationExpression;
|
||||
expect(result.expressionItems.length).toBe(2);
|
||||
expect(result.children.length).toBe(2);
|
||||
});
|
||||
})
|
||||
@@ -1,11 +1,12 @@
|
||||
import ScalarOperand from './ScalarOperand';
|
||||
import ExpressionOperand from './ExpressionOperand'
|
||||
import ScalarExpression from './ScalarExpression';
|
||||
import OperatorExpression from './OperatorExpression'
|
||||
import ListOfNumbersExpression from './ListOfNumbersExpression';
|
||||
import BitwiseOperationExpression from './BitwiseOperationExpression';
|
||||
import { ExpressionInput, ExpressionInputItem, NumberBase } from './expression-interfaces';
|
||||
import { ExpressionInput, Expression } from './expression-interfaces';
|
||||
import { NumberBase } from '../core/formatter';
|
||||
|
||||
export { default as ScalarOperand } from './ScalarOperand';
|
||||
export { default as ExpressionOperand } from './ExpressionOperand';
|
||||
export { default as ScalarExpression } from './ScalarExpression';
|
||||
export { default as OperatorExpression } from './OperatorExpression';
|
||||
export { default as ListOfNumbersExpression } from './ListOfNumbersExpression';
|
||||
export { default as BitwiseOperationExpression } from './BitwiseOperationExpression';
|
||||
|
||||
@@ -46,12 +47,12 @@ class ExpressionParser {
|
||||
return null;
|
||||
};
|
||||
|
||||
parseOperand (input : string) : ScalarOperand {
|
||||
return ScalarOperand.parse(input);
|
||||
parseOperand (input : string) : ScalarExpression {
|
||||
return ScalarExpression.parse(input);
|
||||
};
|
||||
|
||||
createOperand (number : number, base : NumberBase) : ScalarOperand {
|
||||
return ScalarOperand.create(number, base);
|
||||
createOperand (number : number, base : NumberBase) : ScalarExpression {
|
||||
return ScalarExpression.create(number, base);
|
||||
};
|
||||
|
||||
addFactory (factory: IExpressionParserFactory) {
|
||||
@@ -69,7 +70,7 @@ class ListOfNumbersExpressionFactory implements IExpressionParserFactory
|
||||
|
||||
return input.split(' ')
|
||||
.filter(p => p.length > 0)
|
||||
.map(p => ScalarOperand.tryParse(p))
|
||||
.map(p => ScalarExpression.tryParse(p))
|
||||
.filter(n => n == null)
|
||||
.length == 0;
|
||||
};
|
||||
@@ -78,7 +79,7 @@ class ListOfNumbersExpressionFactory implements IExpressionParserFactory
|
||||
|
||||
const numbers = input.split(' ')
|
||||
.filter(p => p.length > 0)
|
||||
.map(m => ScalarOperand.parse(m));
|
||||
.map(m => ScalarExpression.parse(m));
|
||||
|
||||
return new ListOfNumbersExpression(input, numbers);
|
||||
}
|
||||
@@ -99,7 +100,7 @@ class BitwiseOperationExpressionFactory implements IExpressionParserFactory {
|
||||
};
|
||||
|
||||
create (input: string) : ExpressionInput {
|
||||
var m, operands : ExpressionInputItem[] = [],
|
||||
var m, operands : Expression[] = [],
|
||||
normalizedString = this.normalizeString(input);
|
||||
|
||||
while ((m = this.regex.exec(normalizedString)) != null) {
|
||||
@@ -109,23 +110,23 @@ class BitwiseOperationExpressionFactory implements IExpressionParserFactory {
|
||||
return new BitwiseOperationExpression(normalizedString, operands)
|
||||
};
|
||||
|
||||
parseMatch (m:any): ExpressionInputItem {
|
||||
parseMatch (m:any): Expression {
|
||||
var input = m[0],
|
||||
sign = m[1],
|
||||
num = m[2];
|
||||
|
||||
var parsed = null;
|
||||
if(num.indexOf('~') == 0) {
|
||||
parsed = new ExpressionOperand(num, ScalarOperand.parse(num.substring(1)), '~');
|
||||
parsed = new OperatorExpression(num, ScalarExpression.parse(num.substring(1)), '~');
|
||||
}
|
||||
else {
|
||||
parsed = ScalarOperand.parse(num);
|
||||
parsed = ScalarExpression.parse(num);
|
||||
}
|
||||
|
||||
if(sign == null) {
|
||||
return parsed as ExpressionOperand;
|
||||
return parsed as OperatorExpression;
|
||||
} else {
|
||||
return new ExpressionOperand(input, parsed as ScalarOperand, sign);
|
||||
return new OperatorExpression(input, parsed as ScalarExpression, sign);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { NumberBase } from "./expression-interfaces";
|
||||
import { NumberBase } from "../core/formatter";
|
||||
|
||||
const decimalRegex = /^-?\d+$/;
|
||||
const hexRegex = /^-?0x[0-9,a-f]+$/i;
|
||||
|
||||
@@ -44,7 +44,7 @@ export class IpAddressView extends React.Component<IpAddressViewProps>
|
||||
};
|
||||
|
||||
function fmt(num: number) : string {
|
||||
return formatter.padLeft(formatter.formatString(num, 'bin'), 8, '0');
|
||||
return formatter.padLeft(formatter.numberToString(num, 'bin'), 8, '0');
|
||||
}
|
||||
|
||||
export default IpAddressView;
|
||||
@@ -1,8 +1,6 @@
|
||||
import React from 'react';
|
||||
import CommandLink from '../../core/components/CommandLink';
|
||||
import './HelpResultView.css';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { faInfoCircle } from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
function HelpResultView() {
|
||||
|
||||
@@ -14,11 +12,7 @@ function HelpResultView() {
|
||||
<ul>
|
||||
<li><code><CommandLink text="23 | 34" /></code> — type bitwise expression to see the result in binary</li>
|
||||
<li><code><CommandLink text="23 34" /></code> — type one or more numbers to see their binary representations</li>
|
||||
</ul>
|
||||
<p>
|
||||
<FontAwesomeIcon icon={faInfoCircle} className='icon' />
|
||||
<u>Negative</u> 64-bit numbers (lower than int32 min value of <code>-2,147,483,647</code>) are not supported.
|
||||
</p>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="section">
|
||||
<strong className="section-title soft">IP Address & Networking Commands</strong>
|
||||
|
||||
Reference in New Issue
Block a user