<commit_before>/*
 * STLL Simple Text Layouting Library
 *
 * STLL is the legal property of its developers, whose
 * names are listed in the COPYRIGHT file, which is included
 * within the source distribution.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
#include "layouterCSS.h"

#include <vector>
#include <string>
#include <memory>
#include <algorithm>

namespace STLL {

static bool ruleFits(const std::string & sel, const pugi::xml_node & node)
{
  if (sel == node.name()) return true;
  if (sel[0] == '.')
  {
    for (auto attr: node.attributes())
      if ((std::string("class") == attr.name()) && (attr.value() == sel.substr(1)))
      {
        return true;
      }
  }
  if (sel.find_first_of('[') != sel.npos)
  {
    size_t st = sel.find_first_of('[');
    size_t en = sel.find_first_of(']');
    size_t mi = sel.find_first_of('=');

    if (sel[mi-1] == '|')
    {
      std::string tag = sel.substr(0, st);
      std::string attr = sel.substr(st+1, mi-2-st);
      std::string val = sel.substr(mi+1, en-mi-1);

      if (tag == node.name())
      {
        auto a = node.attribute(attr.c_str());
        if (!a.empty())
        {
          std::string nodeattrval = std::string(a.value());
          if (val.length() <= nodeattrval.length() && nodeattrval.substr(0, val.length()) == val)
            return true;
        }
      }
    }
  }

  return false;
}

static uint16_t rulePrio(const std::string & sel)
{
  if (sel[0] == '.') return 2;
  if (sel.find_first_of('[') != sel.npos) return 2;

  return 1;
}

static bool isInheriting(const std::string & attribute)
{
  if (attribute == "color") return true;
  if (attribute == "font-family") return true;
  if (attribute == "font-style") return true;
  if (attribute == "font-size") return true;
  if (attribute == "font-variant") return true;
  if (attribute == "font-weight") return true;
  if (attribute == "padding") return false;
  if (attribute == "padding-left") return false;
  if (attribute == "padding-right") return false;
  if (attribute == "padding-top") return false;
  if (attribute == "padding-bottom") return false;
  if (attribute == "margin") return false;
  if (attribute == "margin-left") return false;
  if (attribute == "margin-right") return false;
  if (attribute == "margin-top") return false;
  if (attribute == "margin-bottom") return false;
  if (attribute == "text-align") return true;
  if (attribute == "text-align-last") return true;
  if (attribute == "text-indent") return true;
  if (attribute == "direction") return true;
  if (attribute == "border-top-width") return false;
  if (attribute == "border-bottom-width") return false;
  if (attribute == "border-left-width") return false;
  if (attribute == "border-right-width") return false;
  if (attribute == "border-width") return false;
  if (attribute == "border-left-color") return false;
  if (attribute == "border-right-color") return false;
  if (attribute == "border-top-color") return false;
  if (attribute == "border-bottom-color") return false;
  if (attribute == "border-color") return false;
  if (attribute == "background-color") return false;
  if (attribute == "text-decoration") return false;
  if (attribute == "text-shadow") return true;
  if (attribute == "width") return false;
  if (attribute == "border-collapse") return true;

  assert(0);
}

static const std::string & getDefault(const std::string & attribute)
{
  static std::string defaults[]= { "sans", "normal", "0px", "", "ltr", "transparent", "separate" };

  if (attribute == "color") throw XhtmlException_c("You must specify the required colors, there is no default");
  if (attribute == "font-family") return defaults[0];
  if (attribute == "font-style") return defaults[1];
  if (attribute == "font-size") throw XhtmlException_c("You must specify all required font sizes, there is no default");
  if (attribute == "font-variant") return defaults[1];
  if (attribute == "font-weight") return defaults[1];
  if (attribute == "padding") return defaults[2];
  if (attribute == "padding-left") return defaults[3];
  if (attribute == "padding-right") return defaults[3];
  if (attribute == "padding-top") return defaults[3];
  if (attribute == "padding-bottom") return defaults[3];
  if (attribute == "margin") return defaults[2];
  if (attribute == "margin-left") return defaults[3];
  if (attribute == "margin-right") return defaults[3];
  if (attribute == "margin-top") return defaults[3];
  if (attribute == "margin-bottom") return defaults[3];
  if (attribute == "text-align") return defaults[3];
  if (attribute == "text-align-last") return defaults[3];
  if (attribute == "text-indent") return defaults[2];
  if (attribute == "direction") return defaults[4];
  if (attribute == "border-width") return defaults[2];
  if (attribute == "border-left-width") return defaults[3];
  if (attribute == "border-right-width") return defaults[3];
  if (attribute == "border-top-width") return defaults[3];
  if (attribute == "border-bottom-width") return defaults[3];
  if (attribute == "border-color") return defaults[3];
  if (attribute == "border-top-color") return defaults[3];
  if (attribute == "border-bottom-color") return defaults[3];
  if (attribute == "border-left-color") return defaults[3];
  if (attribute == "border-right-color") return defaults[3];
  if (attribute == "background-color") return defaults[5];
  if (attribute == "text-decoration") return defaults[3];
  if (attribute == "text-shadow") return defaults[3];
  if (attribute == "width") throw XhtmlException_c("You must specify the width, there is no default");
  if (attribute == "border-collapse") return defaults[6];

  assert(0);
}

static bool isValidAttribute(const std::string & attribute)
{
  if (attribute == "color") return true;
  if (attribute == "font-family") return true;
  if (attribute == "font-style") return true;
  if (attribute == "font-size") return true;
  if (attribute == "font-variant") return true;
  if (attribute == "font-weight") return true;
  if (attribute == "padding") return true;
  if (attribute == "padding-left") return true;
  if (attribute == "padding-right") return true;
  if (attribute == "padding-top") return true;
  if (attribute == "padding-bottom") return true;
  if (attribute == "margin") return true;
  if (attribute == "margin-left") return true;
  if (attribute == "margin-right") return true;
  if (attribute == "margin-top") return true;
  if (attribute == "margin-bottom") return true;
  if (attribute == "text-align") return true;
  if (attribute == "text-align-last") return true;
  if (attribute == "text-indent") return true;
  if (attribute == "direction") return true;
  if (attribute == "border-width") return true;
  if (attribute == "border-left-width") return true;
  if (attribute == "border-right-width") return true;
  if (attribute == "border-top-width") return true;
  if (attribute == "border-bottom-width") return true;
  if (attribute == "border-color") return true;
  if (attribute == "border-left-color") return true;
  if (attribute == "border-right-color") return true;
  if (attribute == "border-top-color") return true;
  if (attribute == "border-bottom-color") return true;
  if (attribute == "background-color") return true;
  if (attribute == "text-decoration") return true;
  if (attribute == "text-shadow") return true;
  if (attribute == "width") return true;
  if (attribute == "border-collapse") return true;

  return false;
}

const std::string & textStyleSheet_c::getValue(pugi::xml_node node, const std::string & attribute) const
{
  // go through all rules, check only the ones that give a value to the requested attribute
  // evaluate rule by priority (look at the CSS priority rules
  // choose the highest priority

  while (!node.empty())
  {
    uint16_t prio = 0;
    size_t bestI;

    for (size_t i = 0; i < rules.size(); i++)
    {
      if (   rules[i].attribute == attribute
          && ruleFits(rules[i].selector, node)
          && rulePrio(rules[i].selector) > prio
         )
      {
        prio = rulePrio(rules[i].selector);
        bestI = i;
      }
    }

    if (prio)
      return rules[bestI].value;

    if (!isInheriting(attribute))
      return getDefault(attribute);

    node = node.parent();
  }

  return getDefault(attribute);
}

void textStyleSheet_c::font(const std::string& family, const fontResource_c & res, const std::string& style, const std::string& variant, const std::string& weight, const std::string& stretch)
{
  auto i = families.find(family);

  if (i == families.end())
  {
    i = families.insert(std::make_pair(family, std::make_shared<fontFamily_c>(cache))).first;
  }

  i->second->addFont(res, style, variant, weight, stretch);
}

void textStyleSheet_c::addRule(const std::string sel, const std::string attr, const std::string val)
{
  if (!isValidAttribute(attr))
    throw XhtmlException_c(std::string("attribute not supported: ") + attr);

  rule r;
  r.selector = sel;
  r.attribute = attr;
  r.value = val;

  rules.push_back(r);
}

textStyleSheet_c::textStyleSheet_c(std::shared_ptr< fontCache_c > c)
{
  if (c)
  {
    cache = c;
  }
  else
  {
    cache = std::make_shared<fontCache_c>();
  }
}

}
<commit_msg>make text-decoration inherited, this is closer to the actual behavior than not inheriting<commit_after>/*
 * STLL Simple Text Layouting Library
 *
 * STLL is the legal property of its developers, whose
 * names are listed in the COPYRIGHT file, which is included
 * within the source distribution.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
#include "layouterCSS.h"

#include <vector>
#include <string>
#include <memory>
#include <algorithm>

namespace STLL {

static bool ruleFits(const std::string & sel, const pugi::xml_node & node)
{
  if (sel == node.name()) return true;
  if (sel[0] == '.')
  {
    for (auto attr: node.attributes())
      if ((std::string("class") == attr.name()) && (attr.value() == sel.substr(1)))
      {
        return true;
      }
  }
  if (sel.find_first_of('[') != sel.npos)
  {
    size_t st = sel.find_first_of('[');
    size_t en = sel.find_first_of(']');
    size_t mi = sel.find_first_of('=');

    if (sel[mi-1] == '|')
    {
      std::string tag = sel.substr(0, st);
      std::string attr = sel.substr(st+1, mi-2-st);
      std::string val = sel.substr(mi+1, en-mi-1);

      if (tag == node.name())
      {
        auto a = node.attribute(attr.c_str());
        if (!a.empty())
        {
          std::string nodeattrval = std::string(a.value());
          if (val.length() <= nodeattrval.length() && nodeattrval.substr(0, val.length()) == val)
            return true;
        }
      }
    }
  }

  return false;
}

static uint16_t rulePrio(const std::string & sel)
{
  if (sel[0] == '.') return 2;
  if (sel.find_first_of('[') != sel.npos) return 2;

  return 1;
}

static bool isInheriting(const std::string & attribute)
{
  if (attribute == "color") return true;
  if (attribute == "font-family") return true;
  if (attribute == "font-style") return true;
  if (attribute == "font-size") return true;
  if (attribute == "font-variant") return true;
  if (attribute == "font-weight") return true;
  if (attribute == "padding") return false;
  if (attribute == "padding-left") return false;
  if (attribute == "padding-right") return false;
  if (attribute == "padding-top") return false;
  if (attribute == "padding-bottom") return false;
  if (attribute == "margin") return false;
  if (attribute == "margin-left") return false;
  if (attribute == "margin-right") return false;
  if (attribute == "margin-top") return false;
  if (attribute == "margin-bottom") return false;
  if (attribute == "text-align") return true;
  if (attribute == "text-align-last") return true;
  if (attribute == "text-indent") return true;
  if (attribute == "direction") return true;
  if (attribute == "border-top-width") return false;
  if (attribute == "border-bottom-width") return false;
  if (attribute == "border-left-width") return false;
  if (attribute == "border-right-width") return false;
  if (attribute == "border-width") return false;
  if (attribute == "border-left-color") return false;
  if (attribute == "border-right-color") return false;
  if (attribute == "border-top-color") return false;
  if (attribute == "border-bottom-color") return false;
  if (attribute == "border-color") return false;
  if (attribute == "background-color") return false;
  if (attribute == "text-decoration") return true;
  if (attribute == "text-shadow") return true;
  if (attribute == "width") return false;
  if (attribute == "border-collapse") return true;

  assert(0);
}

static const std::string & getDefault(const std::string & attribute)
{
  static std::string defaults[]= { "sans", "normal", "0px", "", "ltr", "transparent", "separate" };

  if (attribute == "color") throw XhtmlException_c("You must specify the required colors, there is no default");
  if (attribute == "font-family") return defaults[0];
  if (attribute == "font-style") return defaults[1];
  if (attribute == "font-size") throw XhtmlException_c("You must specify all required font sizes, there is no default");
  if (attribute == "font-variant") return defaults[1];
  if (attribute == "font-weight") return defaults[1];
  if (attribute == "padding") return defaults[2];
  if (attribute == "padding-left") return defaults[3];
  if (attribute == "padding-right") return defaults[3];
  if (attribute == "padding-top") return defaults[3];
  if (attribute == "padding-bottom") return defaults[3];
  if (attribute == "margin") return defaults[2];
  if (attribute == "margin-left") return defaults[3];
  if (attribute == "margin-right") return defaults[3];
  if (attribute == "margin-top") return defaults[3];
  if (attribute == "margin-bottom") return defaults[3];
  if (attribute == "text-align") return defaults[3];
  if (attribute == "text-align-last") return defaults[3];
  if (attribute == "text-indent") return defaults[2];
  if (attribute == "direction") return defaults[4];
  if (attribute == "border-width") return defaults[2];
  if (attribute == "border-left-width") return defaults[3];
  if (attribute == "border-right-width") return defaults[3];
  if (attribute == "border-top-width") return defaults[3];
  if (attribute == "border-bottom-width") return defaults[3];
  if (attribute == "border-color") return defaults[3];
  if (attribute == "border-top-color") return defaults[3];
  if (attribute == "border-bottom-color") return defaults[3];
  if (attribute == "border-left-color") return defaults[3];
  if (attribute == "border-right-color") return defaults[3];
  if (attribute == "background-color") return defaults[5];
  if (attribute == "text-decoration") return defaults[3];
  if (attribute == "text-shadow") return defaults[3];
  if (attribute == "width") throw XhtmlException_c("You must specify the width, there is no default");
  if (attribute == "border-collapse") return defaults[6];

  assert(0);
}

static bool isValidAttribute(const std::string & attribute)
{
  if (attribute == "color") return true;
  if (attribute == "font-family") return true;
  if (attribute == "font-style") return true;
  if (attribute == "font-size") return true;
  if (attribute == "font-variant") return true;
  if (attribute == "font-weight") return true;
  if (attribute == "padding") return true;
  if (attribute == "padding-left") return true;
  if (attribute == "padding-right") return true;
  if (attribute == "padding-top") return true;
  if (attribute == "padding-bottom") return true;
  if (attribute == "margin") return true;
  if (attribute == "margin-left") return true;
  if (attribute == "margin-right") return true;
  if (attribute == "margin-top") return true;
  if (attribute == "margin-bottom") return true;
  if (attribute == "text-align") return true;
  if (attribute == "text-align-last") return true;
  if (attribute == "text-indent") return true;
  if (attribute == "direction") return true;
  if (attribute == "border-width") return true;
  if (attribute == "border-left-width") return true;
  if (attribute == "border-right-width") return true;
  if (attribute == "border-top-width") return true;
  if (attribute == "border-bottom-width") return true;
  if (attribute == "border-color") return true;
  if (attribute == "border-left-color") return true;
  if (attribute == "border-right-color") return true;
  if (attribute == "border-top-color") return true;
  if (attribute == "border-bottom-color") return true;
  if (attribute == "background-color") return true;
  if (attribute == "text-decoration") return true;
  if (attribute == "text-shadow") return true;
  if (attribute == "width") return true;
  if (attribute == "border-collapse") return true;

  return false;
}

const std::string & textStyleSheet_c::getValue(pugi::xml_node node, const std::string & attribute) const
{
  // go through all rules, check only the ones that give a value to the requested attribute
  // evaluate rule by priority (look at the CSS priority rules
  // choose the highest priority

  while (!node.empty())
  {
    uint16_t prio = 0;
    size_t bestI;

    for (size_t i = 0; i < rules.size(); i++)
    {
      if (   rules[i].attribute == attribute
          && ruleFits(rules[i].selector, node)
          && rulePrio(rules[i].selector) > prio
         )
      {
        prio = rulePrio(rules[i].selector);
        bestI = i;
      }
    }

    if (prio)
      return rules[bestI].value;

    if (!isInheriting(attribute))
      return getDefault(attribute);

    node = node.parent();
  }

  return getDefault(attribute);
}

void textStyleSheet_c::font(const std::string& family, const fontResource_c & res, const std::string& style, const std::string& variant, const std::string& weight, const std::string& stretch)
{
  auto i = families.find(family);

  if (i == families.end())
  {
    i = families.insert(std::make_pair(family, std::make_shared<fontFamily_c>(cache))).first;
  }

  i->second->addFont(res, style, variant, weight, stretch);
}

void textStyleSheet_c::addRule(const std::string sel, const std::string attr, const std::string val)
{
  if (!isValidAttribute(attr))
    throw XhtmlException_c(std::string("attribute not supported: ") + attr);

  rule r;
  r.selector = sel;
  r.attribute = attr;
  r.value = val;

  rules.push_back(r);
}

textStyleSheet_c::textStyleSheet_c(std::shared_ptr< fontCache_c > c)
{
  if (c)
  {
    cache = c;
  }
  else
  {
    cache = std::make_shared<fontCache_c>();
  }
}

}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
// Name:      link.cpp
// Purpose:   Implementation of class wxExLink
// Author:    Anton van Wezenbeek
// Copyright: (c) 2013 Anton van Wezenbeek
////////////////////////////////////////////////////////////////////////////////

#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include <wx/config.h>
#include <wx/tokenzr.h>
#include <wx/utils.h> // for wxGetEnv
#include <wx/extension/link.h>
#include <wx/extension/lexer.h>
#include <wx/extension/stc.h>
#include <wx/extension/util.h>

//#define DEBUG

wxExLink::wxExLink(wxExSTC* stc)
  : m_STC(stc)
{
}

bool wxExLink::AddBasePath()
{
  if (m_STC == NULL)
  {
    return false;
  }

  // Find the base path, if this is not yet on the list, add it.
  const wxString basepath_text = "Basepath: ";
  const int find = m_STC->FindText(
    0,
    1000, // the max pos to look for, this seems enough
    basepath_text);

  if (find == -1)
  {
    return false;
  }

  const int line = m_STC->LineFromPosition(find);

  m_PathList.Add(m_STC->GetTextRange(
    find + basepath_text.length(),
    m_STC->GetLineEndPosition(line) - 3));

  return true;
}

const wxString wxExLink::FindPath(const wxString& text) const
{
  if (
    text.empty() ||
    // wxPathList cannot handle links over several lines.
    // add trimmed argument, to skip eol
    wxExGetNumberOfLines(text, true) > 1)
  {
    return wxEmptyString;
  }

  // Path in .po files.
  if (
    m_STC != NULL &&
    m_STC->GetLexer().GetScintillaLexer() == "po" && text.StartsWith("#: "))
  {
    return text.Mid(3);
  }

  // Better first try to find "...", then <...>, as in next example.
  // scintilla component.

  // So, first get text between " signs.
  size_t pos_char1 = text.find("\"");
  size_t pos_char2 = text.rfind("\"");

  // If that did not succeed, then get text between < and >.
  if (pos_char1 == wxString::npos ||
      pos_char2 == wxString::npos ||
      pos_char2 <= pos_char1)
  {
    pos_char1 = text.find("<");
    pos_char2 = text.rfind(">");
  }

  // If that did not succeed, then get text between ' and '.
  if (pos_char1 == wxString::npos ||
      pos_char2 == wxString::npos ||
      pos_char2 <= pos_char1)
  {
    pos_char1 = text.find("'");
    pos_char2 = text.rfind("'");
  }

  wxString out;

  // If we did not find anything.
  if (pos_char1 == wxString::npos ||
      pos_char2 == wxString::npos ||
      pos_char2 <= pos_char1)
  {
    out = text;
  }
  else
  {
    // Okay, get everything inbetween.
    out = text.substr(pos_char1 + 1, pos_char2 - pos_char1 - 1);
  }

  // And make sure we skip white space.
  out.Trim(true);
  out.Trim(false);

  return out;
}

const wxString wxExLink::GetPath(
  const wxString& text,
  int& line_no,
  int& column_no) const
{
  const wxString path(FindPath(text));
  wxString link(path);

#ifdef DEBUG
  wxLogMessage("+wxExLink::GetPath. text: " + text +
    "\nlink: " + link + "\ncwd: " + wxGetCwd());
#endif

  SetLink(link, line_no, column_no);

  if (
    link.empty() ||
    // Otherwise, if you happen to select text that
    // ends with a separator, wx asserts.
    wxFileName::IsPathSeparator(link.Last()))
  {
    return wxEmptyString;
  }

  wxFileName file(link);
  wxString fullpath;

  if (file.FileExists())
  {
    file.MakeAbsolute();
    fullpath = file.GetFullPath();
  }
  else
  {
#ifdef DEBUG
    wxLogMessage("File " + link + " does not exist");
#endif
    if (
      file.IsRelative() &&
      m_STC != NULL &&
      m_STC->GetFileName().FileExists())
    {
      if (file.MakeAbsolute(m_STC->GetFileName().GetPath()))
      {
        if (file.FileExists())
        {
          fullpath = file.GetFullPath();
        }
      }
      else
      {
        wxString pwd;

        if (wxGetEnv("PWD", &pwd))
        {
          if (file.MakeAbsolute(pwd))
          {
            if (file.FileExists())
            {
              fullpath = file.GetFullPath();
            }
          }
        }
      }
#ifdef DEBUG
    wxLogMessage("Fullpath " + fullpath);
#endif
    }

    if (fullpath.empty())
    {
      // Check whether last word is a file.
      wxString word = path.AfterLast(' ').Trim();

      if (
       !word.empty() &&
       !wxFileName::IsPathSeparator(link.Last()) &&
        wxFileExists(word))
      {
        wxFileName file(word);
        file.MakeAbsolute();
        fullpath = file.GetFullPath();
        // And reset line or column.
        line_no = 0;
        column_no = 0;
#ifdef DEBUG
        wxLogMessage("Fullpath updated " + fullpath);
#endif
      }

      if (fullpath.empty() && !m_PathList.empty())
      {
        fullpath = m_PathList.FindAbsoluteValidPath(link);

        if (
          fullpath.empty() &&
         !word.empty() &&
          SetLink(word, line_no, column_no))
        {
          fullpath = m_PathList.FindAbsoluteValidPath(word);
        }
      }

      // Do nothing if fullpath.empty(),
      // as we return empty string if no path could be found.
#ifdef DEBUG
      wxLogMessage("Fullpath after pathlist update " + fullpath);
#endif
    }
  }

#ifdef DEBUG
  wxLogMessage("-wxExLink::GetPath: " + fullpath);
#endif
  return fullpath;
}

bool wxExLink::SetLink(
  wxString& link,
  int& line_no,
  int& column_no) const
{
  if (link.size() < 2)
  {
    return false;
  }

  // Using backslash as separator does not yet work.
  link.Replace("\\\\", "/");
  link.Replace("\\", "/");

  // The harddrive letter is filtererd, it does not work
  // when adding it to wxExMatch.
  wxString prefix;

#ifdef __WXMSW__
  if (isalpha(link[0]) && link[1] == ':')
  {
    prefix = link.SubString(0,1);
    link = link.Mid(2);
  }
#endif

  // file[:line[:column]]
  std::vector <wxString> v;

  if (wxExMatch("([0-9A-Za-z _/.-]+):([0-9]*):?([0-9]*)", link, v))
  {
    link = v[0];
    line_no = 0;
    column_no = 0;

    if (v.size() > 1)
    {
      line_no = atoi(v[1]);

      if (v.size() > 2)
      {
        column_no = atoi(v[2]);
      }
    }

    link = prefix + link;

    return true;
  }

  return false;
}

void wxExLink::SetFromConfig()
{
  wxStringTokenizer tkz(
    wxConfigBase::Get()->Read(_("Include directory")),
    "\r\n");

  m_PathList.Empty();

  while (tkz.HasMoreTokens())
  {
    m_PathList.Add(tkz.GetNextToken());
  }
}
<commit_msg>removed PWD<commit_after>////////////////////////////////////////////////////////////////////////////////
// Name:      link.cpp
// Purpose:   Implementation of class wxExLink
// Author:    Anton van Wezenbeek
// Copyright: (c) 2013 Anton van Wezenbeek
////////////////////////////////////////////////////////////////////////////////

#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include <wx/config.h>
#include <wx/tokenzr.h>
#include <wx/extension/link.h>
#include <wx/extension/lexer.h>
#include <wx/extension/stc.h>
#include <wx/extension/util.h>

//#define DEBUG

wxExLink::wxExLink(wxExSTC* stc)
  : m_STC(stc)
{
}

bool wxExLink::AddBasePath()
{
  if (m_STC == NULL)
  {
    return false;
  }

  // Find the base path, if this is not yet on the list, add it.
  const wxString basepath_text = "Basepath: ";
  const int find = m_STC->FindText(
    0,
    1000, // the max pos to look for, this seems enough
    basepath_text);

  if (find == -1)
  {
    return false;
  }

  const int line = m_STC->LineFromPosition(find);

  m_PathList.Add(m_STC->GetTextRange(
    find + basepath_text.length(),
    m_STC->GetLineEndPosition(line) - 3));

  return true;
}

const wxString wxExLink::FindPath(const wxString& text) const
{
  if (
    text.empty() ||
    // wxPathList cannot handle links over several lines.
    // add trimmed argument, to skip eol
    wxExGetNumberOfLines(text, true) > 1)
  {
    return wxEmptyString;
  }

  // Path in .po files.
  if (
    m_STC != NULL &&
    m_STC->GetLexer().GetScintillaLexer() == "po" && text.StartsWith("#: "))
  {
    return text.Mid(3);
  }

  // Better first try to find "...", then <...>, as in next example.
  // scintilla component.

  // So, first get text between " signs.
  size_t pos_char1 = text.find("\"");
  size_t pos_char2 = text.rfind("\"");

  // If that did not succeed, then get text between < and >.
  if (pos_char1 == wxString::npos ||
      pos_char2 == wxString::npos ||
      pos_char2 <= pos_char1)
  {
    pos_char1 = text.find("<");
    pos_char2 = text.rfind(">");
  }

  // If that did not succeed, then get text between ' and '.
  if (pos_char1 == wxString::npos ||
      pos_char2 == wxString::npos ||
      pos_char2 <= pos_char1)
  {
    pos_char1 = text.find("'");
    pos_char2 = text.rfind("'");
  }

  wxString out;

  // If we did not find anything.
  if (pos_char1 == wxString::npos ||
      pos_char2 == wxString::npos ||
      pos_char2 <= pos_char1)
  {
    out = text;
  }
  else
  {
    // Okay, get everything inbetween.
    out = text.substr(pos_char1 + 1, pos_char2 - pos_char1 - 1);
  }

  // And make sure we skip white space.
  out.Trim(true);
  out.Trim(false);

  return out;
}

const wxString wxExLink::GetPath(
  const wxString& text,
  int& line_no,
  int& column_no) const
{
  const wxString path(FindPath(text));
  wxString link(path);

#ifdef DEBUG
  wxLogMessage("+wxExLink::GetPath. text: " + text +
    "\nlink: " + link + "\ncwd: " + wxGetCwd());
#endif

  SetLink(link, line_no, column_no);

  if (
    link.empty() ||
    // Otherwise, if you happen to select text that
    // ends with a separator, wx asserts.
    wxFileName::IsPathSeparator(link.Last()))
  {
    return wxEmptyString;
  }

  wxFileName file(link);
  wxString fullpath;

  if (file.FileExists())
  {
    file.MakeAbsolute();
    fullpath = file.GetFullPath();
  }
  else
  {
#ifdef DEBUG
    wxLogMessage("File " + link + " does not exist");
#endif
    if (
      file.IsRelative() &&
      m_STC != NULL &&
      m_STC->GetFileName().FileExists())
    {
      if (file.MakeAbsolute(m_STC->GetFileName().GetPath()))
      {
        if (file.FileExists())
        {
          fullpath = file.GetFullPath();
        }
      }

#ifdef DEBUG
      wxLogMessage("Fullpath " + fullpath);
#endif
    }

    if (fullpath.empty())
    {
      // Check whether last word is a file.
      wxString word = path.AfterLast(' ').Trim();

      if (
       !word.empty() &&
       !wxFileName::IsPathSeparator(link.Last()) &&
        wxFileExists(word))
      {
        wxFileName file(word);
        file.MakeAbsolute();
        fullpath = file.GetFullPath();
        // And reset line or column.
        line_no = 0;
        column_no = 0;
#ifdef DEBUG
        wxLogMessage("Fullpath updated " + fullpath);
#endif
      }

      if (fullpath.empty() && !m_PathList.empty())
      {
        fullpath = m_PathList.FindAbsoluteValidPath(link);

        if (
          fullpath.empty() &&
         !word.empty() &&
          SetLink(word, line_no, column_no))
        {
          fullpath = m_PathList.FindAbsoluteValidPath(word);
        }
      }

      // Do nothing if fullpath.empty(),
      // as we return empty string if no path could be found.
#ifdef DEBUG
      wxLogMessage("Fullpath after pathlist update " + fullpath);
#endif
    }
  }

#ifdef DEBUG
  wxLogMessage("-wxExLink::GetPath: " + fullpath);
#endif
  return fullpath;
}

bool wxExLink::SetLink(
  wxString& link,
  int& line_no,
  int& column_no) const
{
  if (link.size() < 2)
  {
    return false;
  }

  // Using backslash as separator does not yet work.
  link.Replace("\\\\", "/");
  link.Replace("\\", "/");

  // The harddrive letter is filtererd, it does not work
  // when adding it to wxExMatch.
  wxString prefix;

#ifdef __WXMSW__
  if (isalpha(link[0]) && link[1] == ':')
  {
    prefix = link.SubString(0,1);
    link = link.Mid(2);
  }
#endif

  // file[:line[:column]]
  std::vector <wxString> v;

  if (wxExMatch("([0-9A-Za-z _/.-]+):([0-9]*):?([0-9]*)", link, v))
  {
    link = v[0];
    line_no = 0;
    column_no = 0;

    if (v.size() > 1)
    {
      line_no = atoi(v[1]);

      if (v.size() > 2)
      {
        column_no = atoi(v[2]);
      }
    }

    link = prefix + link;

    return true;
  }

  return false;
}

void wxExLink::SetFromConfig()
{
  wxStringTokenizer tkz(
    wxConfigBase::Get()->Read(_("Include directory")),
    "\r\n");

  m_PathList.Empty();

  while (tkz.HasMoreTokens())
  {
    m_PathList.Add(tkz.GetNextToken());
  }
}
<|endoftext|>


<commit_before>/**
*************************************************************
* @file webserver.cpp
* @brief Breve descripción
* Pequeña documentación del archivo
*
*
*
*
*
* @author Gaspar Fernández <blakeyed@totaki.com>
* @version
* @date 03 abr 2015
* Changelog:
*
*
*
*
* Compilation:
*  $ g++ -g -o webserver webserver.cpp glovehttpserver.cpp glove.o -std=c++11 -lpthread -lcrypto -lssl
*
*************************************************************/

