<commit_before>#include "kwm.h"

static const CGKeyCode kVK_SPECIAL_Å = 0x21;
static const CGKeyCode kVK_SPECIAL_Ø = 0x29;
static const CGKeyCode kVK_SPECIAL_Æ = 0x27;

extern "C" KWM_KEY_REMAP(RemapKeys)
{
    *Result = -1;

    /*
    if(*CmdKey && *AltKey && *CtrlKey)
    {
    }

    switch(Keycode)
    {
        case kVK_ANSI_A:
        {
            *Result = kVK_ANSI_S;
        } break;
    }
    */
}

extern "C" KWM_HOTKEY_COMMANDS(KWMHotkeyCommands)
{
    bool Result = true;
    if(CmdKey && AltKey && CtrlKey)
    {
        switch(Keycode)
        {
            // Toggle Focus-Mode
            case kVK_ANSI_T:
            {
                if(EX->KwmFocusMode == FocusFollowsMouse)
                {
                    EX->KwmFocusMode = FocusAutoraise;
                    DEBUG("KwmFocusMode: Autoraise")
                }
                else if(EX->KwmFocusMode == FocusAutoraise)
                {
                    EX->KwmFocusMode = FocusDisabled;
                    DEBUG("KwmFocusMode: Disabled")
                }
                else if(EX->KwmFocusMode == FocusDisabled)
                {
                    EX->KwmFocusMode = FocusFollowsMouse;
                    DEBUG("KwmFocusMode: Focus-follows-mouse")
                }
            } break;
            // Mark Container to split
            case kVK_ANSI_M:
            {
                EX->MarkWindowContainer();
            } break;
            // Toggle window floating
            case kVK_ANSI_W:
            {
                bool Found = false;
                for(int Index = 0; Index < EX->FloatingWindowLst.size(); ++Index)
                {
                    if(EX->FloatingWindowLst[Index] == EX->FocusedWindow->WID)
                    {
                        EX->FloatingWindowLst.erase(EX->FloatingWindowLst.begin() + Index);
                        Found = true;
                        EX->KwmFocusMode = FocusAutoraise;
                        EX->AddWindowToTree();
                        break;
                    }
                }

                if(!Found)
                {
                    EX->FloatingWindowLst.push_back(EX->FocusedWindow->WID);
                    EX->KwmFocusMode = FocusFollowsMouse;
                    EX->RemoveWindowFromTree();
                }
            } break;
            // Reapply node container to window
            case kVK_ANSI_R:
            {
                EX->ResizeWindowToContainerSize();
            } break;
            // Restart Kwm
            case kVK_ANSI_Q:
            {
                EX->KwmRestart();
            } break;
            // Use Width/Height ratio to determine split mode
            case kVK_ANSI_O:
            {
                EX->KwmSplitMode = -1;
            } break;
            // Vertical Split-Mode
            case kVK_ANSI_7:
            {
                EX->KwmSplitMode = 1;
            } break;
            // Horizontal Split-Mode
            case kVK_ANSI_Slash:
            {
                EX->KwmSplitMode = 2;
            } break;
            // Resize Panes
            case kVK_ANSI_H:
            {
                EX->MoveContainerSplitter(1, -10);
            } break;
            case kVK_ANSI_L:
            {
                EX->MoveContainerSplitter(1, 10);
            } break;
            case kVK_ANSI_J:
            {
                EX->MoveContainerSplitter(2, 10);
            } break;
            case kVK_ANSI_K:
            {
                EX->MoveContainerSplitter(2, -10);
            } break;
            // Toggle Fullscreen / Parent Container
            case kVK_ANSI_F:
            {
                EX->ToggleFocusedWindowFullscreen();
            } break;
            case kVK_ANSI_P:
            {
                EX->ToggleFocusedWindowParentContainer();
            } break;
            default:
            {
                Result = false;
            } break;
        }
    }
    else if(CmdKey && AltKey && !CtrlKey)
    {
        switch(Keycode)
        {
            // Swap focused window with the previous window
            case kVK_ANSI_P:
            {
                EX->SwapFocusedWindowWithNearest(-1);
            } break;
            // Swap focused window with the next window
            case kVK_ANSI_N:
            {
                EX->SwapFocusedWindowWithNearest(1);
            } break;
            // Shift focus to the previous window
            case kVK_ANSI_H:
            {
                if(EX->FocusedWindow)
                {
                    EX->ShiftWindowFocus(-1);
                }
            } break;
            // Shift focus to the next window
            case kVK_ANSI_L:
            {
                if(EX->FocusedWindow)
                {
                    EX->ShiftWindowFocus(1);
                }
            } break;
            case kVK_ANSI_R:
            {
                EX->ReflectWindowNodeTreeVertically();
            } break;
            default:
            {
                Result = false;
            } break;
        }
    }
    else if(CmdKey && CtrlKey && !AltKey)
    {
        switch(Keycode)
        {
            // Send window to previous screen
            case kVK_ANSI_P:
            {
                EX->CycleFocusedWindowDisplay(-1);
            } break;
            // Send window to next screen
            case kVK_ANSI_N:
            {
                EX->CycleFocusedWindowDisplay(1);
            } break;
            default:
            {
                Result = false;
            };
        }
    }
    else
    {
        Result = false;
    }

    return Result;
}

extern "C" KWM_HOTKEY_COMMANDS(SystemHotkeyCommands)
{
    bool Result = true;
    if (CmdKey && !CtrlKey && !AltKey)
    {
        switch(Keycode)
        {
            // Spotlight fix
            case kVK_Space:
            {
                //EX->KwmFocusMode = FocusAutoraise;
            } break;
            default:
            {
                Result = false;
            } break;
        }
    }
    else
    {
        Result = false;
    }

    return Result;
}

extern "C" KWM_HOTKEY_COMMANDS(CustomHotkeyCommands)
{
    bool Result = true;
    if(CmdKey && AltKey && CtrlKey)
    {
        // Launch Application
        std::string SysCommand = "";
        switch(Keycode)
        {
            // Open New iTerm Window
            case kVK_Return:
            {
                SysCommand = "/Applications/iTerm.app/Contents/MacOS/iTerm2 --new-window &";
            } break;
            // Rebuild Hotkeys
            // case kVK_ANSI_R:
            // {
            //     SysCommand = "sh " + EX->KwmFilePath + "/sobuild.sh";
            // } break;
            // YTD - Media Player Controls
            case kVK_ANSI_Z:
            {
                SysCommand = "ytc prev";
            } break;
            case kVK_ANSI_X:
            {
                SysCommand = "ytc play";
            } break;
            case kVK_ANSI_C:
            {
                SysCommand = "ytc next";
            } break;
            case kVK_ANSI_V:
            {
                SysCommand = "ytc stop";
            } break;
            case kVK_ANSI_A:
            {
                SysCommand = "ytc volup";
            } break;
            case kVK_ANSI_D:
            {
                SysCommand = "ytc voldown";
            } break;
            case kVK_ANSI_S:
            {
                SysCommand = "ytc mkfav";
            } break;
            case kVK_LeftArrow:
            {
                SysCommand = "ytc seekbk";
            } break;
            case kVK_RightArrow:
            {
                SysCommand = "ytc seekfw";
            } break;
            case kVK_ANSI_Grave:
            {
                SysCommand = "ytc fav";
            } break;
            default:
            {
                Result = false;
            } break;
        }

        if(SysCommand != "")
        {
            system(SysCommand.c_str());
        }
    }
    else if(CmdKey && !AltKey && !CtrlKey)
    {
        switch(Keycode)
        {
            // disable retarded hotkey for minimizing an application
            case kVK_ANSI_M:
            {
            } break;
            // disable retarded hotkey for hiding an application
            case kVK_ANSI_H:
            {
            } break;
            // disable cmd+tab window-swap
            case kVK_Tab:
            {
            } break;
            default:
            {
                Result = false;
            } break;
        }
    }
    else
    {
        Result = false;
    }

    return Result;
}
<commit_msg>added hotkeys to increase or decrease various screen padding<commit_after>#include "kwm.h"

static const CGKeyCode kVK_SPECIAL_Å = 0x21;
static const CGKeyCode kVK_SPECIAL_Ø = 0x29;
static const CGKeyCode kVK_SPECIAL_Æ = 0x27;

extern "C" KWM_KEY_REMAP(RemapKeys)
{
    *Result = -1;

    /*
    if(*CmdKey && *AltKey && *CtrlKey)
    {
    }

    switch(Keycode)
    {
        case kVK_ANSI_A:
        {
            *Result = kVK_ANSI_S;
        } break;
    }
    */
}

