CLAM-Development  1.4.0
Flags.cxx
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2001-2004 MUSIC TECHNOLOGY GROUP (MTG)
3  * UNIVERSITAT POMPEU FABRA
4  *
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */
21 
22 #include "Flags.hxx"
23 
24 #include <bitset>
25 #include <string>
26 #include <iostream>
27 #include <iomanip>
28 #include <sstream>
29 #include "Component.hxx"
30 #include "XMLAdapter.hxx"
31 
32 // TODO: This is provisional to share the IllegalValue exception
33 #include "Enum.hxx"
34 
35 using namespace CLAM;
36 
42 std::string FlagsBase::GetFlagString(unsigned int whichOne) const throw (IllegalValue) {
43  for (unsigned int i = 0; mFlagValues[i].name; i++) {
44  if (whichOne==mFlagValues[i].value)
45  return mFlagValues[i].name;
46  }
47  throw IllegalValue("Name not defined for an active flag");
48  return "UnnamedFlag";
49 }
55 unsigned int FlagsBase::GetFlagPosition(const std::string & whichOne) const throw (IllegalValue) {
56  for (int i = 0; mFlagValues[i].name; i++) {
57  if (whichOne==mFlagValues[i].name)
58  return mFlagValues[i].value;
59  }
60  throw IllegalValue("Name not defined for an active flag");
61  return this->GetNFlags();
62 }
63 
64 /*
65  * Stores component's subitems on the given Storage
66  * @param store The given storage where the subitem will be stored
67  * @see Storage
68  * @todo TODO: This method can throw and IllegalValue exception
69  */
70 void FlagsBase::StoreOn (Storage & storage) const {
71  unsigned int N=GetNFlags();
72  for (unsigned int i=0; i<N; i++) {
73  if (!IsSetFlag(i)) continue;
74  std::string s = GetFlagString(i);
75  XMLAdapter<std::string> adapter(s);
76  storage.Store(adapter);
77  }
78 }
79 /*
80  * Loads component's subitems from the given Storage
81  * @param store The given storage where the subitem will be stored
82  * @see Storage
83  * @todo TODO: This method can throw and IllegalValue exception
84  */
85 void FlagsBase::LoadFrom (Storage & storage) {
86  unsigned int N=GetNFlags();
87  for (unsigned int i=0; i<N; i++) {
88  SetFlag(i,false);
89  }
90  do {
91  std::string flagName;
92  XMLAdapter<std::string> adapter(flagName);
93  if (!storage.Load(adapter)) break;
94  unsigned int i = GetFlagPosition(flagName);
95  SetFlag(i,true);
96  }
97  while (true);
98 }
99 
100 std::istream & CLAM::operator >> (std::istream & is, FlagsBase & f) {
101  const unsigned int N = f.GetNFlags();
102  bool * bs = new bool[N];
103  for (unsigned int i=N; i--; ) {
104  bs[i]=false;
105  }
106  if (is.flags() & std::ios::skipws) {
107  char c = '\0';
108  do
109  is.get(c);
110  while (is && isspace(c));
111  if (is) is.putback(c);
112  }
113  char c = '\0';
114  is >> c;
115  if (c!='{') {
116  if (is) is.putback(c);
117  std::cerr << "A flag starting with '" << c << "'" << std::endl;
118  delete [] bs;
119  return is;
120  }
121  std::string flagContent;
122  std::getline(is,flagContent,'}');
123  std::stringstream ss(flagContent);
124  std::string flagName;
125  while (ss>>flagName) {
126  try {
127  unsigned i = f.GetFlagPosition(flagName);
128  bs[i]=true;
129  }
130  catch (IllegalValue) {
131  delete [] bs;
132  throw IllegalValue(std::string("Invalid flag name: '")+
133  flagName+"'");
134  }
135  }
136  for (unsigned i=N; i--;) f.SetFlag(i, bs[i]);
137  delete [] bs;
138  return is;
139 }
140 
141 std::ostream & CLAM::operator << (std::ostream & os, const FlagsBase & f) {
142  const unsigned int N = f.GetNFlags();
143  bool first = true;
144  os << "{";
145  for (unsigned int i=0; i<N; i++) {
146  if (f.IsSetFlag(i)) {
147  if (!first) os << " ";
148  else first=false;
149  os << f.GetFlagString(i);
150  }
151  }
152  os << "}";
153  return os;
154 }
155 
168  // Test that the names array is not a NULL pointer (it still could be invalid)
169  if (!mFlagValues) {
170  std::cerr << "Name definitions are a NULL pointer" << std::endl;
171  return false;
172  }
173  // Test that a NULL name is present at the end of the names array
174  unsigned int top;
175  for (top=0; top<=GetNFlags() && mFlagValues[top].name; top++) {
176  if (top==GetNFlags() && mFlagValues[top].name) {
177  std::cerr << "There are more names than flags or there is no NULL name "
178  "at the end of the name array list" << std::endl;
179  return false;
180  }
181  }
182  // Test that the names array has no values replications and no names replications
183  for (unsigned int i=0; i<top; i++) {
184  for (unsigned int j=i+1; j<top; j++) {
185  if (std::string(mFlagValues[i].name)==std::string(mFlagValues[j].name)) {
186  std::cerr << "Warning: flag names '"<< mFlagValues[i].name
187  << "' and '" << mFlagValues[j].name
188  << "' are replicated" << std::endl;
189  }
190  if (mFlagValues[i].value==mFlagValues[j].value) {
191  std::cerr << "Warning: flag values '"<< mFlagValues[i].value
192  << "' and '" << mFlagValues[j].value
193  << "' are replicated" << std::endl;
194  }
195  }
196  }
197  return true;
198 }
199