#include "glovehttpserver.hpp"
#include <iostream>
#include <chrono>
#include <thread>
#include <zlib.h>
void hello(GloveHttpRequest &request, GloveHttpResponse& response)
{
  std::cout << "TESTING"<<std::endl;
  response << "This is the response\n";
  response << "This is another tesxt" << std::endl;
}

void chatengine(GloveHttpRequest &request, GloveHttpResponse& response)
{
  response << "Chat with me waaraaaanaaaa\n";
}

void chatreceive(GloveWebSocketData& data, GloveWebSocketHandler& ws)
{
	if (data.length()>300)
		ws.send("Message too long");
	else
		ws.send("ECHO: "+data.data());
	/* ws.ping("PINGIO", [] (GloveWebSocketHandler& ws) */
	/* 				{ */
	/* 					std::cout << "SE EJECUTA EL CALLBACK Y TODO\n"; */
	/* 				}); */
}

void chatmaintenance(GloveWebSocketHandler& ws)
{
}

int main(int argc, char *argv[])
{
  GloveHttpServer serv(8080, "", 2048);

	std::cout << "Compression: "<< serv.compression("deflate") << std::endl;

	std::cout << "Timeout: "<<serv.timeout()<<std::endl;
	std::cout << "Keepalive: "<<serv.keepalive_timeout()<<std::endl;
  serv.addVhost("testing");
	/* Necesitamos callback de inicializacion (chatengine), de recepcion de mensaje, de salida de cliente y de mantenimiento (que se llamara cada cierto tiempo).

	 Mirar si desde client podemos acceder a un ID.*/
  serv.addWebSocket("/chat/", chatengine, chatreceive, chatmaintenance);
  serv.addRoute("/hello/$anycon/$anything", hello);
  serv.addRoute("/files/$filename/", GloveHttpServer::fileServer, "testing");
  std::cout << "READY"<<std::endl;
  while(1)
    {
      std::this_thread::sleep_for(std::chrono::seconds(1));
    }

  std::cout << "TEST"<<std::endl;

}