extern "C" KWM_HOTKEY_COMMANDS(KWMHotkeyCommands)
{
    bool Result = true;
    if(CmdKey && AltKey && CtrlKey)
    {
        switch(Keycode)
        {
            // Toggle Focus-Mode
            case kVK_ANSI_T:
            {
                if(EX->KwmFocusMode == FocusFollowsMouse)
                {
                    EX->KwmFocusMode = FocusAutoraise;
                    DEBUG("KwmFocusMode: Autoraise")
                }
                else if(EX->KwmFocusMode == FocusAutoraise)
                {
                    EX->KwmFocusMode = FocusDisabled;
                    DEBUG("KwmFocusMode: Disabled")
                }
                else if(EX->KwmFocusMode == FocusDisabled)
                {
                    EX->KwmFocusMode = FocusFollowsMouse;
                    DEBUG("KwmFocusMode: Focus-follows-mouse")
                }
            } break;
            // Mark Container to split
            case kVK_ANSI_M:
            {
                EX->MarkWindowContainer();
            } break;
            // Toggle window floating
            case kVK_ANSI_W:
            {
                bool Found = false;
                for(int Index = 0; Index < EX->FloatingWindowLst.size(); ++Index)
                {
                    if(EX->FloatingWindowLst[Index] == EX->FocusedWindow->WID)
                    {
                        EX->FloatingWindowLst.erase(EX->FloatingWindowLst.begin() + Index);
                        Found = true;
                        EX->KwmFocusMode = FocusAutoraise;
                        EX->AddWindowToTree();
                        break;
                    }
                }

                if(!Found)
                {
                    EX->FloatingWindowLst.push_back(EX->FocusedWindow->WID);
                    EX->KwmFocusMode = FocusFollowsMouse;
                    EX->RemoveWindowFromTree();
                }
            } break;
            // Reapply node container to window
            case kVK_ANSI_R:
            {
                EX->ResizeWindowToContainerSize();
            } break;
            // Restart Kwm
            case kVK_ANSI_Q:
            {
                EX->KwmRestart();
            } break;
            // Use Width/Height ratio to determine split mode
            case kVK_ANSI_O:
            {
                EX->KwmSplitMode = -1;
            } break;
            // Vertical Split-Mode
            case kVK_ANSI_7:
            {
                EX->KwmSplitMode = 1;
            } break;
            // Horizontal Split-Mode
            case kVK_ANSI_Slash:
            {
                EX->KwmSplitMode = 2;
            } break;
            // Resize Panes
            case kVK_ANSI_H:
            {
                EX->MoveContainerSplitter(1, -10);
            } break;
            case kVK_ANSI_L:
            {
                EX->MoveContainerSplitter(1, 10);
            } break;
            case kVK_ANSI_J:
            {
                EX->MoveContainerSplitter(2, 10);
            } break;
            case kVK_ANSI_K:
            {
                EX->MoveContainerSplitter(2, -10);
            } break;
            // Toggle Fullscreen / Parent Container
            case kVK_ANSI_F:
            {
                EX->ToggleFocusedWindowFullscreen();
            } break;
            case kVK_ANSI_P:
            {
                EX->ToggleFocusedWindowParentContainer();
            } break;
            default:
            {
                Result = false;
            } break;
        }
    }
    else if(CmdKey && AltKey && !CtrlKey)
    {
        switch(Keycode)
        {
            // Swap focused window with the previous window
            case kVK_ANSI_P:
            {
                EX->SwapFocusedWindowWithNearest(-1);
            } break;
            // Swap focused window with the next window
            case kVK_ANSI_N:
            {
                EX->SwapFocusedWindowWithNearest(1);
            } break;
            // Shift focus to the previous window
            case kVK_ANSI_H:
            {
                if(EX->FocusedWindow)
                {
                    EX->ShiftWindowFocus(-1);
                }
            } break;
            // Shift focus to the next window
            case kVK_ANSI_L:
            {
                if(EX->FocusedWindow)
                {
                    EX->ShiftWindowFocus(1);
                }
            } break;
            case kVK_ANSI_R:
            {
                EX->ReflectWindowNodeTreeVertically();
            } break;
            // Decrease screen padding
            case kVK_LeftArrow:
            {
                EX->ChangePaddingOfDisplay("Left", -10);
            } break;
            case kVK_RightArrow:
            {
                EX->ChangePaddingOfDisplay("Right", -10);
            } break;
            case kVK_UpArrow:
            {
                EX->ChangePaddingOfDisplay("Top", -10);
            } break;
            case kVK_DownArrow:
            {
                EX->ChangePaddingOfDisplay("Bottom", -10);
            } break;
            default:
            {
                Result = false;
            } break;
        }
    }
    else if(CmdKey && CtrlKey && !AltKey)
    {
        switch(Keycode)
        {
            // Send window to previous screen
            case kVK_ANSI_P:
            {
                EX->CycleFocusedWindowDisplay(-1);
            } break;
            // Send window to next screen
            case kVK_ANSI_N:
            {
                EX->CycleFocusedWindowDisplay(1);
            } break;
            // Decrease screen padding
            case kVK_LeftArrow:
            {
                EX->ChangePaddingOfDisplay("Left", 10);
            } break;
            case kVK_RightArrow:
            {
                EX->ChangePaddingOfDisplay("Right", 10);
            } break;
            case kVK_UpArrow:
            {
                EX->ChangePaddingOfDisplay("Top", 10);
            } break;
            case kVK_DownArrow:
            {
                EX->ChangePaddingOfDisplay("Bottom", 10);
            } break;
            default:
            {
                Result = false;
            };
        }
    }
    else
    {
        Result = false;
    }

    return Result;
}

extern "C" KWM_HOTKEY_COMMANDS(SystemHotkeyCommands)
{
    bool Result = true;
    if (CmdKey && !CtrlKey && !AltKey)
    {
        switch(Keycode)
        {
            // Spotlight fix
            case kVK_Space:
            {
                //EX->KwmFocusMode = FocusAutoraise;
            } break;
            default:
            {
                Result = false;
            } break;
        }
    }
    else
    {
        Result = false;
    }

    return Result;
}

extern "C" KWM_HOTKEY_COMMANDS(CustomHotkeyCommands)
{
    bool Result = true;
    if(CmdKey && AltKey && CtrlKey)
    {
        // Launch Application
        std::string SysCommand = "";
        switch(Keycode)
        {
            // Open New iTerm Window
            case kVK_Return:
            {
                SysCommand = "/Applications/iTerm.app/Contents/MacOS/iTerm2 --new-window &";
            } break;
            // Rebuild Hotkeys
            // case kVK_ANSI_R:
            // {
            //     SysCommand = "sh " + EX->KwmFilePath + "/sobuild.sh";
            // } break;
            // YTD - Media Player Controls
            case kVK_ANSI_Z:
            {
                SysCommand = "ytc prev";
            } break;
            case kVK_ANSI_X:
            {
                SysCommand = "ytc play";
            } break;
            case kVK_ANSI_C:
            {
                SysCommand = "ytc next";
            } break;
            case kVK_ANSI_V:
            {
                SysCommand = "ytc stop";
            } break;
            case kVK_ANSI_A:
            {
                SysCommand = "ytc volup";
            } break;
            case kVK_ANSI_D:
            {
                SysCommand = "ytc voldown";
            } break;
            case kVK_ANSI_S:
            {
                SysCommand = "ytc mkfav";
            } break;
            case kVK_LeftArrow:
            {
                SysCommand = "ytc seekbk";
            } break;
            case kVK_RightArrow:
            {
                SysCommand = "ytc seekfw";
            } break;
            case kVK_ANSI_Grave:
            {
                SysCommand = "ytc fav";
            } break;
            default:
            {
                Result = false;
            } break;
        }

        if(SysCommand != "")
        {
            system(SysCommand.c_str());
        }
    }
    else if(CmdKey && !AltKey && !CtrlKey)
    {
        switch(Keycode)
        {
            // disable retarded hotkey for minimizing an application
            case kVK_ANSI_M:
            {
            } break;
            // disable retarded hotkey for hiding an application
            case kVK_ANSI_H:
            {
            } break;
            // disable cmd+tab window-swap
            case kVK_Tab:
            {
            } break;
            default:
            {
                Result = false;
            } break;
        }
    }
    else
    {
        Result = false;
    }

    return Result;
}
<|endoftext|>


<commit_before>/*
 * htFollow - follow an http url until content is reached - implementation
 * Copyright(c) 2005-2006 of wave++ (Yuri D'Elia)
 * Distributed under GNU LGPL without ANY warranty.
 */

// interface and local headers
#include "htfollow.hh"
#include "hdrparse.hh"
#include "sanitize.hh"
#include "msg.hh"
using std::string;
using std::map;

// system headers
#include <memory>
using std::auto_ptr;

#include <stdexcept>
using std::runtime_error;

// implementation
string
itos(const int i)
{
  char buf[16];
  snprintf(buf, sizeof(buf), "%d", i);
  return string(buf);
}

