winix/winixd/plugins/group/groups.cpp

283 lines
6.0 KiB
C++

/*
* This file is a part of Winix
* and is distributed under the 2-Clause BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2011-2021, 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:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. 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.
*
* 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 HOLDER 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 <algorithm>
#include <limits>
#include "groups.h"
#include "core/log.h"
namespace Winix
{
namespace GroupItem
{
pt::Space * Groups::GetSpace()
{
return &space;
}
void Groups::Reindex()
{
set_index.clear();
group_index_tab.clear();
size_t seti = 0;
pt::Space::TableType * child_table = space.find_child_space_table();
if( child_table )
{
while( seti < child_table->size() )
{
pt::Space & sp = *(*child_table)[seti];
std::wstring * name = sp.get_wstr(pt::Space::child_spaces_name);
if( name )
{
if( set_index.find(*name) == set_index.end() )
{
set_index[*name] = seti;
group_index_tab.push_back(GroupIndex());
ReindexGroups(group_index_tab.back(), sp);
seti += 1;
}
else
{
slog << logerror << "set: " << name << " already defined (skipping)" << logend;
space.remove_child_space(seti);
}
}
}
}
}
void Groups::ReindexGroups(GroupIndex & group_index, pt::Space & set)
{
size_t i, v;
pt::Space::TableType * child_table = set.find_child_space_table();
if( child_table )
{
for( i=0 ; i < child_table->size() ; ++i )
{
pt::Space * group = (*child_table)[i];
std::wstring key = group->to_wstr(L"key", L"value");
pt::Space::TableType * group_child_table = group->find_child_space_table();
if( group_child_table )
{
for(v=0 ; v < group_child_table->size() ; )
{
std::wstring * vali = (*group_child_table)[v]->get_wstr(key.c_str());
if( vali )
{
GroupIndex::iterator g = group_index.find(*vali);
if( g == group_index.end() )
{
group_index[*vali] = i;
v += 1;
}
else
{
slog << logwarning << "set: " << group->get_child_space_name()
<< " has a group with a duplicated value: "
<< *vali << " (skipping)" << logend;
group->remove_child_space(v);
}
}
else
{
log << log1 << "key: " << key << " was not found" << logend;
slog << logwarning << "set: " << group->get_child_space_name()
<< " has a group without a value (skipping)" << logend;
group->remove_child_space(v);
}
}
}
SortValues(*group);
}
}
}
void Groups::SortValues(pt::Space & group)
{
sort_by = group.to_wstr(L"sort_by");
sort_asc = group.is_equal(L"sort_asc", L"true");
pt::Space::TableType * child_table = group.find_child_space_table();
if( !sort_by.empty() && child_table )
{
group.to_list(L"sort", sort_value, true);
std::sort(child_table->begin(), child_table->end(), SortFunHelper(this));
}
}
bool Groups::SortFunHelper::operator()(pt::Space * sp1, pt::Space * sp2)
{
const std::wstring * val1 = sp1->get_wstr(groups->sort_by.c_str());
const std::wstring * val2 = sp2->get_wstr(groups->sort_by.c_str());
if( !val1 || !val2 )
return false;
if( groups->sort_asc )
return SortValue(*val1) < SortValue(*val2);
else
return SortValue(*val1) > SortValue(*val2);
}
size_t Groups::SortFunHelper::SortValue(const std::wstring & val)
{
for(size_t i=0 ; i<groups->sort_value.size() ; ++i)
if( val == groups->sort_value[i] )
return i;
return std::numeric_limits<size_t>::max();
}
bool Groups::Find(const std::wstring & set, const std::wstring & value, size_t & seti, size_t & groupi)
{
SetIndex::iterator i = set_index.find(set);
if( i != set_index.end() )
{
if( i->second < group_index_tab.size() )
{
GroupIndex::iterator viter = group_index_tab[i->second].find(value);
if( viter != group_index_tab[i->second].end() )
{
seti = i->second;
groupi = viter->second;
return true;
}
}
}
return false;
}
const std::wstring & Groups::GetOption(size_t seti, size_t groupi, size_t valuei, const wchar_t * option)
{
pt::Space * groups = space.find_child_space(seti);
if( groups )
{
pt::Space * value = groups->find_child_space(groupi);
if( value )
{
pt::Space * value_child = value->find_child_space(valuei);
if( value_child )
{
const std::wstring * res = value_child->get_wstr(option);
if( res )
return *res;
}
}
}
return empty_str;
}
const std::wstring & Groups::GetOption(size_t seti, size_t groupi, size_t valuei, const std::wstring & option)
{
return GetOption(seti, groupi, valuei, option.c_str());
}
size_t Groups::Size(size_t seti, size_t groupi)
{
pt::Space * groups = space.find_child_space(seti);
if( groups )
{
pt::Space * group = groups->find_child_space(groupi);
if( group )
return group->child_spaces_size();
}
return 0;
}
void Groups::Clear()
{
space.clear();
set_index.clear();
group_index_tab.clear();
}
}
} // namespace Winix