CLAM-Development
1.1
|
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