tag.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 #include <hn/hnprec.h>
00020 #include "tag.h"
00021 #include <hn/utils.h>
00022 #include <hn/log.h>
00023 
00024 static const std::string TRACE_TAG("trace-tag");
00025 
00026 // Tag class
00027 Tag::Tag(std::istream &i) : m_opcode(0), m_valueType(0) {
00028         uint32_t offset = i.tellg();            // Needed for exception throwing
00029         logTrace(TRACE_TAG,
00030                 boost::format(" * Parsing tag at offset %d")
00031                 % Utils::hexDump(offset)
00032         );
00033         m_valueType = Utils::getVal<uint8_t>(i);
00034         if (m_valueType & 0x80) {
00035                 m_valueType &= 0x7f;
00036                 m_opcode = Utils::getVal<uint8_t>(i);
00037                 if ((m_valueType > 0x10) && (m_valueType -= 0x10)) {
00038                         m_value = Utils::getVal<std::string>(i, m_valueType);
00039                         m_valueType = TT_STRING;
00040                         logTrace(TRACE_TAG,
00041                                 boost::format("   NewTag parsing complete: %s")
00042                                 % dump()
00043                         );
00044                         return;
00045                 }
00046         } else {
00047                 uint16_t len = Utils::getVal<uint16_t>(i);
00048                 if (len == 1) {
00049                         m_opcode = Utils::getVal<uint8_t>(i);
00050                 } else {
00051                         m_name = Utils::getVal<std::string>(i, len);
00052                 }
00053         }
00054         logTrace(TRACE_TAG,
00055                 boost::format("   Tag header parsed: %s") % dump(false)
00056         );
00057         switch (m_valueType) {
00058                 case TT_UINT8:
00059                         m_value = static_cast<uint32_t>(
00060                                 Utils::getVal<uint8_t>(i)
00061                         );
00062                         break;
00063                 case TT_UINT16:
00064                         m_value = static_cast<uint32_t>(
00065                                 Utils::getVal<uint16_t>(i)
00066                         );
00067                         break;
00068                 case TT_UINT32:
00069                         m_value = Utils::getVal<uint32_t>(i);
00070                         break;
00071                 case TT_STRING: {
00072                         uint16_t len = Utils::getVal<uint16_t>(i);
00073                         m_value = Utils::getVal<std::string>(i, len);
00074                         break;
00075                 }
00076                 case TT_FLOAT:
00077                         m_value = Utils::getVal<float>(i);
00078                         break;
00079                 case TT_BOOL:
00080                         i.seekg(1, std::ios::cur);
00081                         break;
00082                 case TT_BOOLARR:
00083                         i.seekg(Utils::getVal<uint16_t>(i), std::ios::cur);
00084                         break;
00085                 case TT_BLOB:
00086                         i.seekg(Utils::getVal<uint16_t>(i), std::ios::cur);
00087                         break;
00088                 case TT_HASH:
00089                         i.seekg(16, std::ios::cur);
00090                         break;
00091                 default:
00092                         throw TagError(
00093                                 boost::format(
00094                                         "invalid valuetype %s at offset %s"
00095                                 ) % Utils::hexDump(m_valueType)
00096                                 % Utils::hexDump(offset)
00097                         );
00098         }
00099         logTrace(TRACE_TAG,
00100                 boost::format("   Tag parsing complete. Tag data: %s") % dump()
00101         );
00102 }
00103 
00104 std::ostream& operator<<(std::ostream &o, const Tag &t) {
00105         Utils::putVal<uint8_t>(o, t.m_valueType);
00106         Utils::putVal<uint16_t>(o, t.m_name.size() ? t.m_name.size() : 1);
00107         if (t.m_name.size()) {
00108                 Utils::putVal(o, t.m_name, t.m_name.size());
00109         } else {
00110                 Utils::putVal<uint8_t>(o, t.m_opcode);
00111         }
00112         using boost::any_cast;
00113         switch (t.m_valueType) {
00114                 case Tag::TT_UINT8:
00115                         Utils::putVal<uint8_t>(o, any_cast<uint8_t>(t.m_value));
00116                         break;
00117                 case Tag::TT_UINT16:
00118                         Utils::putVal<uint16_t>(
00119                                 o, any_cast<uint16_t>(t.m_value)
00120                         );
00121                         break;
00122                 case Tag::TT_UINT32:
00123                         Utils::putVal<uint32_t>(
00124                                 o, any_cast<uint32_t>(t.m_value)
00125                         );
00126                         break;
00127                 case Tag::TT_STRING: {
00128                         uint16_t len = any_cast<std::string>(t.m_value).size();
00129                         Utils::putVal<uint16_t>(o, len);
00130                         Utils::putVal(o, any_cast<std::string>(t.m_value), len);
00131                         break;
00132                 }
00133                 case Tag::TT_FLOAT:
00134                         Utils::putVal<float>(o, any_cast<float>(t.m_value));
00135                         break;
00136                 case Tag::TT_BOOL:
00137                 case Tag::TT_BOOLARR:
00138                 case Tag::TT_BLOB:
00139                 case Tag::TT_HASH:
00140                 default:
00141                         throw TagError(
00142                                 boost::format("writing: invalid valuetype %s")
00143                                 % Utils::hexDump(t.m_valueType)
00144                         );
00145         }
00146         return o;
00147 }
00148 
00149 std::string Tag::dump(bool data) const {
00150         boost::format fmt("type=%1% %2%=%3% valueType=%4% value=%5%");
00151         using Utils::hexDump;
00152         fmt % hexDump(m_valueType) % (m_opcode ? "opcode" : "name");
00153         fmt % (m_opcode ? hexDump(m_opcode) : m_name) % hexDump(m_valueType);
00154         if (data) {
00155                 switch (m_valueType) {
00156                         case TT_UINT8:
00157                         case TT_UINT16:
00158                         case TT_UINT32:
00159                                 fmt % getInt();
00160                                 break;
00161                         case TT_FLOAT:
00162                                 fmt % getFloat();
00163                                 break;
00164                         case TT_STRING:
00165                                 fmt % Utils::hexDump(getStr());
00166                                 break;
00167                         default:
00168                                 fmt % "<unknown-type>";
00169                                 break;
00170                 }
00171         } else {
00172                 fmt % "<incomplete>";
00173         }
00174         return fmt.str();
00175 }
00176 
00177 void warnUnHandled(const std::string &loc, const Tag &t) {
00178         using boost::format;
00179         logWarning(format("Unhandled tag found in %1%: %2%") % loc % t.dump());
00180 }