<commit_msg>Fixed webserver example to support gloveWebSocket changes<commit_after>/**
*************************************************************
* @file webserver.cpp
* @brief Breve descripción
* Pequeña documentación del archivo
*
*
*
*
*
* @author Gaspar Fernández <blakeyed@totaki.com>
* @version
* @date 03 abr 2015
* Changelog:
*
*
*
*
* Compilation:
*  $ g++ -g -o webserver webserver.cpp glovehttpserver.cpp glove.o -std=c++11 -lpthread -lcrypto -lssl
*
*************************************************************/

#include "glovehttpserver.hpp"
#include <iostream>
#include <chrono>
#include <thread>
#include <zlib.h>
void hello(GloveHttpRequest &request, GloveHttpResponse& response)
{
  std::cout << "TESTING"<<std::endl;
  response << "This is the response\n";
  response << "This is another tesxt" << std::endl;
}

void chatengine(GloveHttpRequest &request, GloveHttpResponse& response)
{
  response << "Chat with me waaraaaanaaaa\n";
}

void chatreceive(GloveWebSocketData& data, GloveWebSocketHandler& ws)
{
	if (data.length()>300)
		ws.send("Message too long");
	else
		ws.send("ECHO: "+data.data());
	/* ws.ping("PINGIO", [] (GloveWebSocketHandler& ws) */
	/* 				{ */
	/* 					std::cout << "EXECUTING CALLBACK\n"; */
	/* 				}); */
}

