Confdump Agent
1.4.0
|
00001 /* 00002 * Confdump-Agent - Dump static and runtime system configuration 00003 * Copyright (C) 2009-2012 Straton IT, SAS 00004 * 00005 * This program is free software: you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 3 as 00007 * published by the Free Software Foundation. 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, see <http://www.gnu.org/licenses/>. 00016 */ 00017 00018 #include <cctype> 00019 #include <cassert> 00020 #include <iostream> 00021 #include <stdexcept> 00022 #include <string> 00023 00024 #include "boost/algorithm/string/trim.hpp" 00025 00026 #include "QVariant" 00027 00028 #include "Confdump/RuntimeError.hpp" 00029 #include "Confdump/System/FixedTable.hpp" 00030 #include "Confdump/System/ManagedElement.hpp" 00031 00032 using std::vector; 00033 using std::map; 00034 using std::string; 00035 using std::getline; 00036 using boost::shared_ptr; 00037 using boost::algorithm::trim; 00038 00039 namespace Confdump 00040 { 00041 00042 namespace System 00043 { 00044 00045 FixedTable::FixedTable() 00046 { 00047 } 00048 00049 FixedTable::~FixedTable() 00050 { 00051 } 00052 00053 void FixedTable::readHeaderFrom( QString headers) 00054 { 00055 //needs to be optimisated by converting each called function to use QString instead of std::String 00056 switch ( specification_.parsingMode() ) 00057 { 00058 case UseSpecifiedHeaders: 00059 checkColumnPositionsFromSpecification( headers.toStdString() ); 00060 break; 00061 00062 case DetectWidthsFromHeader: 00063 detectColumnPositionsFromLine( headers.toStdString()); 00064 break; 00065 } 00066 00067 splitLineOnColumnPositions( headers.toStdString(), header_ ); 00068 } 00069 00070 bool FixedTable::readLineFrom( QString line, boost::shared_ptr<ManagedElement> row ) 00071 { 00072 00073 vector<string> lineData; 00074 splitLineOnColumnPositions( line.toStdString(), lineData ); 00075 for ( unsigned i = 0; i < lineData.size(); ++i ) 00076 { 00077 string translatedHeader; 00078 map<string, string>::iterator translation = fieldTranslations_.find( header_[i] ); 00079 if ( translation != fieldTranslations_.end() ) 00080 translatedHeader = translation->second; 00081 else 00082 translatedHeader = header_[i]; 00083 00084 QString unicodeData( QString::fromLocal8Bit( lineData[i].c_str() ) ); 00085 row->setProperty( translatedHeader.c_str(), unicodeData ); 00086 } 00087 00088 return true; 00089 } 00090 00091 void FixedTable::detectColumnPositionsFromLine( const std::string &line ) 00092 { 00093 columnPositions_.clear(); 00094 00095 bool scanning = true; 00096 for ( string::size_type i = 0; i < line.size(); ++i ) 00097 { 00098 if ( scanning ) // looking for the next column 00099 { 00100 if ( line[i] != ' ' ) 00101 { 00102 scanning = false; 00103 columnPositions_.push_back( i ); 00104 } 00105 } 00106 else // reading a column 00107 { 00108 if ( line[i] == ' ' ) 00109 { 00110 scanning = true; 00111 } 00112 } 00113 } 00114 00115 // If the line was empty, consider it as a single column 00116 if ( columnPositions_.empty() ) 00117 columnPositions_.push_back( 0 ); 00118 00119 // For the ease of later use, add a dummy EOL end position 00120 columnPositions_.push_back( line.size() ); 00121 } 00122 00123 void FixedTable::checkColumnPositionsFromSpecification( const std::string &line ) 00124 { 00125 columnPositions_.clear(); 00126 00127 unsigned columnStart = 0; 00128 for ( Specification::ColumnHeadIterator head = specification_.columnHeadsBegin(); 00129 head != specification_.columnHeadsEnd(); ++head ) 00130 { 00131 if ( line.size() >= columnStart + head->skip + head->width ) // Size 00132 { 00133 string headerChunk = line.substr( columnStart + head->skip, head->width ); 00134 trim( headerChunk ); 00135 00136 if ( headerChunk == head->name ) // Trimmed contents 00137 { 00138 columnPositions_.push_back( columnStart + head->skip ); 00139 columnStart += head->skip + head->width; 00140 } 00141 else 00142 { 00143 throw RuntimeError( QObject::tr( "Expected column head '%1', got '%2'" ).arg( QString::fromStdString( head->name ) ).arg( QString::fromStdString( headerChunk ) ) ); 00144 } 00145 } 00146 else 00147 { 00148 throw RuntimeError( QObject::tr( "Reached unexpected end of header line while reading column head '%1'" ).arg( QString::fromStdString( head->name ) ) ); 00149 } 00150 } 00151 00152 // For the ease of later use, add a dummy EOL end position 00153 columnPositions_.push_back( line.size() ); 00154 } 00155 00156 void FixedTable::splitLineOnColumnPositions( const std::string &line, vector<string> &row ) 00157 { 00158 for ( string::size_type i = 0; i < columnPositions_.size()-1; ++i ) 00159 { 00160 string cell; 00161 if ( columnPositions_[i] < columnPositions_[i+1] - 1 ) 00162 { 00163 cell = string( 00164 line.c_str() + columnPositions_[i], 00165 line.c_str() + columnPositions_[i+1] - 1 ); 00166 } 00167 trim( cell ); 00168 row.push_back( cell ); 00169 } 00170 } 00171 00172 void FixedTable::setSpecification( const Specification &spec ) 00173 { 00174 specification_ = spec; 00175 } 00176 00177 void FixedTable::setFieldTranslations( const std::map<string, string> &translations ) 00178 { 00179 fieldTranslations_ = translations; 00180 } 00181 00182 00183 /* 00184 * FixedTable::Specification 00185 */ 00186 00187 FixedTable::Specification::Specification() 00188 { 00189 } 00190 00191 FixedTable::Specification::~Specification() 00192 { 00193 } 00194 00195 FixedTable::Specification& FixedTable::Specification::addColumnHead( const std::string &name, unsigned skip, unsigned width ) 00196 { 00197 ColumnHead head; 00198 head.name = name; 00199 head.skip = skip; 00200 head.width = width; 00201 00202 columnHeads_.push_back( head ); 00203 00204 return *this; 00205 } 00206 00207 FixedTable::Specification::ColumnHeadIterator FixedTable::Specification::columnHeadsBegin() const 00208 { 00209 return columnHeads_.begin(); 00210 } 00211 00212 FixedTable::Specification::ColumnHeadIterator FixedTable::Specification::columnHeadsEnd() const 00213 { 00214 return columnHeads_.end(); 00215 } 00216 00217 } 00218 }