/* * This file is a part of PikoTools * and is distributed under the (new) BSD licence. * Author: Tomasz Sowa */ /* * Copyright (c) 2016-2017, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name Tomasz Sowa nor the names of contributors to this * project may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "mainspaceparser.h" #include "utf8/utf8.h" #include // REMOVE ME #include namespace PT { #ifdef nonexisting_value MainSpaceParser::MainSpaceParser() { space = 0; options_space = 0; use_utf8 = true; last_status = status_ok; } MainSpaceParser::~MainSpaceParser() { } void MainSpaceParser::UTF8(bool utf8) { use_utf8 = utf8; } void MainSpaceParser::SetSpace(Space & space_ref) { space = &space_ref; options_space = 0; } std::wstring & MainSpaceParser::GetErrorToken() { return last_error_token; } MainSpaceParser::Status MainSpaceParser::Parse(int argc, const char ** argv) { if( !space ) { return status_space_not_assigned; } options_space = space->FindSpace(L"options"); last_status = status_ok; last_error_token.clear(); for(size_t i=1 ; i < (size_t)argc && last_status == status_ok ; ) { Parse((size_t)argc, argv, i); } return last_status; } void MainSpaceParser::Parse(size_t argc, const char ** argv, size_t & argv_index) { const char * pchar = argv[argv_index]; if( *pchar == '-' ) { if( *(pchar+1) == '-' ) { ParseMultiArgument(argc, argv, argv_index); } else { ParseSingleArgument(argc, argv, argv_index); } } else { last_status = status_syntax_error; ConvertStr(pchar, last_error_token); } } void MainSpaceParser::ConvertStr(const char * src, std::wstring & dst) { if( use_utf8 ) { PT::UTF8ToWide(src,dst); } else { dst.clear(); for( ; *src ; ++src ) dst += (wchar_t)(unsigned char)*src; } } void MainSpaceParser::ParseSingleArgument(size_t argc, const char ** argv, size_t & argv_index) { ConvertStr(argv[argv_index] + 1, wide_arg); const wchar_t * wide_pchar = wide_arg.c_str(); temp_list_val.clear(); bool was_option = false; argv_index += 1; for( ; *wide_pchar && !was_option ; ++wide_pchar ) { temp_arg = *wide_pchar; size_t opt_size = RequireOption(temp_arg); if( opt_size > 0 ) { was_option = true; if( *(wide_pchar+1) ) { temp_val = wide_pchar + 1; temp_list_val.push_back(temp_val); opt_size -= 1; } for( ; opt_size > 0 && argv_index < argc ; --opt_size, ++argv_index) { ConvertStr(argv[argv_index], temp_val); temp_list_val.push_back(temp_val); } if( opt_size > 0 ) { last_status = status_reading_eof; last_error_token.clear(); } } temp_val.clear(); AddValueToItem(temp_arg, temp_val, temp_list_val); } } void MainSpaceParser::ParseMultiArgument(size_t argc, const char ** argv, size_t & argv_index) { ConvertStr(argv[argv_index] + 2, temp_arg); argv_index += 1; size_t opt_size = RequireOption(temp_arg); temp_list_val.clear(); if( opt_size > 0 ) { for( ; opt_size > 0 && argv_index < argc ; --opt_size, ++argv_index) { ConvertStr(argv[argv_index], temp_val); temp_list_val.push_back(temp_val); } if( opt_size > 0 ) { last_status = status_reading_eof; last_error_token.clear(); } } temp_val.clear(); AddValueToItem(temp_arg, temp_val, temp_list_val); } void MainSpaceParser::AddValueToItem(const std::wstring & name, const std::wstring & empty_value, const std::vector & list) { std::wstring * val = space->GetFirstValue(name); if( !val ) { if( list.empty() ) space->Add(name, empty_value); else if( list.size() == 1 ) space->Add(name, list[0]); else space->table[name] = list; // !! IMPROVE ME there'll be a new api in space } else { PT::Space::Table::iterator i = space->table.find(name); PT::Space::Value * table_value; if( i == space->table.end() ) { table_value = &space->table[name]; table_value->push_back(*val); //space->table_single.erase(name); } else { table_value = &i->second; } if( list.empty() ) { table_value->push_back(empty_value); } else { for(const auto & list_item : list) table_value->push_back(list_item); } } } size_t MainSpaceParser::RequireOption(const std::wstring & arg) { size_t res = 0; if( options_space ) { std::wstring * val = options_space->GetFirstValue(arg); if( val ) { /* * IMPLEMENT ME * add a converter to convert/inttostr.h * */ long res_long = wcstol(val->c_str(), 0, 10); if( res_long < 0 ) res_long = 0; res = (size_t)res_long; //std::wcout << L"argument " << arg << L" needs " << res << L" options" << std::endl; } } return res; } #endif } // namespace