bool chatmaintenance(GloveWebSocketHandler& ws)
{
}

int main(int argc, char *argv[])
{
  GloveHttpServer serv(8080, "", 2048);

	std::cout << "Compression: "<< serv.compression("deflate") << std::endl;

	std::cout << "Timeout: "<<serv.timeout()<<std::endl;
	std::cout << "Keepalive: "<<serv.keepalive_timeout()<<std::endl;
  serv.addVhost("testing");
	/* Necesitamos callback de inicializacion (chatengine), de recepcion de mensaje, de salida de cliente y de mantenimiento (que se llamara cada cierto tiempo).

	 Mirar si desde client podemos acceder a un ID.*/
  serv.addWebSocket("/chat/", chatengine, nullptr, chatreceive, chatmaintenance);
  serv.addRoute("/hello/$anycon/$anything", hello);
  serv.addRoute("/files/$filename/", GloveHttpServer::fileServer, "testing");
  std::cout << "READY"<<std::endl;
  while(1)
    {
      std::this_thread::sleep_for(std::chrono::seconds(1));
    }

  std::cout << "TEST"<<std::endl;

}

<|endoftext|>


<commit_before>#include "Prefix.pch"

#include <boost/log/core.hpp>
#include <boost/log/sinks.hpp>
#if BOOST_VERSION >= 105600
#include <boost/core/demangle.hpp>
#define MSC_BOOST_DEMANGLE boost::core::demangle
#else
#include <boost/units/detail/utility.hpp>
#define MSC_BOOST_DEMANGLE boost::units::detail::demangle
#endif
#include "Logging.hpp"
#include "Utils.hpp"
#include "Exceptions.hpp"

namespace logging = boost::log;
namespace attrs = boost::log::attributes;
namespace sinks = boost::log::sinks;

namespace mcore
{
	Logger::Logger(const std::string &source)
	{
		add_attribute("Source", attrs::constant<std::string>(source));
	}
	Logger::Logger(const std::type_info &source):
	Logger(MSC_BOOST_DEMANGLE(source.name()))
	{
		setHost("Local");
	}

	void Logger::setChannel(const std::string &channel)
	{
		auto r = add_attribute("Channel", attrs::constant<std::string>(channel));
		r.first->second = attrs::constant<std::string>(channel);
	}

	void Logger::setHost(const std::string &host)
	{
		auto r = add_attribute("Host", attrs::constant<std::string>(host));
		r.first->second = attrs::constant<std::string>(host);
	}

	class CustomLogSink: public boost::log::sinks::basic_sink_backend
	<sinks::combine_requirements<
	sinks::concurrent_feeding
	>::type>,
	public boost::enable_shared_from_this<CustomLogSink>
	{
		struct Sink
		{
			MSCLogSink func;
			void *userdata;
		};
		std::list<Sink> sinks;
		std::mutex mutex;
	public:
		CustomLogSink()
		{

		}
		void consume(boost::log::record_view const &rec)
		{
			const auto& values = rec.attribute_values();
			const auto& sev =
			logging::extract_or_default<LogLevel>(values["Severity"], LogLevel::Info);
			const auto& source =
			logging::extract_or_default<std::string>(values["Source"], std::string("(null)"));
			const auto& channel =
			logging::extract_or_default<std::string>(values["Channel"], std::string("(null)"));
			const auto& host =
			logging::extract_or_default<std::string>(values["Host"], std::string("(null)"));

			const auto& msg =
			logging::extract_or_default<std::string>(values["Message"], std::string("(null)"));

			std::lock_guard<std::mutex> lock(mutex);
			for (const auto& s: sinks)
				s.func(static_cast<MSCLogSeverity>(sev),
					   source.c_str(),
					   host.c_str(),
					   channel.c_str(),
					   msg.c_str(),
					   s.userdata);
		}
		MSCLogSinkHandle addSink(MSCLogSink sink, void *userdata)
		{
			std::lock_guard<std::mutex> lock(mutex);
			Sink s = {sink, userdata};
			sinks.emplace_front(s);
			return reinterpret_cast<MSCLogSinkHandle>(new std::list<Sink>::iterator(sinks.begin()));
		}
		void removeSink(MSCLogSinkHandle handle)
		{
			if (handle == nullptr) {
				MSCThrow(InvalidArgumentException("handle"));
			}

			auto *it = reinterpret_cast<std::list<Sink>::iterator *>(handle);

			std::lock_guard<std::mutex> lock(mutex);
			sinks.erase(*it);

			delete it;
		}
	};

	static boost::shared_ptr<CustomLogSink> sink =
	boost::make_shared<CustomLogSink>();

	struct CustomLogSinkInitializer
	{
		CustomLogSinkInitializer()
		{
			auto core = boost::log::core::get();
			auto s = boost::make_shared<sinks::unlocked_sink<CustomLogSink>>(sink);
			core->add_sink(s);
		}
	};

}

extern "C" MSCResult MSCAddLogSink(MSCLogSink sink, void *userdata, MSCLogSinkHandle *outHandle)
{
	return mcore::convertExceptionsToResultCode([&] {
		static mcore::CustomLogSinkInitializer initializer;

		if (sink == nullptr) {
			MSCThrow(mcore::InvalidArgumentException("sink"));
		}

		auto h = mcore::sink->addSink(sink, userdata);
		if (outHandle)
			*outHandle = h;
	});
}
extern "C" MSCResult MSCRemoveLogSink(MSCLogSinkHandle handle)
{
	return mcore::convertExceptionsToResultCode([&] {
		mcore::sink->removeSink(handle);
	});
}
<commit_msg>Work-around for uninitialized static variable<commit_after>#include "Prefix.pch"

#include <boost/log/core.hpp>
#include <boost/log/sinks.hpp>
#if BOOST_VERSION >= 105600
#include <boost/core/demangle.hpp>
#define MSC_BOOST_DEMANGLE boost::core::demangle
#else
#include <boost/units/detail/utility.hpp>
#define MSC_BOOST_DEMANGLE boost::units::detail::demangle
#endif
#include "Logging.hpp"
#include "Utils.hpp"
#include "Exceptions.hpp"

namespace logging = boost::log;
namespace attrs = boost::log::attributes;
namespace sinks = boost::log::sinks;

namespace mcore
{
	Logger::Logger(const std::string &source)
	{
		add_attribute("Source", attrs::constant<std::string>(source));
	}
	Logger::Logger(const std::type_info &source):
	Logger(MSC_BOOST_DEMANGLE(source.name()))
	{
		setHost("Local");
	}

	void Logger::setChannel(const std::string &channel)
	{
		auto r = add_attribute("Channel", attrs::constant<std::string>(channel));
		r.first->second = attrs::constant<std::string>(channel);
	}

	void Logger::setHost(const std::string &host)
	{
		auto r = add_attribute("Host", attrs::constant<std::string>(host));
		r.first->second = attrs::constant<std::string>(host);
	}

	class CustomLogSink: public boost::log::sinks::basic_sink_backend
	<sinks::combine_requirements<
	sinks::concurrent_feeding
	>::type>,
	public boost::enable_shared_from_this<CustomLogSink>
	{
		struct Sink
		{
			MSCLogSink func;
			void *userdata;
		};
		std::list<Sink> sinks;
		std::mutex mutex;
	public:
		CustomLogSink()
		{

		}
		void consume(boost::log::record_view const &rec)
		{
			const auto& values = rec.attribute_values();
			const auto& sev =
			logging::extract_or_default<LogLevel>(values["Severity"], LogLevel::Info);
			const auto& source =
			logging::extract_or_default<std::string>(values["Source"], std::string("(null)"));
			const auto& channel =
			logging::extract_or_default<std::string>(values["Channel"], std::string("(null)"));
			const auto& host =
			logging::extract_or_default<std::string>(values["Host"], std::string("(null)"));

			const auto& msg =
			logging::extract_or_default<std::string>(values["Message"], std::string("(null)"));

			std::lock_guard<std::mutex> lock(mutex);
			for (const auto& s: sinks)
				s.func(static_cast<MSCLogSeverity>(sev),
					   source.c_str(),
					   host.c_str(),
					   channel.c_str(),
					   msg.c_str(),
					   s.userdata);
		}
		MSCLogSinkHandle addSink(MSCLogSink sink, void *userdata)
		{
			std::lock_guard<std::mutex> lock(mutex);
			Sink s = {sink, userdata};
			sinks.emplace_front(s);
			return reinterpret_cast<MSCLogSinkHandle>(new std::list<Sink>::iterator(sinks.begin()));
		}
		void removeSink(MSCLogSinkHandle handle)
		{
			if (handle == nullptr) {
				MSCThrow(InvalidArgumentException("handle"));
			}

			auto *it = reinterpret_cast<std::list<Sink>::iterator *>(handle);

			std::lock_guard<std::mutex> lock(mutex);
			sinks.erase(*it);

			delete it;
		}
	};

	static boost::shared_ptr<CustomLogSink> sink =
	boost::make_shared<CustomLogSink>();

	struct CustomLogSinkInitializer
	{
		CustomLogSinkInitializer()
		{
			auto core = boost::log::core::get();
			if (sink == nullptr) {
				sink = boost::make_shared<CustomLogSink>();
			}
			auto s = boost::make_shared<sinks::unlocked_sink<CustomLogSink>>(sink);
			core->add_sink(s);
		}
	};

}

extern "C" MSCResult MSCAddLogSink(MSCLogSink sink, void *userdata, MSCLogSinkHandle *outHandle)
{
	return mcore::convertExceptionsToResultCode([&] {
		static mcore::CustomLogSinkInitializer initializer;

		if (sink == nullptr) {
			MSCThrow(mcore::InvalidArgumentException("sink"));
		}

		auto h = mcore::sink->addSink(sink, userdata);
		if (outHandle)
			*outHandle = h;
	});
}
extern "C" MSCResult MSCRemoveLogSink(MSCLogSinkHandle handle)
{
	return mcore::convertExceptionsToResultCode([&] {
		mcore::sink->removeSink(handle);
	});
}
<|endoftext|>


<commit_before>#ifndef FALCON_STRING_STOX_HPP
#define FALCON_STRING_STOX_HPP

#include <falcon/type_traits/is_same.hpp>

#include <string>
#include <limits>
#include <stdexcept>
#include <cerrno>
#include <cstdarg>
#if __cplusplus < 201103L
# if defined __USE_GNU || defined __USE_BSD || defined __USE_MISC
#   include <alloca.h>
# endif
#endif

