LOG MESSAGE PARSER

by whelkaholism

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.2/moment.min.js"></script>
<script src="//cdn.cfront-cloud.co.uk/scripts/3/ko.datepicker.js"></script>
<div id="t" data-bind="text: ko.toJSON(LogItem, null, '\t')"></div>
<!-- ko with: LogItem -->
  <p>
    <label>Reason:</label>
    <b data-bind="text: reason"></b>
  </p>
  <p>
    <b>Original values:</b>
  </p>
  <div class="sub">
    <!-- ko foreach: Object.keys($data.original) -->
      <label data-bind="text: $data + ':'"></label>
      <b data-bind="text: $parent.original[$data]"></b><br/>
      <!-- /ko -->  
  </div>
  <p>
    <b>Reissued to tenants:</b>
  </p>
  <div class="sub">
    <!-- ko foreach: issuedtotenants['[]'] -->
      <b data-bind="text: $data"></b><br/>
      <!-- /ko -->  
  </div>
     <!-- /ko -->
<hr/>
<div id="d"></div>

CSS

#t { white-space: pre }
#d { display: none }

.sub { padding-left: 20px;}

JavaScript

var text ='reason=refrefes, original=[MonthlyRent=1500.00,A=B,C=\\[D], issuedtolandlord=False, issuedtotenants=[Rob,Stu], rent=Recalculated\\, okay';

//var text ='a=hi\\,there, b=world';

var log = function(msg, c, state)
{
	document.getElementById('d').innerHTML += msg + (c ? ' "' + c + '"' : '') + '</br>';
}

var Logging = {};
Logging.deserializeMessage = function(s)
{
	var res = {};
  
  var currname = '';
  var currvalue = '';
  var curr = res;
  var stack = [res];
  
  var f_addtoarr = function(o, n)
  {
  	o['[]'] = o['[]'] || [];
    o['[]'].push(n);
    o.length = o['[]'].length;
  };
  
	var actions =  {
    	buildprop: function(c, s) { (c != ' ') && (currname += c); log('buildprop', c, s);},
    	addprop: function(c, s) { curr[currname] = null; log('addprop', c, s);},
    	addpropasvalue: function(c, s) { f_addtoarr(curr, currname); currname = ''; log('addpropasvalue', c, s);},
      //
    	buildvalue: function(c, s) { currvalue += c; log('buildvalue', c, s); },
    	addvalue: function(c, s) { curr[currname] = currvalue; currname = ''; currvalue = ''; log('buildvalue', c, s); },
      //
      push: function(c, s) { curr[currname] = {}; curr = curr[currname]; stack.push(curr); currname = ''; log('push (-> ' + JSON.stringify(curr) + ')'); },
      pop: function(c, s) { if(currname) {  f_addtoarr(curr, currname); currname = ''; } stack.pop(); curr = stack[stack.length - 1]; log('pop (-> ' + JSON.stringify(curr) + ')'); }
   };

	var transitions = {
  	'_reserved': { '=':true, ',':true, '[':true, ']':true },
    '_escape': '\\',
  	'_start': {
      '*': { s: 'propname', a: actions.buildprop }
    },
  	'propname': {
      '=': { s: 'value', a: actions.addprop },
      ',': { a: actions.addpropasvalue },
      ']': { s: 'skip', a: actions.pop },
      '*': { a: actions.buildprop }
    },
  	'value': {
      ',': { s: 'propname', a: actions.addvalue },
      '[': { s:'propname', a: actions.push },
      ']': { s: 'skip', a: [actions.addvalue, actions.pop]...