/* * This file is a part of PikoTools * and is distributed under the (new) BSD licence. * Author: Tomasz Sowa */ /* * Copyright (c) 2008-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 #include #include "space.h" #include "utf8/utf8.h" #include "textstream/textstream.h" #include "convert/convert.h" namespace PT { Space::Space() { parent = 0; } Space::~Space() { Clear(); } Space::Space(const Space & s) { operator=(s); } Space & Space::operator=(const Space & s) { Clear(); name = s.name; table = s.table; parent = s.parent; for(size_t i=0 ; iparent = this; spaces.push_back(pspace); } return *this; } void Space::Clear() { name.clear(); table.clear(); for(size_t i=0 ; isecond; } } const Space::Value * Space::GetValue(const wchar_t * name) const { tmp_name = name; return GetValue(tmp_name); } const Space::Value * Space::GetValue(const std::wstring & name) const { Table::const_iterator t = table.find(name); if( t == table.cend() ) { return 0; } else { return &t->second; } } std::wstring * Space::GetFirstValue(const wchar_t * name) { tmp_name = name; return GetFirstValue(tmp_name); } std::wstring * Space::GetFirstValue(const std::wstring & name) { Table::iterator t = table.find(name); if( t == table.end() || t->second.empty() ) { return 0; } else { return &t->second[0]; } } // CHECK ME const std::wstring * Space::GetFirstValue(const wchar_t * name) const { tmp_name = name; return GetFirstValue(tmp_name); } const std::wstring * Space::GetFirstValue(const std::wstring & name) const { Table::const_iterator t = table.find(name); if( t == table.end() || t->second.empty() ) { return 0; } else { return &t->second[0]; } } bool Space::HasValue(const wchar_t * name, const wchar_t * value) { tmp_name = name; tmp_value_text = value; return HasValue(tmp_name, tmp_value_text); } bool Space::HasValue(const wchar_t * name, const std::wstring & value) { tmp_name = name; return HasValue(tmp_name, value); } bool Space::HasValue(const std::wstring & name, const wchar_t * value) { tmp_value_text = value; return HasValue(name, tmp_value_text); } bool Space::HasValue(const std::wstring & name, const std::wstring & value) { Table::const_iterator t = table.find(name); if( t != table.end() ) { for(size_t i=0 ; i < t->second.size() ; ++i) if( t->second[i] == value ) return true; } return false; } std::wstring Space::Text(const wchar_t * name) const { tmp_name = name; return Text(tmp_name, L""); } std::wstring Space::Text(const wchar_t * name, const wchar_t * def) const { tmp_name = name; return Text(tmp_name, def); } std::wstring Space::Text(const std::wstring & name, const wchar_t * def) const { const std::wstring * value = GetFirstValue(name); if( value ) { return *value; } else { return std::wstring(def); } } std::wstring Space::Text(const std::wstring & name, const std::wstring & def) const { const std::wstring * value = GetFirstValue(name); if( value ) { return *value; } else { return def; } } std::wstring & Space::TextRef(const wchar_t * name) { tmp_name = name; return TextRef(tmp_name, L""); } std::wstring & Space::TextRef(const wchar_t * name, const wchar_t * def) { tmp_name = name; return TextRef(tmp_name, def); } std::wstring & Space::TextRef(const std::wstring & name, const wchar_t * def) { Table::iterator t = table.find(name); if( t == table.end() ) { Value & v = table[name]; v.push_back(def); return v[0]; } else if( t->second.empty() ) { Value & v = t->second; v.push_back(def); return v[0]; } else { return t->second[0]; } } std::wstring & Space::TextRef(const std::wstring & name, const std::wstring & def) { return TextRef(name, def.c_str()); } std::string Space::TextA(const wchar_t * name) const { tmp_name = name; return TextA(tmp_name, ""); } std::string Space::TextA(const wchar_t * name, const char * def) const { tmp_name = name; return TextA(tmp_name, def); } std::string Space::TextA(const std::wstring & name, const char * def) const { const std::wstring * value = GetFirstValue(name); if( value ) { std::string res; PT::WideToUTF8(*value, res); return res; } else { return def; } } std::string Space::TextA(const std::wstring & name, const std::string & def) const { return TextA(name, def.c_str()); } std::string Space::TextA(const wchar_t * name, const wchar_t * def) const { tmp_name = name; return TextA(tmp_name, def); } std::string Space::TextA(const std::wstring & name, const wchar_t * def) const { const std::wstring * value = GetFirstValue(name); std::string res; if( value ) { PT::WideToUTF8(*value, res); return res; } else { PT::WideToUTF8(def, res); return res; } } std::string Space::TextA(const std::wstring & name, const std::wstring & def) const { return TextA(name, def.c_str()); } int Space::CheckIntegerBase(const std::wstring & value, const wchar_t ** save_ptr) { const wchar_t * ptr = SkipWhite(value.c_str()); int base = 10; if( *ptr == '0' ) { base = 8; ptr += 1; // we can skip the first zero } else if( *ptr == '-' && *(ptr+1) == '0' ) { base = 8; // ptr is pointing to '-', do not increment it here } *save_ptr = ptr; return base; } unsigned int Space::ToUInt(const std::wstring & value) { const wchar_t * ptr; int base = CheckIntegerBase(value, &ptr); return Toui(ptr, base); } int Space::ToInt(const std::wstring & value) { const wchar_t * ptr; int base = CheckIntegerBase(value, &ptr); return Toi(ptr, base); } unsigned long Space::ToULong(const std::wstring & value) { const wchar_t * ptr; int base = CheckIntegerBase(value, &ptr); return Toul(ptr, base); } long Space::ToLong(const std::wstring & value) { const wchar_t * ptr; int base = CheckIntegerBase(value, &ptr); return Tol(ptr, base); } unsigned long long Space::ToULongLong(const std::wstring & value) { const wchar_t * ptr; int base = CheckIntegerBase(value, &ptr); return Toull(ptr, base); } long long Space::ToLongLong(const std::wstring & value) { const wchar_t * ptr; int base = CheckIntegerBase(value, &ptr); return Toll(ptr, base); } size_t Space::ToSize(const std::wstring & value) { if( sizeof(size_t) == sizeof(unsigned int) ) return ToUInt(value); else if( sizeof(size_t) == sizeof(unsigned long) ) return ToULong(value); else return ToULongLong(value); } bool Space::ToBool(const std::wstring & value) { // IMPROVE ME add support for trimming white chars? return (EqualNoCase(value.c_str(), L"true") || EqualNoCase(value.c_str(), L"yes") || EqualNoCase(value.c_str(), L"1") ); } int Space::Int(const wchar_t * name, int def) { tmp_name = name; return Int(tmp_name, def); } int Space::Int(const std::wstring & name, int def) { std::wstring * value = GetFirstValue(name); if( value ) return ToInt(*value); return def; } unsigned int Space::UInt(const wchar_t * name, unsigned int def) { tmp_name = name; return UInt(tmp_name, def); } unsigned int Space::UInt(const std::wstring & name, unsigned int def) { std::wstring * value = GetFirstValue(name); if( value ) return ToUInt(*value); return def; } long Space::Long(const wchar_t * name, long def) { tmp_name = name; return Long(tmp_name, def); } long Space::Long(const std::wstring & name, long def) { std::wstring * value = GetFirstValue(name); if( value ) return ToLong(*value); return def; } unsigned long Space::ULong(const wchar_t * name, unsigned long def) { tmp_name = name; return ULong(tmp_name, def); } unsigned long Space::ULong(const std::wstring & name, unsigned long def) { std::wstring * value = GetFirstValue(name); if( value ) return ToULong(*value); return def; } long long Space::LongLong(const wchar_t * name, long long def) { tmp_name = name; return LongLong(tmp_name, def); } long long Space::LongLong(const std::wstring & name, long long def) { std::wstring * value = GetFirstValue(name); if( value ) return ToLongLong(*value); return def; } unsigned long long Space::ULongLong(const wchar_t * name, unsigned long long def) { tmp_name = name; return ULongLong(tmp_name, def); } unsigned long long Space::ULongLong(const std::wstring & name, unsigned long long def) { std::wstring * value = GetFirstValue(name); if( value ) return ToULongLong(*value); return def; } size_t Space::Size(const wchar_t * name, size_t def) { tmp_name = name; return Size(tmp_name, def); } size_t Space::Size(const std::wstring & name, size_t def) { std::wstring * value = GetFirstValue(name); if( value ) return ToSize(*value); return def; } bool Space::Bool(const wchar_t * name, bool def) { tmp_name = name; return Bool(tmp_name, def); } bool Space::Bool(const std::wstring & name, bool def) { std::wstring * value = GetFirstValue(name); if( value ) return ToBool(*value); return def; } // !! CHECKME std::wstring & Space::FindAdd(const std::wstring & name) { Value * value; Table::iterator t = table.find(name); if( t != table.end() ) { value = &t->second; } else { value = &table[name]; } if( value->empty() ) value->push_back(std::wstring()); return (*value)[0]; } // !! CHECKME std::wstring & Space::FindAdd(const wchar_t * name) { tmp_name = name; return FindAdd(tmp_name); } // !! CHECKME std::wstring & Space::FindAdd(const WTextStream & name) { name.to_string(tmp_name); return FindAdd(tmp_name); } /* * * * * * CHECKME !! */ std::wstring & Space::Add(const std::wstring & name, const std::wstring & value, bool replace_existing) { Table::iterator i = table.find(name); if( i == table.end() ) { Value & val = table[name]; val.push_back(value); return val.back(); } else { Value & val = i->second; if( replace_existing ) val.clear(); val.push_back(value); return val.back(); } } // CHECKME !! std::wstring & Space::Add(const std::wstring & name, const wchar_t * value, bool replace_existing) { tmp_value = value; return Add(name, tmp_value, replace_existing); } // CHECKME !! std::wstring & Space::Add(const wchar_t * name, const wchar_t * value, bool replace_existing) { tmp_name = name; tmp_value = value; return Add(tmp_name, tmp_value, replace_existing); } // CHECKME !! std::wstring & Space::Add(const wchar_t * name, const std::wstring & value, bool replace_existing) { tmp_name = name; return Add(tmp_name, value, replace_existing); } // CHECKME !! std::wstring & Space::Add(const wchar_t * name, const WTextStream & value, bool replace_existing) { tmp_name = name; value.to_string(tmp_value); return Add(tmp_name, tmp_value, replace_existing); } // CHECKME !! std::wstring & Space::Add(const std::wstring & name, const WTextStream & value, bool replace_existing) { value.to_string(tmp_value); return Add(name, tmp_value, replace_existing); } // CHECKME !! std::wstring & Space::Add(const WTextStream & name, const WTextStream & value, bool replace_existing) { name.to_string(tmp_name); value.to_string(tmp_value); return Add(tmp_name, tmp_value, replace_existing); } /* * * * * * */ // CHECKME std::wstring & Space::Add(const std::wstring & name, bool value, bool replace_existing) { if( value ) return Add(name, L"true", replace_existing); else return Add(name, L"false", replace_existing); } // CHECKME std::wstring & Space::Add(const wchar_t * name, bool value, bool replace_existing) { tmp_name = name; return Add(tmp_name, value, replace_existing); } // CHECKME std::wstring & Space::Add(const std::wstring & name, int value, bool replace_existing) { wchar_t value_str[50]; #if defined _WIN32 || defined _WIN64 swprintf(value_str, L"%d", value); #else swprintf(value_str, sizeof(value_str)/sizeof(wchar_t), L"%d", value); #endif return Add(name, value_str, replace_existing); } // CHECKME std::wstring & Space::Add(const wchar_t * name, int value, bool replace_existing) { tmp_name = name; return Add(tmp_name, value, replace_existing); } // CHECKME std::wstring & Space::Add(const std::wstring & name, long value, bool replace_existing) { wchar_t value_str[50]; #if defined _WIN32 || defined _WIN64 swprintf(value_str, L"%ld", value); #else swprintf(value_str, sizeof(value_str)/sizeof(wchar_t), L"%ld", value); #endif return Add(name, value_str, replace_existing); } // CHECKME std::wstring & Space::Add(const wchar_t * name, long value, bool replace_existing) { tmp_name = name; return Add(tmp_name, value, replace_existing); } std::wstring & Space::Add(const std::wstring & name, size_t value, bool replace_existing) { wchar_t value_str[50]; #if defined _WIN32 || defined _WIN64 // see http://msdn.microsoft.com/en-us/library/tcxf1dw6%28v=vs.71%29.aspx swprintf(value_str, L"%Iu", value); #else swprintf(value_str, sizeof(value_str)/sizeof(wchar_t), L"%zu", value); #endif return Add(name, value_str, replace_existing); } std::wstring & Space::Add(const wchar_t * name, size_t value, bool replace_existing) { tmp_name = name; return Add(tmp_name, value, replace_existing); } void Space::Remove(const std::wstring & name) { table.erase(name); } void Space::Remove(const wchar_t * name) { tmp_name = name; Remove(tmp_name); } // CHECKME Space & Space::AddSpace(const std::wstring & name) { spaces.push_back(new Space()); spaces.back()->name = name; spaces.back()->parent = this; return *spaces.back(); } // CHECKME Space & Space::AddSpace(const wchar_t * name) { tmp_name = name; return AddSpace(tmp_name); } Space * Space::FindSpace(const wchar_t * name) { for(size_t i=0 ; iname == name ) // there is a special == operator in string class taking c-string as an argument return spaces[i]; } return 0; } Space * Space::FindSpace(const std::wstring & name) { for(size_t i=0 ; iname == name ) return spaces[i]; } return 0; } Space & Space::FindAddSpace(const wchar_t * name) { Space * space = FindSpace(name); if( space ) return *space; return AddSpace(name); } Space & Space::FindAddSpace(const std::wstring & name) { Space * space = FindSpace(name); if( space ) return *space; return AddSpace(name); } void Space::RemoveSpace(const wchar_t * name) { for(size_t i=0 ; iname == name ) RemoveSpace(i); else ++i; } } void Space::RemoveSpace(const std::wstring & name) { for(size_t i=0 ; iname == name ) RemoveSpace(i); else ++i; } } void Space::RemoveSpace(size_t child_index) { if( child_index < spaces.size() ) { delete spaces[child_index]; spaces.erase(spaces.begin() + child_index); } } bool Space::ListText(const std::wstring & name, std::vector & list) { list.clear(); Table::iterator t = table.find(name); if( t != table.end() ) { list = t->second; return true; } return false; } // in lists we don't use default values bool Space::ListText(const wchar_t * name, std::vector & list) { tmp_name = name; return ListText(tmp_name, list); } wchar_t Space::ToSmall(wchar_t c) { if( c >= 'A' && c <= 'Z' ) c = c - 'A' + 'a'; return c; } bool Space::EqualNoCase(const wchar_t * str1, const wchar_t * str2) { while( *str1 && *str2 && ToSmall(*str1) == ToSmall(*str2) ) { ++str1; ++str2; } if( *str1 == 0 && *str2 == 0 ) return true; return false; } /* those white characters here should be the same as in spaceparser.cpp */ bool Space::IsWhite(int c) { // dont use '\n' here // 13 (\r) is at the end of a line in a dos file \r\n // 160 is an unbreakable space if( c==' ' || c=='\t' || c==13 || c==160 ) return true; return false; } bool Space::HasWhite(const std::wstring & str) { for(size_t i=0 ; i