namespace falcon {

namespace detail {
template<typename TRet, typename Ret, typename CharT>
Ret __stoa_aux(const TRet& __tmp, Ret& __ret, const char* __name,
               const CharT* __str, std::size_t* __idx, CharT* __endptr)
{
  if (__endptr == __str)
    throw std::invalid_argument(__name);
  else if (errno == ERANGE
    || (falcon::is_same<Ret, int>::value
    && (__tmp < static_cast<TRet>(std::numeric_limits<int>::min())
    || __tmp > static_cast<TRet>(std::numeric_limits<int>::max()))))
    throw std::out_of_range(__name);
  else
    __ret = static_cast<Ret>(__tmp);

  if (__idx)
    *__idx = __endptr - __str;
}

// Helper for all the sto* functions.
template<typename Ret, typename TRet, typename CharT>
Ret stoa(TRet (*__convf) (const CharT*, CharT**),
         const char* __name, const CharT* __str, std::size_t* __idx)
{
  Ret __ret;

  CharT* __endptr;
  errno = 0;
  const TRet __tmp = __convf(__str, &__endptr);
  __stoa_aux(__tmp, __ret, __name, __str, __idx, __endptr);
  return __ret;
}

template<typename Ret, typename TRet, typename CharT>
Ret stoa(TRet (*__convf) (const CharT*, CharT**, int base),
         const char* __name, const CharT* __str, std::size_t* __idx,
         int __base)
{
  Ret __ret;

  CharT* __endptr;
  errno = 0;
  const TRet __tmp = __convf(__str, &__endptr, __base);
  __stoa_aux(__tmp, __ret, __name, __str, __idx, __endptr);
  return __ret;
}

// Helper for the to_string / to_wstring functions.
template<typename String, typename CharT>
String to_xstring(int (*__convf) (CharT*, std::size_t, const CharT*, std::va_list),
                  std::size_t __n, const CharT* __fmt, ...)
{
#if __cplusplus >= 201103L
  String ret;
  ret.resize(__n);
  CharT* __s = &ret[0];
#elif defined __USE_GNU || defined __USE_BSD || defined __USE_MISC
  CharT* __s = static_cast<CharT*>(alloca(sizeof(CharT) * __n));
#else
  CharT* __s = new CharT[__n];
#endif

  std::va_list __args;
  va_start(__args, __fmt);

  const int __len = __convf(__s, __n, __fmt, __args);

  va_end(__args);

#if __cplusplus >= 201103L
  (void)__len;
  return ret;
#elif defined __USE_GNU || defined __USE_BSD || defined __USE_MISC
  return String(__s, __s + __len);
# else
  String ret(__s, __s + __len);
  delete [] __s;
  return ret;
#endif
}
}

#define FALCON_BASIC_CSTRING_TO_IMPL(result_type, fname, std_fname)            \
  template<typename CharT, typename Allocator>                                 \
  inline result_type                                                           \
  fname(const std::basic_string<CharT, std::char_traits<CharT>, Allocator>& s, \
        std::size_t* __idx = 0, int __base = 10)                               \
  { return ::falcon::detail::stoa<result_type>                                 \
  (&std_fname, #fname, s.c_str(), __idx, __base); }

#define FALCON_BASIC_CSTRING_TO(result_type, fname, type)       \
  FALCON_BASIC_CSTRING_TO_IMPL(result_type, fname, strto##type)

FALCON_BASIC_CSTRING_TO(int, stoi, l)
FALCON_BASIC_CSTRING_TO(long, stol, l)
FALCON_BASIC_CSTRING_TO(unsigned long, stoul, ul)
#if __cplusplus >= 201103L
FALCON_BASIC_CSTRING_TO(long long, stoll, ll)
FALCON_BASIC_CSTRING_TO(unsigned long long, stoull, ull)
#endif

#undef FALCON_BASIC_CSTRING_TO_IMPL

#define FALCON_BASIC_CSTRING_TO_IMPL(result_type, fname, std_fname)            \
  template<typename CharT, typename Allocator>                                 \
  inline result_type                                                           \
  fname(const std::basic_string<CharT, std::char_traits<CharT>, Allocator>& s, \
        std::size_t* __idx = 0)                                                \
  { return ::falcon::detail::stoa<result_type>                                 \
  (&std_fname, #fname, s.c_str(), __idx); }

FALCON_BASIC_CSTRING_TO(float, stof, f)
FALCON_BASIC_CSTRING_TO(double, stod, d)
#if __cplusplus >= 201103L
FALCON_BASIC_CSTRING_TO(double long, stold, ld)
#endif
#undef FALCON_BASIC_CSTRING_TO
#undef FALCON_BASIC_CSTRING_TO_IMPL

}

#endif
<commit_msg>new interface for sto* and removing detail::xstring<commit_after>#ifndef FALCON_STRING_STOX_HPP
#define FALCON_STRING_STOX_HPP

#include <falcon/type_traits/is_same.hpp>

#include <string>
#include <limits>
#include <stdexcept>
#include <cerrno>

namespace falcon {

namespace aux_ {

template<typename TRet, typename Ret, typename CharT>
void stoa_aux(const TRet tmp, Ret& ret, const char* name,
              const CharT* str, std::size_t* idx, CharT* endptr)
{
  if (endptr == str)
    throw std::invalid_argument(name);
  else if (errno == ERANGE
    || (falcon::is_same<Ret, int>::value
      && (tmp < static_cast<TRet>(std::numeric_limits<int>::min())
      || tmp > static_cast<TRet>(std::numeric_limits<int>::max()))))
    throw std::out_of_range(name);
  else
    ret = static_cast<Ret>(tmp);

  if (idx)
    *idx = std::size_t(endptr - str);
}

// Helper for all the sto* functions.
template<typename Ret, typename Conv, typename CharT>
Ret stoa(Conv conv, const char* name, const CharT* str, std::size_t* idx)
{
  Ret ret;
  CharT* endptr;
  errno = 0;
  stoa_aux(conv(str, &endptr), ret, name, str, idx, endptr);
  return ret;
}

template<typename Ret, typename Conv, typename CharT>
Ret stoa(Conv conv, const char* name, const CharT* str, std::size_t* idx, int base)
{
  Ret ret;
  CharT* endptr;
  errno = 0;
  stoa_aux(conv(str, &endptr, base), ret, name, str, idx, endptr);
  return ret;
}

}

#define FALCON_BASIC_CSTRING_TO_WRAPPER(result_type, std_fname, std_wfname)   \
  namespace aux_ {                                                            \
    struct std_fname##_wrapper {                                              \
      result_type                                                             \
      operator()(const char * str, char ** endptr = 0, int base = 10) const { \
        return static_cast<result_type>(::std::std_fname(str, endptr, base)); \
      }                                                                       \
                                                                              \
      result_type                                                             \
      operator()(const wchar_t * str, wchar_t ** endptr = 0,                  \
                 int base = 10) const {                                       \
        return static_cast<result_type>(                                      \
          ::std::std_wfname(str, endptr, base));                              \
      }                                                                       \
    };                                                                        \
  }

#define FALCON_BASIC_CSTRING_TO_IMPL(result_type, char_type, fname, std_fname) \
  template<typename Trait, typename Allocator>                                 \
  inline result_type                                                           \
  fname(const std::basic_string<char_type, Trait, Allocator>& s,               \
        std::size_t* idx = 0, int base = 10)                                   \
  { return ::falcon::aux_::stoa<result_type>                                   \
    (::falcon::aux_::std_fname##_wrapper(), #fname, s.c_str(), idx, base); }

#define FALCON_BASIC_CSTRING_TO(result_type, fname, type)                   \
  FALCON_BASIC_CSTRING_TO_WRAPPER(result_type, strto##type, wcsto##type)    \
  FALCON_BASIC_CSTRING_TO_IMPL(result_type, char, fname, strto##type)       \
  FALCON_BASIC_CSTRING_TO_IMPL(result_type, const char, fname, strto##type) \
  FALCON_BASIC_CSTRING_TO_IMPL(result_type, wchar_t, fname, strto##type)    \
  FALCON_BASIC_CSTRING_TO_IMPL(result_type, const wchar_t, fname, strto##type)

FALCON_BASIC_CSTRING_TO(long, stol, l)
FALCON_BASIC_CSTRING_TO(unsigned long, stoul, ul)
#if __cplusplus >= 201103L
FALCON_BASIC_CSTRING_TO(long long, stoll, ll)
FALCON_BASIC_CSTRING_TO(unsigned long long, stoull, ull)
#endif

# undef FALCON_BASIC_CSTRING_TO_WRAPPER
#define FALCON_BASIC_CSTRING_TO_WRAPPER(result_type, std_fname, std_wfname)
FALCON_BASIC_CSTRING_TO(int, stoi, l)

# undef FALCON_BASIC_CSTRING_TO_WRAPPER
#define FALCON_BASIC_CSTRING_TO_WRAPPER(result_type, std_fname, std_wfname) \
  namespace aux_ {                                                          \
    struct std_fname##_wrapper {                                            \
      result_type                                                           \
      operator()(const char * str, char ** endptr = 0) const {              \
        return ::std::std_fname(str, endptr);                               \
      }                                                                     \
                                                                            \
      result_type                                                           \
      operator()(const wchar_t * str, wchar_t ** endptr = 0) const {        \
        return ::std::std_wfname(str, endptr);                              \
      }                                                                     \
    };                                                                      \
  }

# undef FALCON_BASIC_CSTRING_TO_IMPL
#define FALCON_BASIC_CSTRING_TO_IMPL(result_type, char_type, fname, std_fname) \
  template<typename Trait, typename Allocator>                                 \
  inline result_type                                                           \
  fname(const std::basic_string<char_type, Trait, Allocator>& s,               \
        std::size_t* idx = 0)                                                  \
  { return ::falcon::aux_::stoa<result_type>                                   \
    (::falcon::aux_::std_fname##_wrapper(), #fname, s.c_str(), idx); }

FALCON_BASIC_CSTRING_TO(float, stof, f)
FALCON_BASIC_CSTRING_TO(double, stod, d)
#if __cplusplus >= 201103L
FALCON_BASIC_CSTRING_TO(double long, stold, ld)
#endif
#undef FALCON_BASIC_CSTRING_TO
#undef FALCON_BASIC_CSTRING_TO_IMPL
#undef FALCON_BASIC_CSTRING_TO_WRAPPER

}

#endif
<|endoftext|>


<commit_before>/*!
 * This file is part of CameraPlus.
 *
 * Copyright (C) 2012-2014 Mohammed Sameer <msameer@foolab.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "qtcammetadata.h"
#include <gst/gsttaglist.h>
#include "qtcamdevice.h"
#include "qtcamdevice_p.h"
#include <QDebug>
#include <QDate>
#include <QTime>
#include <QDateTime>
#include <QPointer>
#include <ctime>

class QtCamMetaDataPrivate {
public:
  void addTag(const char *tag, const QString& value) {
    GstTagSetter *s = setter();
    if (!s) {
      return;
    }

    gst_tag_setter_add_tags(s, GST_TAG_MERGE_REPLACE, tag, value.toUtf8().data(), NULL);

    gst_object_unref(s);
  }

  void addTag(const char *tag, double value) {
    GstTagSetter *s = setter();
    if (!s) {
      return;
    }

    gst_tag_setter_add_tags(s, GST_TAG_MERGE_REPLACE, tag, value, NULL);

    gst_object_unref(s);
  }

  void addTag(const char *tag, GstDateTime *value) {
    GstTagSetter *s = setter();
    if (!s) {
      return;
    }

    gst_tag_setter_add_tags(s, GST_TAG_MERGE_REPLACE, tag, value, NULL);

    gst_object_unref(s);
  }

  GstTagSetter *setter() {
    if (!device || !device->d_ptr->cameraBin) {
      return 0;
    }

    if (!GST_IS_TAG_SETTER(device->d_ptr->cameraBin)) {
      return 0;
    }

    return GST_TAG_SETTER(gst_object_ref(device->d_ptr->cameraBin));
  }

  QPointer<QtCamDevice> device;
};

QtCamMetaData::QtCamMetaData(QObject *parent) :
  QObject(parent), d_ptr(new QtCamMetaDataPrivate) {
}

QtCamMetaData::~QtCamMetaData() {
  setDevice(0);
  delete d_ptr; d_ptr = 0;
}

void QtCamMetaData::setDevice(QtCamDevice *device) {
  if (device != d_ptr->device) {
    d_ptr->device = device;
  }
}

void QtCamMetaData::setManufacturer(const QString& manufacturer) {
  d_ptr->addTag(GST_TAG_DEVICE_MANUFACTURER, manufacturer);
}

void QtCamMetaData::setModel(const QString& model) {
  d_ptr->addTag(GST_TAG_DEVICE_MODEL, model);
}

void QtCamMetaData::setCountry(const QString& country) {
  d_ptr->addTag(GST_TAG_GEO_LOCATION_COUNTRY, country);
}

void QtCamMetaData::setCity(const QString& city) {
  d_ptr->addTag(GST_TAG_GEO_LOCATION_CITY, city);
}

void QtCamMetaData::setSuburb(const QString& suburb) {
  d_ptr->addTag(GST_TAG_GEO_LOCATION_SUBLOCATION, suburb);
}

void QtCamMetaData::setLongitude(double longitude) {
  d_ptr->addTag(GST_TAG_GEO_LOCATION_LONGITUDE, longitude);
}

void QtCamMetaData::setLatitude(double latitude) {
  d_ptr->addTag(GST_TAG_GEO_LOCATION_LATITUDE, latitude);
}

void QtCamMetaData::setElevation(double elevation) {
  d_ptr->addTag(GST_TAG_GEO_LOCATION_ELEVATION, elevation);
}

void QtCamMetaData::setOrientationAngle(int angle) {
  if (angle == -1) {
    qWarning() << "QtCamMetaData::setOrientationAngle called with an unknown angle";
    return;
  }

  gchar *orientation = g_strdup_printf("rotate-%d", angle);
  d_ptr->addTag(GST_TAG_IMAGE_ORIENTATION, orientation);
  g_free(orientation);
}

void QtCamMetaData::setArtist(const QString& artist) {
  /* try the shortcut first */
  if (!artist.contains('%')) {
    d_ptr->addTag(GST_TAG_ARTIST, artist);
    return;
  }

  std::vector<char> result(artist.size());
  struct tm tm;
  time_t t;
  t = time(NULL);
  if (t == -1) {
    qWarning() << "Failed to get current time";
    d_ptr->addTag(GST_TAG_ARTIST, artist);
    return;
  }

  if (!localtime_r(&t, &tm)) {
    qWarning() << "Failed to get local time";
    d_ptr->addTag(GST_TAG_ARTIST, artist);
    return;
  }

  while (!strftime(result.data(), result.size(), artist.toUtf8().constData(), &tm)) {
    result.resize(result.size() * 2);
  }

  d_ptr->addTag(GST_TAG_ARTIST, QString::fromUtf8(result.data()));
}

void QtCamMetaData::setDateTime(const QDateTime& dateTime) {
  QDate d = dateTime.date();
  QTime t = dateTime.time();

  int day = d.day();
  int month = d.month();
  int year = d.year();
  int hour = t.hour();
  int minute = t.minute();

  // GstDateTime seconds expects microseconds to be there too :|
  gdouble seconds = t.second();
  seconds += t.msec()/(1000.0);

  // Current UTC time. Created through string so that the link between
  // current and utc is lost and secsTo returns non-zero values.
  QDateTime utcTime = QDateTime::fromString(dateTime.toUTC().toString());
  gfloat tzoffset = (utcTime.secsTo(dateTime)/3600.0);

  GstDateTime *dt = gst_date_time_new(tzoffset, year, month, day,
				      hour, minute, seconds);

  d_ptr->addTag(GST_TAG_DATE_TIME, dt);

  gst_date_time_unref(dt);
}

void QtCamMetaData::setCaptureDirection(double direction) {
  d_ptr->addTag(GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, direction);
}

void QtCamMetaData::setHorizontalError(double error) {
  d_ptr->addTag(GST_TAG_GEO_LOCATION_HORIZONTAL_ERROR, error);
}

void QtCamMetaData::reset() {
  GstTagSetter *s = d_ptr->setter();
  if (!s) {
    return;
  }

  gst_tag_setter_reset_tags(s);

  gst_object_unref(s);
}
<commit_msg>libqtcamera: fix compilation error under sailfish<commit_after>/*!
 * This file is part of CameraPlus.
 *
 * Copyright (C) 2012-2014 Mohammed Sameer <msameer@foolab.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "qtcammetadata.h"
#include <gst/gst.h>
#include "qtcamdevice.h"
#include "qtcamdevice_p.h"
#include <QDebug>
#include <QDate>
#include <QTime>
#include <QDateTime>
#include <QPointer>
#include <ctime>

class QtCamMetaDataPrivate {
public:
  void addTag(const char *tag, const QString& value) {
    GstTagSetter *s = setter();
    if (!s) {
      return;
    }

    gst_tag_setter_add_tags(s, GST_TAG_MERGE_REPLACE, tag, value.toUtf8().data(), NULL);

    gst_object_unref(s);
  }

  void addTag(const char *tag, double value) {
    GstTagSetter *s = setter();
    if (!s) {
      return;
    }

    gst_tag_setter_add_tags(s, GST_TAG_MERGE_REPLACE, tag, value, NULL);

    gst_object_unref(s);
  }

  void addTag(const char *tag, GstDateTime *value) {
    GstTagSetter *s = setter();
    if (!s) {
      return;
    }

    gst_tag_setter_add_tags(s, GST_TAG_MERGE_REPLACE, tag, value, NULL);

    gst_object_unref(s);
  }

  GstTagSetter *setter() {
    if (!device || !device->d_ptr->cameraBin) {
      return 0;
    }

    if (!GST_IS_TAG_SETTER(device->d_ptr->cameraBin)) {
      return 0;
    }

    return GST_TAG_SETTER(gst_object_ref(device->d_ptr->cameraBin));
  }

  QPointer<QtCamDevice> device;
};

QtCamMetaData::QtCamMetaData(QObject *parent) :
  QObject(parent), d_ptr(new QtCamMetaDataPrivate) {
}

QtCamMetaData::~QtCamMetaData() {
  setDevice(0);
  delete d_ptr; d_ptr = 0;
}

void QtCamMetaData::setDevice(QtCamDevice *device) {
  if (device != d_ptr->device) {
    d_ptr->device = device;
  }
}

void QtCamMetaData::setManufacturer(const QString& manufacturer) {
  d_ptr->addTag(GST_TAG_DEVICE_MANUFACTURER, manufacturer);
}

void QtCamMetaData::setModel(const QString& model) {
  d_ptr->addTag(GST_TAG_DEVICE_MODEL, model);
}

void QtCamMetaData::setCountry(const QString& country) {
  d_ptr->addTag(GST_TAG_GEO_LOCATION_COUNTRY, country);
}

void QtCamMetaData::setCity(const QString& city) {
  d_ptr->addTag(GST_TAG_GEO_LOCATION_CITY, city);
}

void QtCamMetaData::setSuburb(const QString& suburb) {
  d_ptr->addTag(GST_TAG_GEO_LOCATION_SUBLOCATION, suburb);
}

void QtCamMetaData::setLongitude(double longitude) {
  d_ptr->addTag(GST_TAG_GEO_LOCATION_LONGITUDE, longitude);
}

void QtCamMetaData::setLatitude(double latitude) {
  d_ptr->addTag(GST_TAG_GEO_LOCATION_LATITUDE, latitude);
}

void QtCamMetaData::setElevation(double elevation) {
  d_ptr->addTag(GST_TAG_GEO_LOCATION_ELEVATION, elevation);
}

void QtCamMetaData::setOrientationAngle(int angle) {
  if (angle == -1) {
    qWarning() << "QtCamMetaData::setOrientationAngle called with an unknown angle";
    return;
  }

  gchar *orientation = g_strdup_printf("rotate-%d", angle);
  d_ptr->addTag(GST_TAG_IMAGE_ORIENTATION, orientation);
  g_free(orientation);
}

void QtCamMetaData::setArtist(const QString& artist) {
  /* try the shortcut first */
  if (!artist.contains('%')) {
    d_ptr->addTag(GST_TAG_ARTIST, artist);
    return;
  }

  std::vector<char> result(artist.size());
  struct tm tm;
  time_t t;
  t = time(NULL);
  if (t == -1) {
    qWarning() << "Failed to get current time";
    d_ptr->addTag(GST_TAG_ARTIST, artist);
    return;
  }

  if (!localtime_r(&t, &tm)) {
    qWarning() << "Failed to get local time";
    d_ptr->addTag(GST_TAG_ARTIST, artist);
    return;
  }

  while (!strftime(result.data(), result.size(), artist.toUtf8().constData(), &tm)) {
    result.resize(result.size() * 2);
  }

  d_ptr->addTag(GST_TAG_ARTIST, QString::fromUtf8(result.data()));
}

void QtCamMetaData::setDateTime(const QDateTime& dateTime) {
  QDate d = dateTime.date();
  QTime t = dateTime.time();

  int day = d.day();
  int month = d.month();
  int year = d.year();
  int hour = t.hour();
  int minute = t.minute();

  // GstDateTime seconds expects microseconds to be there too :|
  gdouble seconds = t.second();
  seconds += t.msec()/(1000.0);

  // Current UTC time. Created through string so that the link between
  // current and utc is lost and secsTo returns non-zero values.
  QDateTime utcTime = QDateTime::fromString(dateTime.toUTC().toString());
  gfloat tzoffset = (utcTime.secsTo(dateTime)/3600.0);

  GstDateTime *dt = gst_date_time_new(tzoffset, year, month, day,
				      hour, minute, seconds);

  d_ptr->addTag(GST_TAG_DATE_TIME, dt);

  gst_date_time_unref(dt);
}

void QtCamMetaData::setCaptureDirection(double direction) {
  d_ptr->addTag(GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, direction);
}

void QtCamMetaData::setHorizontalError(double error) {
  d_ptr->addTag(GST_TAG_GEO_LOCATION_HORIZONTAL_ERROR, error);
}

void QtCamMetaData::reset() {
  GstTagSetter *s = d_ptr->setter();
  if (!s) {
    return;
  }

  gst_tag_setter_reset_tags(s);

  gst_object_unref(s);
}
<|endoftext|>


<commit_before>/*
 * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Affero General Public License as published by the
 * Free Software Foundation; either version 3 of the License, or (at your
 * option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "azjol_nerub.h"

DoorData const doorData[] =
{
    { GO_KRIKTHIR_DOORS,    DATA_KRIKTHIR_THE_GATEWATCHER_EVENT,    DOOR_TYPE_PASSAGE },
    { GO_ANUBARAK_DOORS1,   DATA_ANUBARAK_EVENT,    DOOR_TYPE_ROOM },
    { GO_ANUBARAK_DOORS2,   DATA_ANUBARAK_EVENT,    DOOR_TYPE_ROOM },
    { GO_ANUBARAK_DOORS3,   DATA_ANUBARAK_EVENT,    DOOR_TYPE_ROOM },
    { 0,                    0,                      DOOR_TYPE_ROOM }
};

ObjectData const creatureData[] =
{
    { NPC_KRIKTHIR_THE_GATEWATCHER, DATA_KRIKTHIR_THE_GATEWATCHER_EVENT },
    { NPC_HADRONOX,                 DATA_HADRONOX_EVENT                 }
};

class instance_azjol_nerub : public InstanceMapScript
{
public:
    instance_azjol_nerub() : InstanceMapScript("instance_azjol_nerub", 601) { }

    struct instance_azjol_nerub_InstanceScript : public InstanceScript
    {
        instance_azjol_nerub_InstanceScript(Map* map) : InstanceScript(map)
        {
            SetBossNumber(MAX_ENCOUNTERS);
            LoadDoorData(doorData);
            LoadObjectData(creatureData, nullptr);
        };

        void OnCreatureCreate(Creature* creature) override
        {
            switch (creature->GetEntry())
            {
                case NPC_SKITTERING_SWARMER:
                case NPC_SKITTERING_INFECTIOR:
                    if (Creature* krikthir = GetCreature((DATA_KRIKTHIR_THE_GATEWATCHER_EVENT)))
                        krikthir->AI()->JustSummoned(creature);
                    break;
                case NPC_ANUB_AR_CHAMPION:
                case NPC_ANUB_AR_NECROMANCER:
                case NPC_ANUB_AR_CRYPTFIEND:
                    if (Creature* hadronox = GetCreature(DATA_HADRONOX_EVENT))
                        hadronox->AI()->JustSummoned(creature);
                    break;
            }

            InstanceScript::OnCreatureCreate(creature);
        }

        void OnGameObjectCreate(GameObject* go) override
        {
            switch (go->GetEntry())
            {
                case GO_KRIKTHIR_DOORS:
                case GO_ANUBARAK_DOORS1:
                case GO_ANUBARAK_DOORS2:
                case GO_ANUBARAK_DOORS3:
                    AddDoor(go, true);
                    break;
            }
        }

        void OnGameObjectRemove(GameObject* go) override
        {
            switch (go->GetEntry())
            {
                case GO_KRIKTHIR_DOORS:
                case GO_ANUBARAK_DOORS1:
                case GO_ANUBARAK_DOORS2:
                case GO_ANUBARAK_DOORS3:
                    AddDoor(go, false);
                    break;
            }
        }

        bool SetBossState(uint32 id, EncounterState state) override
        {
            return InstanceScript::SetBossState(id, state);
        }

        std::string GetSaveData() override
        {
            std::ostringstream saveStream;
            saveStream << "A N " << GetBossSaveData();
            return saveStream.str();
        }

        void Load(const char* in) override
        {
            if( !in )
                return;

            char dataHead1, dataHead2;
            std::istringstream loadStream(in);
            loadStream >> dataHead1 >> dataHead2;
            if (dataHead1 == 'A' && dataHead2 == 'N')
            {
                for (uint8 i = 0; i < MAX_ENCOUNTERS; ++i)
                {
                    uint32 tmpState;
                    loadStream >> tmpState;
                    if (tmpState == IN_PROGRESS || tmpState > SPECIAL)
                        tmpState = NOT_STARTED;
                    SetBossState(i, EncounterState(tmpState));
                }
            }
        }
    };

    InstanceScript* GetInstanceScript(InstanceMap* map) const override
    {
        return new instance_azjol_nerub_InstanceScript(map);
    }
};

class spell_azjol_nerub_fixate : public SpellScriptLoader
{
public:
    spell_azjol_nerub_fixate() : SpellScriptLoader("spell_azjol_nerub_fixate") { }

    class spell_azjol_nerub_fixate_SpellScript : public SpellScript
    {
        PrepareSpellScript(spell_azjol_nerub_fixate_SpellScript);

        void HandleScriptEffect(SpellEffIndex effIndex)
        {
            PreventHitDefaultEffect(effIndex);
            if (Unit* target = GetHitUnit())
                target->CastSpell(GetCaster(), GetEffectValue(), true);
        }

        void Register() override
        {
            OnEffectHitTarget += SpellEffectFn(spell_azjol_nerub_fixate_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
        }
    };

    SpellScript* GetSpellScript() const override
    {
        return new spell_azjol_nerub_fixate_SpellScript();
    }
};

class spell_azjol_nerub_web_wrap : public SpellScriptLoader
{
public:
    spell_azjol_nerub_web_wrap() : SpellScriptLoader("spell_azjol_nerub_web_wrap") { }

    class spell_azjol_nerub_web_wrap_AuraScript : public AuraScript
    {
        PrepareAuraScript(spell_azjol_nerub_web_wrap_AuraScript);

        void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
        {
            Unit* target = GetTarget();
            if (!target->HasAura(SPELL_WEB_WRAP_TRIGGER))
                target->CastSpell(target, SPELL_WEB_WRAP_TRIGGER, true);
        }

        void Register() override
        {
            OnEffectRemove += AuraEffectRemoveFn(spell_azjol_nerub_web_wrap_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_MOD_ROOT, AURA_EFFECT_HANDLE_REAL);
        }
    };

    AuraScript* GetAuraScript() const override
    {
        return new spell_azjol_nerub_web_wrap_AuraScript();
    }
};

void AddSC_instance_azjol_nerub()
{
    new instance_azjol_nerub();
    new spell_azjol_nerub_fixate();
    new spell_azjol_nerub_web_wrap();
}
<commit_msg>feat(Core/Scripts): Added Boundary in Azjol nerub (#12159)<commit_after>/*
 * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Affero General Public License as published by the
 * Free Software Foundation; either version 3 of the License, or (at your
 * option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#include "AreaBoundary.h"
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "azjol_nerub.h"

DoorData const doorData[] =
{
    { GO_KRIKTHIR_DOORS,    DATA_KRIKTHIR_THE_GATEWATCHER_EVENT,    DOOR_TYPE_PASSAGE },
    { GO_ANUBARAK_DOORS1,   DATA_ANUBARAK_EVENT,    DOOR_TYPE_ROOM },
    { GO_ANUBARAK_DOORS2,   DATA_ANUBARAK_EVENT,    DOOR_TYPE_ROOM },
    { GO_ANUBARAK_DOORS3,   DATA_ANUBARAK_EVENT,    DOOR_TYPE_ROOM },
    { 0,                    0,                      DOOR_TYPE_ROOM }
};

ObjectData const creatureData[] =
{
    { NPC_KRIKTHIR_THE_GATEWATCHER, DATA_KRIKTHIR_THE_GATEWATCHER_EVENT },
    { NPC_HADRONOX,                 DATA_HADRONOX_EVENT                 }
};

BossBoundaryData const boundaries =
{
    { DATA_KRIKTHIR_THE_GATEWATCHER_EVENT, new RectangleBoundary(400.0f, 580.0f, 623.5f, 810.0f) },
    { DATA_HADRONOX_EVENT, new ZRangeBoundary(666.0f, 776.0f) },
    { DATA_ANUBARAK_EVENT, new CircleBoundary(Position(550.6178f, 253.5917f), 26.0f) }
};

class instance_azjol_nerub : public InstanceMapScript
{
public:
    instance_azjol_nerub() : InstanceMapScript("instance_azjol_nerub", 601) { }

    struct instance_azjol_nerub_InstanceScript : public InstanceScript
    {
        instance_azjol_nerub_InstanceScript(Map* map) : InstanceScript(map)
        {
            SetBossNumber(MAX_ENCOUNTERS);
            LoadBossBoundaries(boundaries);
            LoadDoorData(doorData);
            LoadObjectData(creatureData, nullptr);
        };

        void OnCreatureCreate(Creature* creature) override
        {
            switch (creature->GetEntry())
            {
                case NPC_SKITTERING_SWARMER:
                case NPC_SKITTERING_INFECTIOR:
                    if (Creature* krikthir = GetCreature((DATA_KRIKTHIR_THE_GATEWATCHER_EVENT)))
                        krikthir->AI()->JustSummoned(creature);
                    break;
                case NPC_ANUB_AR_CHAMPION:
                case NPC_ANUB_AR_NECROMANCER:
                case NPC_ANUB_AR_CRYPTFIEND:
                    if (Creature* hadronox = GetCreature(DATA_HADRONOX_EVENT))
                        hadronox->AI()->JustSummoned(creature);
                    break;
            }

            InstanceScript::OnCreatureCreate(creature);
        }

        void OnGameObjectCreate(GameObject* go) override
        {
            switch (go->GetEntry())
            {
                case GO_KRIKTHIR_DOORS:
                case GO_ANUBARAK_DOORS1:
                case GO_ANUBARAK_DOORS2:
                case GO_ANUBARAK_DOORS3:
                    AddDoor(go, true);
                    break;
            }
        }

        void OnGameObjectRemove(GameObject* go) override
        {
            switch (go->GetEntry())
            {
                case GO_KRIKTHIR_DOORS:
                case GO_ANUBARAK_DOORS1:
                case GO_ANUBARAK_DOORS2:
                case GO_ANUBARAK_DOORS3:
                    AddDoor(go, false);
                    break;
            }
        }

        bool SetBossState(uint32 id, EncounterState state) override
        {
            return InstanceScript::SetBossState(id, state);
        }

        std::string GetSaveData() override
        {
            std::ostringstream saveStream;
            saveStream << "A N " << GetBossSaveData();
            return saveStream.str();
        }

        void Load(const char* in) override
        {
            if( !in )
                return;

            char dataHead1, dataHead2;
            std::istringstream loadStream(in);
            loadStream >> dataHead1 >> dataHead2;
            if (dataHead1 == 'A' && dataHead2 == 'N')
            {
                for (uint8 i = 0; i < MAX_ENCOUNTERS; ++i)
                {
                    uint32 tmpState;
                    loadStream >> tmpState;
                    if (tmpState == IN_PROGRESS || tmpState > SPECIAL)
                        tmpState = NOT_STARTED;
                    SetBossState(i, EncounterState(tmpState));
                }
            }
        }
    };

    InstanceScript* GetInstanceScript(InstanceMap* map) const override
    {
        return new instance_azjol_nerub_InstanceScript(map);
    }
};

class spell_azjol_nerub_fixate : public SpellScriptLoader
{
public:
    spell_azjol_nerub_fixate() : SpellScriptLoader("spell_azjol_nerub_fixate") { }

    class spell_azjol_nerub_fixate_SpellScript : public SpellScript
    {
        PrepareSpellScript(spell_azjol_nerub_fixate_SpellScript);

        void HandleScriptEffect(SpellEffIndex effIndex)
        {
            PreventHitDefaultEffect(effIndex);
            if (Unit* target = GetHitUnit())
                target->CastSpell(GetCaster(), GetEffectValue(), true);
        }

        void Register() override
        {
            OnEffectHitTarget += SpellEffectFn(spell_azjol_nerub_fixate_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
        }
    };

    SpellScript* GetSpellScript() const override
    {
        return new spell_azjol_nerub_fixate_SpellScript();
    }
};

class spell_azjol_nerub_web_wrap : public SpellScriptLoader
{
public:
    spell_azjol_nerub_web_wrap() : SpellScriptLoader("spell_azjol_nerub_web_wrap") { }

    class spell_azjol_nerub_web_wrap_AuraScript : public AuraScript
    {
        PrepareAuraScript(spell_azjol_nerub_web_wrap_AuraScript);

        void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
        {
            Unit* target = GetTarget();
            if (!target->HasAura(SPELL_WEB_WRAP_TRIGGER))
                target->CastSpell(target, SPELL_WEB_WRAP_TRIGGER, true);
        }

        void Register() override
        {
            OnEffectRemove += AuraEffectRemoveFn(spell_azjol_nerub_web_wrap_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_MOD_ROOT, AURA_EFFECT_HANDLE_REAL);
        }
    };

    AuraScript* GetAuraScript() const override
    {
        return new spell_azjol_nerub_web_wrap_AuraScript();
    }
};

void AddSC_instance_azjol_nerub()
{
    new instance_azjol_nerub();
    new spell_azjol_nerub_fixate();
    new spell_azjol_nerub_web_wrap();
}
<|endoftext|>


<commit_before>/* LICENSE NOTICE
	Copyright (c) 2009, Frederick Emmott <mail@fredemmott.co.uk>

	Permission to use, copy, modify, and/or distribute this software for any
	purpose with or without fee is hereby granted, provided that the above
	copyright notice and this permission notice appear in all copies.

	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
	WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
	MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
	ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
	WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
	ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
	OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "Request.h"
#include "Request_Private.h"

#include <QDebug>
#include <QNetworkCookie>
#include <QRegExp>
#include <QUrl>

namespace FastCgiQt
{
	Request::Request(Private* _d, QObject* parent)
	: QIODevice(parent)
	, d(_d)
	{
		open(QIODevice::ReadWrite);
		d->device->setParent(this);
		connect(
			d->device,
			SIGNAL(readyRead()),
			this,
			SIGNAL(readyRead())
		);
	}

	bool Request::atEnd() const
	{
		const bool atEnd = d->device->atEnd() && QIODevice::atEnd();
		return atEnd;
	}

	bool Request::isSequential() const
	{
		return true;
	}

	qint64 Request::readData(char* data, qint64 maxSize)
	{
		Q_ASSERT(d->postDataMode == Private::UnknownPostData || d->postDataMode == Private::RawPostData);
		d->postDataMode = Private::RawPostData;
		Q_ASSERT(d->device->isOpen());
		Q_ASSERT(d->device->isReadable());
		const qint64 bytesRead = d->device->read(data, maxSize);
		return bytesRead;
	}

	qint64 Request::writeData(const char* data, qint64 maxSize)
	{
		QIODevice* device = d->device;

		if(!d->haveSentHeaders)
		{
			d->haveSentHeaders = true;
			for(ClientIODevice::HeaderMap::ConstIterator it = d->responseHeaders.constBegin(); it != d->responseHeaders.constEnd(); ++it)
			{
				device->write(it.key());
				device->write(": ");
				device->write(it.value());
				device->write("\r\n");
			}
			device->write("\r\n");
		}
		return device->write(data, maxSize);
	}

	qint64 Request::size() const
	{
		return QString::fromLatin1(rawValue(ServerData, "CONTENT_LENGTH")).toLongLong();
	}

	QUrl Request::url(UrlPart part) const
	{
		QUrl url;
		// Protocol and host are needed, regardless of part

		///@fixme - HTTPS support
		url.setScheme("http");
		// authority == user:password@host:port - as HTTP_HOST contains user and port, go with that
		url.setAuthority(value(ServerData, "HTTP_HOST"));

		const int queryStringOffset = rawValue(ServerData, "REQUEST_URI").contains('?') ? 1 : 0;
		const int queryStringLength = rawValue(ServerData, "QUERY_STRING").length() + queryStringOffset;
		switch(part)
		{
			case RootUrl:
			{
				const int pathInfoLength = rawValue(ServerData, "PATH_INFO").length();
				QByteArray basePath = rawValue(ServerData, "REQUEST_URI");
				basePath.chop(queryStringLength + pathInfoLength);
				url.setEncodedPath(basePath);
				break;
			}
			case LocationUrl:
			case RequestUrl:
			{
				QByteArray basePath = rawValue(ServerData, "REQUEST_URI");
				basePath.chop(queryStringLength);
				url.setEncodedPath(basePath);
				if(part == RequestUrl)
				{
					url.setEncodedQuery(rawValue(ServerData, "QUERY_STRING"));
				}
				break;
			}
			default:
				qFatal("Unknown URL part: %d", part);
		}
		return url;
	}

	QList<QNetworkCookie> Request::cookies() const
	{
		QList<QNetworkCookie> cookies;
		for(ClientIODevice::HeaderMap::ConstIterator it = d->serverData.constBegin(); it != d->serverData.constEnd(); ++it)
		{
			if(it.key().toUpper() == "HTTP_COOKIE")
			{
				QList<QByteArray> list = it.value().split(';');
				for(int i = 0; i < list.length(); ++i)
				{
					cookies.append(QNetworkCookie::parseCookies(list.at(i)));
				}
			}
		}
		return cookies;
	}

	void Request::sendCookie(const QNetworkCookie& cookie)
	{
		addHeader("set-cookie", cookie.toRawForm());
	}

	void Request::setHeader(const QByteArray& name, const QByteArray& value)
	{
		Q_ASSERT(!d->haveSentHeaders);
		d->responseHeaders[name] = value;
	}

	void Request::addHeader(const QByteArray& name, const QByteArray& value)
	{
		Q_ASSERT(!d->haveSentHeaders);
		d->responseHeaders.insertMulti(name, value);
	}

	QByteArray Request::responseHeader(const QByteArray& name)
	{
		return d->responseHeaders.value(name);
	}

	QHash<QByteArray, QByteArray> Request::rawValues(DataSource source) const
	{
		switch(source)
		{
			case GetData:
				return d->getData;
			case PostData:
				d->loadPostVariables();
				return d->postData;
			case ServerData:
				return d->serverData;
			default:
				qFatal("Unknown value type: %d", source);
		}
		return QHash<QByteArray, QByteArray>();
	}

	QByteArray Request::rawValue(DataSource source, const QByteArray& name) const
	{
		return rawValues(source).value(name);
	}

	QString Request::value(DataSource source, const QByteArray& name) const
	{
		return QUrl::fromPercentEncoding(rawValue(source, name));
	}

	Request::~Request()
	{
		emit finished(this);
		delete d;
	}
}
<commit_msg>Support HTTPS base URLs - Thanks to Hauke Wintjen<commit_after>/* LICENSE NOTICE
	Copyright (c) 2009, Frederick Emmott <mail@fredemmott.co.uk>

	Permission to use, copy, modify, and/or distribute this software for any
	purpose with or without fee is hereby granted, provided that the above
	copyright notice and this permission notice appear in all copies.

	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
	WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
	MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
	ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
	WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
	ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
	OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "Request.h"
#include "Request_Private.h"

#include <QDebug>
#include <QNetworkCookie>
#include <QRegExp>
#include <QUrl>

namespace FastCgiQt
{
	Request::Request(Private* _d, QObject* parent)
	: QIODevice(parent)
	, d(_d)
	{
		open(QIODevice::ReadWrite);
		d->device->setParent(this);
		connect(
			d->device,
			SIGNAL(readyRead()),
			this,
			SIGNAL(readyRead())
		);
	}

	bool Request::atEnd() const
	{
		const bool atEnd = d->device->atEnd() && QIODevice::atEnd();
		return atEnd;
	}

	bool Request::isSequential() const
	{
		return true;
	}

	qint64 Request::readData(char* data, qint64 maxSize)
	{
		Q_ASSERT(d->postDataMode == Private::UnknownPostData || d->postDataMode == Private::RawPostData);
		d->postDataMode = Private::RawPostData;
		Q_ASSERT(d->device->isOpen());
		Q_ASSERT(d->device->isReadable());
		const qint64 bytesRead = d->device->read(data, maxSize);
		return bytesRead;
	}

	qint64 Request::writeData(const char* data, qint64 maxSize)
	{
		QIODevice* device = d->device;

		if(!d->haveSentHeaders)
		{
			d->haveSentHeaders = true;
			for(ClientIODevice::HeaderMap::ConstIterator it = d->responseHeaders.constBegin(); it != d->responseHeaders.constEnd(); ++it)
			{
				device->write(it.key());
				device->write(": ");
				device->write(it.value());
				device->write("\r\n");
			}
			device->write("\r\n");
		}
		return device->write(data, maxSize);
	}

	qint64 Request::size() const
	{
		return QString::fromLatin1(rawValue(ServerData, "CONTENT_LENGTH")).toLongLong();
	}

	QUrl Request::url(UrlPart part) const
	{
		QUrl url;
		// Protocol and host are needed, regardless of part
		if(rawValue(ServerData,"HTTPS") == "on")
		{
			url.setScheme("https");
		}
		else
		{
			url.setScheme("http");
		}
		// authority == user:password@host:port - as HTTP_HOST contains user and port, go with that
		url.setAuthority(value(ServerData, "HTTP_HOST"));

		const int queryStringOffset = rawValue(ServerData, "REQUEST_URI").contains('?') ? 1 : 0;
		const int queryStringLength = rawValue(ServerData, "QUERY_STRING").length() + queryStringOffset;
		switch(part)
		{
			case RootUrl:
			{
				const int pathInfoLength = rawValue(ServerData, "PATH_INFO").length();
				QByteArray basePath = rawValue(ServerData, "REQUEST_URI");
				basePath.chop(queryStringLength + pathInfoLength);
				url.setEncodedPath(basePath);
				break;
			}
			case LocationUrl:
			case RequestUrl:
			{
				QByteArray basePath = rawValue(ServerData, "REQUEST_URI");
				basePath.chop(queryStringLength);
				url.setEncodedPath(basePath);
				if(part == RequestUrl)
				{
					url.setEncodedQuery(rawValue(ServerData, "QUERY_STRING"));
				}
				break;
			}
			default:
				qFatal("Unknown URL part: %d", part);
		}
		return url;
	}

	QList<QNetworkCookie> Request::cookies() const
	{
		QList<QNetworkCookie> cookies;
		for(ClientIODevice::HeaderMap::ConstIterator it = d->serverData.constBegin(); it != d->serverData.constEnd(); ++it)
		{
			if(it.key().toUpper() == "HTTP_COOKIE")
			{
				QList<QByteArray> list = it.value().split(';');
				for(int i = 0; i < list.length(); ++i)
				{
					cookies.append(QNetworkCookie::parseCookies(list.at(i)));
				}
			}
		}
		return cookies;
	}

	void Request::sendCookie(const QNetworkCookie& cookie)
	{
		addHeader("set-cookie", cookie.toRawForm());
	}

	void Request::setHeader(const QByteArray& name, const QByteArray& value)
	{
		Q_ASSERT(!d->haveSentHeaders);
		d->responseHeaders[name] = value;
	}

	void Request::addHeader(const QByteArray& name, const QByteArray& value)
	{
		Q_ASSERT(!d->haveSentHeaders);
		d->responseHeaders.insertMulti(name, value);
	}

	QByteArray Request::responseHeader(const QByteArray& name)
	{
		return d->responseHeaders.value(name);
	}

	QHash<QByteArray, QByteArray> Request::rawValues(DataSource source) const
	{
		switch(source)
		{
			case GetData:
				return d->getData;
			case PostData:
				d->loadPostVariables();
				return d->postData;
			case ServerData:
				return d->serverData;
			default:
				qFatal("Unknown value type: %d", source);
		}
		return QHash<QByteArray, QByteArray>();
	}

	QByteArray Request::rawValue(DataSource source, const QByteArray& name) const
	{
		return rawValues(source).value(name);
	}

	QString Request::value(DataSource source, const QByteArray& name) const
	{
		return QUrl::fromPercentEncoding(rawValue(source, name));
	}

	Request::~Request()
	{
		emit finished(this);
		delete d;
	}
}
<|endoftext|>