Socket*
htFollow(map<string, string>& pReply, const URL& url,
    const Http::Header qHeaders, size_t limit, time_t timeout)
{
  URL buf = url;
  timeval tmBuf;
  if(timeout)
  {
    tmBuf.tv_sec = timeout;
    tmBuf.tv_usec = 0;
  }

  // connection loop
  auto_ptr<Socket> s;
  for(size_t level = limit;; --level)
  {
    msg("connecting to (%s %d)", sanitize_esc(buf.server).c_str(), buf.port);
    Http::Http httpc(sanitize_esc(buf.server).c_str(),
	buf.port, (timeout? &tmBuf: NULL));

    msg("requesting data on (%s)", sanitize_esc(buf.path).c_str());
    Http::Header aHeaders;
    Http::Reply reply(&aHeaders);
    s.reset(httpc.get(buf.path.c_str(), reply, &qHeaders));

    // validate the reply code
    if(reply.code != Http::Proto::ok &&
	reply.code != Http::Proto::moved &&
	reply.code != Http::Proto::found &&
	reply.code != Http::Proto::other)
      throw runtime_error(string("unexpected reply: ") +
	  itos(reply.code) + " " + sanitize_esc((reply.description.size()?
		  reply.description: reply.proto)).c_str());

    // parse the headers
    pReply = Http::hdrParse(aHeaders);
    if(reply.code == Http::Proto::ok)
      break;

    // recursion
    if(!level)
      throw runtime_error(string("hit redirect follow limit: ") + itos(limit));

    map<string, string>::iterator urlPos = pReply.find(Http::Proto::location);
    if(urlPos == pReply.end())
      throw runtime_error("redirection didn't contain an url");
    if(reply.code == Http::Proto::moved)
      err("warning: content moved permanently to %s",
	  sanitize_esc(urlPos->second).c_str());

    buf = urlPos->second;
    if(buf.proto.size() && buf.proto != url.proto)
      throw runtime_error(
	  string("protocol changes are not allowed in redirection (") +
	  url.proto + " -> " + sanitize_esc(buf.proto) + ")");
  }

  return s.release();
}
<commit_msg>htfollow.cc: include <cstdio> for snprintf<commit_after>/*
 * htFollow - follow an http url until content is reached - implementation
 * Copyright(c) 2005-2006 of wave++ (Yuri D'Elia)
 * Distributed under GNU LGPL without ANY warranty.
 */

// interface and local headers
#include "htfollow.hh"
#include "hdrparse.hh"
#include "sanitize.hh"
#include "msg.hh"
using std::string;
using std::map;

// system headers
#include <cstdio>

#include <memory>
using std::auto_ptr;

#include <stdexcept>
using std::runtime_error;

// implementation
string
itos(const int i)
{
  char buf[16];
  snprintf(buf, sizeof(buf), "%d", i);
  return string(buf);
}

Socket*
htFollow(map<string, string>& pReply, const URL& url,
    const Http::Header qHeaders, size_t limit, time_t timeout)
{
  URL buf = url;
  timeval tmBuf;
  if(timeout)
  {
    tmBuf.tv_sec = timeout;
    tmBuf.tv_usec = 0;
  }

  // connection loop
  auto_ptr<Socket> s;
  for(size_t level = limit;; --level)
  {
    msg("connecting to (%s %d)", sanitize_esc(buf.server).c_str(), buf.port);
    Http::Http httpc(sanitize_esc(buf.server).c_str(),
	buf.port, (timeout? &tmBuf: NULL));

    msg("requesting data on (%s)", sanitize_esc(buf.path).c_str());
    Http::Header aHeaders;
    Http::Reply reply(&aHeaders);
    s.reset(httpc.get(buf.path.c_str(), reply, &qHeaders));

    // validate the reply code
    if(reply.code != Http::Proto::ok &&
	reply.code != Http::Proto::moved &&
	reply.code != Http::Proto::found &&
	reply.code != Http::Proto::other)
      throw runtime_error(string("unexpected reply: ") +
	  itos(reply.code) + " " + sanitize_esc((reply.description.size()?
		  reply.description: reply.proto)).c_str());

    // parse the headers
    pReply = Http::hdrParse(aHeaders);
    if(reply.code == Http::Proto::ok)
      break;

    // recursion
    if(!level)
      throw runtime_error(string("hit redirect follow limit: ") + itos(limit));

    map<string, string>::iterator urlPos = pReply.find(Http::Proto::location);
    if(urlPos == pReply.end())
      throw runtime_error("redirection didn't contain an url");
    if(reply.code == Http::Proto::moved)
      err("warning: content moved permanently to %s",
	  sanitize_esc(urlPos->second).c_str());

    buf = urlPos->second;
    if(buf.proto.size() && buf.proto != url.proto)
      throw runtime_error(
	  string("protocol changes are not allowed in redirection (") +
	  url.proto + " -> " + sanitize_esc(buf.proto) + ")");
  }

  return s.release();
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2011 Google Inc. 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 GOOGLE, INC. ``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 APPLE COMPUTER, INC. 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 "config.h"
#include "core/dom/SecurityContext.h"

#include <wtf/text/StringBuilder.h>
#include "core/dom/WebCoreMemoryInstrumentation.h"
#include "core/html/parser/HTMLParserIdioms.h"
#include "core/page/ContentSecurityPolicy.h"
#include "weborigin/SecurityOrigin.h"

namespace WebCore {

SecurityContext::SecurityContext()
    : m_mayDisplaySeamlesslyWithParent(false)
    , m_haveInitializedSecurityOrigin(false)
    , m_sandboxFlags(SandboxNone)
{
}

SecurityContext::~SecurityContext()
{
}

void SecurityContext::setSecurityOrigin(PassRefPtr<SecurityOrigin> securityOrigin)
{
    m_securityOrigin = securityOrigin;
    m_haveInitializedSecurityOrigin = true;
}

void SecurityContext::setContentSecurityPolicy(PassOwnPtr<ContentSecurityPolicy> contentSecurityPolicy)
{
    m_contentSecurityPolicy = contentSecurityPolicy;
}

bool SecurityContext::isSecureTransitionTo(const KURL& url) const
{
    // If we haven't initialized our security origin by now, this is probably
    // a new window created via the API (i.e., that lacks an origin and lacks
    // a place to inherit the origin from).
    if (!haveInitializedSecurityOrigin())
        return true;

    RefPtr<SecurityOrigin> other = SecurityOrigin::create(url);
    return securityOrigin()->canAccess(other.get());
}

void SecurityContext::enforceSandboxFlags(SandboxFlags mask)
{
    m_sandboxFlags |= mask;

    // The SandboxOrigin is stored redundantly in the security origin.
    if (isSandboxed(SandboxOrigin) && securityOrigin() && !securityOrigin()->isUnique()) {
        setSecurityOrigin(SecurityOrigin::createUnique());
        didUpdateSecurityOrigin();
    }
}

void SecurityContext::didUpdateSecurityOrigin()
{
    // Subclasses can override this function if the need to do extra work when the security origin changes.
}

SandboxFlags SecurityContext::parseSandboxPolicy(const String& policy, String& invalidTokensErrorMessage)
{
    // http://www.w3.org/TR/html5/the-iframe-element.html#attr-iframe-sandbox
    // Parse the unordered set of unique space-separated tokens.
    SandboxFlags flags = SandboxAll;
    const UChar* characters = policy.bloatedCharacters();
    unsigned length = policy.length();
    unsigned start = 0;
    unsigned numberOfTokenErrors = 0;
    StringBuilder tokenErrors;
    while (true) {
        while (start < length && isHTMLSpace(characters[start]))
            ++start;
        if (start >= length)
            break;
        unsigned end = start + 1;
        while (end < length && !isHTMLSpace(characters[end]))
            ++end;

        // Turn off the corresponding sandbox flag if it's set as "allowed".
        String sandboxToken = policy.substring(start, end - start);
        if (equalIgnoringCase(sandboxToken, "allow-same-origin"))
            flags &= ~SandboxOrigin;
        else if (equalIgnoringCase(sandboxToken, "allow-forms"))
            flags &= ~SandboxForms;
        else if (equalIgnoringCase(sandboxToken, "allow-scripts")) {
            flags &= ~SandboxScripts;
            flags &= ~SandboxAutomaticFeatures;
        } else if (equalIgnoringCase(sandboxToken, "allow-top-navigation"))
            flags &= ~SandboxTopNavigation;
        else if (equalIgnoringCase(sandboxToken, "allow-popups"))
            flags &= ~SandboxPopups;
        else if (equalIgnoringCase(sandboxToken, "allow-pointer-lock"))
            flags &= ~SandboxPointerLock;
        else {
            if (numberOfTokenErrors)
                tokenErrors.appendLiteral(", '");
            else
                tokenErrors.append('\'');
            tokenErrors.append(sandboxToken);
            tokenErrors.append('\'');
            numberOfTokenErrors++;
        }

        start = end + 1;
    }

    if (numberOfTokenErrors) {
        if (numberOfTokenErrors > 1)
            tokenErrors.appendLiteral(" are invalid sandbox flags.");
        else
            tokenErrors.appendLiteral(" is an invalid sandbox flag.");
        invalidTokensErrorMessage = tokenErrors.toString();
    }

    return flags;
}

void SecurityContext::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
{
    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM);
    info.addMember(m_securityOrigin, "securityOrigin");
    info.addMember(m_contentSecurityPolicy, "contentSecurityPolicy");
}

}
<commit_msg>SecurityContext shouldn't bloatCharacters()<commit_after>/*
 * Copyright (C) 2011 Google Inc. 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 GOOGLE, INC. ``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 APPLE COMPUTER, INC. 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 "config.h"
