/************************************************************** * * 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 #include // NOT FULLY DECLARED SERVICES #include 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 StringCIteratorList; typedef std::vector 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