ctkPluginFrameworkUtil.cpp

Go to the documentation of this file.
00001 /*=============================================================================
00002 
00003   Library: CTK
00004 
00005   Copyright (c) 2010 German Cancer Research Center,
00006     Division of Medical and Biological Informatics
00007 
00008   Licensed under the Apache License, Version 2.0 (the "License");
00009   you may not use this file except in compliance with the License.
00010   You may obtain a copy of the License at
00011 
00012     http://www.apache.org/licenses/LICENSE-2.0
00013 
00014   Unless required by applicable law or agreed to in writing, software
00015   distributed under the License is distributed on an "AS IS" BASIS,
00016   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00017   See the License for the specific language governing permissions and
00018   limitations under the License.
00019 
00020 =============================================================================*/
00021 
00022 #include "ctkPluginFrameworkUtil_p.h"
00023 
00024 #include <QString>
00025 
00026 #include <stdexcept>
00027 
00028 
00032 class AttributeTokenizer {
00033 
00034 public:
00035 
00036   QString s;
00037   int length;
00038   int pos;
00039 
00040   AttributeTokenizer(const QString& input)
00041     : s(input), length(input.size()), pos(0)
00042   {
00043 
00044   }
00045 
00046   QString getWord()
00047   {
00048     skipWhite();
00049     bool backslash = false;
00050     bool quote = false;
00051     QString val;
00052     int end = 0;
00053     for (; pos < length; pos++)
00054     {
00055       bool breakLoop = false;
00056       if (backslash)
00057       {
00058         backslash = false;
00059         val.append(s.at(pos));
00060       }
00061       else
00062       {
00063         QChar c = s.at(pos);
00064         switch (c.toAscii())
00065         {
00066         case '"':
00067           quote = !quote;
00068           end = val.length();
00069           break;
00070         case '\\':
00071           backslash = true;
00072           break;
00073         case ',': case ':': case ';': case '=':
00074           if (!quote)
00075           {
00076             breakLoop = true;
00077             break;
00078           }
00079           // Fall through
00080         default:
00081           val.append(c);
00082           if (!c.isSpace())
00083           {
00084             end = val.length();
00085           }
00086           break;
00087         }
00088         if (breakLoop) break;
00089       }
00090     }
00091     if (quote || backslash || end == 0)
00092     {
00093       return QString();
00094     }
00095     return val.left(end);
00096   }
00097 
00098   QString getKey()
00099   {
00100     if (pos >= length) {
00101       return QString();
00102     }
00103     int save = pos;
00104     if (s.at(pos) == ';') {
00105       pos++;
00106     }
00107     QString res = getWord();
00108     if (!res.isNull()) {
00109       if (pos == length) {
00110         return res;
00111       }
00112       QChar c = s.at(pos);
00113       if (c == ';' || c == ',') {
00114         return res;
00115       }
00116     }
00117     pos = save;
00118     return QString();
00119   }
00120 
00121   QString getParam()
00122   {
00123     if (pos == length || s.at(pos) != ';') {
00124       return QString();
00125     }
00126     int save = pos++;
00127     QString res = getWord();
00128     if (!res.isNull()) {
00129       if (pos < length && s.at(pos) == '=') {
00130         return res;
00131       } if (pos + 1 < length && s.at(pos) == ':' && s.at(pos+1) == '=') {
00132         return res;
00133       }
00134     }
00135     pos = save;
00136     return QString();
00137   }
00138 
00139   bool isDirective()
00140   {
00141     if (pos + 1 < length && s.at(pos) == ':')
00142     {
00143       pos++;
00144       return true;
00145     }
00146     else
00147     {
00148       return false;
00149     }
00150   }
00151 
00152   QString getValue()
00153   {
00154     if (s.at(pos) != '=')
00155     {
00156       return QString();
00157     }
00158     int save = pos++;
00159     skipWhite();
00160     QString val = getWord();
00161     if (val.isNull())
00162     {
00163       pos = save;
00164       return QString();
00165     }
00166     return val;
00167   }
00168 
00169   bool getEntryEnd()
00170   {
00171     int save = pos;
00172     skipWhite();
00173     if (pos == length) {
00174       return true;
00175     } else if (s.at(pos) == ',') {
00176       pos++;
00177       return true;
00178     } else {
00179       pos = save;
00180       return false;
00181     }
00182   }
00183 
00184   bool getEnd()
00185   {
00186     int save = pos;
00187     skipWhite();
00188     if (pos == length) {
00189       return true;
00190     } else {
00191       pos = save;
00192       return false;
00193     }
00194   }
00195 
00196   QString getRest()
00197   {
00198     QString res = s.mid(pos).trimmed();
00199     return res.length() == 0 ? "<END OF LINE>" : res;
00200   }
00201 
00202 private:
00203 
00204   void skipWhite()
00205   {
00206     for (; pos < length; pos++) {
00207       if (!s.at(pos).isSpace()) {
00208         break;
00209       }
00210     }
00211   }
00212 };
00213 
00214 QList<QMap<QString, QStringList> > ctkPluginFrameworkUtil::parseEntries(const QString& a, const QString& s,
00215                                            bool single, bool unique, bool single_entry)
00216 {
00217   QList<QMap<QString, QStringList> > result;
00218   if (!s.isNull())
00219   {
00220     AttributeTokenizer at(s);
00221     do {
00222       QList<QString> keys;
00223       QMap<QString, QStringList > params;
00224       QStringList directives;
00225 
00226       QString key = at.getKey();
00227       if (key.isNull())
00228       {
00229         QString what = QString("Definition, ") + a + ", expected key at: " + at.getRest()
00230                        + ". Key values are terminated by a ';' or a ',' and may not "
00231                        + "contain ':', '='.";
00232         throw std::invalid_argument(what.toStdString());
00233       }
00234       if (!single)
00235       {
00236         keys.push_back(key);
00237         while (!(key = at.getKey()).isNull())
00238         {
00239           keys.push_back(key);
00240         }
00241       }
00242       QString param;
00243       while (!(param = at.getParam()).isNull())
00244       {
00245         QStringList& old = params[param];
00246         bool is_directive = at.isDirective();
00247         if (!old.isEmpty() && unique)
00248         {
00249           QString what = QString("Definition, ") + a + ", duplicate " +
00250                          (is_directive ? "directive" : "attribute") +
00251                          ": " + param;
00252           throw std::invalid_argument(what.toStdString());
00253         }
00254         QString value = at.getValue();
00255         if (value.isNull())
00256         {
00257           QString what = QString("Definition, ") + a + ", expected value at: " + at.getRest();
00258           throw std::invalid_argument(what.toStdString());
00259         }
00260         if (is_directive)
00261         {
00262           // NYI Handle directives and check them
00263           directives.push_back(param);
00264         }
00265         if (unique)
00266         {
00267           params.insert(param, QStringList(value));
00268         } else {
00269           old.push_back(value);
00270         }
00271       }
00272 
00273       if (at.getEntryEnd())
00274       {
00275         if (single)
00276         {
00277           params.insert("$key", QStringList(key));
00278         }
00279         else
00280         {
00281           params.insert("$keys", keys);
00282         }
00283         result.push_back(params);
00284       }
00285       else
00286       {
00287         QString what = QString("Definition, ") + a + ", expected end of entry at: " + at.getRest();
00288         throw std::invalid_argument(what.toStdString());
00289       }
00290 
00291       if (single_entry && !at.getEnd())
00292       {
00293         QString what = QString("Definition, ") + a + ", expected end of single entry at: " + at.getRest();
00294         throw std::invalid_argument(what.toStdString());
00295       }
00296 
00297       params.insert("$directives", directives); // $ is not allowed in
00298                                              // param names...
00299     } while (!at.getEnd());
00300   }
00301   return result;
00302 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines

Generated on 21 May 2010 for CTK by  doxygen 1.6.1