#include "core/dom/SecurityContext.h"

#include <wtf/text/StringBuilder.h>
#include "core/dom/WebCoreMemoryInstrumentation.h"
#include "core/html/parser/HTMLParserIdioms.h"
#include "core/page/ContentSecurityPolicy.h"
#include "weborigin/SecurityOrigin.h"

namespace WebCore {

SecurityContext::SecurityContext()
    : m_mayDisplaySeamlesslyWithParent(false)
    , m_haveInitializedSecurityOrigin(false)
    , m_sandboxFlags(SandboxNone)
{
}

SecurityContext::~SecurityContext()
{
}

void SecurityContext::setSecurityOrigin(PassRefPtr<SecurityOrigin> securityOrigin)
{
    m_securityOrigin = securityOrigin;
    m_haveInitializedSecurityOrigin = true;
}

void SecurityContext::setContentSecurityPolicy(PassOwnPtr<ContentSecurityPolicy> contentSecurityPolicy)
{
    m_contentSecurityPolicy = contentSecurityPolicy;
}

bool SecurityContext::isSecureTransitionTo(const KURL& url) const
{
    // If we haven't initialized our security origin by now, this is probably
    // a new window created via the API (i.e., that lacks an origin and lacks
    // a place to inherit the origin from).
    if (!haveInitializedSecurityOrigin())
        return true;

    RefPtr<SecurityOrigin> other = SecurityOrigin::create(url);
    return securityOrigin()->canAccess(other.get());
}

void SecurityContext::enforceSandboxFlags(SandboxFlags mask)
{
    m_sandboxFlags |= mask;

    // The SandboxOrigin is stored redundantly in the security origin.
    if (isSandboxed(SandboxOrigin) && securityOrigin() && !securityOrigin()->isUnique()) {
        setSecurityOrigin(SecurityOrigin::createUnique());
        didUpdateSecurityOrigin();
    }
}

void SecurityContext::didUpdateSecurityOrigin()
{
    // Subclasses can override this function if the need to do extra work when the security origin changes.
}

SandboxFlags SecurityContext::parseSandboxPolicy(const String& policy, String& invalidTokensErrorMessage)
{
    // http://www.w3.org/TR/html5/the-iframe-element.html#attr-iframe-sandbox
    // Parse the unordered set of unique space-separated tokens.
    SandboxFlags flags = SandboxAll;
    unsigned length = policy.length();
    unsigned start = 0;
    unsigned numberOfTokenErrors = 0;
    StringBuilder tokenErrors;
    while (true) {
        while (start < length && isHTMLSpace(policy[start]))
            ++start;
        if (start >= length)
            break;
        unsigned end = start + 1;
        while (end < length && !isHTMLSpace(policy[end]))
            ++end;

        // Turn off the corresponding sandbox flag if it's set as "allowed".
        String sandboxToken = policy.substring(start, end - start);
        if (equalIgnoringCase(sandboxToken, "allow-same-origin"))
            flags &= ~SandboxOrigin;
        else if (equalIgnoringCase(sandboxToken, "allow-forms"))
            flags &= ~SandboxForms;
        else if (equalIgnoringCase(sandboxToken, "allow-scripts")) {
            flags &= ~SandboxScripts;
            flags &= ~SandboxAutomaticFeatures;
        } else if (equalIgnoringCase(sandboxToken, "allow-top-navigation"))
            flags &= ~SandboxTopNavigation;
        else if (equalIgnoringCase(sandboxToken, "allow-popups"))
            flags &= ~SandboxPopups;
        else if (equalIgnoringCase(sandboxToken, "allow-pointer-lock"))
            flags &= ~SandboxPointerLock;
        else {
            if (numberOfTokenErrors)
                tokenErrors.appendLiteral(", '");
            else
                tokenErrors.append('\'');
            tokenErrors.append(sandboxToken);
            tokenErrors.append('\'');
            numberOfTokenErrors++;
        }

        start = end + 1;
    }

    if (numberOfTokenErrors) {
        if (numberOfTokenErrors > 1)
            tokenErrors.appendLiteral(" are invalid sandbox flags.");
        else
            tokenErrors.appendLiteral(" is an invalid sandbox flag.");
        invalidTokensErrorMessage = tokenErrors.toString();
    }

    return flags;
}

void SecurityContext::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
{
    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM);
    info.addMember(m_securityOrigin, "securityOrigin");
    info.addMember(m_contentSecurityPolicy, "contentSecurityPolicy");
}

}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2007, 2008, 2009 Apple Inc. 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.
 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS 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 APPLE OR ITS 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 "config.h"
#include "core/xml/XSLTUnicodeSort.h"

#include <libxslt/templates.h>
#include <libxslt/xsltutils.h>
#include <wtf/text/WTFString.h>
#include <wtf/unicode/Collator.h>

