Home | History | Annotate | Download | only in Common
      1 // CommandLineParser.cpp
      2 
      3 #include "StdAfx.h"
      4 
      5 #include "CommandLineParser.h"
      6 
      7 namespace NCommandLineParser {
      8 
      9 bool SplitCommandLine(const UString &src, UString &dest1, UString &dest2)
     10 {
     11   dest1.Empty();
     12   dest2.Empty();
     13   bool quoteMode = false;
     14   int i;
     15   for (i = 0; i < src.Length(); i++)
     16   {
     17     wchar_t c = src[i];
     18     if (c == L' ' && !quoteMode)
     19     {
     20       dest2 = src.Mid(i + 1);
     21       return i != 0;
     22     }
     23     if (c == L'\"')
     24       quoteMode = !quoteMode;
     25     else
     26       dest1 += c;
     27   }
     28   return i != 0;
     29 }
     30 
     31 void SplitCommandLine(const UString &s, UStringVector &parts)
     32 {
     33   UString sTemp = s;
     34   sTemp.Trim();
     35   parts.Clear();
     36   for (;;)
     37   {
     38     UString s1, s2;
     39     if (SplitCommandLine(sTemp, s1, s2))
     40       parts.Add(s1);
     41     if (s2.IsEmpty())
     42       break;
     43     sTemp = s2;
     44   }
     45 }
     46 
     47 
     48 static const wchar_t kSwitchID1 = '-';
     49 // static const wchar_t kSwitchID2 = '/';
     50 
     51 static const wchar_t kSwitchMinus = '-';
     52 static const wchar_t *kStopSwitchParsing = L"--";
     53 
     54 static bool IsItSwitchChar(wchar_t c)
     55 {
     56   return (c == kSwitchID1 /*|| c == kSwitchID2 */);
     57 }
     58 
     59 CParser::CParser(int numSwitches):
     60   _numSwitches(numSwitches)
     61 {
     62   _switches = new CSwitchResult[_numSwitches];
     63 }
     64 
     65 CParser::~CParser()
     66 {
     67   delete []_switches;
     68 }
     69 
     70 void CParser::ParseStrings(const CSwitchForm *switchForms,
     71   const UStringVector &commandStrings)
     72 {
     73   int numCommandStrings = commandStrings.Size();
     74   bool stopSwitch = false;
     75   for (int i = 0; i < numCommandStrings; i++)
     76   {
     77     const UString &s = commandStrings[i];
     78     if (stopSwitch)
     79       NonSwitchStrings.Add(s);
     80     else
     81       if (s == kStopSwitchParsing)
     82         stopSwitch = true;
     83       else
     84         if (!ParseString(s, switchForms))
     85           NonSwitchStrings.Add(s);
     86   }
     87 }
     88 
     89 // if string contains switch then function updates switch structures
     90 // out: (string is a switch)
     91 bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms)
     92 {
     93   int len = s.Length();
     94   if (len == 0)
     95     return false;
     96   int pos = 0;
     97   if (!IsItSwitchChar(s[pos]))
     98     return false;
     99   while (pos < len)
    100   {
    101     if (IsItSwitchChar(s[pos]))
    102       pos++;
    103     const int kNoLen = -1;
    104     int matchedSwitchIndex = 0; // GCC Warning
    105     int maxLen = kNoLen;
    106     for (int switchIndex = 0; switchIndex < _numSwitches; switchIndex++)
    107     {
    108       int switchLen = MyStringLen(switchForms[switchIndex].IDString);
    109       if (switchLen <= maxLen || pos + switchLen > len)
    110         continue;
    111 
    112       UString temp = s + pos;
    113       temp = temp.Left(switchLen);
    114       if (temp.CompareNoCase(switchForms[switchIndex].IDString) == 0)
    115       // if (_strnicmp(switchForms[switchIndex].IDString, LPCSTR(s) + pos, switchLen) == 0)
    116       {
    117         matchedSwitchIndex = switchIndex;
    118         maxLen = switchLen;
    119       }
    120     }
    121     if (maxLen == kNoLen)
    122       throw "maxLen == kNoLen";
    123     CSwitchResult &matchedSwitch = _switches[matchedSwitchIndex];
    124     const CSwitchForm &switchForm = switchForms[matchedSwitchIndex];
    125     if ((!switchForm.Multi) && matchedSwitch.ThereIs)
    126       throw "switch must be single";
    127     matchedSwitch.ThereIs = true;
    128     pos += maxLen;
    129     int tailSize = len - pos;
    130     NSwitchType::EEnum type = switchForm.Type;
    131     switch(type)
    132     {
    133       case NSwitchType::kPostMinus:
    134         {
    135           if (tailSize == 0)
    136             matchedSwitch.WithMinus = false;
    137           else
    138           {
    139             matchedSwitch.WithMinus = (s[pos] == kSwitchMinus);
    140             if (matchedSwitch.WithMinus)
    141               pos++;
    142           }
    143           break;
    144         }
    145       case NSwitchType::kPostChar:
    146         {
    147           if (tailSize < switchForm.MinLen)
    148             throw "switch is not full";
    149           UString set = switchForm.PostCharSet;
    150           const int kEmptyCharValue = -1;
    151           if (tailSize == 0)
    152             matchedSwitch.PostCharIndex = kEmptyCharValue;
    153           else
    154           {
    155             int index = set.Find(s[pos]);
    156             if (index < 0)
    157               matchedSwitch.PostCharIndex =  kEmptyCharValue;
    158             else
    159             {
    160               matchedSwitch.PostCharIndex = index;
    161               pos++;
    162             }
    163           }
    164           break;
    165         }
    166       case NSwitchType::kLimitedPostString:
    167       case NSwitchType::kUnLimitedPostString:
    168         {
    169           int minLen = switchForm.MinLen;
    170           if (tailSize < minLen)
    171             throw "switch is not full";
    172           if (type == NSwitchType::kUnLimitedPostString)
    173           {
    174             matchedSwitch.PostStrings.Add(s.Mid(pos));
    175             return true;
    176           }
    177           int maxLen = switchForm.MaxLen;
    178           UString stringSwitch = s.Mid(pos, minLen);
    179           pos += minLen;
    180           for (int i = minLen; i < maxLen && pos < len; i++, pos++)
    181           {
    182             wchar_t c = s[pos];
    183             if (IsItSwitchChar(c))
    184               break;
    185             stringSwitch += c;
    186           }
    187           matchedSwitch.PostStrings.Add(stringSwitch);
    188           break;
    189         }
    190       case NSwitchType::kSimple:
    191           break;
    192     }
    193   }
    194   return true;
    195 }
    196 
    197 const CSwitchResult& CParser::operator[](size_t index) const
    198 {
    199   return _switches[index];
    200 }
    201 
    202 /////////////////////////////////
    203 // Command parsing procedures
    204 
    205 int ParseCommand(int numCommandForms, const CCommandForm *commandForms,
    206     const UString &commandString, UString &postString)
    207 {
    208   for (int i = 0; i < numCommandForms; i++)
    209   {
    210     const UString id = commandForms[i].IDString;
    211     if (commandForms[i].PostStringMode)
    212     {
    213       if (commandString.Find(id) == 0)
    214       {
    215         postString = commandString.Mid(id.Length());
    216         return i;
    217       }
    218     }
    219     else
    220       if (commandString == id)
    221       {
    222         postString.Empty();
    223         return i;
    224       }
    225   }
    226   return -1;
    227 }
    228 
    229 }
    230