1 (изменено: Rumata, 2013-07-25 00:52:47)

Тема: JS Шестнадцатеричное представление строки

Написал по мотивам темы JScript Шестнадцатеричное представление файла.

Краткое описание:

String#dumpHex()
Преобразует строковый объект в его шестнадцатеричное представление, которое сгруппировано по 16 символов, разделенных символом перевода строки, и включает в себя смещение каждой группы относительно начала строки, шестнадцатеричное представление группы и оригинал.

Исходный код:


(function()
{
    var ofsLen = 10;
    var ofsPad = new Array(10).join('0');

    var dumper = function(string)
    {
        return string.replace(/.|\n/g, function($0)
        {
            return ' ' + ('00' + $0.charCodeAt(0).toString(16)).slice(-2);
        });
    };

    String.prototype.dumpHex = function()
    {
        var offset = 0;

        var parts = this.match(/.{16}|.+/g);

        var tailLen = this.length % 16;
        var tailPart;
        var tailSpace;

        if ( tailLen ) {
            tailPart = parts.pop();
            tailSpace = new Array((16 - tailLen) * 3 + 1).join(' ');
        }

        var result = [];
        for (var i = 0; i < parts.length; i++) {
            var ofs = (ofsPad + offset.toString(16)).slice(-ofsLen);
            offset += 16;

            var orig = parts[i];

            result.push(ofs + ': ' + dumper(orig) + '  ' + orig);
        }

        if ( tailLen ) {
            result.push(ofs + ': ' + dumper(tailPart) + tailSpace + '  ' + tailPart);
        }

        return result.join('\n');
    };
})();

Пример использования:


var s = '0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz /+=';

var t = s.dumpHex();

alert(t);
( 2 * b ) || ! ( 2 * b )

2

Re: JS Шестнадцатеричное представление строки

Хм, интересно.

3 (изменено: max7, 2013-07-25 03:28:36)

Re: JS Шестнадцатеричное представление строки

Не, некошерно. А как же юникод?
Я бы переписал так:

var ofsLen = 10, 
    partLen = 8, 
    outPartBlockLen = (2 + 1 + 2 + 2),
    ofsPads = [""],
    tailPads = [""],
    re = (new RegExp(".{" + partLen.toString(10) + "}|.+", "g"));
    
for(var i = 1; i <= ofsLen; ++i)
   ofsPads[i] = (new Array(i)).join("0");
   
for(var i = 1; i <= partLen; ++i)
   tailPads[i] = (new Array(i * outPartBlockLen)).join(" ");
   
function string_dumpHex_bytes(out, part)
{
   for(var j = 0, charCode, ccb0, ccb1; j < part.length; ++j)
   {
      charCode = part.charCodeAt(j);
      ccb0 = (charCode & 0xff).toString(16);
      ccb1 = ((charCode >> 8) & 0xff).toString(16);
         
      if(ccb1.length == 1) { out.push("0"); } // (charCode & 0xf000) == 0
      out.push( ccb1, " " ); 
         
      if(ccb0.length == 1) { out.push("0"); } // (charCode & 0xf0) == 0
      out.push( ccb0, "  " );
   }
};

function string_dumpHex_offset(out, offset)
{
   var offs = offset.toString(16);
   out.push(ofsPads[ofsLen - offs.length], offs, ":   ");
};

String.prototype.dumpHex = function string_dumpHex()
{
   var parts = (this.match(re) || [""]); //this.split_len(partLen);
   var tail = parts.pop();
   
   var offset = 0, out = [];
   
   for(var i = 0; i < parts.length; ++i)
   {
      string_dumpHex_offset(out, offset);
      offset += partLen;
      string_dumpHex_bytes(out, parts[i]);
      out.push("  ", parts[i], "\n");
   }
   
   string_dumpHex_offset(out, offset);
   string_dumpHex_bytes(out, tail);
      
   if(tail.length < partLen)
      out.push(tailPads[partLen - tail.length], " ");  
      
   out.push("  ", tail);
   
   return out.join("");
};
alert(('0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz >Вова<').dumpHex())

4

Re: JS Шестнадцатеричное представление строки

С Unicode у всех проблемы. Лучше его не интерпретировать, чем интерпретировать неправильно.

max7
Ваш пример преобразует все символы строки в двухбайтовые коды, что не есть хорошо. Например "0" это "30", а не "00 30", как у Вас.

Кстати есть еще одна общая ошибка - забыли про управляющие символы. Следующий код исправляет эту ошибку:


(function()
{
    var ofsLen = 10;
    var ofsPad = new Array(10).join('0');

    var dumper = function(string)
    {
        return string.replace(/.|\n/g, function($0)
        {
            return ' ' + ('00' + $0.charCodeAt(0).toString(16)).slice(-2);
        });
    };

    var safer = function(string)
    {
        return string.replace(/[\x00-\x1F]/g, ' ');
    };

    String.prototype.dumpHex = function()
    {
        var offset = 0;

        var parts = this.match(/[\s\S]{16}|[\s\S]+/g);

        var tailLen = this.length % 16;
        var tailPart;
        var tailSpace;

        if ( tailLen ) {
            tailPart = parts.pop();
            tailSpace = new Array((16 - tailLen) * 3 + 1).join(' ');
        }

        var result = [];
        for (var i = 0; i < parts.length; i++) {
            var ofs = (ofsPad + offset.toString(16)).slice(-ofsLen);
            offset += 16;

            var orig = parts[i];

            result.push(ofs + ': ' + dumper(orig) + '  ' + safer(orig));
        }

        if ( tailLen ) {
            result.push(ofs + ': ' + dumper(tailPart) + tailSpace + '  ' + safer(tailPart));
        }

        return result.join('\n');
    };
})();
( 2 * b ) || ! ( 2 * b )

5 (изменено: max7, 2013-07-28 23:34:36)

Re: JS Шестнадцатеричное представление строки

Нет, с юникодом никаких проблем нет. У нас тут UCS-2 (и UTF-16), т. е. два байта. А про управляющие символы забыл. Придётся исправить.

((function()
{
   var ofsLen = 10, 
       partLen = 8, 
       outPartBlockLen = (2 + 1 + 2 + 2),
       ofsPads = [""],
       tailPads = [""];
       
   for(var i = 1; i <= ofsLen; ++i)
      ofsPads[i] = (new Array(i)).join("0");
      
   for(var i = 1; i <= partLen; ++i)
      tailPads[i] = (new Array(i * outPartBlockLen)).join(" ");
      
   function string_dumpHex_bytes(out, str)
   {
      for(var j = 0, charCode, ccb0, ccb1; j < str.length; ++j)
      {
         charCode = str.charCodeAt(j);
         ccb0 = (charCode & 0xff).toString(16);
         ccb1 = ((charCode >> 8) & 0xff).toString(16);
            
         if(ccb1.length == 1) { out.push("0"); } // (charCode & 0xf000) == 0
         out.push( ccb1, " " ); 
            
         if(ccb0.length == 1) { out.push("0"); } // (charCode & 0xf0) == 0
         out.push( ccb0, "  " );
      }
   };

   function string_dumpHex_offset(out, offset)
   {
      var offs = offset.toString(16);
      out.push(ofsPads[ofsLen - offs.length], offs, ":   ");
   };

   var __escape_char_map = 
   {
      "\b": "\\b",
      "\t": "\\t",
      "\n": "\\n",
      "\f": "\\f",
      "\r": "\\r",
      "\"": "\\\"",
      "\\": "\\\\",
      "\'": "\\\'",
      "\0": "\\0"
   };

   function string_dumpHex_escape(out, str)
   {
      for(var i = 0, ch, charCode; i < str.length; ++i)
      {
         ch = str.charAt(i);
         
         if((charCode = ch.charCodeAt(0)) <= 0x1f)
         {
            if(ch in __escape_char_map)
            {
               out.push(__escape_char_map[ch]);
            }
            else
            {
               ch = charCode.toString(16);
               out.push( "\\x" );
               if(ch.length == 1) { out.push("0"); } // (charCode & 0xf0) == 0
               out.push(ch);
            }
         }
         else
         {
            out.push(ch);
         }
      }
   };
   
   function string_dumpHex_split(str)
   {
      if(!str.length)
         return [""];
               
      var out = [];
         
      if(str.length > partLen)
      {
         for(var i = 0, ii = ((str.length/partLen)|0)*partLen; i < ii; i += partLen)
            out.push(str.substr(i,partLen));
                  
         if(str.length%partLen > 0)  
            out.push(str.substr(str.length - (str.length%partLen))); 
      }
      else
      {
         out.push(str);
      }
      
      return out;
   };

   String.prototype.dumpHex = function string_dumpHex()
   {
      var parts = string_dumpHex_split(this);
      var tail = parts.pop();
      
      var offset = 0, out = [];
      
      for(var i = 0; i < parts.length; ++i)
      {
         string_dumpHex_offset(out, offset);
         offset += partLen;
         string_dumpHex_bytes(out, parts[i]);
         
         out.push("  ");
         string_dumpHex_escape(out, parts[i]);
         out.push("\n");
      }
      
      string_dumpHex_offset(out, offset);
      string_dumpHex_bytes(out, tail);
         
      if(tail.length < partLen)
         out.push(tailPads[partLen - tail.length], " ");  
         
      out.push("  ");
      string_dumpHex_escape(out, tail);
      
      return out.join("");
   };
   
})());

И без регэкспов и реплейсов, вот!