namespace WebCore {

// Based on default implementation from libxslt 1.1.22 and xsltICUSort.c example.
void xsltUnicodeSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts, int nbsorts)
{
#ifdef XSLT_REFACTORED
    xsltStyleItemSortPtr comp;
#else
    xsltStylePreCompPtr comp;
#endif
    xmlXPathObjectPtr *resultsTab[XSLT_MAX_SORT];
    xmlXPathObjectPtr *results = NULL, *res;
    xmlNodeSetPtr list = NULL;
    int descending, number, desc, numb;
    int len = 0;
    int i, j, incr;
    int tst;
    int depth;
    xmlNodePtr node;
    xmlXPathObjectPtr tmp;
    int tempstype[XSLT_MAX_SORT], temporder[XSLT_MAX_SORT];

    if ((ctxt == NULL) || (sorts == NULL) || (nbsorts <= 0) ||
        (nbsorts >= XSLT_MAX_SORT))
        return;
    if (sorts[0] == NULL)
        return;
    comp = static_cast<xsltStylePreComp*>(sorts[0]->psvi);
    if (comp == NULL)
        return;

    list = ctxt->nodeList;
    if ((list == NULL) || (list->nodeNr <= 1))
        return; /* nothing to do */

    for (j = 0; j < nbsorts; j++) {
        comp = static_cast<xsltStylePreComp*>(sorts[j]->psvi);
        tempstype[j] = 0;
        if ((comp->stype == NULL) && (comp->has_stype != 0)) {
            comp->stype =
                xsltEvalAttrValueTemplate(ctxt, sorts[j],
                                          (const xmlChar *) "data-type",
                                          XSLT_NAMESPACE);
            if (comp->stype != NULL) {
                tempstype[j] = 1;
                if (xmlStrEqual(comp->stype, (const xmlChar *) "text"))
                    comp->number = 0;
                else if (xmlStrEqual(comp->stype, (const xmlChar *) "number"))
                    comp->number = 1;
                else {
                    xsltTransformError(ctxt, NULL, sorts[j],
                          "xsltDoSortFunction: no support for data-type = %s\n",
                                     comp->stype);
                    comp->number = 0; /* use default */
                }
            }
        }
        temporder[j] = 0;
        if ((comp->order == NULL) && (comp->has_order != 0)) {
            comp->order = xsltEvalAttrValueTemplate(ctxt, sorts[j],
                                                    (const xmlChar *) "order",
                                                    XSLT_NAMESPACE);
            if (comp->order != NULL) {
                temporder[j] = 1;
                if (xmlStrEqual(comp->order, (const xmlChar *) "ascending"))
                    comp->descending = 0;
                else if (xmlStrEqual(comp->order,
                                     (const xmlChar *) "descending"))
                    comp->descending = 1;
                else {
                    xsltTransformError(ctxt, NULL, sorts[j],
                             "xsltDoSortFunction: invalid value %s for order\n",
                                     comp->order);
                    comp->descending = 0; /* use default */
                }
            }
        }
    }

    len = list->nodeNr;

    resultsTab[0] = xsltComputeSortResult(ctxt, sorts[0]);
    for (i = 1;i < XSLT_MAX_SORT;i++)
        resultsTab[i] = NULL;

    results = resultsTab[0];

    comp = static_cast<xsltStylePreComp*>(sorts[0]->psvi);
    descending = comp->descending;
    number = comp->number;
    if (results == NULL)
        return;

    // We are passing a language identifier to a function that expects a locale identifier.
    // The implementation of Collator should be lenient, and accept both "en-US" and "en_US", for example.
    // This lets an author to really specify sorting rules, e.g. "de_DE@collation=phonebook", which isn't
    // possible with language alone.
    Collator collator(comp->has_lang ? (const char*)comp->lang : "en");
    collator.setOrderLowerFirst(comp->lower_first);

    /* Shell's sort of node-set */
    for (incr = len / 2; incr > 0; incr /= 2) {
        for (i = incr; i < len; i++) {
            j = i - incr;
            if (results[i] == NULL)
                continue;

            while (j >= 0) {
                if (results[j] == NULL)
                    tst = 1;
                else {
                    if (number) {
                        /* We make NaN smaller than number in accordance
                           with XSLT spec */
                        if (xmlXPathIsNaN(results[j]->floatval)) {
                            if (xmlXPathIsNaN(results[j + incr]->floatval))
                                tst = 0;
                            else
                                tst = -1;
                        } else if (xmlXPathIsNaN(results[j + incr]->floatval))
                            tst = 1;
                        else if (results[j]->floatval ==
                                results[j + incr]->floatval)
                            tst = 0;
                        else if (results[j]->floatval >
                                results[j + incr]->floatval)
                            tst = 1;
                        else tst = -1;
                    } else {
                        String str1 = String::fromUTF8((const char*)results[j]->stringval);
                        String str2 = String::fromUTF8((const char*)results[j + incr]->stringval);
                        tst = collator.collate(str1.bloatedCharacters(), str1.length(), str2.bloatedCharacters(), str2.length());
                    }
                    if (descending)
                        tst = -tst;
                }
                if (tst == 0) {
                    /*
                     * Okay we need to use multi level sorts
                     */
                    depth = 1;
                    while (depth < nbsorts) {
                        if (sorts[depth] == NULL)
                            break;
                        comp = static_cast<xsltStylePreComp*>(sorts[depth]->psvi);
                        if (comp == NULL)
                            break;
                        desc = comp->descending;
                        numb = comp->number;

                        /*
                         * Compute the result of the next level for the
                         * full set, this might be optimized ... or not
                         */
                        if (resultsTab[depth] == NULL)
                            resultsTab[depth] = xsltComputeSortResult(ctxt,
                                                        sorts[depth]);
                        res = resultsTab[depth];
                        if (res == NULL)
                            break;
                        if (res[j] == NULL) {
                            if (res[j+incr] != NULL)
                                tst = 1;
                        } else {
                            if (numb) {
                                /* We make NaN smaller than number in
                                   accordance with XSLT spec */
                                if (xmlXPathIsNaN(res[j]->floatval)) {
                                    if (xmlXPathIsNaN(res[j +
                                                    incr]->floatval))
                                        tst = 0;
                                    else
                                        tst = -1;
                                } else if (xmlXPathIsNaN(res[j + incr]->
                                                floatval))
                                    tst = 1;
                                else if (res[j]->floatval == res[j + incr]->
                                                floatval)
                                    tst = 0;
                                else if (res[j]->floatval >
                                        res[j + incr]->floatval)
                                    tst = 1;
                                else tst = -1;
                            } else {
                                String str1 = String::fromUTF8((const char*)res[j]->stringval);
                                String str2 = String::fromUTF8((const char*)res[j + incr]->stringval);
                                tst = collator.collate(str1.bloatedCharacters(), str1.length(), str2.bloatedCharacters(), str2.length());
                            }
                            if (desc)
                                tst = -tst;
                        }

                        /*
                         * if we still can't differenciate at this level
                         * try one level deeper.
                         */
                        if (tst != 0)
                            break;
                        depth++;
                    }
                }
                if (tst == 0) {
                    tst = results[j]->index > results[j + incr]->index;
                }
                if (tst > 0) {
                    tmp = results[j];
                    results[j] = results[j + incr];
                    results[j + incr] = tmp;
                    node = list->nodeTab[j];
                    list->nodeTab[j] = list->nodeTab[j + incr];
                    list->nodeTab[j + incr] = node;
                    depth = 1;
                    while (depth < nbsorts) {
                        if (sorts[depth] == NULL)
                            break;
                        if (resultsTab[depth] == NULL)
                            break;
                        res = resultsTab[depth];
                        tmp = res[j];
                        res[j] = res[j + incr];
                        res[j + incr] = tmp;
                        depth++;
                    }
                    j -= incr;
                } else
                    break;
            }
        }
    }

    for (j = 0; j < nbsorts; j++) {
        comp = static_cast<xsltStylePreComp*>(sorts[j]->psvi);
        if (tempstype[j] == 1) {
            /* The data-type needs to be recomputed each time */
            xmlFree((void *)(comp->stype));
            comp->stype = NULL;
        }
        if (temporder[j] == 1) {
            /* The order needs to be recomputed each time */
            xmlFree((void *)(comp->order));
            comp->order = NULL;
        }
        if (resultsTab[j] != NULL) {
            for (i = 0;i < len;i++)
                xmlXPathFreeObject(resultsTab[j][i]);
            xmlFree(resultsTab[j]);
        }
    }
}

} // namespace WebCore
<commit_msg>XSLTUnicodeSort shouldn't use bloatedCharacters<commit_after>/*
 * Copyright (C) 2007, 2008, 2009 Apple Inc. 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.
 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS 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 APPLE OR ITS 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 "config.h"
#include "core/xml/XSLTUnicodeSort.h"

#include <libxslt/templates.h>
#include <libxslt/xsltutils.h>
#include <wtf/text/WTFString.h>
#include <wtf/unicode/Collator.h>

