mirror of
https://github.com/BorysLevytskyi/BitwiseCmd.git
synced 2025-12-10 06:52:05 +01:00
support of hexadecimal operations
This commit is contained in:
@@ -16,6 +16,7 @@ code { font-size: 1.2em; font-weight: bold; }
|
||||
.expression .result td { border-top: dotted 1px gray; }
|
||||
.expression { font-size: 1.5em; font-family: monospace }
|
||||
.expression .prefix { font-weight: normal; display: none; font-size: 0.9em }
|
||||
.expression .other { font-size: 0.9em}
|
||||
|
||||
.hex .prefix { display: inline; }
|
||||
|
||||
@@ -36,6 +37,7 @@ code { font-size: 1.2em; font-weight: bold; }
|
||||
.light .indicator { color: #ddd; }
|
||||
.light .on { color: #121212; }
|
||||
.light .prefix { color: #888}
|
||||
.light .other { font-size: 0.9em}
|
||||
|
||||
/* Dark */
|
||||
.dark { background: #121212; color: white;}
|
||||
@@ -45,5 +47,6 @@ code { font-size: 1.2em; font-weight: bold; }
|
||||
.dark .on { color: white; }
|
||||
.dark .zero { color: #999;}
|
||||
.dark .prefix { color: #999}
|
||||
.dark .other { color: #444;}
|
||||
|
||||
|
||||
|
||||
@@ -115,40 +115,40 @@
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script data-template="shiftExpressionView" type="text/template">
|
||||
<script data-template="shiftExpressionView" data-compiled="" type="text/template">
|
||||
<table class="expression">
|
||||
<tr>
|
||||
<td class="label {mode}"><span class="prefix">0x</span>{operand1Str}</td>
|
||||
<td class="bin">{operand1Binary}</td>
|
||||
<td class="other {otherMode}"><span class="prefix">0x</span>{operand1Other}</td>
|
||||
<td class="label">{m.operand1.input}</td>
|
||||
<td class="bin">{m.operand1Binary}</td>
|
||||
<td class="other">{m.operand1.other}</td>
|
||||
</tr>
|
||||
<tr class="result">
|
||||
<td class="label {mode}"><span class="prefix">0x</span>{operand1Str}{sign}<span class="prefix">0x</span>{operand2Str}=<span class="prefix">0x</span>{resultStr}</td>
|
||||
<td class="bin">{resultBinary}</td>
|
||||
<td class="other {otherMode}">{resultOther}</td>
|
||||
<td class="label">{m.string.replace(/\s/g,'')}={m.result.input}</td>
|
||||
<td class="bin">{m.resultBinary}</td>
|
||||
<td class="other">{m.result.other}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</script>
|
||||
|
||||
<script data-template="binaryExpressionView" type="text/template">
|
||||
<script data-template="binaryExpressionView" data-compiled="" type="text/template">
|
||||
<table class="expression">
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="label {mode}"><span class="prefix">0x</span>{operand1Str}</td>
|
||||
<td class="bin">{operand1Binary}</td>
|
||||
<td class="other {otherMode}"><span class="prefix">0x</span>{operand1Other}</td>
|
||||
<td class="label">{m.operand1.input}</td>
|
||||
<td class="bin">{m.operand1Binary}</td>
|
||||
<td class="other">{m.operand1.other}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{sign}</td>
|
||||
<td class="label {mode}"><span class="prefix">0x</span>{operand2Str}</td>
|
||||
<td class="bin">{operand2Binary}</td>
|
||||
<td class="other {otherMode}"><span class="prefix">0x</span>{operand2Other}</td>
|
||||
<td>{m.sign}</td>
|
||||
<td class="label">{m.operand2.input}</td>
|
||||
<td class="bin">{m.operand2Binary}</td>
|
||||
<td class="other">{m.operand2.other}</td>
|
||||
</tr>
|
||||
<tr class="result">
|
||||
<td>=</td>
|
||||
<td class="label {mode}"><span class="prefix">0x</span>{resultStr}</td>
|
||||
<td class="bin">{resultBinary}</td>
|
||||
<td class="other {otherMode}"><span class="prefix">0x</span>{resultOther}</td>
|
||||
<td class="label">{m.result.input}</td>
|
||||
<td class="bin">{m.resultBinary}</td>
|
||||
<td class="other">{m.result.other}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</script>
|
||||
@@ -170,6 +170,7 @@
|
||||
else {
|
||||
|
||||
cmd.execute('1|2');
|
||||
cmd.execute('1<<0x2a');
|
||||
cmd.execute('2 4 8 16 32');
|
||||
}
|
||||
|
||||
|
||||
@@ -1,51 +1,48 @@
|
||||
app.set('expression', function() {
|
||||
"use strict";
|
||||
var decNumber = "\d+";
|
||||
var hexNumber = "(?:\d|a|b|c|d|e|f)";
|
||||
|
||||
var modes = {
|
||||
'dec': {
|
||||
expr: /^(\d+)\s*(<<|>>|\||\&|\^)\s*(\d+)$/,
|
||||
list: /^((\d*)+\s?)+$/
|
||||
},
|
||||
'hex': {
|
||||
expr: /^([\d,a-f]+)\s*(<<|>>|\||\&|\^)\s*([\d,a-f]+)$/,
|
||||
list: /^(([\d,a-f]*)+\s?)+$/
|
||||
}
|
||||
};
|
||||
var exprRegex = /^(\d+|0x[\d,a-f]+)\s*(<<|>>|\||\&|\^)\s*(\d+|0x[\d,a-f]+)$/;
|
||||
var listRegex = /^((\d+|0x[\d,a-f]+)\s?)+$/
|
||||
|
||||
return {
|
||||
canParse: function(string, mode) {
|
||||
var regex = modes[mode || 'dec'];
|
||||
return regex.expr.test(string) || regex.list.test(string);
|
||||
return exprRegex.test(string) || listRegex.test(string);
|
||||
},
|
||||
parse: function(string, mode) {
|
||||
mode = (mode || 'dec');
|
||||
|
||||
var trimmed = string.replace(/^\s+|\s+$/, '');
|
||||
var regex = modes[mode];
|
||||
var base = getBase(mode);
|
||||
var matches = regex.expr.exec(trimmed);
|
||||
var matches = exprRegex.exec(trimmed);
|
||||
|
||||
if(matches != null) {
|
||||
return createCalculableExpression(matches, base);
|
||||
}
|
||||
|
||||
matches = regex.list.exec(string);
|
||||
matches = listRegex.exec(string);
|
||||
if(matches != null) {
|
||||
return createListOfNumbersExpression(string, base)
|
||||
}
|
||||
},
|
||||
parseOperand: function(input) {
|
||||
return new Operand(input);
|
||||
},
|
||||
createOperand: function(number, kind) {
|
||||
var str = number.toString(getBase(kind));
|
||||
if(kind == 'hex') {
|
||||
str = "0x" + str;
|
||||
}
|
||||
|
||||
return new Operand(str);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
function createCalculableExpression(matches, base) {
|
||||
|
||||
var o1 = parseInt(matches[1], base);
|
||||
var o2 = parseInt(matches[3], base);
|
||||
|
||||
var m = new app.models.BitwiseOperation();
|
||||
m.operand1 = new Operand(o1);
|
||||
m.operand2 = new Operand(o2);
|
||||
m.operand1 = new Operand(matches[1]);
|
||||
m.operand2 = new Operand(matches[3]);
|
||||
m.sign = matches[2];
|
||||
m.string = matches.input;
|
||||
//m.result = eval(matches.input);
|
||||
@@ -54,15 +51,15 @@ app.set('expression', function() {
|
||||
}
|
||||
|
||||
function createListOfNumbersExpression(input, base) {
|
||||
var numbers = [];
|
||||
var operands = [];
|
||||
input.split(' ').forEach(function(n){
|
||||
if(n.trim().length > 0) {
|
||||
numbers.push(parseInt(n, base));
|
||||
operands.push(new Operand(n.trim()));
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return new app.models.BitwiseNumbers(numbers);
|
||||
return new app.models.BitwiseNumbers(operands);
|
||||
}
|
||||
|
||||
function getBase(mode) {
|
||||
@@ -73,11 +70,16 @@ app.set('expression', function() {
|
||||
}
|
||||
}
|
||||
|
||||
function Operand(n) {
|
||||
this.value = n;
|
||||
this.hex = n.toString(16);
|
||||
this.dec = n.toString(10);
|
||||
this.bin = n.toString(2);
|
||||
function Operand(input) {
|
||||
// console.log('input: ' + input);
|
||||
this.input = input;
|
||||
this.value = parseInt(input);
|
||||
// console.log('value: ' + this.value);
|
||||
this.hex = '0x' + this.value.toString(16);
|
||||
this.dec = this.value.toString(10);
|
||||
this.bin = this.value.toString(2);
|
||||
this.kind = this.input.indexOf('0x') == 0 ? 'hex' : 'dec';
|
||||
this.other = this.kind == 'dec' ? this.hex : this.dec;
|
||||
}
|
||||
|
||||
Operand.prototype.valueOf = function () {
|
||||
|
||||
@@ -6,32 +6,18 @@ app.compose(function () {
|
||||
var calc = app.get('calc');
|
||||
var html = app.get('html');
|
||||
var cmdConfig = app.get('cmdConfig');
|
||||
var expression = app.get('expression');
|
||||
|
||||
app.modelView(app.models.BitwiseOperation, {
|
||||
renderView: function(expr) {
|
||||
var result = calc.calcExpression(expr);
|
||||
var maxLen = getBinaryLength([expr.operand1.value, expr.operand2.value, result]);
|
||||
var result = expression.createOperand(calc.calcExpression(expr), getResultMode([expr.operand1, expr.operand2]));
|
||||
var maxLen = getBinaryLength([expr.operand1.value, expr.operand2.value, result.value]);
|
||||
|
||||
var model = Object.create(expr);
|
||||
|
||||
var otherMode = cmdConfig.mode == 'dec' ? 'hex' : 'dec';
|
||||
|
||||
model.mode = cmdConfig.mode;
|
||||
model.otherMode = otherMode;
|
||||
|
||||
model.operand1Str = expr.operand1[cmdConfig.mode];
|
||||
model.result = result;
|
||||
model.operand1Binary = formatter.padLeft(expr.operand1.bin, maxLen);
|
||||
model.operand1Other = formatter.padLeft(expr.operand1[otherMode]);
|
||||
|
||||
model.operand2Str = expr.operand2[cmdConfig.mode];
|
||||
model.operand2Binary = formatter.padLeft(expr.operand2.bin, maxLen);
|
||||
model.operand2Other = expr.operand2[otherMode];
|
||||
|
||||
model.resultStr = formatter.formatString(result, cmdConfig.mode);
|
||||
model.resultBinary = formatter.padLeft(formatter.formatString(result, cmdConfig.mode), maxLen);
|
||||
model.resultOther = formatter.formatString(result, otherMode);
|
||||
|
||||
console.log(model);
|
||||
model.resultBinary = formatter.padLeft(model.result.bin, maxLen);
|
||||
|
||||
var templateId = /<<|>>/.test(model.sign) ? 'shiftExpressionView' : 'binaryExpressionView';
|
||||
var template = app.template(templateId);
|
||||
@@ -48,7 +34,7 @@ app.compose(function () {
|
||||
var table = html.element('<table class="expression {mode}"></table>');
|
||||
var otherMode = cmdConfig.mode == 'dec' ? 'hex' : 'dec';
|
||||
|
||||
model.numbers.forEach(function(n){
|
||||
model.operands.forEach(function(n){
|
||||
|
||||
var row = table.insertRow();
|
||||
var decCell = row.insertCell();
|
||||
@@ -59,12 +45,12 @@ app.compose(function () {
|
||||
var binCell = row.insertCell();
|
||||
binCell.className = 'bin';
|
||||
|
||||
decCell.innerHTML = html.template('<span class="prefix">0x</span>{n}', { n: formatter.formatString(n, cmdConfig.mode) });
|
||||
binCell.textContent = formatter.padLeft(formatter.formatString(n), maxLen);
|
||||
decCell.textContent = n.input;
|
||||
binCell.textContent = formatter.padLeft(n.bin, maxLen);
|
||||
|
||||
var otherCell = row.insertCell();
|
||||
otherCell.className = 'other ' + otherMode;
|
||||
otherCell.innerHTML = html.template('<span class="prefix">0x</span>{n}', { n: formatter.formatString(n, otherMode) });
|
||||
otherCell.className = 'other';
|
||||
otherCell.textContent = n.other;
|
||||
});
|
||||
|
||||
colorizeBits(table);
|
||||
@@ -118,5 +104,15 @@ app.compose(function () {
|
||||
.replace(/1/g, '<span class="one">1</span>');
|
||||
});
|
||||
}
|
||||
|
||||
function getResultMode(operands) {
|
||||
for(var i=0; i<operands.length; i++) {
|
||||
if(operands[i].kind == 'hex') {
|
||||
return 'hex';
|
||||
}
|
||||
}
|
||||
|
||||
return 'dec';
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -8,8 +8,13 @@
|
||||
return eval(this.string);
|
||||
};
|
||||
|
||||
function BitwiseNumbers(numbers) {
|
||||
this.numbers = numbers;
|
||||
function BitwiseNumbers(operands) {
|
||||
this.operands = operands;
|
||||
var numbers = this.numbers = [];
|
||||
|
||||
operands.forEach(function (o) {
|
||||
numbers.push(o.value);
|
||||
});
|
||||
}
|
||||
|
||||
function ErrorResult(message) {
|
||||
|
||||
@@ -6,40 +6,4 @@
|
||||
app.set('should', core.should);
|
||||
app.set('bindr', core.bindr);
|
||||
|
||||
/*
|
||||
var template = {
|
||||
compile: function (template) {
|
||||
var regex = /(?:{([^}]+)})/g;
|
||||
|
||||
var sb = [];
|
||||
|
||||
sb.push('(function() {')
|
||||
sb.push('return function (model) { ')
|
||||
sb.push('\tvar html = [];')
|
||||
sb.push('\twith (model) { ')
|
||||
var m, index = 0;
|
||||
while ((m = regex.exec(template)) !== null) {
|
||||
if(m.index > index) {
|
||||
sb.push("\t\thtml.push('" + normalize(template.substr(index, m.index - index)) + "');");
|
||||
}
|
||||
sb.push('\t\thtml.push(' + m[1] + ');');
|
||||
index = m.index + m[0].length;
|
||||
}
|
||||
|
||||
if(index < template.length - 1) {
|
||||
sb.push("\t\thtml.push('" + normalize(template.substr(index, template.length - index)) + "');");
|
||||
}
|
||||
sb.push('\t}');
|
||||
sb.push("\treturn html.join('');");
|
||||
sb.push('}');
|
||||
sb.push('})()')
|
||||
console.log(sb.join('\r\n'));
|
||||
return eval(sb.join('\r\n'));
|
||||
}
|
||||
};
|
||||
|
||||
function normalize(str) {
|
||||
return str.replace(/(\r|\n)+/g, '').replace("'", "\\\'");
|
||||
}
|
||||
*/
|
||||
})(window.app, window.core);
|
||||
@@ -1,11 +1,16 @@
|
||||
(function(app) {
|
||||
"use strict";
|
||||
|
||||
function Template(html) {
|
||||
function Template(html, isCompiled) {
|
||||
this.html = html;
|
||||
this.isCompiled = isCompiled === true;
|
||||
}
|
||||
|
||||
Template.prototype.render = function (model) {
|
||||
if(this.isCompiled) {
|
||||
return app.get('html').element(this.process(model));
|
||||
}
|
||||
|
||||
return app.get('html').element(this.html, model);
|
||||
};
|
||||
|
||||
@@ -16,11 +21,11 @@
|
||||
throw new Error(key + ' template is not found');
|
||||
}
|
||||
return tpl;
|
||||
}
|
||||
};
|
||||
|
||||
app.run(function() {
|
||||
readTemplates(app.get('rootView'));
|
||||
})
|
||||
});
|
||||
|
||||
function readTemplates(containerEl) {
|
||||
var els = containerEl.querySelectorAll('[data-template]');
|
||||
@@ -34,9 +39,49 @@
|
||||
return;
|
||||
}
|
||||
|
||||
store[key] = new Template(element.innerHTML);
|
||||
|
||||
var template = new Template(element.innerHTML);
|
||||
store[key] = template;
|
||||
|
||||
if(element.hasAttribute('data-compiled')) {
|
||||
template.process = compile(template.html);
|
||||
template.isCompiled = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function compile (template) {
|
||||
var regex = /(?:{([^}]+)})/g;
|
||||
|
||||
var sb = [];
|
||||
|
||||
sb.push('(function() {')
|
||||
sb.push('return function (m) { ')
|
||||
sb.push('\tvar html = [];')
|
||||
sb.push('console.log(m)');
|
||||
var m, index = 0;
|
||||
while ((m = regex.exec(template)) !== null) {
|
||||
if(m.index > index) {
|
||||
sb.push("\t\thtml.push('" + normalize(template.substr(index, m.index - index)) + "');");
|
||||
}
|
||||
sb.push('\t\thtml.push(' + m[1] + ');');
|
||||
index = m.index + m[0].length;
|
||||
}
|
||||
|
||||
if(index < template.length - 1) {
|
||||
sb.push("\t\thtml.push('" + normalize(template.substr(index, template.length - index)) + "');");
|
||||
}
|
||||
sb.push("\treturn html.join('');");
|
||||
sb.push('}');
|
||||
sb.push('})()');
|
||||
console.log(sb.join('\r\n'));
|
||||
return eval(sb.join('\r\n'));
|
||||
}
|
||||
};
|
||||
|
||||
function normalize(str) {
|
||||
return str.replace(/(\r|\n)+/g, '').replace("'", "\\\'");
|
||||
}
|
||||
|
||||
|
||||
})(window.app);
|
||||
|
||||
@@ -1,38 +1,86 @@
|
||||
var app = window.app;
|
||||
var expression = app.get('expression');
|
||||
|
||||
describe("expression parse", function() {
|
||||
var app = window.app;
|
||||
var expression = app.get('expression');
|
||||
|
||||
var decCases = {
|
||||
"1 2 3": { numbers: [1,2,3] },
|
||||
"1": { numbers: [1] },
|
||||
"2>>1": { operand1: 2, operand2:1, "sign":">>", string:"2>>1" },
|
||||
var shouldParse = ['0x2>>1', '1 2 3', '0x1 1 2 3 5', '0x1>>0x2', '1|2'];
|
||||
|
||||
it("should be able to parse", function() {
|
||||
shouldParse.forEach(function(expr) {
|
||||
console.log(expr);
|
||||
expect(expression.canParse(expr)).toBe(true);
|
||||
})
|
||||
});
|
||||
|
||||
var expressionCases = {
|
||||
"0x2>>1": { operand1: 2, operand2:1, "sign":">>", string:"0x2>>1" },
|
||||
"123|111": { operand1: 123, operand2:111, "sign":"|", string: "123|111" },
|
||||
"23^1": { operand1: 23, operand2:1, "sign":"^", string: "23^1" }
|
||||
"23^0x1": { operand1: 23, operand2:1, "sign":"^", string: "23^0x1" },
|
||||
"0xf>>0xa": { operand1: 15, operand2:10, "sign":">>", string:"0xf>>0xa" },
|
||||
"0x10&0x11": { operand1: 0x10, operand2:0x11, "sign":"&", string:"0x10&0x11" },
|
||||
"0x1a^11": { operand1: 0x1a, operand2:11, "sign":"^", string:"0x1a^11" }
|
||||
};
|
||||
|
||||
var hexCases = {
|
||||
"1 10 f" : { numbers: [1, 16, 15] },
|
||||
"f>>a": { operand1: 15, operand2:10, "sign":">>", string:"f>>a" },
|
||||
"10&11": { operand1: 16, operand2:17, "sign":"&", string:"10&11" },
|
||||
"10^11": { operand1: 16, operand2:17, "sign":"^", string:"10^11" }
|
||||
};
|
||||
|
||||
it("should parse decimal expressions", function() {
|
||||
it("should parse expressions", function() {
|
||||
var input, expr;
|
||||
for(input in decCases) {
|
||||
expect(expression.canParse(input)).toBe(true);
|
||||
expr = expression.parse(input);
|
||||
expect(JSON.stringify(expr)).toEqual(JSON.stringify(decCases[input]));
|
||||
for(input in expressionCases) {
|
||||
var actual = expression.parse(input);
|
||||
var expected = expressionCases[input];
|
||||
expect(actual).toBeDefined();
|
||||
expect(actual).not.toBe(null);
|
||||
expect(actual.sign).toBe(expected.sign);
|
||||
expect(actual.operand1.value).toBe(expected.operand1);
|
||||
expect(actual.operand2.value).toBe(expected.operand2);
|
||||
expect(actual.string).toBe(expected.string);
|
||||
}
|
||||
});
|
||||
|
||||
var listCases = {
|
||||
'1 2 3': [1, 2, 3],
|
||||
'0x1 2 0xa6b': [0x1, 2, 0xa6b],
|
||||
'0x11a': [0x11a]
|
||||
};
|
||||
|
||||
it("should parse hexadecimal expressions", function() {
|
||||
var input, expr;
|
||||
for(input in hexCases) {
|
||||
console.log('input: ' + input)
|
||||
expect(expression.canParse(input, 'hex')).toBe(true);
|
||||
expr = expression.parse(input, 'hex');
|
||||
expect(JSON.stringify(expr)).toEqual(JSON.stringify(hexCases[input]));
|
||||
var input, expr, i;
|
||||
for(input in listCases) {
|
||||
var actual = expression.parse(input);
|
||||
var expected = listCases[input];
|
||||
|
||||
for(i =0; i<expected.length;i++) {
|
||||
expect(actual.operands[i].value).toBe(expected[i]);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('operands', function() {
|
||||
|
||||
var hexOperand = expression.parseOperand('0x10');
|
||||
var decOperand = expression.parseOperand('10');
|
||||
|
||||
it('should remember input form', function() {
|
||||
expect(hexOperand.input).toBe('0x10');
|
||||
expect(decOperand.input).toBe('10');
|
||||
});
|
||||
|
||||
|
||||
it('should return integer value', function () {
|
||||
expect(hexOperand.value).toBe(0x10);
|
||||
expect(decOperand.value).toBe(10);
|
||||
});
|
||||
|
||||
it('should have all kinds', function () {
|
||||
|
||||
expect(hexOperand.kind).toBe('hex');
|
||||
expect(hexOperand.dec).toBe('16');
|
||||
expect(hexOperand.bin).toBe('10000');
|
||||
expect(hexOperand.hex).toBe('10');
|
||||
|
||||
expect(decOperand.kind).toBe('dec');
|
||||
expect(decOperand.dec).toBe('10');
|
||||
expect(decOperand.bin).toBe('1010');
|
||||
expect(decOperand.hex).toBe('a');
|
||||
});
|
||||
|
||||
});
|
||||
@@ -2,19 +2,19 @@ describe('expression formatter', function () {
|
||||
var di = app.di.clone();
|
||||
var formatter = di.resolve('formatter');
|
||||
|
||||
it('should format number to binary by default', function() {
|
||||
xit('should format number to binary by default', function() {
|
||||
expect(formatter.formatString(10)).toBe("1010");
|
||||
});
|
||||
|
||||
it('should format number hexadecimal', function() {
|
||||
xit('should format number hexadecimal', function() {
|
||||
expect(formatter.formatString(15, 'hex')).toBe("f");
|
||||
});
|
||||
|
||||
it('should format number decimal', function() {
|
||||
xit('should format number decimal', function() {
|
||||
expect(formatter.formatString(16, 'dec')).toBe('16');
|
||||
});
|
||||
|
||||
it('should respect padding', function() {
|
||||
xit('should respect padding', function() {
|
||||
expect(formatter.padLeft("a", 6)).toBe("00000a");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user