winix/winixd/templates/miscspace.cpp

238 lines
5.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) 2012-2018, 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 "templates.h"
namespace Winix
{
namespace TemplatesFunctions
{
bool are_spaces_the_same(const std::vector<Ezc::Var> & params, const std::vector<std::wstring> & spaces)
{
// last value from params is the parameter name (not a space)
if( spaces.size() + 1 != params.size() )
return false;
for(size_t i=0 ; i<spaces.size() ; ++i)
if( spaces[i] != params[i].str )
return false;
return true;
}
void copy_space(const std::vector<Ezc::Var> & params, std::vector<std::wstring> & spaces)
{
if( !params.empty() )
{
spaces.resize(params.size() - 1);
for(size_t i=0 ; i<params.size() - 1 ; ++i)
spaces[i] = params[i].str;
}
else
{
spaces.clear();
}
}
PT::Space * find_space(const std::vector<Ezc::Var> & params, PT::Space & space, size_t level = 0)
{
if( level + 1 < params.size() )
{
for(size_t i=0 ; i<space.spaces.size() ; ++i)
{
if( space.spaces[i]->name == params[level].str )
return find_space(params, *space.spaces[i], level+1);
}
// there is no such a space
return 0;
}
else
{
return &space;
}
}
/*
*
* IMPROVE ME
* add a private namespace?
*
*/
struct SpaceInfo
{
bool inited;
PT::Space * last_space;
std::vector<std::wstring> spaces;
SpaceInfo()
{
inited = false;
last_space = 0;
}
};
static std::map<PT::Space*, SpaceInfo> spaces_map;
static size_t space_reqid = 0;
void space_init(const std::vector<Ezc::Var> & params, PT::Space & space, SpaceInfo & space_info)
{
if( !space_info.inited || !are_spaces_the_same(params, space_info.spaces) )
{
space_info.inited = true;
copy_space(params, space_info.spaces);
space_info.last_space = find_space(params, space);
}
}
void space_check_reqid()
{
if( space_reqid != cur->request->id )
{
space_reqid = cur->request->id;
spaces_map.clear();
}
}
void space_value(Info & i, PT::Space & space, bool escape)
{
space_check_reqid();
if( !i.params.empty() )
{
SpaceInfo & space_info = spaces_map[&space];
space_init(i.params, space, space_info);
if( space_info.last_space )
{
const std::wstring & param = i.params.back().str;
const std::wstring * value = space_info.last_space->GetFirstValue(param);
if( value )
{
if( escape )
i.out << *value;
else
i.out << R(*value);
}
}
}
}
struct SpaceTabStackItem : public Ezc::FunData
{
std::vector<std::wstring> values;
};
void space_list_tab(Info & i, PT::Space & space)
{
if( !i.stack.fun_data )
{
if( !i.params.empty() )
{
SpaceTabStackItem * stack_item = new SpaceTabStackItem();
i.stack.fun_data = stack_item;
PT::Space * dst_space = find_space(i.params, space);
if( dst_space )
dst_space->ListText(i.params.back().str, stack_item->values);
i.res = i.iter < stack_item->values.size();
}
}
else
{
auto stack_item = reinterpret_cast<SpaceTabStackItem*>(i.stack.fun_data);
i.res = i.iter < stack_item->values.size();
}
}
void space_list_tab_value(Info & i, PT::Space & space, const std::wstring & function_name)
{
Ezc::Stack * stack;
auto user_object = i.FindUserObject<SpaceTabStackItem>(function_name, &stack);
if( user_object && stack->iter < user_object->values.size() )
i.out << user_object->values[stack->iter];
}
void space_list_tab_has_next(Info & i, PT::Space & space, const std::wstring & function_name)
{
Ezc::Stack * stack;
auto user_object = i.FindUserObject<SpaceTabStackItem>(function_name, &stack);
if( user_object && stack->iter + 1 < user_object->values.size() )
i.res = true;
}
} // namespace TemplatesFunctions
} // namespace Winix