namespace WebCore {

// Based on default implementation from libxslt 1.1.22 and xsltICUSort.c example.
void xsltUnicodeSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts, int nbsorts)
{
#ifdef XSLT_REFACTORED
    xsltStyleItemSortPtr comp;
#else
    xsltStylePreCompPtr comp;
#endif
    xmlXPathObjectPtr *resultsTab[XSLT_MAX_SORT];
    xmlXPathObjectPtr *results = NULL, *res;
    xmlNodeSetPtr list = NULL;
    int descending, number, desc, numb;
    int len = 0;
    int i, j, incr;
    int tst;
    int depth;
    xmlNodePtr node;
    xmlXPathObjectPtr tmp;
    int tempstype[XSLT_MAX_SORT], temporder[XSLT_MAX_SORT];

    if ((ctxt == NULL) || (sorts == NULL) || (nbsorts <= 0) ||
        (nbsorts >= XSLT_MAX_SORT))
        return;
    if (sorts[0] == NULL)
        return;
    comp = static_cast<xsltStylePreComp*>(sorts[0]->psvi);
    if (comp == NULL)
        return;

    list = ctxt->nodeList;
    if ((list == NULL) || (list->nodeNr <= 1))
        return; /* nothing to do */

    for (j = 0; j < nbsorts; j++) {
        comp = static_cast<xsltStylePreComp*>(sorts[j]->psvi);
        tempstype[j] = 0;
        if ((comp->stype == NULL) && (comp->has_stype != 0)) {
            comp->stype =
                xsltEvalAttrValueTemplate(ctxt, sorts[j],
                                          (const xmlChar *) "data-type",
                                          XSLT_NAMESPACE);
            if (comp->stype != NULL) {
                tempstype[j] = 1;
                if (xmlStrEqual(comp->stype, (const xmlChar *) "text"))
                    comp->number = 0;
                else if (xmlStrEqual(comp->stype, (const xmlChar *) "number"))
                    comp->number = 1;
                else {
                    xsltTransformError(ctxt, NULL, sorts[j],
                          "xsltDoSortFunction: no support for data-type = %s\n",
                                     comp->stype);
                    comp->number = 0; /* use default */
                }
            }
        }
        temporder[j] = 0;
        if ((comp->order == NULL) && (comp->has_order != 0)) {
            comp->order = xsltEvalAttrValueTemplate(ctxt, sorts[j],
                                                    (const xmlChar *) "order",
                                                    XSLT_NAMESPACE);
            if (comp->order != NULL) {
                temporder[j] = 1;
                if (xmlStrEqual(comp->order, (const xmlChar *) "ascending"))
                    comp->descending = 0;
                else if (xmlStrEqual(comp->order,
                                     (const xmlChar *) "descending"))
                    comp->descending = 1;
                else {
                    xsltTransformError(ctxt, NULL, sorts[j],
                             "xsltDoSortFunction: invalid value %s for order\n",
                                     comp->order);
                    comp->descending = 0; /* use default */
                }
            }
        }
    }

    len = list->nodeNr;

    resultsTab[0] = xsltComputeSortResult(ctxt, sorts[0]);
    for (i = 1;i < XSLT_MAX_SORT;i++)
        resultsTab[i] = NULL;

    results = resultsTab[0];

    comp = static_cast<xsltStylePreComp*>(sorts[0]->psvi);
    descending = comp->descending;
    number = comp->number;
    if (results == NULL)
        return;

    // We are passing a language identifier to a function that expects a locale identifier.
    // The implementation of Collator should be lenient, and accept both "en-US" and "en_US", for example.
    // This lets an author to really specify sorting rules, e.g. "de_DE@collation=phonebook", which isn't
    // possible with language alone.
    Collator collator(comp->has_lang ? (const char*)comp->lang : "en");
    collator.setOrderLowerFirst(comp->lower_first);

    /* Shell's sort of node-set */
    for (incr = len / 2; incr > 0; incr /= 2) {
        for (i = incr; i < len; i++) {
            j = i - incr;
            if (results[i] == NULL)
                continue;

            while (j >= 0) {
                if (results[j] == NULL)
                    tst = 1;
                else {
                    if (number) {
                        /* We make NaN smaller than number in accordance
                           with XSLT spec */
                        if (xmlXPathIsNaN(results[j]->floatval)) {
                            if (xmlXPathIsNaN(results[j + incr]->floatval))
                                tst = 0;
                            else
                                tst = -1;
                        } else if (xmlXPathIsNaN(results[j + incr]->floatval))
                            tst = 1;
                        else if (results[j]->floatval ==
                                results[j + incr]->floatval)
                            tst = 0;
                        else if (results[j]->floatval >
                                results[j + incr]->floatval)
                            tst = 1;
                        else tst = -1;
                    } else {
                        Vector<UChar> string1;
                        Vector<UChar> string2;
                        String::fromUTF8(reinterpret_cast<const char*>(results[j]->stringval)).appendTo(string1);
                        String::fromUTF8(reinterpret_cast<const char*>(results[j + incr]->stringval)).appendTo(string2);
                        tst = collator.collate(string1.data(), string1.size(), string2.data(), string2.size());
                    }
                    if (descending)
                        tst = -tst;
                }
                if (tst == 0) {
                    /*
                     * Okay we need to use multi level sorts
                     */
                    depth = 1;
                    while (depth < nbsorts) {
                        if (sorts[depth] == NULL)
                            break;
                        comp = static_cast<xsltStylePreComp*>(sorts[depth]->psvi);
                        if (comp == NULL)
                            break;
                        desc = comp->descending;
                        numb = comp->number;

                        /*
                         * Compute the result of the next level for the
                         * full set, this might be optimized ... or not
                         */
                        if (resultsTab[depth] == NULL)
                            resultsTab[depth] = xsltComputeSortResult(ctxt,
                                                        sorts[depth]);
                        res = resultsTab[depth];
                        if (res == NULL)
                            break;
                        if (res[j] == NULL) {
                            if (res[j+incr] != NULL)
                                tst = 1;
                        } else {
                            if (numb) {
                                /* We make NaN smaller than number in
                                   accordance with XSLT spec */
                                if (xmlXPathIsNaN(res[j]->floatval)) {
                                    if (xmlXPathIsNaN(res[j +
                                                    incr]->floatval))
                                        tst = 0;
                                    else
                                        tst = -1;
                                } else if (xmlXPathIsNaN(res[j + incr]->
                                                floatval))
                                    tst = 1;
                                else if (res[j]->floatval == res[j + incr]->
                                                floatval)
                                    tst = 0;
                                else if (res[j]->floatval >
                                        res[j + incr]->floatval)
                                    tst = 1;
                                else tst = -1;
                            } else {
                                String str1 = String::fromUTF8((const char*)res[j]->stringval);
                                String str2 = String::fromUTF8((const char*)res[j + incr]->stringval);
                                tst = collator.collate(str1.bloatedCharacters(), str1.length(), str2.bloatedCharacters(), str2.length());
                            }
                            if (desc)
                                tst = -tst;
                        }

                        /*
                         * if we still can't differenciate at this level
                         * try one level deeper.
                         */
                        if (tst != 0)
                            break;
                        depth++;
                    }
                }
                if (tst == 0) {
                    tst = results[j]->index > results[j + incr]->index;
                }
                if (tst > 0) {
                    tmp = results[j];
                    results[j] = results[j + incr];
                    results[j + incr] = tmp;
                    node = list->nodeTab[j];
                    list->nodeTab[j] = list->nodeTab[j + incr];
                    list->nodeTab[j + incr] = node;
                    depth = 1;
                    while (depth < nbsorts) {
                        if (sorts[depth] == NULL)
                            break;
                        if (resultsTab[depth] == NULL)
                            break;
                        res = resultsTab[depth];
                        tmp = res[j];
                        res[j] = res[j + incr];
                        res[j + incr] = tmp;
                        depth++;
                    }
                    j -= incr;
                } else
                    break;
            }
        }
    }

    for (j = 0; j < nbsorts; j++) {
        comp = static_cast<xsltStylePreComp*>(sorts[j]->psvi);
        if (tempstype[j] == 1) {
            /* The data-type needs to be recomputed each time */
            xmlFree((void *)(comp->stype));
            comp->stype = NULL;
        }
        if (temporder[j] == 1) {
            /* The order needs to be recomputed each time */
            xmlFree((void *)(comp->order));
            comp->order = NULL;
        }
        if (resultsTab[j] != NULL) {
            for (i = 0;i < len;i++)
                xmlXPathFreeObject(resultsTab[j][i]);
            xmlFree(resultsTab[j]);
        }
    }
}

} // namespace WebCore
<|endoftext|>


<commit_before>#include "vast/archive.h"

#include <cppa/cppa.hpp>
#include "vast/aliases.h"
#include "vast/bitstream.h"
#include "vast/exception.h"
#include "vast/file_system.h"
#include "vast/segment.h"
#include "vast/segment_manager.h"
#include "vast/serialization.h"
#include "vast/io/file_stream.h"

namespace vast {

archive::archive(std::string directory)
  : directory_{std::move(directory)}
{
}

path const& archive::dir() const
{
  return directory_;
}

void archive::load()
{
  assert(exists(directory_));
  traverse(
      directory_,
      [&](path const& p) -> bool
      {
        file f{p};
        // FIXME: factor the segment header and load it as a single unit.
        uint32_t m;
        uint8_t v;
        uuid id;
        io::compression c;
        event_id base;
        uint32_t n;
        f.open(file::read_only);
        io::file_input_stream source(f);
        binary_deserializer d{source};
        d >> m >> v >> id >> c >> base >> n;
        VAST_LOG_DEBUG("found segment " << p.basename() <<
                       " for ID range [" << base << ", " << base + n << ")");
        if (m != segment::magic)
        {
          VAST_LOG_ERROR("got invalid segment magic for " << id);
          return false;
        }
        else if (! ranges_.insert(base, base + n, std::move(id)))
        {
          VAST_LOG_ERROR("inconsistency in ID space for [" << base
                         << ", " << base + n << ")");
          return false;
        }
        return true;
      });
}

void archive::store(segment const& s)
{
  if (! ranges_.insert(s.base(), s.base() + s.events(), s.id()))
    VAST_LOG_ERROR("failed to register segment " << s.id());
}

uuid const* archive::lookup(event_id eid) const
{
  return ranges_.lookup(eid);
}

using namespace cppa;

archive_actor::archive_actor(std::string const& directory, size_t max_segments)
  : archive_{directory}
{
  segment_manager_ =
    spawn<segment_manager_actor, linked>(max_segments, directory);
}

void archive_actor::act()
{
  if (! exists(archive_.dir()) && ! mkdir(archive_.dir()))
  {
    VAST_LOG_ACTOR_ERROR("failed to create directory " << archive_.dir());
    quit(exit::error);
    return;
  }
  archive_.load();
  become(
      on_arg_match >> [=](uuid const&)
      {
        forward_to(segment_manager_);
      },
      on_arg_match >> [=](event_id eid)
      {
        if (auto id = archive_.lookup(eid))
        {
          VAST_LOG_ACTOR_VERBOSE("got segment " << *id << " for event " << eid);
          send(segment_manager_, *id, last_sender());
        }
        else
        {
          VAST_LOG_ACTOR_WARN("no segment found for event " << eid);
          reply(eid);
        }
      },
      on(arg_match) >> [=](segment const& s)
      {
        archive_.store(s);
        forward_to(segment_manager_);
        reply(atom("segment"), atom("ack"), s.id());
      });
}

char const* archive_actor::description() const
{
  return "archive";
}

} // namespace vast
<commit_msg>Support plain UUID lookup.<commit_after>#include "vast/archive.h"

#include <cppa/cppa.hpp>
#include "vast/aliases.h"
#include "vast/bitstream.h"
#include "vast/exception.h"
#include "vast/file_system.h"
#include "vast/segment.h"
#include "vast/segment_manager.h"
#include "vast/serialization.h"
#include "vast/io/file_stream.h"

