mirror of
https://github.com/BorysLevytskyi/BitwiseCmd.git
synced 2026-01-22 11:44:19 +01:00
Allow to switch a number sign (#47)
This commit is contained in:
@@ -3,7 +3,7 @@ import formatter from '../../core/formatter';
|
||||
import BinaryStringView, { FlipBitEventArg } from '../../core/components/BinaryString';
|
||||
import BitwiseResultViewModel from './BitwiseResultViewModel';
|
||||
import { Expression, ExpressionElement } from '../expression-interfaces';
|
||||
import { BitwiseOperator, ScalarValue } from '../expression';
|
||||
import { Operator, Operand, ListOfNumbers } from '../expression';
|
||||
import calc from '../../core/calc';
|
||||
|
||||
type BitwiseResultViewProps = {
|
||||
@@ -27,18 +27,18 @@ export default class BitwiseResultView extends React.Component<BitwiseResultView
|
||||
render() {
|
||||
|
||||
let model : BitwiseResultViewModel | null = null
|
||||
const isListOfNumbers = this.props.expression instanceof ListOfNumbers;
|
||||
|
||||
try
|
||||
{
|
||||
{
|
||||
model = BitwiseResultViewModel.createModel(this.props.expression, this.props.emphasizeBytes);
|
||||
}
|
||||
catch(err) {
|
||||
}
|
||||
catch(err) {
|
||||
const text = (err as any).message;
|
||||
return <div className='error'>Error: {text}</div>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var rows = this.getRows(model!);
|
||||
var rows = this.getRows(model!, isListOfNumbers);
|
||||
|
||||
return <table className="expression">
|
||||
<tbody>
|
||||
@@ -47,7 +47,7 @@ export default class BitwiseResultView extends React.Component<BitwiseResultView
|
||||
</table>
|
||||
}
|
||||
|
||||
getRows(model: BitwiseResultViewModel): JSX.Element[] {
|
||||
getRows(model: BitwiseResultViewModel, allowSignChange : boolean): JSX.Element[] {
|
||||
|
||||
this.maxSeenLengthNumberOfBits = Math.max(model.maxNumberOfBits, this.maxSeenLengthNumberOfBits);
|
||||
|
||||
@@ -58,6 +58,7 @@ export default class BitwiseResultView extends React.Component<BitwiseResultView
|
||||
css={itm.css}
|
||||
bitSize={itm.maxBitSize}
|
||||
allowFlipBits={itm.allowFlipBits}
|
||||
allowSignChange={allowSignChange}
|
||||
expressionItem={itm.expression}
|
||||
emphasizeBytes={this.props.emphasizeBytes}
|
||||
maxNumberOfBits={this.maxSeenLengthNumberOfBits}
|
||||
@@ -77,15 +78,20 @@ type ExpressionRowProps = {
|
||||
maxNumberOfBits: number,
|
||||
emphasizeBytes: boolean,
|
||||
allowFlipBits: boolean,
|
||||
allowSignChange: boolean,
|
||||
expressionItem: ExpressionElement,
|
||||
onBitFlipped: any
|
||||
}
|
||||
|
||||
class ExpressionRow extends React.Component<ExpressionRowProps> {
|
||||
|
||||
infoWasShown: boolean = false;
|
||||
|
||||
constructor(props: ExpressionRowProps) {
|
||||
super(props);
|
||||
this.state = { operand: null };
|
||||
}
|
||||
|
||||
render() {
|
||||
const { sign, css, maxNumberOfBits, emphasizeBytes, allowFlipBits } = this.props;
|
||||
const scalar = this.props.expressionItem.evaluate();
|
||||
@@ -113,17 +119,17 @@ class ExpressionRow extends React.Component<ExpressionRowProps> {
|
||||
// For expressions like |~2
|
||||
// TODO: find a better way...
|
||||
if (this.props.expressionItem.isOperator) {
|
||||
const ex = this.props.expressionItem as BitwiseOperator;
|
||||
return ex.operator + this.getLabelString(ex.getUnderlyingScalarOperand());
|
||||
const ex = this.props.expressionItem as Operator;
|
||||
return ex.operator + this.getLabelString(ex.getUnderlyingOperand());
|
||||
}
|
||||
|
||||
return this.getLabelString(this.props.expressionItem.getUnderlyingScalarOperand());
|
||||
return this.getLabelString(this.props.expressionItem.getUnderlyingOperand());
|
||||
}
|
||||
|
||||
getAlternative() {
|
||||
|
||||
if (this.props.expressionItem.isOperator) {
|
||||
const ex = this.props.expressionItem as BitwiseOperator;
|
||||
const ex = this.props.expressionItem as Operator;
|
||||
const res = ex.evaluate();
|
||||
|
||||
return formatter.numberToString(res.value, res.base);
|
||||
@@ -134,13 +140,13 @@ class ExpressionRow extends React.Component<ExpressionRowProps> {
|
||||
return formatter.numberToString(v.value, altBase);
|
||||
}
|
||||
|
||||
getLabelString(op: ScalarValue): string {
|
||||
getLabelString(op: Operand): string {
|
||||
return formatter.numberToString(op.value, op.base == 'bin' ? 'dec' : op.base);
|
||||
}
|
||||
|
||||
flipBit(args: FlipBitEventArg) {
|
||||
|
||||
const op = this.props.expressionItem.getUnderlyingScalarOperand();
|
||||
const op = this.props.expressionItem.getUnderlyingOperand();
|
||||
const { bitIndex: index, binaryStringLength: totalLength } = args;
|
||||
|
||||
const maxBitSize = op.value.maxBitSize;
|
||||
@@ -155,27 +161,47 @@ class ExpressionRow extends React.Component<ExpressionRowProps> {
|
||||
this.props.onBitFlipped();
|
||||
}
|
||||
|
||||
onChangeSign () {
|
||||
var op = this.props.expressionItem.getUnderlyingOperand();
|
||||
op.setValue(op.value.signed ? op.value.toUnsigned() : op.value.toSigned());
|
||||
this.forceUpdate();
|
||||
}
|
||||
|
||||
getInfo(maxNumberOfBits:number) {
|
||||
var op = this.props.expressionItem.getUnderlyingScalarOperand();
|
||||
|
||||
const op = this.props.expressionItem.getUnderlyingOperand();
|
||||
const allBitsDisplayed = op.value.maxBitSize != 32 || op.value.maxBitSize <= maxNumberOfBits;
|
||||
const { allowSignChange } = this.props;
|
||||
const hasLabel = op.label.length > 0;
|
||||
|
||||
if((op.value.maxBitSize != 32 || op.value.maxBitSize <= maxNumberOfBits) || op.label.length > 0)
|
||||
if(!allBitsDisplayed && !hasLabel && !this.infoWasShown)
|
||||
return null;
|
||||
|
||||
this.infoWasShown = true;
|
||||
|
||||
const children = [];
|
||||
let title = `BitwiseCmd treats this number as ${op.value.maxBitSize}-bit integer`;
|
||||
let text = `${op.value.maxBitSize}-bit `;
|
||||
const signedStr = op.value.signed ? 'signed' : 'unsigned';
|
||||
const signedOther = op.value.signed ? 'usigned' : 'signed';
|
||||
const signedTitle = `Click to change to ${signedOther} preserving the same bits`;
|
||||
|
||||
if(op.label.length > 0)
|
||||
{
|
||||
let title = `BitwiseCmd treats this number as ${op.value.maxBitSize}-bit integer`;
|
||||
let text = `${op.value.maxBitSize}-bit `;
|
||||
|
||||
if(!op.value.signed)
|
||||
text += " unsigned ";
|
||||
|
||||
if(op.label.length > 0)
|
||||
{
|
||||
text += " (converted)";
|
||||
title += ". This number was converted to facilitate bitwise operation with an operand of a different type";
|
||||
}
|
||||
|
||||
return <span title={title} style={{cursor:"help"}}>{text}</span>;
|
||||
text += " (converted)";
|
||||
title += ". This number was converted to facilitate bitwise operation with an operand of a different type";
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
children.push(<span title={title} style={{cursor:"help"}}>{text.trim()}</span>);
|
||||
|
||||
if(allBitsDisplayed)
|
||||
{
|
||||
if(allowSignChange)
|
||||
children.push(<button className='accent1' title={signedTitle} onClick={() => this.onChangeSign()}>{signedStr}</button>);
|
||||
else if(!op.value.signed)
|
||||
children.push(<span className='accent1'> {signedStr}</span>)
|
||||
}
|
||||
|
||||
return <React.Fragment>{children}</React.Fragment>
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ScalarValue, ListOfNumbersExpression, BitwiseOperationExpression, BitwiseOperator } from '../expression';
|
||||
import { Operand, ListOfNumbers, BitwiseOperation, Operator } from '../expression';
|
||||
import { ExpressionElement, Expression } from '../expression-interfaces';
|
||||
import calc from '../../core/calc';
|
||||
import formatter from '../../core/formatter';
|
||||
@@ -31,30 +31,30 @@ export default class BitwiseResultViewModel {
|
||||
this.allowFlipBits = allowFlipBits === true;
|
||||
}
|
||||
|
||||
static buildListOfNumbers(expr : ListOfNumbersExpression, config : Config) {
|
||||
static buildListOfNumbers(expr : ListOfNumbers, config : Config) {
|
||||
var model = new BitwiseResultViewModel(config);
|
||||
expr.children.forEach(op => model.addScalarRow(op));
|
||||
model.maxNumberOfBits = BitwiseResultViewModel.applyEmphasizeBytes(model.maxNumberOfBits, model.emphasizeBytes);
|
||||
return model;
|
||||
}
|
||||
|
||||
static buildBitwiseOperation (expr : BitwiseOperationExpression, config : Config) {
|
||||
static buildBitwiseOperation (expr : BitwiseOperation, config : Config) {
|
||||
|
||||
var op = expr.children[0],
|
||||
i = 0, len = expr.children.length,
|
||||
ex, m = new BitwiseResultViewModel(config);
|
||||
|
||||
var prev : ScalarValue | null = null;
|
||||
var prev : Operand | null = null;
|
||||
|
||||
for (;i<len;i++) {
|
||||
ex = expr.children[i];
|
||||
if(ex instanceof ScalarValue) {
|
||||
if(ex instanceof Operand) {
|
||||
m.addScalarRow(ex);
|
||||
prev = ex;
|
||||
continue;
|
||||
}
|
||||
|
||||
var eo = ex as BitwiseOperator;
|
||||
var eo = ex as Operator;
|
||||
|
||||
// If it a single NOT expression
|
||||
if(eo.isNotExpression) {
|
||||
@@ -64,11 +64,11 @@ export default class BitwiseResultViewModel {
|
||||
prev = notResult;
|
||||
}
|
||||
else if(eo.isShiftExpression){
|
||||
prev = eo.evaluate(prev as ScalarValue);
|
||||
prev = eo.evaluate(prev as Operand);
|
||||
m.addShiftExpressionResultRow(eo, prev);
|
||||
} else {
|
||||
|
||||
prev = eo.evaluate(prev as ScalarValue);
|
||||
prev = eo.evaluate(prev as Operand);
|
||||
m.addOperatorRow(eo);
|
||||
m.addExpressionResultRow(prev);
|
||||
}
|
||||
@@ -78,7 +78,7 @@ export default class BitwiseResultViewModel {
|
||||
return m;
|
||||
};
|
||||
|
||||
addScalarRow(expr: ScalarValue) {
|
||||
addScalarRow(expr: Operand) {
|
||||
const bits = calc.numberOfBitsDisplayed(expr.value);
|
||||
this.maxNumberOfBits = Math.max(bits, this.maxNumberOfBits);
|
||||
this.items.push({
|
||||
@@ -91,9 +91,9 @@ export default class BitwiseResultViewModel {
|
||||
});
|
||||
};
|
||||
|
||||
addOperatorRow(expr: BitwiseOperator) {
|
||||
addOperatorRow(expr: Operator) {
|
||||
|
||||
const resultNumber = expr.isNotExpression ? expr.evaluate() : expr.getUnderlyingScalarOperand();
|
||||
const resultNumber = expr.isNotExpression ? expr.evaluate() : expr.getUnderlyingOperand();
|
||||
const bits = calc.numberOfBitsDisplayed(resultNumber.value);
|
||||
|
||||
this.maxNumberOfBits = Math.max(bits, this.maxNumberOfBits);
|
||||
@@ -108,10 +108,10 @@ export default class BitwiseResultViewModel {
|
||||
});
|
||||
};
|
||||
|
||||
addShiftExpressionResultRow(expr : BitwiseOperator, resultExpr : ScalarValue) {
|
||||
addShiftExpressionResultRow(expr : Operator, resultExpr : Operand) {
|
||||
const bits = calc.numberOfBitsDisplayed(resultExpr.value);
|
||||
this.maxNumberOfBits = Math.max(bits, this.maxNumberOfBits);
|
||||
const child = expr.operand.getUnderlyingScalarOperand();
|
||||
const child = expr.operand.getUnderlyingOperand();
|
||||
this.items.push({
|
||||
sign: expr.operator + formatter.numberToString(child.value, child.base),
|
||||
css: 'expression-result',
|
||||
@@ -122,7 +122,7 @@ export default class BitwiseResultViewModel {
|
||||
});
|
||||
};
|
||||
|
||||
addExpressionResultRow(expr : ScalarValue) {
|
||||
addExpressionResultRow(expr : Operand) {
|
||||
const bits = calc.numberOfBitsDisplayed(expr.value);
|
||||
this.maxNumberOfBits = Math.max(bits, this.maxNumberOfBits);
|
||||
this.items.push({
|
||||
@@ -135,7 +135,7 @@ export default class BitwiseResultViewModel {
|
||||
});
|
||||
};
|
||||
|
||||
getLabel (op: ScalarValue) : string {
|
||||
getLabel (op: Operand) : string {
|
||||
|
||||
return formatter.numberToString(op.value, op.base === 'bin' ? 'dec' : op.base)
|
||||
}
|
||||
@@ -155,14 +155,15 @@ export default class BitwiseResultViewModel {
|
||||
};
|
||||
|
||||
static createModel(expr : Expression, emphasizeBytes: boolean) : BitwiseResultViewModel {
|
||||
if(expr instanceof ListOfNumbersExpression) {
|
||||
|
||||
if(expr instanceof ListOfNumbers) {
|
||||
return BitwiseResultViewModel.buildListOfNumbers(expr, {
|
||||
emphasizeBytes: emphasizeBytes,
|
||||
allowFlipBits: true
|
||||
});
|
||||
}
|
||||
|
||||
if(expr instanceof BitwiseOperationExpression) {
|
||||
if(expr instanceof BitwiseOperation) {
|
||||
return BitwiseResultViewModel.buildBitwiseOperation(expr, {
|
||||
emphasizeBytes: emphasizeBytes,
|
||||
allowFlipBits: true
|
||||
|
||||
Reference in New Issue
Block a user