Flags.cxx

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2001-2004 MUSIC TECHNOLOGY GROUP (MTG)
00003  *                         UNIVERSITAT POMPEU FABRA
00004  *
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  */
00021 
00022 #include "Flags.hxx"
00023 
00024 #include <bitset>
00025 #include <string>
00026 #include <iostream>
00027 #include <iomanip>
00028 #include <sstream>
00029 #include "Component.hxx"
00030 #include "XMLAdapter.hxx"
00031 
00032 // TODO: This is provisional to share the IllegalValue exception
00033 #include "Enum.hxx"
00034 
00035 using namespace CLAM;
00036 
00042 std::string FlagsBase::GetFlagString(unsigned int whichOne) const throw (IllegalValue) {
00043         for (unsigned int i = 0; mFlagValues[i].name; i++) {
00044                 if (whichOne==mFlagValues[i].value) 
00045                         return mFlagValues[i].name;
00046         }
00047         throw IllegalValue("Name not defined for an active flag");
00048         return "UnnamedFlag";
00049 }
00055 unsigned int FlagsBase::GetFlagPosition(const std::string & whichOne) const throw (IllegalValue) {
00056         for (int i = 0; mFlagValues[i].name; i++) {
00057                 if (whichOne==mFlagValues[i].name) 
00058                         return mFlagValues[i].value;
00059         }
00060         throw IllegalValue("Name not defined for an active flag");
00061         return this->GetNFlags();
00062 }
00063 
00064 /* 
00065  * Stores component's subitems on the given Storage
00066  * @param store The given storage where the subitem will be stored
00067  * @see Storage
00068  * @todo TODO: This method can throw and IllegalValue exception
00069  */
00070 void FlagsBase::StoreOn (Storage & storage) const {
00071         unsigned int N=GetNFlags();
00072         for (unsigned int i=0; i<N; i++) {
00073                 if (!IsSetFlag(i)) continue;
00074                 std::string s = GetFlagString(i);
00075                 XMLAdapter<std::string> adapter(s);
00076                 storage.Store(adapter);
00077         }
00078 }
00079 /* 
00080  * Loads component's subitems from the given Storage
00081  * @param store The given storage where the subitem will be stored
00082  * @see Storage
00083  * @todo TODO: This method can throw and IllegalValue exception
00084  */
00085 void FlagsBase::LoadFrom (Storage & storage) {
00086         unsigned int N=GetNFlags();
00087         for (unsigned int i=0; i<N; i++) {
00088                 SetFlag(i,false);
00089         }
00090         do {
00091                 std::string flagName;
00092                 XMLAdapter<std::string> adapter(flagName);
00093                 if (!storage.Load(adapter)) break;
00094                 unsigned int i = GetFlagPosition(flagName);
00095                 SetFlag(i,true);
00096         }
00097         while (true);
00098 }
00099 
00100 std::istream & CLAM::operator >> (std::istream & is, FlagsBase & f) {
00101         const unsigned int N = f.GetNFlags();
00102         bool * bs = new bool[N];
00103         for (unsigned int i=N; i--; ) {
00104                 bs[i]=false;
00105         }
00106         if (is.flags() & std::ios::skipws) {
00107                 char c = '\0';
00108                 do
00109                         is.get(c);
00110                 while (is && isspace(c));
00111                 if (is) is.putback(c);
00112         }
00113         char c = '\0';
00114         is >> c;
00115         if (c!='{') {
00116                 if (is) is.putback(c);
00117                 std::cerr << "A flag starting with '" << c << "'" << std::endl;
00118                 delete [] bs;
00119                 return is;
00120         }
00121         std::string flagContent;
00122         std::getline(is,flagContent,'}');
00123         std::stringstream ss(flagContent);
00124         std::string flagName;
00125         while (ss>>flagName) {
00126                 try {
00127                         unsigned i = f.GetFlagPosition(flagName);
00128                         bs[i]=true;
00129                 }
00130                 catch (IllegalValue) {
00131                         delete [] bs;
00132                         throw IllegalValue(std::string("Invalid flag name: '")+
00133                                 flagName+"'");
00134                 }
00135         }
00136         for (unsigned i=N; i--;) f.SetFlag(i, bs[i]);
00137         delete [] bs;
00138         return is;
00139 }
00140 
00141 std::ostream & CLAM::operator << (std::ostream & os, const FlagsBase & f) {
00142         const unsigned int N = f.GetNFlags();
00143         bool first = true;
00144         os << "{";
00145         for (unsigned int i=0; i<N; i++) {
00146                 if (f.IsSetFlag(i)) {
00147                         if (!first) os << " ";
00148                         else first=false;
00149                         os << f.GetFlagString(i);
00150                 }
00151         }
00152         os << "}";
00153         return os;
00154 }
00155 
00167 bool FlagsBase::CheckInvariant() {
00168         // Test that the names array is not a NULL pointer (it still could be invalid)
00169         if (!mFlagValues) {
00170                 std::cerr << "Name definitions are a NULL pointer" << std::endl;
00171                 return false;
00172         }
00173         // Test that a NULL name is present at the end of the names array
00174         unsigned int top;
00175         for (top=0; top<=GetNFlags() && mFlagValues[top].name; top++) {
00176                 if (top==GetNFlags() && mFlagValues[top].name) {
00177                         std::cerr << "There are more names than flags or there is no NULL name "
00178                                 "at the end of the name array list" << std::endl;
00179                 return false;
00180                 }
00181         }
00182         // Test that the names array has no values replications and no names replications
00183         for (unsigned int i=0; i<top; i++) {
00184                 for (unsigned int j=i+1; j<top; j++) {
00185                         if (std::string(mFlagValues[i].name)==std::string(mFlagValues[j].name)) {
00186                                 std::cerr << "Warning: flag names '"<< mFlagValues[i].name 
00187                                         << "' and '" << mFlagValues[j].name 
00188                                         << "' are replicated" << std::endl;
00189                         }
00190                         if (mFlagValues[i].value==mFlagValues[j].value) {
00191                                 std::cerr << "Warning: flag values '"<< mFlagValues[i].value 
00192                                         << "' and '" << mFlagValues[j].value 
00193                                         << "' are replicated" << std::endl;
00194                         }
00195                 }
00196         }
00197         return true;
00198 }
00199 
Generated by  doxygen 1.6.3