namespace vast {

archive::archive(std::string directory)
  : directory_{std::move(directory)}
{
}

path const& archive::dir() const
{
  return directory_;
}

void archive::load()
{
  assert(exists(directory_));
  traverse(
      directory_,
      [&](path const& p) -> bool
      {
        file f{p};
        // FIXME: factor the segment header and load it as a single unit.
        uint32_t m;
        uint8_t v;
        uuid id;
        io::compression c;
        event_id base;
        uint32_t n;
        f.open(file::read_only);
        io::file_input_stream source(f);
        binary_deserializer d{source};
        d >> m >> v >> id >> c >> base >> n;
        VAST_LOG_DEBUG("found segment " << p.basename() <<
                       " for ID range [" << base << ", " << base + n << ")");
        if (m != segment::magic)
        {
          VAST_LOG_ERROR("got invalid segment magic for " << id);
          return false;
        }
        else if (! ranges_.insert(base, base + n, std::move(id)))
        {
          VAST_LOG_ERROR("inconsistency in ID space for [" << base
                         << ", " << base + n << ")");
          return false;
        }
        return true;
      });
}

void archive::store(segment const& s)
{
  if (! ranges_.insert(s.base(), s.base() + s.events(), s.id()))
    VAST_LOG_ERROR("failed to register segment " << s.id());
}

uuid const* archive::lookup(event_id eid) const
{
  return ranges_.lookup(eid);
}

using namespace cppa;

archive_actor::archive_actor(std::string const& directory, size_t max_segments)
  : archive_{directory}
{
  segment_manager_ =
    spawn<segment_manager_actor, linked>(max_segments, directory);
}

void archive_actor::act()
{
  if (! exists(archive_.dir()) && ! mkdir(archive_.dir()))
  {
    VAST_LOG_ACTOR_ERROR("failed to create directory " << archive_.dir());
    quit(exit::error);
    return;
  }
  archive_.load();
  become(
      on_arg_match >> [=](uuid const& id)
      {
        send(segment_manager_, id, last_sender());
      },
      on(atom("uuid"), arg_match) >> [=](event_id eid)
      {
        if (auto id = archive_.lookup(eid))
         reply(*id);
        else
          reply(eid);
      },
      on(atom("segment"), arg_match) >> [=](event_id eid)
      {
        if (auto id = archive_.lookup(eid))
        {
          VAST_LOG_ACTOR_VERBOSE("got segment " << *id << " for event " << eid);
          send(segment_manager_, *id, last_sender());
        }
        else
        {
          VAST_LOG_ACTOR_WARN("no segment found for event " << eid);
          reply(eid);
        }
      },
      on(arg_match) >> [=](segment const& s)
      {
        archive_.store(s);
        forward_to(segment_manager_);
        reply(atom("segment"), atom("ack"), s.id());
      });
}

char const* archive_actor::description() const
{
  return "archive";
}

} // namespace vast
<|endoftext|>


<commit_before>#define DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS
#include <doctest/doctest.h>
#include <rtti/metadefine.h>

namespace {

uint16_t explicit_constructed = 0;
uint16_t default_constructed = 0;
uint16_t copy_constructed = 0;
uint16_t move_constructed = 0;
uint16_t copy_assigned = 0;
uint16_t move_assigned = 0;

void reset_counters()
{
    explicit_constructed = 0;
    default_constructed = 0;
    copy_constructed = 0;
    move_constructed = 0;
    copy_assigned = 0;
    move_assigned = 0;
}

}

namespace test {

class TestQPointer;

class PrivateImpl {
public:
    PrivateImpl() = default;
    PrivateImpl(const PrivateImpl &other)
        : m_value{other.m_value}
        , m_priority{other.m_priority}
    {}
    PrivateImpl(PrivateImpl &&other) = delete;
    PrivateImpl& operator=(const PrivateImpl&) = delete;
    PrivateImpl& operator=(PrivateImpl&&) = delete;

    explicit PrivateImpl(std::string_view value)
        : m_value{value}
    {}
private:
    std::string m_value;
    int64_t m_priority = 0;
    TestQPointer *m_qImpl = nullptr;

    friend class TestQPointer;
};

class TestQPointer {
public:
    TestQPointer()
    {
        ++default_constructed;
    }

    TestQPointer(std::string_view value)
        : m_pImpl{new PrivateImpl{value}}
    {
        m_pImpl->m_qImpl = this;
        ++explicit_constructed;
    }

    TestQPointer(TestQPointer const &other)
        : m_pImpl{other.m_pImpl ? new PrivateImpl(*other.m_pImpl) : nullptr}
    {
        if (m_pImpl)
            m_pImpl->m_qImpl = this;
        ++copy_constructed;
    }

    TestQPointer(TestQPointer &&other) noexcept
    {
        swap(other);
        ++move_constructed;
    }

    TestQPointer& operator=(TestQPointer const &other)
    {
        if (m_pImpl != other.m_pImpl)
            TestQPointer{other}.swap(*this);
        ++copy_assigned;
        --copy_constructed;
        return *this;
    }

    TestQPointer& operator=(TestQPointer &&other) noexcept
    {
        if (m_pImpl != other.m_pImpl)
            TestQPointer{std::move(other)}.swap(*this);
        ++move_assigned;
        --move_constructed;
        return *this;
    }

    void swap(TestQPointer &other) noexcept
    {
        std::swap(m_pImpl, other.m_pImpl);
        if (m_pImpl)
            m_pImpl->m_qImpl = this;
        if (other.m_pImpl)
            other.m_pImpl->m_qImpl = &other;
    }

    virtual ~TestQPointer()
    {
        if (m_pImpl)
            delete m_pImpl;
    }

    bool check() const
    {
        return m_pImpl && (this == m_pImpl->m_qImpl);
    }

    std::string const& value() const
    {
        if (empty())
            throw std::runtime_error{"Empty!"};
        return m_pImpl->m_value;
    }

    std::string& value()
    {
        allocate_pimpl();
        return m_pImpl->m_value;
    }

    int64_t get_priority() const
    {
        if (empty())
            throw std::runtime_error{"Empty!"};
        return m_pImpl->m_priority;
    }

    void set_priority(int64_t value)
    {
        allocate_pimpl();
        if (m_pImpl->m_priority != value)
        {
            m_pImpl->m_priority = value;
            m_pImpl->m_value = std::to_string(value);
        }
    }

    bool empty() const
    {  return !m_pImpl; }

private:
    void allocate_pimpl()
    {
        if (!m_pImpl)
            m_pImpl = new PrivateImpl();
    }

    PrivateImpl *m_pImpl = nullptr;

    friend class PrivatePimpl;
};

} // namespace test

RTTI_REGISTER
{
    rtti::global_define()
        ._namespace("test")
            ._class<test::TestQPointer>("TestQPointer")
                ._constructor<std::string_view>()
                ._method("empty", &test::TestQPointer::empty)
                ._method("check", &test::TestQPointer::check)
                ._property("priority", &test::TestQPointer::get_priority, &test::TestQPointer::set_priority)
                ._method<std::string& (test::TestQPointer::*)()>("value", &test::TestQPointer::value)
                ._method<std::string const& (test::TestQPointer::*)() const>("const_value", &test::TestQPointer::value)
            ._end()
        ._end()
    ;
}

TEST_CASE("Variant")
{
    SUBCASE("1")
    {
        reset_counters();

        using namespace std::literals;
        rtti::variant v = "Hello, World!"sv;
        auto qp = v.to<test::TestQPointer>();
        REQUIRE(qp.check());
        REQUIRE(qp.value() == "Hello, World!");
        REQUIRE(qp.get_priority() == 0);
        REQUIRE((
            (explicit_constructed == 1)
            && (default_constructed == 0)
            && (copy_constructed == 0)
            && (move_constructed == 1)
            && (copy_assigned == 0)
            && (move_assigned == 0)
        ));

        SUBCASE("Copy")
        {
            reset_counters();

            rtti::variant v = qp;
            REQUIRE(v.invoke("check") == true);
            REQUIRE(v.invoke("empty") == false);

            auto *meta_class = v.metaClass();
            REQUIRE(meta_class == rtti::MetaNamespace::global()->getNamespace("test")->getClass("TestQPointer"));

            auto rov = v.invoke("const_value");
            REQUIRE(rov == "Hello, World!"s);
            auto ev = v.invoke("value");
            ev.ref<std::string>() = "Qwerty";
            REQUIRE(rov == "Qwerty"s);

            REQUIRE_FALSE(qp.empty());
            REQUIRE(qp.value() == "Hello, World!");

            REQUIRE((
                (explicit_constructed == 0)
                && (default_constructed == 0)
                && (copy_constructed == 1)
                && (move_constructed == 0)
                && (copy_assigned == 0)
                && (move_assigned == 0)
            ));

            auto *meta_prop = meta_class->getProperty("priority");
            REQUIRE(meta_prop);
            meta_prop->set(v, 100);
            REQUIRE(meta_prop->get(v) == 100LL);
            REQUIRE(meta_prop->get(v).eq(100));
            REQUIRE(rov == "100"s);
            REQUIRE(rov.eq("100"));
            REQUIRE(rov.eq(100));

            v.set_property("priority", 256);
            REQUIRE(v.get_property("priority").eq(256));
            REQUIRE(meta_prop->get(v).eq(256));
        }

        SUBCASE("Move")
        {
            reset_counters();

            rtti::variant v = std::move(qp);
            REQUIRE(v.invoke("check") == true);
            REQUIRE(v.invoke("empty") == false);

            auto rov = v.invoke("const_value");
            REQUIRE(rov == "Hello, World!"s);
            auto ev = v.invoke("value");
            ev.ref<std::string>() = "Qwerty";
            REQUIRE(rov == "Qwerty"s);

            REQUIRE(qp.empty());
            REQUIRE_FALSE(qp.check());

            REQUIRE((
                (explicit_constructed == 0)
                && (default_constructed == 0)
                && (copy_constructed == 0)
                && (move_constructed == 1)
                && (copy_assigned == 0)
                && (move_assigned == 0)
            ));
        }

        SUBCASE("Reference")
        {
            reset_counters();

            rtti::variant v = std::ref(qp);
            REQUIRE(v.invoke("check") == true);
            REQUIRE(v.invoke("empty") == false);

            auto rov = v.invoke("const_value");
            REQUIRE(rov == "Hello, World!"s);
            auto ev = v.invoke("value");
            ev.ref<std::string>() = "Qwerty";
            REQUIRE(rov == "Qwerty"s);
            REQUIRE(qp.value() == "Qwerty");

            REQUIRE((
                (explicit_constructed == 0)
                && (default_constructed == 0)
                && (copy_constructed == 0)
                && (move_constructed == 0)
                && (copy_assigned == 0)
                && (move_assigned == 0)
            ));

//            v.set_property
        }
    }
}
<commit_msg>New variant tests<commit_after>#define DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS
#include <doctest/doctest.h>
#include <rtti/metadefine.h>

