| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| #include <precomp.h> |
| #include <cosv/commandline.hxx> |
| |
| // NOT FULLY DECLARED SERVICES |
| #include <cosv/file.hxx> |
| |
| |
| namespace csv |
| { |
| |
| namespace |
| { |
| |
| const intt C_nNoOption = -1; |
| |
| const char * sIncludeOptionShort = "-A:"; |
| const char * sIncludeOptionLong = "--Arguments:"; |
| const uintt nIncludeOptionShort_Length = strlen(sIncludeOptionShort); |
| const uintt nIncludeOptionLong_Length = strlen(sIncludeOptionLong); |
| |
| |
| /** Analyses, if an option is the one to include a file with |
| further command line arguments. |
| */ |
| bool IsIncludeOption( |
| const String & i_option ); |
| |
| /** Gets the file name from an include-arguments-option. |
| */ |
| String IncludeFile_fromIncludeOption( |
| const String & i_option ); |
| |
| |
| bool |
| IsIncludeOption(const String & i_option) |
| { |
| return strncmp(i_option, sIncludeOptionShort, nIncludeOptionShort_Length) == 0 |
| OR |
| strncmp(i_option, sIncludeOptionLong, nIncludeOptionLong_Length) == 0; |
| } |
| |
| String |
| IncludeFile_fromIncludeOption(const String & i_option) |
| { |
| if ( strncmp(i_option, sIncludeOptionShort, nIncludeOptionShort_Length) |
| == 0 ) |
| { |
| return String(i_option, nIncludeOptionShort_Length, str::maxsize); |
| } |
| else |
| if ( strncmp(i_option, sIncludeOptionLong, nIncludeOptionLong_Length) |
| == 0 ) |
| { |
| return String(i_option, nIncludeOptionLong_Length, str::maxsize); |
| } |
| return String::Null_(); |
| } |
| |
| |
| } // end anonymous namespace |
| |
| |
| |
| |
| /** Local helper class for searching a possible option name in a vector of |
| ->OptionDescription. |
| */ |
| struct CommandLine:: |
| FindOptionByText |
| { |
| bool operator()( |
| const CommandLine::OptionDescription & |
| i_option ) |
| { return i_option.sText == sOption; } |
| |
| /// @param i_searchText [i_searchText != ""] |
| FindOptionByText( |
| const String & i_option ) |
| : sOption(i_option) { } |
| private: |
| const String sOption; |
| }; |
| |
| |
| typedef std::vector<StringVector::const_iterator> StringCIteratorList; |
| typedef std::vector<intt> OptionIdList; |
| |
| bool |
| CommandLine::Interpret( int argc, |
| char * argv[] ) |
| { |
| Get_Arguments(argc,argv); |
| csv_assert(aOptionPoints.size() == aOptionIds.size()); |
| |
| StringVector::const_iterator |
| itNext = aCommandLine.begin(); |
| ++itNext; // Move 1 forward from program name. |
| StringVector::const_iterator |
| itEnd = aCommandLine.end(); |
| StringCIteratorList::const_iterator |
| itOptPtsEnd = aOptionPoints.end(); |
| |
| OptionIdList::const_iterator |
| itOptIds = aOptionIds.begin(); |
| for ( StringCIteratorList::const_iterator itOptPts = aOptionPoints.begin(); |
| itOptPts != itOptPtsEnd AND bIsOk; |
| ++itOptPts, ++itOptIds ) |
| { |
| // May be, there are arguments which do not belong to the last option: |
| // itNext != *is |
| Handle_FreeArguments(itNext, *itOptPts); |
| |
| itNext = do_HandleOption( *itOptIds, |
| *itOptPts + 1, |
| itOptPts+1 == itOptPtsEnd ? itEnd : *(itOptPts+1) ); |
| csv_assert(itNext <= itEnd); |
| } // end for (is) |
| Handle_FreeArguments(itNext, itEnd); |
| |
| return bIsOk; |
| } |
| |
| CommandLine::CommandLine() |
| : aOptions(), |
| aCommandLine(), |
| bIsOk(false) |
| { |
| } |
| |
| void |
| CommandLine::Add_Option( intt i_id, |
| String i_text ) |
| { |
| aOptions.push_back(OptionDescription( i_id, |
| i_text )); |
| } |
| |
| void |
| CommandLine::Get_Arguments( int argc, |
| char * argv[] ) |
| { |
| aCommandLine.erase(aCommandLine.begin(),aCommandLine.end()); |
| aCommandLine.reserve(argc); |
| |
| char ** pArgEnd = argv + argc; |
| for ( char ** pArg = &argv[0]; |
| pArg != pArgEnd; |
| ++pArg ) |
| { |
| Store_Argument(*pArg); |
| } // end for |
| Find_OptionPoints(); |
| bIsOk = true; |
| } |
| |
| intt |
| CommandLine::Find_Option( const String & i_text ) const |
| { |
| if (i_text.empty()) |
| return C_nNoOption; |
| |
| FindOptionByText aSearch(i_text); |
| OptionList::const_iterator |
| itFound = std::find_if( aOptions.begin(), |
| aOptions.end(), |
| aSearch ); |
| if (itFound != aOptions.end()) |
| { |
| return (*itFound).nId; |
| } |
| return C_nNoOption; |
| } |
| |
| bool |
| CommandLine::Store_Argument( const String & i_arg ) |
| { |
| if ( NOT IsIncludeOption(i_arg) ) |
| { |
| aCommandLine.push_back(i_arg); |
| return true; |
| } |
| |
| return Try2Include_Options(i_arg); |
| } |
| |
| void |
| CommandLine::Find_OptionPoints() |
| { |
| StringVector::const_iterator itEnd = aCommandLine.end(); |
| for ( StringVector::const_iterator it = aCommandLine.begin() + 1; |
| it != itEnd; |
| ++it ) |
| { |
| intt nOption = Find_Option(*it); |
| if (nOption != C_nNoOption) |
| { |
| aOptionPoints.push_back(it); |
| aOptionIds.push_back(nOption); |
| } |
| } // end for (i) |
| } |
| |
| void |
| CommandLine::Handle_FreeArguments( StringVector::const_iterator i_begin, |
| StringVector::const_iterator i_end ) |
| { |
| for ( StringVector::const_iterator it = i_begin; |
| it != i_end AND bIsOk; |
| ++it ) |
| { |
| do_HandleFreeArgument(*it); |
| } |
| } |
| |
| bool |
| CommandLine::Try2Include_Options(const String & i_includeOption) |
| { |
| static StringVector |
| aIncludedOptionFiles_; |
| |
| const String |
| aOptionFile(IncludeFile_fromIncludeOption(i_includeOption)); |
| |
| // Avoid recursion deadlock 1 |
| if ( std::find( aIncludedOptionFiles_.begin(), |
| aIncludedOptionFiles_.end(), |
| aOptionFile ) |
| != aIncludedOptionFiles_.end() ) |
| { |
| Cerr() << "\nError: Self inclusion of option file " |
| << aOptionFile |
| << ".\n" |
| << Endl(); |
| return false; |
| } |
| |
| // Avoid recursion deadlock 2 |
| aIncludedOptionFiles_.push_back(aOptionFile); |
| |
| bool ok = Include_Options(aOptionFile); |
| |
| // Avoid recursion deadlock 3 |
| aIncludedOptionFiles_.pop_back(); |
| |
| return ok; |
| } |
| |
| bool |
| CommandLine::Include_Options( const String & i_optionsFile ) |
| { |
| StreamStr |
| aIncludedText(500); |
| bool ok = Load_Options(aIncludedText, i_optionsFile); |
| if (NOT ok) |
| return false; |
| |
| StringVector |
| aIncludedOptions; |
| Split(aIncludedOptions, aIncludedText.c_str()); |
| |
| StringVector::const_iterator itEnd = aIncludedOptions.end(); |
| for ( StringVector::const_iterator it = aIncludedOptions.begin(); |
| it != itEnd; |
| ++it ) |
| { |
| Store_Argument(*it); |
| } // end for |
| |
| return true; |
| } |
| |
| bool |
| CommandLine::Load_Options( StreamStr & o_text, |
| const String & i_optionsFile ) |
| { |
| if (i_optionsFile.empty()) |
| return false; |
| |
| File |
| aOptionsFile(i_optionsFile, CFM_READ); |
| OpenCloseGuard |
| aOFGuard(aOptionsFile); |
| if (NOT aOFGuard) |
| { |
| Cerr() << "\nError: Options file " |
| << i_optionsFile |
| << " not found.\n" |
| << Endl(); |
| return false; |
| } |
| |
| StreamStr |
| aLoad(aOptionsFile); |
| o_text.swap(aLoad); |
| return true; |
| } |
| |
| |
| |
| |
| /****************** OptionDescription ***********************/ |
| |
| |
| CommandLine:: |
| OptionDescription::OptionDescription( intt i_id, |
| String i_text ) |
| : nId(i_id), |
| sText(i_text) |
| { |
| } |
| |
| |
| |
| |
| } // namespace csv |