utils.cpp

Go to the documentation of this file.
00001 /*
00002  *  Copyright (C) 2004-2005 Alo Sarv <madcat_@users.sourceforge.net>
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017  */
00018 
00019 /** @file utils.cpp Implementation of various useful utility functions */
00020 
00021 #include <hn/hnprec.h>
00022 #include <hn/utils.h>
00023 #include <sstream>
00024 
00025 namespace Utils {
00026         /**
00027          * Converts passed character to decimal notation.
00028          *
00029          * @param c         Hexadecimal-compatible unsigned character
00030          * @return          Decimal notation of given input
00031          */
00032         inline unsigned char hex2dec(unsigned char c) {
00033                 if (c >= '0' && c <= '9') c-='0';     // numbers
00034                 if (c >= 'A' && c <= 'G') c-='A'-10;  // upper-case letters
00035                 if (c >= 'a' && c <= 'g') c-='a'-10;  // lower-case letters
00036                 if (c > 15) {
00037                         throw std::runtime_error(
00038                                 "Hash::hex2dec: c > 15. Possibly input is not"
00039                                 " well-formed hexadecimal character."
00040                         );
00041                 }
00042                 return c;
00043         }
00044 
00045         // Decode data
00046         std::string decode(const char *data, uint32_t length) {
00047                 std::ostringstream o;
00048                 for (uint32_t i = 0; i < length; i++) {
00049                         uint16_t c = (data[i] < 0) ? data[i]+256 : data[i];
00050                         if (c < 16) {
00051                                 o << "0";
00052                         }
00053                         o << std::hex << c << std::dec;
00054                 }
00055                 CHECK_THROW(o.str().size() == length*2);
00056                 return o.str();
00057         }
00058 
00059         // Encode data
00060         std::string encode(const char *data, uint32_t length) {
00061                 std::string s;
00062                 for (uint32_t i = 0, j = 0; i < length; i++, j++) {
00063                         s    += hex2dec(data[  i]) * 16;
00064                         s[j] += hex2dec(data[++i]);
00065                 }
00066                 CHECK_THROW(s.size() == length/2);
00067                 return s;
00068         }
00069 
00070         // Produces standard hexdump to output stream of given data
00071         // The expected output is something like this:
00072         /*
00073 00000000  3c 3f 78 6d 6c 20 76 65  72 73 69 6f 6e 3d 22 31  |<?xml version="1|
00074 00000010  2e 30 22 20 65 6e 63 6f  64 69 6e 67 3d 22 55 54  |.0" encoding="UT|
00075 00000020  46 2d 38 22 3f 3e 0d 0a  3c 21 2d 2d 43 2b 2b 42  |F-8"?>..<!--C++B|
00076         */
00077         void hexDump(std::ostream &o, const std::string &data) {
00078                 uint32_t pos = 0;
00079                 int lpos = 0;
00080                 while (pos <= data.size()) try {
00081                         lpos = 0;
00082                         o << std::hex;
00083                         o.fill('0');
00084                         o.width(8);
00085                         // this is here to trigger exception if we'r out of
00086                         // range already at this point
00087                         data.at(pos);
00088                         o << pos << " ";
00089                         for (uint8_t i = 0; i < 8; ++i, ++lpos, pos++) {
00090                                 o << " ";
00091                                 int c = static_cast<int>(data.at(pos));
00092                                 if ((c < 0 ? c += 256 : c) < 16) {
00093                                         o << "0";
00094                                 }
00095                                 o << c;
00096                         }
00097                         o << " ";
00098                         for (uint8_t i = 0; i < 8; ++i, ++lpos, pos++) {
00099                                 o << " ";
00100                                 int c = static_cast<int>(data.at(pos));
00101                                 if ((c < 0 ? c += 256 : c) < 16) {
00102                                         o << "0";
00103                                 }
00104                                 o << c;
00105                         }
00106                         o << "  ";
00107                         o << "|";
00108                         pos -= 16;
00109                         for (uint8_t i = 0; i < 16; ++i, ++pos) {
00110                                 uint8_t c = data.at(pos);
00111                                 o.put((c > 32 && c < 127) ? c : '.');
00112                         }
00113                         o << "|" << std::endl;
00114                 } catch (std::out_of_range &) {
00115                         if (!(data.size() % 16)) {
00116                                 break;
00117                         }
00118                         int curpos = 12+3*lpos;
00119                         if (lpos < 8) {
00120                                 --curpos;
00121                         }
00122                         for (uint8_t i = 0; i < 60-curpos; ++i) {
00123                                 o << " ";
00124                         };
00125                         o << " |";
00126                         pos -= lpos;
00127                         for (uint8_t i = 0; i < lpos; ++i, ++pos) {
00128                                 uint8_t c = data.at(pos);
00129                                 if (c > 32 && c < 127) {
00130                                         o << c;
00131                                 } else {
00132                                         o << ".";
00133                                 }
00134                         }
00135                         o << "|" << std::endl;
00136                         break;
00137                 }
00138                 o << std::dec;
00139         }
00140 
00141         std::string hexDump(const std::string &data) {
00142                 std::ostringstream o;
00143                 o << std::endl;
00144                 hexDump(o, data);
00145                 return o.str();
00146         }
00147 }