namespace {

uint16_t explicit_constructed = 0;
uint16_t default_constructed = 0;
uint16_t copy_constructed = 0;
uint16_t move_constructed = 0;
uint16_t copy_assigned = 0;
uint16_t move_assigned = 0;

void reset_counters()
{
    explicit_constructed = 0;
    default_constructed = 0;
    copy_constructed = 0;
    move_constructed = 0;
    copy_assigned = 0;
    move_assigned = 0;
}

}

namespace test {

class TestQPointer;

class PrivateImpl {
public:
    PrivateImpl() = default;
    PrivateImpl(const PrivateImpl &other)
        : m_value{other.m_value}
        , m_priority{other.m_priority}
    {}
    PrivateImpl(PrivateImpl &&other) = delete;
    PrivateImpl& operator=(const PrivateImpl&) = delete;
    PrivateImpl& operator=(PrivateImpl&&) = delete;

    explicit PrivateImpl(std::string_view value)
        : m_value{value}
    {}
private:
    std::string m_value;
    int64_t m_priority = 0;
    TestQPointer *m_qImpl = nullptr;

    friend class TestQPointer;
};

class TestQPointer {
public:
    TestQPointer()
    {
        ++default_constructed;
    }

    TestQPointer(std::string_view value)
        : m_pImpl{new PrivateImpl{value}}
    {
        m_pImpl->m_qImpl = this;
        ++explicit_constructed;
    }

    TestQPointer(TestQPointer const &other)
        : m_pImpl{other.m_pImpl ? new PrivateImpl(*other.m_pImpl) : nullptr}
    {
        if (m_pImpl)
            m_pImpl->m_qImpl = this;
        ++copy_constructed;
    }

    TestQPointer(TestQPointer &&other) noexcept
    {
        swap(other);
        ++move_constructed;
    }

    TestQPointer& operator=(TestQPointer const &other)
    {
        if (m_pImpl != other.m_pImpl)
            TestQPointer{other}.swap(*this);
        ++copy_assigned;
        --copy_constructed;
        return *this;
    }

    TestQPointer& operator=(TestQPointer &&other) noexcept
    {
        if (m_pImpl != other.m_pImpl)
            TestQPointer{std::move(other)}.swap(*this);
        ++move_assigned;
        --move_constructed;
        return *this;
    }

    void swap(TestQPointer &other) noexcept
    {
        std::swap(m_pImpl, other.m_pImpl);
        if (m_pImpl)
            m_pImpl->m_qImpl = this;
        if (other.m_pImpl)
            other.m_pImpl->m_qImpl = &other;
    }

    virtual ~TestQPointer()
    {
        if (m_pImpl)
            delete m_pImpl;
    }

    bool check() const
    {
        return m_pImpl && (this == m_pImpl->m_qImpl);
    }

    std::string const& value() const
    {
        if (empty())
            throw std::runtime_error{"Empty!"};
        return m_pImpl->m_value;
    }

    std::string& value()
    {
        allocate_pimpl();
        return m_pImpl->m_value;
    }

    int64_t get_priority() const
    {
        if (empty())
            throw std::runtime_error{"Empty!"};
        return m_pImpl->m_priority;
    }

    void set_priority(int64_t value)
    {
        allocate_pimpl();
        if (m_pImpl->m_priority != value)
        {
            m_pImpl->m_priority = value;
            m_pImpl->m_value = std::to_string(value);
        }
    }

    bool empty() const
    {  return !m_pImpl; }

private:
    void allocate_pimpl()
    {
        if (!m_pImpl)
            m_pImpl = new PrivateImpl();
    }

    PrivateImpl *m_pImpl = nullptr;

    friend class PrivatePimpl;
};

} // namespace test

RTTI_REGISTER
{
    rtti::global_define()
        ._namespace("test")
            ._class<test::TestQPointer>("TestQPointer")
                ._constructor<std::string_view>()
                ._method("empty", &test::TestQPointer::empty)
                ._method("check", &test::TestQPointer::check)
                ._property("priority", &test::TestQPointer::get_priority, &test::TestQPointer::set_priority)
                ._method<std::string& (test::TestQPointer::*)()>("value", &test::TestQPointer::value)
                ._method<std::string const& (test::TestQPointer::*)() const>("const_value", &test::TestQPointer::value)
            ._end()
        ._end()
    ;
}

TEST_CASE("Variant")
{
    reset_counters();

    using namespace std::literals;
    rtti::variant v = "Hello, World!"sv;
    auto qp = v.to<test::TestQPointer>();
    REQUIRE(qp.check());
    REQUIRE(qp.value() == "Hello, World!");
    REQUIRE(qp.get_priority() == 0);
    REQUIRE((
                (explicit_constructed == 1)
                && (default_constructed == 0)
                && (copy_constructed == 0)
                && (move_constructed == 1)
                && (copy_assigned == 0)
                && (move_assigned == 0)
    ));

    SUBCASE("Metaclass")
    {
        rtti::variant v = qp;
        auto *meta_class = v.metaClass();
        REQUIRE(meta_class == rtti::MetaNamespace::global()->getNamespace("test")->getClass("TestQPointer"));
        REQUIRE(meta_class == rtti::metaType<test::TestQPointer>().metaClass());
        REQUIRE(meta_class == rtti::MetaType("test::TestQPointer").metaClass());
    }

    SUBCASE("Copy")
    {
        reset_counters();

        rtti::variant v = qp;
        REQUIRE(v.invoke("check") == true);
        REQUIRE(v.invoke("empty") == false);

        auto rov = v.invoke("const_value");
        REQUIRE(rov == "Hello, World!"s);
        auto ev = v.invoke("value");
        ev.ref<std::string>() = "Qwerty";
        REQUIRE(rov == "Qwerty"s);

        REQUIRE_FALSE(qp.empty());
        REQUIRE(qp.value() == "Hello, World!");

        REQUIRE((
                    (explicit_constructed == 0)
                    && (default_constructed == 0)
                    && (copy_constructed == 1)
                    && (move_constructed == 0)
                    && (copy_assigned == 0)
                    && (move_assigned == 0)
        ));

        auto *meta_class = v.metaClass();
        auto *meta_prop = meta_class->getProperty("priority");
        REQUIRE(meta_prop);
        meta_prop->set(v, 100);
        REQUIRE(meta_prop->get(v) == 100LL);
        REQUIRE(meta_prop->get(v).eq(100));
        REQUIRE(rov == "100"s);
        REQUIRE(rov.eq("100"));
        REQUIRE(rov.eq(100));

        v.set_property("priority", 256);
        REQUIRE(v.get_property("priority").eq(256));
        REQUIRE(meta_prop->get(v).eq(256));
    }

    SUBCASE("Move")
    {
        reset_counters();

        rtti::variant v = std::move(qp);
        REQUIRE(v.invoke("check") == true);
        REQUIRE(v.invoke("empty") == false);

        auto rov = v.invoke("const_value");
        REQUIRE(rov == "Hello, World!"s);
        auto ev = v.invoke("value");
        ev.ref<std::string>() = "Qwerty";
        REQUIRE(rov == "Qwerty"s);

        REQUIRE(qp.empty());
        REQUIRE_FALSE(qp.check());

        REQUIRE((
                    (explicit_constructed == 0)
                    && (default_constructed == 0)
                    && (copy_constructed == 0)
                    && (move_constructed == 1)
                    && (copy_assigned == 0)
                    && (move_assigned == 0)
                    ));
    }

    SUBCASE("Reference")
    {
        reset_counters();

        rtti::variant v = std::ref(qp);
        REQUIRE(v.invoke("check") == true);
        REQUIRE(v.invoke("empty") == false);

        auto rov = v.invoke("const_value");
        REQUIRE(rov == "Hello, World!"s);
        auto ev = v.invoke("value");
        ev.ref<std::string>() = "Qwerty";
        REQUIRE(rov == "Qwerty"s);
        REQUIRE(qp.value() == "Qwerty");

        REQUIRE((
                    (explicit_constructed == 0)
                    && (default_constructed == 0)
                    && (copy_constructed == 0)
                    && (move_constructed == 0)
                    && (copy_assigned == 0)
                    && (move_assigned == 0)
                    ));

        v.set_property("priority", 1024);
        REQUIRE(v.get_property("priority") == 1024LL);
        REQUIRE(v.get_property("priority").eq(1024));
        REQUIRE(qp.get_priority() == 1024);
    }
}
<|endoftext|>