<commit_before>////////////////////////////////////////////////////////////////////////////////
// Name:      lexer.cpp
// Purpose:   Implementation of wxExLexer class
// Author:    Anton van Wezenbeek
// Copyright: (c) 2014 Anton van Wezenbeek
////////////////////////////////////////////////////////////////////////////////

#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include <algorithm>
#include <functional>
//#include <numeric> // both for accumulate
#include <wx/stc/stc.h>
#include <wx/tokenzr.h>
#include <wx/xml/xml.h>
#include <wx/extension/lexer.h>
#include <wx/extension/lexers.h>
#include <wx/extension/util.h> // for wxExAlignText

// We always use lines with 80 characters.
const int line_size = 80;

wxExLexer::wxExLexer()
{
  Initialize();
}

wxExLexer::wxExLexer(const wxXmlNode* node)
{
  Initialize();
  Set(node);
}

wxExLexer::wxExLexer(const wxString& lexer, wxStyledTextCtrl* stc, bool clear)
{
  Initialize();
  Set(lexer, stc, true);
}

wxExLexer::wxExLexer(const wxExLexer& lexer, wxStyledTextCtrl* stc)
{
  Initialize();
  Set(lexer, stc);
}

// Adds the specified keywords to the keywords map and the keywords set.
// The text might contain the keyword set after a ':'.
// Returns false if specified set is illegal or value is empty.
bool wxExLexer::AddKeywords(const wxString& value)
{
  if (value.empty())
  {
    return false;
  }

  std::set<wxString> keywords_set;

  wxStringTokenizer tkz(value, "\r\n ");

  int setno = 0;

  while (tkz.HasMoreTokens())
  {
    const wxString line = tkz.GetNextToken();
    wxStringTokenizer fields(line, ":");
    wxString keyword;

    if (fields.CountTokens() > 1)
    {
      keyword = fields.GetNextToken();

      const int new_setno = atoi(fields.GetNextToken().c_str());

      if (new_setno <= 0 || new_setno >= wxSTC_KEYWORDSET_MAX)
      {
        wxLogError("Invalid keyword set: %d", new_setno);
        return false;
      }

      if (new_setno != setno)
      {
        if (!keywords_set.empty())
        {
          m_KeywordsSet.insert(make_pair(setno, keywords_set));
          keywords_set.clear();
        }

        setno = new_setno;
      }
    }
    else
    {
      keyword = line;
    }

    keywords_set.insert(keyword);
    m_Keywords.insert(keyword);
  }

  auto it = m_KeywordsSet.find(setno);

  if (it == m_KeywordsSet.end())
  {
    m_KeywordsSet.insert(make_pair(setno, keywords_set));
  }
  else
  {
    it->second.insert(keywords_set.begin(), keywords_set.end());
  }

  return true;
}

void wxExLexer::Apply(wxStyledTextCtrl* stc, bool clear) const
{
  if (clear)
  {
    stc->ClearDocumentStyle();
  }

  for_each (m_Properties.begin(), m_Properties.end(),
    std::bind2nd(std::mem_fun_ref(&wxExProperty::ApplyReset), stc));

  // Reset keywords, also if no lexer is available.
  for (size_t setno = 0; setno < wxSTC_KEYWORDSET_MAX; setno++)
  {
    stc->SetKeyWords(setno, wxEmptyString);
  }

  if (clear)
  {
    wxExLexers::Get()->ApplyGlobalStyles(stc);
  }

  if (wxExLexers::Get()->GetThemeOk())
  {
    for (const auto& it : m_KeywordsSet)
    {
      stc->SetKeyWords(
        it.first,
        GetKeywordsString(it.first));
    }

    wxExLexers::Get()->GetDefaultStyle().Apply(stc);
    wxExLexers::Get()->ApplyIndicators(stc);
    wxExLexers::Get()->ApplyProperties(stc);
    wxExLexers::Get()->ApplyMarkers(stc);

    for_each (m_Properties.begin(), m_Properties.end(),
      std::bind2nd(std::mem_fun_ref(&wxExProperty::Apply), stc));

    for_each (m_Styles.begin(), m_Styles.end(),
      std::bind2nd(std::mem_fun_ref(&wxExStyle::Apply), stc));
  }

  // And finally colour the entire document.
  stc->Colourise(0, stc->GetLength() - 1);
}

void wxExLexer::ApplyWhenSet(
  const wxString& lexer, wxStyledTextCtrl* stc, bool clear)
{
  if (stc == NULL)
  {
    return;
  }

  stc->SetLexerLanguage(m_ScintillaLexer);

  if (m_ScintillaLexer.empty() && lexer.empty())
  {
    m_IsOk = (stc->GetLexer() == wxSTC_LEX_NULL);
  }
  else
  {
    m_IsOk = (stc->GetLexer() != wxSTC_LEX_NULL);
  }

  if (m_IsOk)
  {
    stc->SetStyleBits(stc->GetStyleBitsNeeded());
    Apply(stc, clear);

    if (m_ScintillaLexer == "diff")
    {
      stc->SetEdgeMode(wxSTC_EDGE_NONE);
    }
  }
}

void wxExLexer::AutoMatch(const wxString& lexer)
{
  for (const auto& it : wxExLexers::Get()->GetMacros(lexer))
  {
    for (const auto& style : wxExLexers::Get()->GetThemeMacros())
    {
      if (it.first.Contains(style.first))
      {
        m_Styles.push_back(wxExStyle(it.second, style.second));
        break;
      }
    }
  }
}

const wxString wxExLexer::CommentComplete(const wxString& comment) const
{
  if (m_CommentEnd.empty())
  {
    return wxEmptyString;
  }

  // Fill out rest of comment with spaces, and comment end string.
  const int n = line_size - comment.size() - m_CommentEnd.size();

  if (n <= 0)
  {
    return wxEmptyString;
  }

  const wxString blanks = wxString(' ', n);

  return blanks + m_CommentEnd;
}

const wxString wxExLexer::GetFormattedText(
  const wxString& lines,
  const wxString& header,
  bool fill_out_with_space,
  bool fill_out) const
{
  wxString text = lines, header_to_use = header;
  size_t nCharIndex;
  wxString out;

  // Process text between the carriage return line feeds.
  while ((nCharIndex = text.find("\n")) != wxString::npos)
  {
    out << wxExAlignText(
      text.substr(0, nCharIndex),
      header_to_use,
      fill_out_with_space,
      fill_out,
      *this);

    text = text.substr(nCharIndex + 1);
    header_to_use = wxString(' ', header.size());
  }

  if (!text.empty())
  {
    out << wxExAlignText(
      text,
      header_to_use,
      fill_out_with_space,
      fill_out,
      *this);
  }

  return out;
}

const wxString wxExLexer::GetKeywordsString(int keyword_set) const
{
  if (keyword_set == -1)
  {
    return GetKeywordsStringSet(m_Keywords);
  }
  else
  {
    const auto it = m_KeywordsSet.find(keyword_set);

    if (it != m_KeywordsSet.end())
    {
      return GetKeywordsStringSet(it->second);
    }
  }

  return wxEmptyString;
}

const wxString wxExLexer::GetKeywordsStringSet(
  const std::set<wxString>& kset) const
{
  // accumulate would be nice, but does not add a space, could not do it easily.
  // return accumulate(kset.begin(), kset.end(), wxEmptyString);
  wxString keywords;

  for (const auto& it : kset)
  {
    keywords += it + " ";
  }

  return keywords.Trim(); // remove the ending space
}

void wxExLexer::Initialize()
{
  m_IsOk = false;

  m_CommentBegin.clear();
  m_CommentBegin2.clear();
  m_CommentEnd.clear();
  m_CommentEnd2.clear();
  m_Styles.clear();
  m_Extensions.clear();
  m_Properties.clear();
  m_Keywords.clear();
  m_KeywordsSet.clear();
  m_ScintillaLexer.clear();
  m_DisplayLexer.clear();
}

bool wxExLexer::IsKeyword(const wxString& word) const
{
  return m_Keywords.find(word) != m_Keywords.end();
}

bool wxExLexer::KeywordStartsWith(const wxString& word) const
{
  const auto it = m_Keywords.lower_bound(word);
  return
    it != m_Keywords.end() &&
    it->StartsWith(word);
}

const wxString wxExLexer::MakeComment(
  const wxString& text,
  bool fill_out_with_space,
  bool fill_out) const
{
  wxString out;

  text.find("\n") != wxString::npos ?
    out << GetFormattedText(text, wxEmptyString, fill_out_with_space, fill_out):
    out << wxExAlignText(text, wxEmptyString, fill_out_with_space, fill_out, *this);

  return out;
}

const wxString wxExLexer::MakeComment(
  const wxString& prefix,
  const wxString& text) const
{
  wxString out;

  text.find("\n") != wxString::npos ?
    out << GetFormattedText(text, prefix, true, true):
    out << wxExAlignText(text, prefix, true, true, *this);

  return out;
}

const wxString wxExLexer::MakeSingleLineComment(
  const wxString& text,
  bool fill_out_with_space,
  bool fill_out) const
{
  if (m_CommentBegin.empty() && m_CommentEnd.empty())
  {
    return text;
  }

  // First set the fill_out_character.
  wxUniChar fill_out_character;

  if (fill_out_with_space || m_ScintillaLexer == "hypertext")
  {
    fill_out_character = ' ';
  }
  else
  {
    if (text.empty())
    {
      if (m_CommentBegin == m_CommentEnd)
           fill_out_character = '-';
      else fill_out_character = m_CommentBegin[m_CommentBegin.size() - 1];
    }
    else   fill_out_character = ' ';
  }

  wxString out = m_CommentBegin + fill_out_character + text;

  // Fill out characters.
  if (fill_out)
  {
    // To prevent filling out spaces
    if (fill_out_character != ' ' || !m_CommentEnd.empty())
    {
      const int fill_chars = UsableCharactersPerLine() - text.size();

      if (fill_chars > 0)
      {
        const wxString fill_out(fill_out_character, fill_chars);
        out += fill_out;
      }
    }
  }

  if (!m_CommentEnd.empty()) out += fill_out_character + m_CommentEnd;

  return out;
}

bool wxExLexer::Reset(wxStyledTextCtrl* stc)
{
  Initialize();

  stc->SetLexer(wxSTC_LEX_NULL);

  m_IsOk = (stc->GetLexer() == wxSTC_LEX_NULL);

  if (m_IsOk)
  {
    Apply(stc, true);
  }

  return m_IsOk;
}

bool wxExLexer::Set(
  const wxString& lexer,
  wxStyledTextCtrl* stc,
  bool clear)
{
  (*this) = wxExLexers::Get()->FindByName(lexer);

  if (!m_IsOk && stc != NULL)
  {
    (*this) = wxExLexers::Get()->FindByText(stc->GetLine(0));
  }

  ApplyWhenSet(lexer, stc, clear);

  if (!m_IsOk)
  {
    wxLogError("Lexer is not known: " + lexer);
  }

  return m_IsOk;
}

bool wxExLexer::Set(const wxExLexer& lexer, wxStyledTextCtrl* stc)
{
  if (lexer.GetScintillaLexer().empty() && stc != NULL)
  {
    (*this) = wxExLexers::Get()->FindByText(stc->GetLine(0));
  }
  else
  {
    if (this != &lexer)
    {
      (*this) = lexer;
    }
  }

  ApplyWhenSet(lexer.GetScintillaLexer(), stc, true);

  return m_IsOk;
}

void wxExLexer::Set(const wxXmlNode* node)
{
  m_ScintillaLexer = node->GetAttribute("name");

  // Just set ok if there is a lexer,
  // when we Apply to a stc component we really can set it.
  m_IsOk = !m_ScintillaLexer.empty();

  if (!m_IsOk)
  {
    wxLogError("Missing lexer on line: %d", node->GetLineNumber());
  }
  else
  {
    m_DisplayLexer = (!node->GetAttribute("display").empty() ?
      node->GetAttribute("display"):
      m_ScintillaLexer);

    m_Extensions = node->GetAttribute("extensions");

    AutoMatch((!node->GetAttribute("macro").empty() ?
      node->GetAttribute("macro"):
      m_ScintillaLexer));

    if (m_ScintillaLexer == "hypertext")
    {
      // As our lexers.xml files cannot use xml comments,
      // add them here.
      m_CommentBegin = "<!--";
      m_CommentEnd = "-->";
    }

    wxXmlNode *child = node->GetChildren();

    while (child)
    {
      if (child->GetName() == "styles")
      {
        wxExNodeStyles(child, m_ScintillaLexer, m_Styles);
      }
      else if (child->GetName() == "keywords")
      {
        // Add all direct keywords
        const wxString& direct(child->GetNodeContent().Strip(wxString::both));

        if (!direct.empty() && !AddKeywords(direct))
        {
          wxLogError(
            "Keywords could not be set on line: %d",
            child->GetLineNumber());
        }

        // Add all keywords that point to a keyword set.
        wxXmlAttribute* att = child->GetAttributes();

        while (att != NULL)
        {
          if (!AddKeywords(wxExLexers::Get()->GetKeywords(
            att->GetValue().Strip(wxString::both))))
          {
            wxLogError(
              "Keywords for %s could not be set on line: %d",
              att->GetValue().c_str(),
              child->GetLineNumber());
          }

          att = att->GetNext();
        }
      }
      else if (child->GetName() == "properties")
      {
        wxExNodeProperties(child, m_Properties);
      }
      else if (child->GetName() == "comments")
      {
        m_CommentBegin = child->GetAttribute("begin1");
        m_CommentEnd = child->GetAttribute("end1");
        m_CommentBegin2 = child->GetAttribute("begin2");
        m_CommentEnd2 = child->GetAttribute("end2");
      }

      child = child->GetNext();
    }
  }

#ifdef DEBUG
  wxString keywords;

  for (const auto& it : m_KeywordsSet)
  {
    keywords += wxString::Format("set: %d %s\n",
      it.first, GetKeywordsString(it.first).c_str());
  }

  if (!keywords.empty())
  {
    wxLogMessage("Lexer: %s Display: %s Keywords: %s",
     m_ScintillaLexer.c_str(), m_DisplayLexer.c_str(), keywords.c_str());
  }
#endif
}

void wxExLexer::SetProperty(const wxString& name, const wxString& value)
{
  for (auto& it : m_Properties)
  {
    if (it.GetName() == name)
    {
      it.Set(value);
      return;
    }
  }

  m_Properties.push_back(wxExProperty(name, value));
}

int wxExLexer::UsableCharactersPerLine() const
{
  // We adjust this here for
  // the space the beginning and end of the comment characters occupy.
  return line_size
    - ((m_CommentBegin.size() != 0) ? m_CommentBegin.size() + 1 : 0)
    - ((m_CommentEnd.size() != 0) ? m_CommentEnd.size() + 1 : 0);
}
<commit_msg>minor simplification<commit_after>////////////////////////////////////////////////////////////////////////////////
// Name:      lexer.cpp
// Purpose:   Implementation of wxExLexer class
// Author:    Anton van Wezenbeek
// Copyright: (c) 2014 Anton van Wezenbeek
////////////////////////////////////////////////////////////////////////////////

#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include <algorithm>
#include <functional>
//#include <numeric> // both for accumulate
#include <wx/stc/stc.h>
#include <wx/tokenzr.h>
#include <wx/xml/xml.h>
#include <wx/extension/lexer.h>
#include <wx/extension/lexers.h>
#include <wx/extension/util.h> // for wxExAlignText

// We always use lines with 80 characters.
const int line_size = 80;

wxExLexer::wxExLexer()
{
  Initialize();
}

wxExLexer::wxExLexer(const wxXmlNode* node)
{
  Initialize();
  Set(node);
}

wxExLexer::wxExLexer(const wxString& lexer, wxStyledTextCtrl* stc, bool clear)
{
  Initialize();
  Set(lexer, stc, true);
}

wxExLexer::wxExLexer(const wxExLexer& lexer, wxStyledTextCtrl* stc)
{
  Initialize();
  Set(lexer, stc);
}

// Adds the specified keywords to the keywords map and the keywords set.
// The text might contain the keyword set after a ':'.
// Returns false if specified set is illegal or value is empty.
bool wxExLexer::AddKeywords(const wxString& value)
{
  if (value.empty())
  {
    return false;
  }

  std::set<wxString> keywords_set;

  wxStringTokenizer tkz(value, "\r\n ");

  int setno = 0;

  while (tkz.HasMoreTokens())
  {
    const wxString line = tkz.GetNextToken();
    wxStringTokenizer fields(line, ":");
    wxString keyword;

    if (fields.CountTokens() > 1)
    {
      keyword = fields.GetNextToken();

      const int new_setno = atoi(fields.GetNextToken().c_str());

      if (new_setno <= 0 || new_setno >= wxSTC_KEYWORDSET_MAX)
      {
        wxLogError("Invalid keyword set: %d", new_setno);
        return false;
      }

      if (new_setno != setno)
      {
        if (!keywords_set.empty())
        {
          m_KeywordsSet.insert(make_pair(setno, keywords_set));
          keywords_set.clear();
        }

        setno = new_setno;
      }
    }
    else
    {
      keyword = line;
    }

    keywords_set.insert(keyword);
    m_Keywords.insert(keyword);
  }

  auto it = m_KeywordsSet.find(setno);

  if (it == m_KeywordsSet.end())
  {
    m_KeywordsSet.insert(make_pair(setno, keywords_set));
  }
  else
  {
    it->second.insert(keywords_set.begin(), keywords_set.end());
  }

  return true;
}

void wxExLexer::Apply(wxStyledTextCtrl* stc, bool clear) const
{
  if (clear)
  {
    stc->ClearDocumentStyle();
  }

  for_each (m_Properties.begin(), m_Properties.end(),
    std::bind2nd(std::mem_fun_ref(&wxExProperty::ApplyReset), stc));

  // Reset keywords, also if no lexer is available.
  for (size_t setno = 0; setno < wxSTC_KEYWORDSET_MAX; setno++)
  {
    stc->SetKeyWords(setno, wxEmptyString);
  }

  if (clear)
  {
    wxExLexers::Get()->ApplyGlobalStyles(stc);
  }

  if (wxExLexers::Get()->GetThemeOk())
  {
    for (const auto& it : m_KeywordsSet)
    {
      stc->SetKeyWords(it.first, GetKeywordsStringSet(it.second));
    }

    wxExLexers::Get()->GetDefaultStyle().Apply(stc);
    wxExLexers::Get()->ApplyIndicators(stc);
    wxExLexers::Get()->ApplyProperties(stc);
    wxExLexers::Get()->ApplyMarkers(stc);

    for_each (m_Properties.begin(), m_Properties.end(),
      std::bind2nd(std::mem_fun_ref(&wxExProperty::Apply), stc));

    for_each (m_Styles.begin(), m_Styles.end(),
      std::bind2nd(std::mem_fun_ref(&wxExStyle::Apply), stc));
  }

  // And finally colour the entire document.
  stc->Colourise(0, stc->GetLength() - 1);
}

void wxExLexer::ApplyWhenSet(
  const wxString& lexer, wxStyledTextCtrl* stc, bool clear)
{
  if (stc == NULL)
  {
    return;
  }

  stc->SetLexerLanguage(m_ScintillaLexer);

  if (m_ScintillaLexer.empty() && lexer.empty())
  {
    m_IsOk = (stc->GetLexer() == wxSTC_LEX_NULL);
  }
  else
  {
    m_IsOk = (stc->GetLexer() != wxSTC_LEX_NULL);
  }

  if (m_IsOk)
  {
    stc->SetStyleBits(stc->GetStyleBitsNeeded());
    Apply(stc, clear);

    if (m_ScintillaLexer == "diff")
    {
      stc->SetEdgeMode(wxSTC_EDGE_NONE);
    }
  }
}

void wxExLexer::AutoMatch(const wxString& lexer)
{
  for (const auto& it : wxExLexers::Get()->GetMacros(lexer))
  {
    for (const auto& style : wxExLexers::Get()->GetThemeMacros())
    {
      if (it.first.Contains(style.first))
      {
        m_Styles.push_back(wxExStyle(it.second, style.second));
        break;
      }
    }
  }
}

const wxString wxExLexer::CommentComplete(const wxString& comment) const
{
  if (m_CommentEnd.empty())
  {
    return wxEmptyString;
  }

  // Fill out rest of comment with spaces, and comment end string.
  const int n = line_size - comment.size() - m_CommentEnd.size();

  if (n <= 0)
  {
    return wxEmptyString;
  }

  const wxString blanks = wxString(' ', n);

  return blanks + m_CommentEnd;
}

const wxString wxExLexer::GetFormattedText(
  const wxString& lines,
  const wxString& header,
  bool fill_out_with_space,
  bool fill_out) const
{
  wxString text = lines, header_to_use = header;
  size_t nCharIndex;
  wxString out;

  // Process text between the carriage return line feeds.
  while ((nCharIndex = text.find("\n")) != wxString::npos)
  {
    out << wxExAlignText(
      text.substr(0, nCharIndex),
      header_to_use,
      fill_out_with_space,
      fill_out,
      *this);

    text = text.substr(nCharIndex + 1);
    header_to_use = wxString(' ', header.size());
  }

  if (!text.empty())
  {
    out << wxExAlignText(
      text,
      header_to_use,
      fill_out_with_space,
      fill_out,
      *this);
  }

  return out;
}

const wxString wxExLexer::GetKeywordsString(int keyword_set) const
{
  if (keyword_set == -1)
  {
    return GetKeywordsStringSet(m_Keywords);
  }
  else
  {
    const auto it = m_KeywordsSet.find(keyword_set);

    if (it != m_KeywordsSet.end())
    {
      return GetKeywordsStringSet(it->second);
    }
  }

  return wxEmptyString;
}

const wxString wxExLexer::GetKeywordsStringSet(
  const std::set<wxString>& kset) const
{
  // accumulate would be nice, but does not add a space, could not do it easily.
  // return accumulate(kset.begin(), kset.end(), wxEmptyString);
  wxString keywords;

  for (const auto& it : kset)
  {
    keywords += it + " ";
  }

  return keywords.Trim(); // remove the ending space
}

void wxExLexer::Initialize()
{
  m_IsOk = false;

  m_CommentBegin.clear();
  m_CommentBegin2.clear();
  m_CommentEnd.clear();
  m_CommentEnd2.clear();
  m_Styles.clear();
  m_Extensions.clear();
  m_Properties.clear();
  m_Keywords.clear();
  m_KeywordsSet.clear();
  m_ScintillaLexer.clear();
  m_DisplayLexer.clear();
}

bool wxExLexer::IsKeyword(const wxString& word) const
{
  return m_Keywords.find(word) != m_Keywords.end();
}

bool wxExLexer::KeywordStartsWith(const wxString& word) const
{
  const auto it = m_Keywords.lower_bound(word);
  return
    it != m_Keywords.end() &&
    it->StartsWith(word);
}

const wxString wxExLexer::MakeComment(
  const wxString& text,
  bool fill_out_with_space,
  bool fill_out) const
{
  wxString out;

  text.find("\n") != wxString::npos ?
    out << GetFormattedText(text, wxEmptyString, fill_out_with_space, fill_out):
    out << wxExAlignText(text, wxEmptyString, fill_out_with_space, fill_out, *this);

  return out;
}

const wxString wxExLexer::MakeComment(
  const wxString& prefix,
  const wxString& text) const
{
  wxString out;

  text.find("\n") != wxString::npos ?
    out << GetFormattedText(text, prefix, true, true):
    out << wxExAlignText(text, prefix, true, true, *this);

  return out;
}

const wxString wxExLexer::MakeSingleLineComment(
  const wxString& text,
  bool fill_out_with_space,
  bool fill_out) const
{
  if (m_CommentBegin.empty() && m_CommentEnd.empty())
  {
    return text;
  }

  // First set the fill_out_character.
  wxUniChar fill_out_character;

  if (fill_out_with_space || m_ScintillaLexer == "hypertext")
  {
    fill_out_character = ' ';
  }
  else
  {
    if (text.empty())
    {
      if (m_CommentBegin == m_CommentEnd)
           fill_out_character = '-';
      else fill_out_character = m_CommentBegin[m_CommentBegin.size() - 1];
    }
    else   fill_out_character = ' ';
  }

  wxString out = m_CommentBegin + fill_out_character + text;

  // Fill out characters.
  if (fill_out)
  {
    // To prevent filling out spaces
    if (fill_out_character != ' ' || !m_CommentEnd.empty())
    {
      const int fill_chars = UsableCharactersPerLine() - text.size();

      if (fill_chars > 0)
      {
        const wxString fill_out(fill_out_character, fill_chars);
        out += fill_out;
      }
    }
  }

  if (!m_CommentEnd.empty()) out += fill_out_character + m_CommentEnd;

  return out;
}

bool wxExLexer::Reset(wxStyledTextCtrl* stc)
{
  Initialize();

  stc->SetLexer(wxSTC_LEX_NULL);

  m_IsOk = (stc->GetLexer() == wxSTC_LEX_NULL);

  if (m_IsOk)
  {
    Apply(stc, true);
  }

  return m_IsOk;
}

bool wxExLexer::Set(
  const wxString& lexer,
  wxStyledTextCtrl* stc,
  bool clear)
{
  (*this) = wxExLexers::Get()->FindByName(lexer);

  if (!m_IsOk && stc != NULL)
  {
    (*this) = wxExLexers::Get()->FindByText(stc->GetLine(0));
  }

  ApplyWhenSet(lexer, stc, clear);

  if (!m_IsOk)
  {
    wxLogError("Lexer is not known: " + lexer);
  }

  return m_IsOk;
}

bool wxExLexer::Set(const wxExLexer& lexer, wxStyledTextCtrl* stc)
{
  if (lexer.GetScintillaLexer().empty() && stc != NULL)
  {
    (*this) = wxExLexers::Get()->FindByText(stc->GetLine(0));
  }
  else
  {
    if (this != &lexer)
    {
      (*this) = lexer;
    }
  }

  ApplyWhenSet(lexer.GetScintillaLexer(), stc, true);

  return m_IsOk;
}

void wxExLexer::Set(const wxXmlNode* node)
{
  m_ScintillaLexer = node->GetAttribute("name");

  // Just set ok if there is a lexer,
  // when we Apply to a stc component we really can set it.
  m_IsOk = !m_ScintillaLexer.empty();

  if (!m_IsOk)
  {
    wxLogError("Missing lexer on line: %d", node->GetLineNumber());
  }
  else
  {
    m_DisplayLexer = (!node->GetAttribute("display").empty() ?
      node->GetAttribute("display"):
      m_ScintillaLexer);

    m_Extensions = node->GetAttribute("extensions");

    AutoMatch((!node->GetAttribute("macro").empty() ?
      node->GetAttribute("macro"):
      m_ScintillaLexer));

    if (m_ScintillaLexer == "hypertext")
    {
      // As our lexers.xml files cannot use xml comments,
      // add them here.
      m_CommentBegin = "<!--";
      m_CommentEnd = "-->";
    }

    wxXmlNode *child = node->GetChildren();

    while (child)
    {
      if (child->GetName() == "styles")
      {
        wxExNodeStyles(child, m_ScintillaLexer, m_Styles);
      }
      else if (child->GetName() == "keywords")
      {
        // Add all direct keywords
        const wxString& direct(child->GetNodeContent().Strip(wxString::both));

        if (!direct.empty() && !AddKeywords(direct))
        {
          wxLogError(
            "Keywords could not be set on line: %d",
            child->GetLineNumber());
        }

        // Add all keywords that point to a keyword set.
        wxXmlAttribute* att = child->GetAttributes();

        while (att != NULL)
        {
          if (!AddKeywords(wxExLexers::Get()->GetKeywords(
            att->GetValue().Strip(wxString::both))))
          {
            wxLogError(
              "Keywords for %s could not be set on line: %d",
              att->GetValue().c_str(),
              child->GetLineNumber());
          }

          att = att->GetNext();
        }
      }
      else if (child->GetName() == "properties")
      {
        wxExNodeProperties(child, m_Properties);
      }
      else if (child->GetName() == "comments")
      {
        m_CommentBegin = child->GetAttribute("begin1");
        m_CommentEnd = child->GetAttribute("end1");
        m_CommentBegin2 = child->GetAttribute("begin2");
        m_CommentEnd2 = child->GetAttribute("end2");
      }

      child = child->GetNext();
    }
  }

#ifdef DEBUG
  wxString keywords;

  for (const auto& it : m_KeywordsSet)
  {
    keywords += wxString::Format("set: %d %s\n",
      it.first, GetKeywordsString(it.first).c_str());
  }

  if (!keywords.empty())
  {
    wxLogMessage("Lexer: %s Display: %s Keywords: %s",
     m_ScintillaLexer.c_str(), m_DisplayLexer.c_str(), keywords.c_str());
  }
#endif
}

void wxExLexer::SetProperty(const wxString& name, const wxString& value)
{
  for (auto& it : m_Properties)
  {
    if (it.GetName() == name)
    {
      it.Set(value);
      return;
    }
  }

  m_Properties.push_back(wxExProperty(name, value));
}

int wxExLexer::UsableCharactersPerLine() const
{
  // We adjust this here for
  // the space the beginning and end of the comment characters occupy.
  return line_size
    - ((m_CommentBegin.size() != 0) ? m_CommentBegin.size() + 1 : 0)
    - ((m_CommentEnd.size() != 0) ? m_CommentEnd.size() + 1 : 0);
}
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// See the corresponding header file for description of the functions in this
// file.

#include "install_util.h"

#include <algorithm>
#include <shellapi.h>
#include <shlobj.h>

#include "base/logging.h"
#include "base/registry.h"
#include "base/string_util.h"
#include "base/win_util.h"

#include "chrome/installer/util/browser_distribution.h"
#include "chrome/installer/util/google_update_constants.h"
#include "chrome/installer/util/l10n_string_util.h"
#include "chrome/installer/util/work_item_list.h"

bool InstallUtil::ExecuteExeAsAdmin(const std::wstring& exe,
                                    const std::wstring& params,
                                    DWORD* exit_code) {
  SHELLEXECUTEINFO info = {0};
  info.cbSize = sizeof(SHELLEXECUTEINFO);
  info.fMask = SEE_MASK_NOCLOSEPROCESS;
  info.lpVerb = L"runas";
  info.lpFile = exe.c_str();
  info.lpParameters = params.c_str();
  info.nShow = SW_SHOW;
  if (::ShellExecuteEx(&info) == FALSE)
    return false;

  ::WaitForSingleObject(info.hProcess, INFINITE);
  DWORD ret_val = 0;
  if (!::GetExitCodeProcess(info.hProcess, &ret_val))
    return false;

  if (exit_code)
    *exit_code = ret_val;
  return true;
}

std::wstring InstallUtil::GetChromeUninstallCmd(bool system_install) {
  HKEY root = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
  RegKey key(root, dist->GetUninstallRegPath().c_str());
  std::wstring uninstall_cmd;
  key.ReadValue(installer_util::kUninstallStringField, &uninstall_cmd);
  return uninstall_cmd;
}

installer::Version* InstallUtil::GetChromeVersion(bool system_install) {
  RegKey key;
  std::wstring version_str;

  HKEY reg_root = (system_install) ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
  if (!key.Open(reg_root, dist->GetVersionKey().c_str(), KEY_READ) ||
      !key.ReadValue(google_update::kRegVersionField, &version_str)) {
    LOG(INFO) << "No existing Chrome install found.";
    key.Close();
    return NULL;
  }
  key.Close();
  LOG(INFO) << "Existing Chrome version found " << version_str;
  return installer::Version::GetVersionFromString(version_str);
}

bool InstallUtil::IsOSSupported() {
  int major, minor;
  win_util::WinVersion version = win_util::GetWinVersion();
  win_util::GetServicePackLevel(&major, &minor);

  // We do not support Win2K or older, or XP without service pack 1.
  LOG(INFO) << "Windows Version: " << version
            << ", Service Pack: " << major << "." << minor;
  if ((version == win_util::WINVERSION_VISTA) ||
      (version == win_util::WINVERSION_SERVER_2003) ||
      (version == win_util::WINVERSION_XP && major >= 1)) {
    return true;
  }
  return false;
}

void InstallUtil::WriteInstallerResult(bool system_install,
                                       installer_util::InstallStatus status,
                                       int string_resource_id,
                                       const std::wstring* const launch_cmd) {
  HKEY root = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
  std::wstring key = dist->GetStateKey();
  int installer_result = (dist->GetInstallReturnCode(status) == 0) ? 0 : 1;
  scoped_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList());
  install_list->AddCreateRegKeyWorkItem(root, key);
  install_list->AddSetRegValueWorkItem(root, key, L"InstallerResult",
                                       installer_result, true);
  install_list->AddSetRegValueWorkItem(root, key, L"InstallerError",
                                       status, true);
  if (string_resource_id != 0) {
    std::wstring msg = installer_util::GetLocalizedString(string_resource_id);
    install_list->AddSetRegValueWorkItem(root, key, L"InstallerResultUIString",
                                         msg, true);
  }
  if (launch_cmd != NULL) {
    install_list->AddSetRegValueWorkItem(root, key,
                                         L"InstallerSuccessLaunchCmdLine",
                                         *launch_cmd, true);
  }
  if (!install_list->Do())
    LOG(ERROR) << "Failed to record installer error information in registry.";
}

bool InstallUtil::IsPerUserInstall(const wchar_t* const exe_path) {

  wchar_t program_files_path[MAX_PATH] = {0};
  if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES, NULL,
                                SHGFP_TYPE_CURRENT, program_files_path))) {
    return !StartsWith(exe_path, program_files_path, false);
  } else {
    NOTREACHED();
  }
  return true;
}
<commit_msg>Fix mini_installer failing on Windows 7 (issue 7732).<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// See the corresponding header file for description of the functions in this
// file.

#include "install_util.h"

#include <algorithm>
#include <shellapi.h>
#include <shlobj.h>

#include "base/logging.h"
#include "base/registry.h"
#include "base/string_util.h"
#include "base/win_util.h"

#include "chrome/installer/util/browser_distribution.h"
#include "chrome/installer/util/google_update_constants.h"
#include "chrome/installer/util/l10n_string_util.h"
#include "chrome/installer/util/work_item_list.h"

bool InstallUtil::ExecuteExeAsAdmin(const std::wstring& exe,
                                    const std::wstring& params,
                                    DWORD* exit_code) {
  SHELLEXECUTEINFO info = {0};
  info.cbSize = sizeof(SHELLEXECUTEINFO);
  info.fMask = SEE_MASK_NOCLOSEPROCESS;
  info.lpVerb = L"runas";
  info.lpFile = exe.c_str();
  info.lpParameters = params.c_str();
  info.nShow = SW_SHOW;
  if (::ShellExecuteEx(&info) == FALSE)
    return false;

  ::WaitForSingleObject(info.hProcess, INFINITE);
  DWORD ret_val = 0;
  if (!::GetExitCodeProcess(info.hProcess, &ret_val))
    return false;

  if (exit_code)
    *exit_code = ret_val;
  return true;
}

std::wstring InstallUtil::GetChromeUninstallCmd(bool system_install) {
  HKEY root = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
  RegKey key(root, dist->GetUninstallRegPath().c_str());
  std::wstring uninstall_cmd;
  key.ReadValue(installer_util::kUninstallStringField, &uninstall_cmd);
  return uninstall_cmd;
}

installer::Version* InstallUtil::GetChromeVersion(bool system_install) {
  RegKey key;
  std::wstring version_str;

  HKEY reg_root = (system_install) ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
  if (!key.Open(reg_root, dist->GetVersionKey().c_str(), KEY_READ) ||
      !key.ReadValue(google_update::kRegVersionField, &version_str)) {
    LOG(INFO) << "No existing Chrome install found.";
    key.Close();
    return NULL;
  }
  key.Close();
  LOG(INFO) << "Existing Chrome version found " << version_str;
  return installer::Version::GetVersionFromString(version_str);
}

bool InstallUtil::IsOSSupported() {
  int major, minor;
  win_util::WinVersion version = win_util::GetWinVersion();
  win_util::GetServicePackLevel(&major, &minor);

  // We do not support Win2K or older, or XP without service pack 1.
  LOG(INFO) << "Windows Version: " << version
            << ", Service Pack: " << major << "." << minor;
  if ((version > win_util::WINVERSION_XP) ||
      (version == win_util::WINVERSION_XP && major >= 1)) {
    return true;
  }
  return false;
}

void InstallUtil::WriteInstallerResult(bool system_install,
                                       installer_util::InstallStatus status,
                                       int string_resource_id,
                                       const std::wstring* const launch_cmd) {
  HKEY root = system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
  std::wstring key = dist->GetStateKey();
  int installer_result = (dist->GetInstallReturnCode(status) == 0) ? 0 : 1;
  scoped_ptr<WorkItemList> install_list(WorkItem::CreateWorkItemList());
  install_list->AddCreateRegKeyWorkItem(root, key);
  install_list->AddSetRegValueWorkItem(root, key, L"InstallerResult",
                                       installer_result, true);
  install_list->AddSetRegValueWorkItem(root, key, L"InstallerError",
                                       status, true);
  if (string_resource_id != 0) {
    std::wstring msg = installer_util::GetLocalizedString(string_resource_id);
    install_list->AddSetRegValueWorkItem(root, key, L"InstallerResultUIString",
                                         msg, true);
  }
  if (launch_cmd != NULL) {
    install_list->AddSetRegValueWorkItem(root, key,
                                         L"InstallerSuccessLaunchCmdLine",
                                         *launch_cmd, true);
  }
  if (!install_list->Do())
    LOG(ERROR) << "Failed to record installer error information in registry.";
}

bool InstallUtil::IsPerUserInstall(const wchar_t* const exe_path) {

  wchar_t program_files_path[MAX_PATH] = {0};
  if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES, NULL,
                                SHGFP_TYPE_CURRENT, program_files_path))) {
    return !StartsWith(exe_path, program_files_path, false);
  } else {
    NOTREACHED();
  }
  return true;
}
<|endoftext|>


<commit_before>#include <SDL2/SDL.h>
#include <string>
#include "spinner/misc.hpp"
#include <exception>
#include <stdexcept>

#define Assert(expr) AssertMsg(expr, "Assertion failed")
#define AssertMsg(expr, msg) { if(!(expr)) throw std::runtime_error(msg); }
#define SDLW_Check sdlw::CheckSDLError(__LINE__);
#ifdef DEBUG
	#define AAssert(expr) AAssertMsg(expr, "Assertion failed")
	#define AAssertMsg(expr, msg) AssertMsg(expr, msg)
	#define SDLW_ACheck sdlw::CheckSDLError(__LINE__);
#else
	#define AAssert(expr)
	#define AAssertMsg(expr,msg)
	#define SDLW_ACheck
#endif

namespace sdlw {
	extern SDL_threadID thread_local tls_threadID;
	void CheckSDLError(int line=-1);
	//! 実行環境に関する情報を取得
	class Spec : public spn::Singleton<Spec> {
		public:
			enum Feature : uint32_t {
				F_3DNow = 0x01,
				F_AltiVec = 0x02,
				F_MMX = 0x04,
				F_RDTSC = 0x08,
				F_SSE = 0x10,
				F_SSE2 = 0x11,
				F_SSE3 = 0x12,
				F_SSE41 = 0x14,
				F_SSE42 = 0x18
			};
			enum class PStatN {
				Unknown,
				OnBattery,
				NoBattery,
				Charging,
				Charged
			};
			struct PStat {
				PStatN	state;
				int		seconds,
				percentage;

				void output(std::ostream& os) const;
			};
		private:
			uint32_t		_feature;
			std::string		_platform;
			int				_nCacheLine,
			_nCpu;
		public:
			Spec();
			const std::string& getPlatform() const;

			int cpuCacheLineSize() const;
			int cpuCount() const;
			bool hasFuture(uint32_t flag) const;
			PStat powerStatus() const;
	};
	//! SDLのMutexラッパ
	class Mutex {
		SDL_mutex*	_mutex;

		public:
			Mutex();
			Mutex(const Mutex& m) = delete;
			Mutex& operator = (const Mutex& m) = delete;
			~Mutex();

			bool lock();
			bool try_lock();
			void unlock();
			SDL_mutex* getMutex();
	};
	//! 再帰対応のスピンロック
	template <class T>
	class SpinLock {
		struct Inner {
			SpinLock&	_src;
			T*			_data;

			Inner(const Inner&) = delete;
			Inner& operator = (const Inner&) = delete;
			Inner(SpinLock& src, T* data): _src(src), _data(data) { _src._lock(); }
			~Inner() {
				unlock();
			}
			T* operator -> () { return _data; }
			bool valid() const { return _data != nullptr; }
			void unlock() {
				if(_data) {
					_src._unlock();
					_data = nullptr;
				}
			}
		};
		SDL_atomic_t	_atmLock,
		_atmCount;
		void _unlock() {
			if(SDL_AtomicDecRef(&_atmCount) == SDL_TRUE)
				SDL_AtomicSet(&_atmLock, 0);
		}

		T	_data;
		Inner _lock(bool bBlock) {
			do {
				bool bSuccess = false;
				if(SDL_AtomicCAS(&_atmLock, 0, tls_threadID) == 0)
					bSuccess = true;
				else if(SDL_AtomicGet(&_atmLock) == tls_threadID) {
					// 同じスレッドからのロック
					bSuccess = true;
				}

				if(bSuccess) {
					// ロック成功
					SDL_AtomicAddRef(&_atmCount);
					return Inner(*this, &_data);
				}
			} while(bBlock);
			return Inner(*this, nullptr);
		}

		public:
			SpinLock() {
				SDL_AtomicSet(&_atmLock, 0);
				SDL_AtomicSet(&_atmCount, 0);
			}
			Inner lock() {
				return _lock(true);
			}
			Inner try_lock() {
				return _lock(false);
			}
	};

	// SIG = スレッドに関するシグニチャ
	template <class SIG>
	class Thread;
	template <class RET, class... Args>
	class Thread<RET (Args...)> {
		using This = Thread<RET (Args...)>;
		RET					_retVal;
		SDL_atomic_t		_atmInt;
		SDL_Thread*			_thread;
		std::exception_ptr	_eptr;

		enum Stat {
			Idle,			//!< スレッド開始前
			Running,		//!< スレッド実行中
			Interrupted,	//!< 中断要求がされたが、まだスレッドが終了していない
			Interrupted_End,//!< 中断要求によりスレッドが終了した
			Error_End,		//!< 例外による異常終了
			Finished		//!< 正常終了
		};
		SDL_atomic_t		_atmStat;
		SDL_cond			*_condC,		//!< 子スレッドが開始された事を示す
		*_condP;		//!< 親スレッドがクラス変数にスレッドポインタを格納した事を示す
		Mutex				_mtxC,
		_mtxP;

		static int ThreadFunc(void* p) {
			This* ths = reinterpret_cast<This*>(p);
			ths->_mtxC.lock();
			ths->_mtxP.lock();
			SDL_CondBroadcast(ths->_condC);
			ths->_mtxC.unlock();
			// 親スレッドが子スレッド変数をセットするまで待つ
			SDL_CondWait(ths->_condP, ths->_mtxP.getMutex());
			ths->_mtxP.unlock();

			// この時点でスレッドのポインタは有効な筈
			tls_threadID = SDL_GetThreadID(ths->_thread);
			Stat stat;
			try {
				ths->_retVal = ths->run();
				stat = (ths->isInterrupted()) ? Interrupted_End : Finished;
			} catch(...) {
				ths->_eptr = std::current_exception();
				stat = Error_End;
			}
			SDL_AtomicSet(&ths->_atmStat, stat);
			// SDLの戻り値は使わない
			return 0;
		}
		protected:
			virtual RET run(Args...) = 0;
		public:
			Thread(const Thread& t) = delete;
			Thread& operator = (const Thread& t) = delete;
			Thread(): _thread(nullptr), _eptr(nullptr) {
				_condC = SDL_CreateCond();
				_condP = SDL_CreateCond();
				// 中断フラグに0をセット
				SDL_AtomicSet(&_atmInt, 0);
				SDL_AtomicSet(&_atmStat, Idle);
			}
			~Thread() {
				// スレッド実行中だったらエラーを出す
				Assert(!isRunning())
				SDL_DestroyCond(_condC);
				SDL_DestroyCond(_condP);
			}
			template <class... Args0>
			void start(Args0&&... args0) {
				// 2回以上呼ぶとエラー
				Assert(SDL_AtomicGet(&_atmStat) == Idle)
				SDL_AtomicSet(&_atmStat, Running);

				_mtxC.lock();
				// 一旦クラス内部に変数を参照で取っておく
				SDL_Thread* th = SDL_CreateThread(ThreadFunc, "", this);
				// 子スレッドが開始されるまで待つ
				SDL_CondWait(_condC, _mtxC.getMutex());
				_mtxC.unlock();

				_mtxP.lock();
				_thread = th;
				SDL_CondBroadcast(_condP);
				_mtxP.unlock();
			}
			Stat getStatus() {
				return static_cast<Stat>(SDL_AtomicGet(&_atmStat));
			}
			bool isRunning() {
				Stat stat = getStatus();
				return stat==Running || stat==Interrupted;
			}
			//! 中断を指示する
			bool interrupt() {
				auto ret = SDL_AtomicCAS(&_atmStat, Running, Interrupted);
				SDL_AtomicSet(&_atmInt, 1);
				SDLW_ACheck
				return ret == SDL_TRUE;
			}
			//! スレッド内部で中断指示がされているかを確認
			bool isInterrupted() {
				return SDL_AtomicGet(&_atmInt) == 1;
			}
			void join() {
				_mtxP.lock();
				if(_thread) {
					int ret;
					SDL_WaitThread(_thread, &ret);
					_thread = nullptr;
				}
				_mtxP.unlock();
			}
			bool try_join(uint32_t ms) {
				_mtxP.lock();
				int res = SDL_CondWaitTimeout(_condP, _mtxP.getMutex(), ms);
				_mtxP.unlock();
				SDLW_Check
				return res == 0;
			}
			const RET& getResult() {
				// まだスレッドが終了して無い時の為にjoinを呼ぶ
				join();
				return _retVal;
			}
	};

	class Window;
	using SPWindow = std::shared_ptr<Window>;
	class GLContext;
	using SPGLContext = std::shared_ptr<GLContext>;

	class Window {
		public:
			enum class Stat {
				Minimized,
				Maximized,
				Hidden,
				Fullscreen,
				Shown
			};
		private:
			SDL_Window*	_window;
			Stat		_stat;
			Window(SDL_Window* w);

			void _checkState();
		public:
			static SPWindow CreateWindow(const std::string& title, int w, int h, uint32_t flag=0);
			static SPWindow CreateWindow(const std::string& title, int x, int y, int w, int h, uint32_t flag=0);
			~Window();

			void setFullscreen(bool bFull);
			void setGrab(bool bGrab);
			void setMaximumSize(int w, int h);
			void setMinimumSize(int w, int h);
			void setSize(int w, int h);
			void setTitle(const std::string& title);
			void show(bool bShow);
			void maximize();
			void minimize();
			void restore();
			void setPosition(int x, int y);
			void raise();
			// for logging
			uint32_t getID() const;

			Stat getState() const;
			bool isGrabbed() const;
			bool isResizable() const;
			bool hasInputFocus() const;
			bool hasMouseFocus() const;
			uint32_t getSDLFlag() const;
			SDL_Window* getWindow() const;

			static void EnableScreenSaver(bool bEnable);
	};
	class GLContext {
		SPWindow		_spWindow;
		SDL_GLContext	_ctx;

		GLContext(const SPWindow& w);
		public:
			static SPGLContext CreateContext(const SPWindow& w);
			~GLContext();
			void makeCurrent(const SPWindow& w);
			void makeCurrent();
			void swapWindow();
			static int SetSwapInterval(int n);
	};
}
<commit_msg>SpinLock: カウンタのバグ修正<commit_after>#include <SDL2/SDL.h>
#include <string>
#include "spinner/misc.hpp"
#include <exception>
#include <stdexcept>

#define Assert(expr) AssertMsg(expr, "Assertion failed")
#define AssertMsg(expr, msg) { if(!(expr)) throw std::runtime_error(msg); }
#define SDLW_Check sdlw::CheckSDLError(__LINE__);
#ifdef DEBUG
	#define AAssert(expr) AAssertMsg(expr, "Assertion failed")
	#define AAssertMsg(expr, msg) AssertMsg(expr, msg)
	#define SDLW_ACheck sdlw::CheckSDLError(__LINE__);
#else
	#define AAssert(expr)
	#define AAssertMsg(expr,msg)
	#define SDLW_ACheck
#endif

namespace sdlw {
	extern SDL_threadID thread_local tls_threadID;
	void CheckSDLError(int line=-1);
	//! 実行環境に関する情報を取得
	class Spec : public spn::Singleton<Spec> {
		public:
			enum Feature : uint32_t {
				F_3DNow = 0x01,
				F_AltiVec = 0x02,
				F_MMX = 0x04,
				F_RDTSC = 0x08,
				F_SSE = 0x10,
				F_SSE2 = 0x11,
				F_SSE3 = 0x12,
				F_SSE41 = 0x14,
				F_SSE42 = 0x18
			};
			enum class PStatN {
				Unknown,
				OnBattery,
				NoBattery,
				Charging,
				Charged
			};
			struct PStat {
				PStatN	state;
				int		seconds,
				percentage;

				void output(std::ostream& os) const;
			};
		private:
			uint32_t		_feature;
			std::string		_platform;
			int				_nCacheLine,
			_nCpu;
		public:
			Spec();
			const std::string& getPlatform() const;

			int cpuCacheLineSize() const;
			int cpuCount() const;
			bool hasFuture(uint32_t flag) const;
			PStat powerStatus() const;
	};
	//! SDLのMutexラッパ
	class Mutex {
		SDL_mutex*	_mutex;

		public:
			Mutex();
			Mutex(const Mutex& m) = delete;
			Mutex& operator = (const Mutex& m) = delete;
			~Mutex();

			bool lock();
			bool try_lock();
			void unlock();
			SDL_mutex* getMutex();
	};
	//! 再帰対応のスピンロック
	template <class T>
	class SpinLock {
		struct Inner {
			SpinLock&	_src;
			T*			_data;

			Inner(const Inner&) = delete;
			Inner& operator = (const Inner&) = delete;
			Inner(Inner&& n): _src(n._src), _data(n._data) {}
			Inner(SpinLock& src, T* data): _src(src), _data(data) {}
			~Inner() {
				unlock();
			}
			T& operator * () { return *_data; }
			T* operator -> () { return _data; }
			bool valid() const { return _data != nullptr; }
			void unlock() {
				if(_data) {
					_src._unlock();
					_data = nullptr;
				}
			}
		};
		SDL_atomic_t	_atmLock,
		_atmCount;
		void _unlock() {
			if(SDL_AtomicDecRef(&_atmCount) == SDL_TRUE)
				SDL_AtomicSet(&_atmLock, 0);
		}

		T	_data;
		Inner _lock(bool bBlock) {
			do {
				bool bSuccess = false;
				if(SDL_AtomicCAS(&_atmLock, 0, tls_threadID) == SDL_TRUE)
					bSuccess = true;
				else if(SDL_AtomicGet(&_atmLock) == tls_threadID) {
					// 同じスレッドからのロック
					bSuccess = true;
				}

				if(bSuccess) {
					// ロック成功
					SDL_AtomicAdd(&_atmCount, 1);
					return Inner(*this, &_data);
				}
			} while(bBlock);
			return Inner(*this, nullptr);
		}

		public:
			SpinLock() {
				SDL_AtomicSet(&_atmLock, 0);
				SDL_AtomicSet(&_atmCount, 0);
			}
			Inner lock() {
				return _lock(true);
			}
			Inner try_lock() {
				return _lock(false);
			}
	};

	// SIG = スレッドに関するシグニチャ
	template <class SIG>
	class Thread;
	template <class RET, class... Args>
	class Thread<RET (Args...)> {
		using This = Thread<RET (Args...)>;
		RET					_retVal;
		SDL_atomic_t		_atmInt;
		SDL_Thread*			_thread;
		std::exception_ptr	_eptr;

		enum Stat {
			Idle,			//!< スレッド開始前
			Running,		//!< スレッド実行中
			Interrupted,	//!< 中断要求がされたが、まだスレッドが終了していない
			Interrupted_End,//!< 中断要求によりスレッドが終了した
			Error_End,		//!< 例外による異常終了
			Finished		//!< 正常終了
		};
		SDL_atomic_t		_atmStat;
		SDL_cond			*_condC,		//!< 子スレッドが開始された事を示す
		*_condP;		//!< 親スレッドがクラス変数にスレッドポインタを格納した事を示す
		Mutex				_mtxC,
		_mtxP;

		static int ThreadFunc(void* p) {
			This* ths = reinterpret_cast<This*>(p);
			ths->_mtxC.lock();
			ths->_mtxP.lock();
			SDL_CondBroadcast(ths->_condC);
			ths->_mtxC.unlock();
			// 親スレッドが子スレッド変数をセットするまで待つ
			SDL_CondWait(ths->_condP, ths->_mtxP.getMutex());
			ths->_mtxP.unlock();

			// この時点でスレッドのポインタは有効な筈
			tls_threadID = SDL_GetThreadID(ths->_thread);
			Stat stat;
			try {
				ths->_retVal = ths->run();
				stat = (ths->isInterrupted()) ? Interrupted_End : Finished;
			} catch(...) {
				ths->_eptr = std::current_exception();
				stat = Error_End;
			}
			SDL_AtomicSet(&ths->_atmStat, stat);
			// SDLの戻り値は使わない
			return 0;
		}
		protected:
			virtual RET run(Args...) = 0;
		public:
			Thread(const Thread& t) = delete;
			Thread& operator = (const Thread& t) = delete;
			Thread(): _thread(nullptr), _eptr(nullptr) {
				_condC = SDL_CreateCond();
				_condP = SDL_CreateCond();
				// 中断フラグに0をセット
				SDL_AtomicSet(&_atmInt, 0);
				SDL_AtomicSet(&_atmStat, Idle);
			}
			~Thread() {
				// スレッド実行中だったらエラーを出す
				Assert(!isRunning())
				SDL_DestroyCond(_condC);
				SDL_DestroyCond(_condP);
			}
			template <class... Args0>
			void start(Args0&&... args0) {
				// 2回以上呼ぶとエラー
				Assert(SDL_AtomicGet(&_atmStat) == Idle)
				SDL_AtomicSet(&_atmStat, Running);

				_mtxC.lock();
				// 一旦クラス内部に変数を参照で取っておく
				SDL_Thread* th = SDL_CreateThread(ThreadFunc, "", this);
				// 子スレッドが開始されるまで待つ
				SDL_CondWait(_condC, _mtxC.getMutex());
				_mtxC.unlock();

				_mtxP.lock();
				_thread = th;
				SDL_CondBroadcast(_condP);
				_mtxP.unlock();
			}
			Stat getStatus() {
				return static_cast<Stat>(SDL_AtomicGet(&_atmStat));
			}
			bool isRunning() {
				Stat stat = getStatus();
				return stat==Running || stat==Interrupted;
			}
			//! 中断を指示する
			bool interrupt() {
				auto ret = SDL_AtomicCAS(&_atmStat, Running, Interrupted);
				SDL_AtomicSet(&_atmInt, 1);
				SDLW_ACheck
				return ret == SDL_TRUE;
			}
			//! スレッド内部で中断指示がされているかを確認
			bool isInterrupted() {
				return SDL_AtomicGet(&_atmInt) == 1;
			}
			void join() {
				_mtxP.lock();
				if(_thread) {
					int ret;
					SDL_WaitThread(_thread, &ret);
					_thread = nullptr;
				}
				_mtxP.unlock();
			}
			bool try_join(uint32_t ms) {
				_mtxP.lock();
				int res = SDL_CondWaitTimeout(_condP, _mtxP.getMutex(), ms);
				_mtxP.unlock();
				SDLW_Check
				return res == 0;
			}
			const RET& getResult() {
				// まだスレッドが終了して無い時の為にjoinを呼ぶ
				join();
				return _retVal;
			}
	};

	class Window;
	using SPWindow = std::shared_ptr<Window>;
	class GLContext;
	using SPGLContext = std::shared_ptr<GLContext>;

	class Window {
		public:
			enum class Stat {
				Minimized,
				Maximized,
				Hidden,
				Fullscreen,
				Shown
			};
		private:
			SDL_Window*	_window;
			Stat		_stat;
			Window(SDL_Window* w);

			void _checkState();
		public:
			static SPWindow CreateWindow(const std::string& title, int w, int h, uint32_t flag=0);
			static SPWindow CreateWindow(const std::string& title, int x, int y, int w, int h, uint32_t flag=0);
			~Window();

			void setFullscreen(bool bFull);
			void setGrab(bool bGrab);
			void setMaximumSize(int w, int h);
			void setMinimumSize(int w, int h);
			void setSize(int w, int h);
			void setTitle(const std::string& title);
			void show(bool bShow);
			void maximize();
			void minimize();
			void restore();
			void setPosition(int x, int y);
			void raise();
			// for logging
			uint32_t getID() const;

			Stat getState() const;
			bool isGrabbed() const;
			bool isResizable() const;
			bool hasInputFocus() const;
			bool hasMouseFocus() const;
			uint32_t getSDLFlag() const;
			SDL_Window* getWindow() const;

			static void EnableScreenSaver(bool bEnable);
	};
	class GLContext {
		SPWindow		_spWindow;
		SDL_GLContext	_ctx;

		GLContext(const SPWindow& w);
		public:
			static SPGLContext CreateContext(const SPWindow& w);
			~GLContext();
			void makeCurrent(const SPWindow& w);
			void makeCurrent();
			void swapWindow();
			static int SetSwapInterval(int n);
	};
}
<|endoftext|>


<commit_before>#include "MyArea.h"
#include "figuras/Arco.h"
#include "figuras/Circulo.h"
#include "figuras/Elipse.h"
#include "figuras/Quadrado.h"
#include "figuras/Retangulo.h"
#include <cstdlib>
#include <ctime>
#include <iostream>

using namespace Gtk;
using namespace std;

MyArea::MyArea() {
    tempo = false;

    srand( time( NULL ) );

    add_events( Gdk::BUTTON_PRESS_MASK );

    int timeOutValue = 1000; // 1000 in ms (1.0 sec)
    sigc::slot<bool> mySlot = sigc::mem_fun( *this, &MyArea::on_timeout );
    Glib::signal_timeout().connect( mySlot, timeOutValue );
}

bool MyArea::on_timeout() {
    tempo = true;
    cout << "Tempo" << endl;
    queue_draw();
    return true;
}

MyArea::~MyArea() {
    cout << "Chamando destrutor" << '\n';
    for( Figura *figura : figuras ) {
        delete figura;
    }
}

Ponto MyArea::randPosition() const {
    Gtk::Allocation allocation = get_allocation();
    const int width = allocation.get_width();
    const int height = allocation.get_height();

    int x = rand() % width;
    int y = rand() % height;

    return Ponto( x, y );
}

bool MyArea::on_draw( const Cairo::RefPtr<Cairo::Context> &cr ) {
    for( vector<Figura *>::iterator it = figuras.begin(); it != figuras.end(); it++ ) {
        if( tempo ) {
            ( *it )->setPosition( randPosition() );
        }

        cr->save();

        ( *it )->draw( cr );

        cr->stroke();
        cr->restore();
    }
    tempo = false;
    return true;
}

int sortearTipoFigura( const int quantidadeDeTipo ) {
    return rand() % quantidadeDeTipo;
}

bool MyArea::on_button_press_event( GdkEventButton *event ) {
    cout << "Clicou" << '\n';
    if( ( event->type == GDK_BUTTON_PRESS ) && ( event->button == 1 ) ) {
        tipoFigura = sortearTipoFigura( 5 ); // 5 é qtd de tipos de figuras
        switch( tipoFigura ) {
            case 0:
                addFigura( new Circulo( event->x, event->y, 2 ) );
                break;
            case 1:
                addFigura( new Elipse( event->x, event->y, 2 ) );
                break;
            case 2:
                addFigura( new Quadrado( event->x, event->y, 2 ) );
                break;
            case 3:
                addFigura( new Retangulo( event->x, event->y, 1, 2 ) );
                break;
            case 4:
                addFigura( new Arco( event->x, event->y, 4 ) );
                break;
            default:
                cout << "Erro" << '\n';
        }
        queue_draw();
    }
    return true;
}

void MyArea::addFigura( Figura *figura ) {
    figuras.push_back( figura );
}
<commit_msg>Organização do código<commit_after>#include "MyArea.h"
#include "figuras/Arco.h"
#include "figuras/Circulo.h"
#include "figuras/Elipse.h"
#include "figuras/Quadrado.h"
#include "figuras/Retangulo.h"
#include <cstdlib>
#include <ctime>
#include <iostream>

using namespace Gtk;
using namespace std;

MyArea::MyArea() {
    tempo = false;
    int timeOutValue = 1000; // 1000 in ms (1.0 sec)

    srand( time( NULL ) );
    sigc::slot<bool> mySlot = sigc::mem_fun( *this, &MyArea::on_timeout );

    add_events( Gdk::BUTTON_PRESS_MASK );
    Glib::signal_timeout().connect( mySlot, timeOutValue );
}

bool MyArea::on_timeout() {
    tempo = true;
    cout << "Tempo" << endl;
    queue_draw();
    return true;
}

MyArea::~MyArea() {
    cout << "Chamando destrutor" << '\n';
    for( Figura *figura : figuras ) {
        delete figura;
    }
}

Ponto MyArea::randPosition() const {
    Gtk::Allocation allocation = get_allocation();
    const int width = allocation.get_width();
    const int height = allocation.get_height();

    int x = rand() % width;
    int y = rand() % height;

    return Ponto( x, y );
}

bool MyArea::on_draw( const Cairo::RefPtr<Cairo::Context> &cr ) {
    for( vector<Figura *>::iterator it = figuras.begin(); it != figuras.end(); it++ ) {
        if( tempo ) {
            ( *it )->setPosition( randPosition() );
        }

        cr->save();

        ( *it )->draw( cr );

        cr->stroke();
        cr->restore();
    }
    tempo = false;
    return true;
}

int sortearTipoFigura( const int quantidadeDeTipo ) {
    return rand() % quantidadeDeTipo;
}

bool MyArea::on_button_press_event( GdkEventButton *event ) {
    cout << "Clicou" << '\n';
    if( ( event->type == GDK_BUTTON_PRESS ) && ( event->button == 1 ) ) {
        tipoFigura = sortearTipoFigura( 5 ); // 5 é qtd de tipos de figuras
        switch( tipoFigura ) {
            case 0:
                addFigura( new Circulo( event->x, event->y, 2 ) );
                break;
            case 1:
                addFigura( new Elipse( event->x, event->y, 2 ) );
                break;
            case 2:
                addFigura( new Quadrado( event->x, event->y, 2 ) );
                break;
            case 3:
                addFigura( new Retangulo( event->x, event->y, 1, 2 ) );
                break;
            case 4:
                addFigura( new Arco( event->x, event->y, 4 ) );
                break;
            default:
                cout << "Erro" << '\n';
        }
        queue_draw();
    }
    return true;
}

void MyArea::addFigura( Figura *figura ) {
    figuras.push_back( figura );
}
<|endoftext|>


<commit_before>#include <Energia.h>
#include "inc/hw_gpio.h"
#include "driverlib/rom_map.h"
#include "driverlib/prcm.h"
#include "driverlib/interrupt.h"
#include "driverlib/systick.h"
#include <driverlib/utils.h>
#include "inc/hw_hib1p2.h"
#include "inc/hw_hib3p3.h"

extern void (* const g_pfnVectors[])(void);
extern void setup1();

extern void foo();

void MCUInit(void)
{

    unsigned long ulRegVal;

    //
    // DIG DCDC NFET SEL and COT mode disable
    //
    HWREG(0x4402F010) = 0x30031820;
    HWREG(0x4402F00C) = 0x04000000;

    UtilsDelay(32000);

    //
    // ANA DCDC clock config
    //
    HWREG(0x4402F11C) = 0x099;
    HWREG(0x4402F11C) = 0x0AA;
    HWREG(0x4402F11C) = 0x1AA;

    //
    // PA DCDC clock config
    //
    HWREG(0x4402F124) = 0x099;
    HWREG(0x4402F124) = 0x0AA;
    HWREG(0x4402F124) = 0x1AA;

    //
    // Enable RTC
    //
    if(MAP_PRCMSysResetCauseGet()== PRCM_POWER_ON)
    {
        HWREG(0x4402F804) = 0x1;
    }

    //
    // TD Flash timing configurations in case of MCU WDT reset
    //

    if((HWREG(0x4402D00C) & 0xFF) == 0x00000005)
    {
        HWREG(0x400F707C) |= 0x01840082;
        HWREG(0x400F70C4)= 0x1;
        HWREG(0x400F70C4)= 0x0;
    }

    //
    // JTAG override for I2C in SWD mode
    //
    if(((HWREG(0x4402F0C8) & 0xFF) == 0x2))
    {
        MAP_PinModeSet(PIN_19,PIN_MODE_2);
        MAP_PinModeSet(PIN_20,PIN_MODE_2);
        HWREG(0x4402E184) |= 0x1;
    }

    //
    // Enable uDMA
    //
    PRCMPeripheralClkEnable(PRCM_UDMA,PRCM_RUN_MODE_CLK);

    //
    // Reset uDMA
    //
    PRCMPeripheralReset(PRCM_UDMA);

    //
    // Disable uDMA
    //
    PRCMPeripheralClkDisable(PRCM_UDMA,PRCM_RUN_MODE_CLK);

}

int main(void)
{
	IntVTableBaseSet((unsigned long)&g_pfnVectors[0]);

	MAP_PRCMPeripheralClkEnable(PRCM_GPIOA0, PRCM_RUN_MODE_CLK);
	MAP_PRCMPeripheralClkEnable(PRCM_GPIOA1, PRCM_RUN_MODE_CLK);
	MAP_PRCMPeripheralClkEnable(PRCM_GPIOA2, PRCM_RUN_MODE_CLK);
	MAP_PRCMPeripheralClkEnable(PRCM_GPIOA3, PRCM_RUN_MODE_CLK);

	MAP_IntMasterEnable();
	MCUInit();
	MAP_SysTickIntEnable();
	MAP_SysTickPeriodSet(F_CPU / 1000);
	MAP_SysTickEnable();

	setup();

	for (;;) {
		loop();
		if (serialEventRun) serialEventRun();
	}
}
<commit_msg>Change CPU init to use driverlib internal func<commit_after>#include <Energia.h>
#include "inc/hw_gpio.h"
#include "driverlib/rom_map.h"
#include "driverlib/prcm.h"
#include "driverlib/interrupt.h"
#include "driverlib/systick.h"
#include <driverlib/utils.h>
#include "inc/hw_hib1p2.h"
#include "inc/hw_hib3p3.h"

extern void (* const g_pfnVectors[])(void);

int main(void)
{
	IntVTableBaseSet((unsigned long)&g_pfnVectors[0]);

	MAP_PRCMPeripheralClkEnable(PRCM_GPIOA0, PRCM_RUN_MODE_CLK);
	MAP_PRCMPeripheralClkEnable(PRCM_GPIOA1, PRCM_RUN_MODE_CLK);
	MAP_PRCMPeripheralClkEnable(PRCM_GPIOA2, PRCM_RUN_MODE_CLK);
	MAP_PRCMPeripheralClkEnable(PRCM_GPIOA3, PRCM_RUN_MODE_CLK);

	MAP_IntMasterEnable();
	PRCMCC3200MCUInit();
	MAP_SysTickIntEnable();
	MAP_SysTickPeriodSet(F_CPU / 1000);
	MAP_SysTickEnable();

	setup();

	for (;;) {
		loop();
		if (serialEventRun) serialEventRun();
	}
}
<|endoftext|>


<commit_before>/**
 * Copyright 2017 Shusheng Shao <iblackangel@163.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <mpl/mstring.h>

#ifdef _MSC_VER
# pragma warning (push)
# pragma warning (disable: 4996)
#endif

MPL_BEGIN_NAMESPACE

std::string toXString(const char *fmt, ...)
{
	std::string buffer;
	va_list vargs;
	va_start(vargs, fmt);
	int len = vsnprintf(NULL, 0, fmt, vargs);
	buffer.resize(len);
	va_start(vargs, fmt);
	vsnprintf(&buffer[0], len + 1, fmt, vargs);
	va_end(vargs);

	return buffer;
}

std::string hex2str(const uint8_t *data, size_t len)
{
	std::string buffer;
	char buf[3] = {0x00};
	for (size_t m = 0; m < len; ++m) {
		snprintf (buf, sizeof(buf), "%02X", data[m]);
		buf[2] = '\0';
		buffer += buf;
		buffer += " ";
	}

	if (buffer.size() > 0) {
		buffer.erase(buffer.begin() + (buffer.size() - 1));
	}
	return buffer;
}

std::string toString(int val)
{
	return toXString("%d", val);
}

std::string toString(unsigned val)
{
	return toXString("%u", val);
}

std::string toString(long val)
{
	return toXString("%ld", val);
}

std::string toString(unsigned long val)
{
	return toXString("%lu", val);
}

std::string toString(long long val)
{
	return toXString("%lld", val);
}

std::string toString(unsigned long long val)
{
	return toXString("%llu", val);
}

std::string toString(float val)
{
	return toXString("%f", val);
}

std::string toString(double val)
{
	return toXString("%f", val);
}

std::string toString(long double val)
{
	return toXString("%Lf", val);
}

std::string toUTF8(const std::string &str)
{
#if defined(_MSC_VER) || defined(M_OS_WIN)
	// convert GBK to Unicode
	int len = MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, NULL, 0);
	wchar_t *strUnicode = new wchar_t[len];
	wmemset(strUnicode, 0, len);
	MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, strUnicode, len);

	// convert Unicode to UTF-8
	len = WideCharToMultiByte(CP_UTF8, 0, strUnicode, -1, NULL, 0, NULL, NULL);
	char * strUtf8 = new char[len];
	WideCharToMultiByte(CP_UTF8, 0, strUnicode, -1, strUtf8, len, NULL, NULL);

	std::string strOut(strUtf8); // strTemp is encoding UTF-8
	delete[]strUnicode;
	delete[]strUtf8;
	strUnicode = NULL;
	strUtf8 = NULL;
	return strOut;
#else
	char *gbk = new char[str.size() + 1];
	size_t inbytes = str.size();
	strcpy(gbk, str.c_str());

	char *utf8 = new char[str.size() * 2 + 1]; // twice of gbk
	size_t outbytes = str.size() * 2;

	char *inptr = gbk;
	char *outptr = utf8;

	// iconv_open
	iconv_t cd = iconv_open("UTF-8", "GB18030");
	if (cd == (iconv_t)-1) {
		log_error("iconv_open failed: %s", error().c_str());
		delete gbk;
		delete utf8;
		return std::string();
	}

	// iconv
	size_t res = iconv(cd, &inptr, &inbytes, &outptr, &outbytes);
	if (res == -1) {
		log_error("iconv failed: %s", error().c_str());
		iconv_close(cd);
		delete gbk;
		delete utf8;
		return std::string();
	}

	// iconv_close
	std::string outstr = utf8;

	iconv_close(cd);
	delete gbk;
	delete utf8;
	return outstr;
#endif
}

std::string toGBK(const std::string &str)
{
#if defined(_MSC_VER) || defined(M_OS_WIN)
	// convert UTF-8 to Unicode
	int len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, NULL, 0);
	unsigned short *wszGBK = new unsigned short[len + 1];
	memset(wszGBK, 0, len * 2 + 2);
	MultiByteToWideChar(CP_UTF8, 0, (LPCTSTR)str.c_str(), -1, (LPWSTR)wszGBK, len);

	// convert UTF-8 to Unicode
	len = WideCharToMultiByte(CP_ACP, 0, (LPCWCH)wszGBK, -1, NULL, 0, NULL, NULL);
	char *szGBK = new char[len + 1];
	memset(szGBK, 0, len + 1);
	WideCharToMultiByte(CP_ACP, 0, (LPCWCH)wszGBK, -1, szGBK, len, NULL, NULL);
	std::string strTemp(szGBK);
	delete[]szGBK;
	delete[]wszGBK;
	return strTemp;
#else
	char *utf8 = new char[str.size() + 1];
	size_t inbytes = str.size();
	strcpy(utf8, str.c_str());

	char *gbk = new char[str.size() * 2 + 1]; // twice size
	size_t outbytes = str.size() * 2;

	char *inptr = utf8;
	char *outptr = gbk;

	// iconv_open
	iconv_t cd = iconv_open("GB18030", "UTF-8");
	if (cd == (iconv_t)-1) {
		log_error("iconv_open failed: %s", error().c_str());
		delete gbk;
		delete utf8;
		return std::string();
	}

	// iconv
	size_t res = iconv(cd, &inptr, &inbytes, &outptr, &outbytes);
	if (res == -1) {
		log_error("iconv failed: %s", error().c_str());
		iconv_close(cd);
		delete gbk;
		delete utf8;
		return std::string();
	}

	// iconv_close
	std::string outstr = gbk;

	iconv_close(cd);
	delete gbk;
	delete utf8;
	return outstr;
#endif
}

MString::MString()
{
}

MString::MString(const std::string &str)
	: std::string(str)
{
}

MString::MString(const char *s)
	: std::string(s)
{
}

MString::~MString()
{
}

std::string& MString::replace(char before, char after)
{
	size_type pos = rfind(before);
	while (pos != npos) {
		std::string::replace(pos, 1, 1, after);
		pos = rfind(before);
	}
	return *this;
}

std::string& MString::replace(const std::string &before, const std::string &after)
{
	size_type pos = rfind(before);
	while (pos != npos) {
		std::string::replace(pos, before.size(), after);
		pos = rfind(before);
	}
	return *this;
}

MPL_END_NAMESPACE

#ifdef _MSC_VER
# pragma warning (pop)
#endif
<commit_msg>update new revision<commit_after>/**
 * Copyright 2017 Shusheng Shao <iblackangel@163.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <mpl/mstring.h>

#ifdef _MSC_VER
# pragma warning (push)
# pragma warning (disable: 4996)
#endif

MPL_BEGIN_NAMESPACE

std::string toXString(const char *fmt, ...)
{
	std::string buffer;
	va_list vargs;
	va_start(vargs, fmt);
	int len = vsnprintf(NULL, 0, fmt, vargs);
	buffer.resize(len);
	va_start(vargs, fmt);
	vsnprintf(&buffer[0], len + 1, fmt, vargs);
	va_end(vargs);

	return buffer;
}

std::string hex2str(const uint8_t *data, size_t len)
{
	std::string buffer;
	char buf[3] = {0x00};
	for (size_t m = 0; m < len; ++m) {
		snprintf (buf, sizeof(buf), "%02X", data[m]);
		buf[2] = '\0';
		buffer += buf;
		buffer += " ";
	}

	if (buffer.size() > 0) {
		buffer.erase(buffer.begin() + (buffer.size() - 1));
	}
	return buffer;
}

std::string toString(int val)
{
	return toXString("%d", val);
}

std::string toString(unsigned val)
{
	return toXString("%u", val);
}

std::string toString(long val)
{
	return toXString("%ld", val);
}

std::string toString(unsigned long val)
{
	return toXString("%lu", val);
}

std::string toString(long long val)
{
	return toXString("%lld", val);
}

std::string toString(unsigned long long val)
{
	return toXString("%llu", val);
}

std::string toString(float val)
{
	return toXString("%f", val);
}

std::string toString(double val)
{
	return toXString("%f", val);
}

std::string toString(long double val)
{
	return toXString("%Lf", val);
}

std::string toUTF8(const std::string &str)
{
#if defined(_MSC_VER) || defined(M_OS_WIN)
	// convert GBK to Unicode
	int len = MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, NULL, 0);
	wchar_t *strUnicode = new wchar_t[len];
	wmemset(strUnicode, 0, len);
	MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, strUnicode, len);

	// convert Unicode to UTF-8
	len = WideCharToMultiByte(CP_UTF8, 0, strUnicode, -1, NULL, 0, NULL, NULL);
	char * strUtf8 = new char[len];
	WideCharToMultiByte(CP_UTF8, 0, strUnicode, -1, strUtf8, len, NULL, NULL);

	std::string strOut(strUtf8); // strTemp is encoding UTF-8
	delete[]strUnicode;
	delete[]strUtf8;
	strUnicode = NULL;
	strUtf8 = NULL;
	return strOut;
#elif defined(HAVE_ICONV_H)
	char *gbk = new char[str.size() + 1];
	size_t inbytes = str.size();
	strcpy(gbk, str.c_str());

	char *utf8 = new char[str.size() * 2 + 1]; // twice of gbk
	size_t outbytes = str.size() * 2;

	char *inptr = gbk;
	char *outptr = utf8;

	// iconv_open
	iconv_t cd = iconv_open("UTF-8", "GB18030");
	if (cd == (iconv_t)-1) {
		log_error("iconv_open failed: %s", error().c_str());
		delete gbk;
		delete utf8;
		return std::string();
	}

	// iconv
	size_t res = iconv(cd, &inptr, &inbytes, &outptr, &outbytes);
	if (res == -1) {
		log_error("iconv failed: %s", error().c_str());
		iconv_close(cd);
		delete gbk;
		delete utf8;
		return std::string();
	}

	// iconv_close
	std::string outstr = utf8;

	iconv_close(cd);
	delete gbk;
	delete utf8;
	return outstr;
#else
	return str;
#endif
}

std::string toGBK(const std::string &str)
{
#if defined(_MSC_VER) || defined(M_OS_WIN)
	// convert UTF-8 to Unicode
	int len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, NULL, 0);
	unsigned short *wszGBK = new unsigned short[len + 1];
	memset(wszGBK, 0, len * 2 + 2);
	MultiByteToWideChar(CP_UTF8, 0, (LPCTSTR)str.c_str(), -1, (LPWSTR)wszGBK, len);

	// convert UTF-8 to Unicode
	len = WideCharToMultiByte(CP_ACP, 0, (LPCWCH)wszGBK, -1, NULL, 0, NULL, NULL);
	char *szGBK = new char[len + 1];
	memset(szGBK, 0, len + 1);
	WideCharToMultiByte(CP_ACP, 0, (LPCWCH)wszGBK, -1, szGBK, len, NULL, NULL);
	std::string strTemp(szGBK);
	delete[]szGBK;
	delete[]wszGBK;
	return strTemp;
#elif defined(HAVE_ICONV_H)
	char *utf8 = new char[str.size() + 1];
	size_t inbytes = str.size();
	strcpy(utf8, str.c_str());

	char *gbk = new char[str.size() * 2 + 1]; // twice size
	size_t outbytes = str.size() * 2;

	char *inptr = utf8;
	char *outptr = gbk;

	// iconv_open
	iconv_t cd = iconv_open("GB18030", "UTF-8");
	if (cd == (iconv_t)-1) {
		log_error("iconv_open failed: %s", error().c_str());
		delete gbk;
		delete utf8;
		return std::string();
	}

	// iconv
	size_t res = iconv(cd, &inptr, &inbytes, &outptr, &outbytes);
	if (res == -1) {
		log_error("iconv failed: %s", error().c_str());
		iconv_close(cd);
		delete gbk;
		delete utf8;
		return std::string();
	}

	// iconv_close
	std::string outstr = gbk;

	iconv_close(cd);
	delete gbk;
	delete utf8;
	return outstr;
#else
	return str;
#endif
}

MString::MString()
{
}

MString::MString(const std::string &str)
	: std::string(str)
{
}

MString::MString(const char *s)
	: std::string(s)
{
}

MString::~MString()
{
}

std::string& MString::replace(char before, char after)
{
	size_type pos = rfind(before);
	while (pos != npos) {
		std::string::replace(pos, 1, 1, after);
		pos = rfind(before);
	}
	return *this;
}

std::string& MString::replace(const std::string &before, const std::string &after)
{
	size_type pos = rfind(before);
	while (pos != npos) {
		std::string::replace(pos, before.size(), after);
		pos = rfind(before);
	}
	return *this;
}

MPL_END_NAMESPACE

#ifdef _MSC_VER
# pragma warning (pop)
#endif
<|endoftext|>


<commit_before>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "VTKOutput.h"

#include "libmesh/vtk_io.h"
#include "libmesh/equation_systems.h"

#ifdef LIBMESH_HAVE_VTK
registerMooseObjectAliased("MooseApp", VTKOutput, "VTK");
#endif

template <>
InputParameters
validParams<VTKOutput>()
{
  InputParameters params = validParams<OversampleOutput>();

  // Set default padding to 3
  params.set<unsigned int>("padding") = 3;

  // Add binary toggle
  params.addParam<bool>("binary", false, "Set VTK files to output in binary format");
  params.addParamNamesToGroup("binary", "Advanced");

  return params;
}

VTKOutput::VTKOutput(const InputParameters & parameters)
  : OversampleOutput(parameters), _binary(getParam<bool>("binary"))
{
}

void
VTKOutput::output(const ExecFlagType & /*type*/)
{
#ifdef LIBMESH_HAVE_VTK
  /// Create VTKIO object
  VTKIO vtk(_es_ptr->get_mesh());

  // Set the comppression
  vtk.set_compression(_binary);

  // Write the data
  vtk.write_equation_systems(filename(), *_es_ptr);
  _file_num++;
#else
  mooseError("libMesh not configured with VTK");
#endif
}

std::string
VTKOutput::filename()
{
  // Append the .e extension on the base file name
  std::ostringstream output;
  output << _file_base;

  // In serial, add the _00x.vtk extension.
  // In parallel, add the _00x.pvtu extension.
  std::string ext = (n_processors() == 1) ? ".vtk" : ".pvtu";
  output << "_" << std::setw(_padding) << std::setfill('0') << std::right << _file_num << ext;

  // Return the filename
  return output.str();
}
<commit_msg>Registered VTK even if LIBMESH_HAVE_VTK is false<commit_after>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "VTKOutput.h"

#include "libmesh/vtk_io.h"
#include "libmesh/equation_systems.h"

registerMooseObjectAliased("MooseApp", VTKOutput, "VTK");

template <>
InputParameters
validParams<VTKOutput>()
{
  InputParameters params = validParams<OversampleOutput>();

  // Set default padding to 3
  params.set<unsigned int>("padding") = 3;

  // Add binary toggle
  params.addParam<bool>("binary", false, "Set VTK files to output in binary format");
  params.addParamNamesToGroup("binary", "Advanced");

  return params;
}

VTKOutput::VTKOutput(const InputParameters & parameters)
  : OversampleOutput(parameters), _binary(getParam<bool>("binary"))
{
#ifndef LIBMESH_HAVE_VTK
  mooseError("VTK output was requested, but libMesh was not configured with VTK. To fix this, you "
             "must reconfigure libMesh to use VTK.");
#endif
}

void
VTKOutput::output(const ExecFlagType & /*type*/)
{
#ifdef LIBMESH_HAVE_VTK
  /// Create VTKIO object
  VTKIO vtk(_es_ptr->get_mesh());

  // Set the comppression
  vtk.set_compression(_binary);

  // Write the data
  vtk.write_equation_systems(filename(), *_es_ptr);
  _file_num++;
#endif
}

std::string
VTKOutput::filename()
{
  // Append the .e extension on the base file name
  std::ostringstream output;
  output << _file_base;

  // In serial, add the _00x.vtk extension.
  // In parallel, add the _00x.pvtu extension.
  std::string ext = (n_processors() == 1) ? ".vtk" : ".pvtu";
  output << "_" << std::setw(_padding) << std::setfill('0') << std::right << _file_num << ext;

  // Return the filename
  return output.str();
}
<|endoftext|>


<commit_before>#include <kernel/ext2.h>
#include <kernel/ata.h>
#include <kernel/panic.h>

Ext2::Ext2(Pager *pager, uint32_t lba) : pager(pager), lba(lba) {
	ata_pio_read(lba + 1024 / 512, 2, &this->superblock);
	if(this->superblock.base.signature != SUPERBLOCK_SIGNATURE) {
		kernel_panic("invalid ext2 superblock signature");
	}
}

uint32_t Ext2::GetBlockSize(void) {
	return 1024u << this->superblock.base.block_shift;
}

uint32_t Ext2::GetBlockAddr(uint32_t block_id) {
	return block_id * this->GetBlockSize();
}

uint32_t Ext2::GetInodeAddr(uint32_t inode_id) {
	uint32_t group_id = (inode_id - 1) / this->superblock.base.group_inode_count;
	GroupDesc gd = this->GetGroupDesc(group_id);
	uint32_t index = (inode_id - 1) % this->superblock.base.group_inode_count;
	return gd.inode_table_addr * this->GetBlockSize() + index * sizeof(Inode);
}

uint32_t Ext2::GetGroupDescAddr(uint32_t group_id) {
	uint32_t block_id = this->superblock.base.superblock_id + 1;
	return this->GetBlockAddr(block_id) + group_id * sizeof(GroupDesc);
}
#include <kernel/itoa.h>
uint32_t Ext2::GetInodeBlockAddr(Inode inode, uint32_t block_ptr_id) {
	uint32_t block_size = this->GetBlockSize();
	uint32_t block_num_ptrs = block_size / sizeof(uint32_t);
	uint32_t block_addr;

	if(block_ptr_id < 12) {
		block_addr = this->GetBlockAddr(inode.block_ptr[block_ptr_id]);
	} else if(block_ptr_id < 12 + block_num_ptrs) {
		uint32_t singly_addr = this->GetBlockAddr(inode.block_ptr_singly);
		uint32_t singly_offset = (block_ptr_id - 12) * sizeof(uint32_t);
		ata_pio_read_bytes(this->lba * 512 + singly_addr + singly_offset, &block_addr);
	} else {
		kernel_panic("doubly indirect ptrs not implemented yet");
	}

	return block_addr;
}

Ext2::GroupDesc Ext2::GetGroupDesc(uint32_t group_id) {
	uint32_t offset = this->GetGroupDescAddr(group_id);
	GroupDesc gd;
	ata_pio_read_bytes(this->lba * 512 + offset, &gd);
	return gd;
}

Maybe<Ext2::Inode> Ext2::GetInode(uint32_t inode_id) {
	uint32_t inode_addr = this->GetInodeAddr(inode_id);
	Inode inode;
	ata_pio_read_bytes(this->lba * 512 + inode_addr, &inode);
	return Maybe<Inode>(inode);
}

Maybe<Ext2::Inode> Ext2::GetInode(Inode &pwd, const char *name) {
	// XXX: this assumes all dir entries will fit in a single block, which is bad
	auto mDirent = this->GetDirectoryEntry(pwd.block_ptr[0], name);
	if(mDirent.IsNothing()) {
		return Maybe<Inode>();
	} else {
		return this->GetInode(mDirent.FromJust().inode_id);
	}
}

Maybe<Ext2::Inode> Ext2::GetInode(size_t count, const char *paths[]) {
	auto mRoot = this->GetInode(ROOT_INODE);
	if(mRoot.IsNothing()) { return Maybe<Inode>(); }

	Inode ref = mRoot.FromJust();

	for(size_t i = 0; i < count; ++i) {
		auto mRef = this->GetInode(ref, paths[i]);
		if(mRef.IsNothing()) { return Maybe<Inode>(); }
		ref = mRef.FromJust();
	}

	return ref;
}

Maybe<Ext2::DirectoryEntry> Ext2::GetDirectoryEntry(uint32_t block_id, const char *name) {
	uint32_t block_size = this->GetBlockSize();
	uint32_t block_addr = this->GetBlockAddr(block_id);

	// XXX: this assumes a block is 1024 bytes, which is very bad if it's not
	char buffer[1024];
	ata_pio_read(this->lba + block_addr / 512, 2, &buffer);

	DirectoryEntry *dirent;
	for(size_t offset = 0; offset < block_size; offset += dirent->size) {
		dirent = reinterpret_cast<DirectoryEntry *>(&buffer[offset]);
		if(dirent->inode_id == 0) { break; }

		bool match = true;
		for(size_t n = 0; n < dirent->len; ++n) {
			if(buffer[offset + sizeof(DirectoryEntry) + n] != name[n]) {
				match = false;
				break;
			}
		}
		if(match) {
			return Maybe<DirectoryEntry>(*dirent);
		}
	}
	return Maybe<DirectoryEntry>();
}

#include <kernel/screen.h>
void Ext2::ReadInode(Inode inode, uint32_t offset, size_t count, char *ptr) {
	uint32_t block_size = this->GetBlockSize();
	size_t offset_end = offset + count;
	size_t block_ptr_begin = offset / block_size;
	size_t block_ptr_end = offset_end / block_size + (offset_end % block_size != 0) + 1;

	size_t n = 0;
	size_t off = offset % block_size;

	for(size_t b = block_ptr_begin; b < block_ptr_end; ++b) {
		uint32_t block_ptr = this->GetInodeBlockAddr(inode, b);
		char buffer[1024]; // XXX: assuming block size is 1024 again
		ata_pio_read(this->lba + block_ptr / 512, block_size / 512, &buffer);
		while(off < block_size && n < count) {
			ptr[n++] = buffer[off++];
		}
		off = 0;
	}
}
<commit_msg>Fix ext2 block index=>id lookups<commit_after>#include <kernel/ext2.h>
#include <kernel/ata.h>
#include <kernel/panic.h>

Ext2::Ext2(Pager *pager, uint32_t lba) : pager(pager), lba(lba) {
	ata_pio_read(lba + 1024 / 512, 2, &this->superblock);
	if(this->superblock.base.signature != SUPERBLOCK_SIGNATURE) {
		kernel_panic("invalid ext2 superblock signature");
	}
}

uint32_t Ext2::GetBlockSize(void) {
	return 1024u << this->superblock.base.block_shift;
}

uint32_t Ext2::GetBlockAddr(uint32_t block_id) {
	return block_id * this->GetBlockSize();
}

uint32_t Ext2::GetInodeAddr(uint32_t inode_id) {
	uint32_t group_id = (inode_id - 1) / this->superblock.base.group_inode_count;
	GroupDesc gd = this->GetGroupDesc(group_id);
	uint32_t index = (inode_id - 1) % this->superblock.base.group_inode_count;
	return gd.inode_table_addr * this->GetBlockSize() + index * sizeof(Inode);
}

uint32_t Ext2::GetGroupDescAddr(uint32_t group_id) {
	uint32_t block_id = this->superblock.base.superblock_id + 1;
	return this->GetBlockAddr(block_id) + group_id * sizeof(GroupDesc);
}

uint32_t Ext2::GetInodeBlockAddr(Inode inode, uint32_t block_index) {
	uint32_t block_size = this->GetBlockSize();
	uint32_t block_num_ptrs = block_size / sizeof(uint32_t);
	uint32_t block_id;

	if(block_index < 12) {
		block_id = inode.block_ptr[block_index];
	} else if(block_index - 12 < block_num_ptrs) {
		uint32_t addr = this->GetBlockAddr(inode.block_ptr_singly);
		uint32_t offset = (block_index - 12) * sizeof(uint32_t);
		ata_pio_read_bytes(this->lba * 512 + addr + offset, &block_id);
	} else {
		kernel_panic("doubly indirect ptrs not implemented yet");
	}

	return this->GetBlockAddr(block_id);
}

Ext2::GroupDesc Ext2::GetGroupDesc(uint32_t group_id) {
	uint32_t offset = this->GetGroupDescAddr(group_id);
	GroupDesc gd;
	ata_pio_read_bytes(this->lba * 512 + offset, &gd);
	return gd;
}

Maybe<Ext2::Inode> Ext2::GetInode(uint32_t inode_id) {
	uint32_t inode_addr = this->GetInodeAddr(inode_id);
	Inode inode;
	ata_pio_read_bytes(this->lba * 512 + inode_addr, &inode);
	return Maybe<Inode>(inode);
}

Maybe<Ext2::Inode> Ext2::GetInode(Inode &pwd, const char *name) {
	// XXX: this assumes all dir entries will fit in a single block, which is bad
	auto mDirent = this->GetDirectoryEntry(pwd.block_ptr[0], name);
	if(mDirent.IsNothing()) {
		return Maybe<Inode>();
	} else {
		return this->GetInode(mDirent.FromJust().inode_id);
	}
}

Maybe<Ext2::Inode> Ext2::GetInode(size_t count, const char *paths[]) {
	auto mRoot = this->GetInode(ROOT_INODE);
	if(mRoot.IsNothing()) { return Maybe<Inode>(); }

	Inode ref = mRoot.FromJust();

	for(size_t i = 0; i < count; ++i) {
		auto mRef = this->GetInode(ref, paths[i]);
		if(mRef.IsNothing()) { return Maybe<Inode>(); }
		ref = mRef.FromJust();
	}

	return ref;
}

Maybe<Ext2::DirectoryEntry> Ext2::GetDirectoryEntry(uint32_t block_id, const char *name) {
	uint32_t block_size = this->GetBlockSize();
	uint32_t block_addr = this->GetBlockAddr(block_id);

	// XXX: this assumes a block is 1024 bytes, which is very bad if it's not
	char buffer[1024];
	ata_pio_read(this->lba + block_addr / 512, 2, &buffer);

	DirectoryEntry *dirent;
	for(size_t offset = 0; offset < block_size; offset += dirent->size) {
		dirent = reinterpret_cast<DirectoryEntry *>(&buffer[offset]);
		if(dirent->inode_id == 0) { break; }

		bool match = true;
		for(size_t n = 0; n < dirent->len; ++n) {
			if(buffer[offset + sizeof(DirectoryEntry) + n] != name[n]) {
				match = false;
				break;
			}
		}
		if(match) {
			return Maybe<DirectoryEntry>(*dirent);
		}
	}
	return Maybe<DirectoryEntry>();
}

void Ext2::ReadInode(Inode inode, uint32_t offset, size_t count, char *ptr) {
	uint32_t block_size = this->GetBlockSize();
	size_t offset_end = offset + count;
	size_t block_ptr_begin = offset / block_size;
	size_t block_ptr_end = offset_end / block_size + (offset_end % block_size != 0) + 1;

	size_t n = 0;
	size_t off = offset % block_size;

	for(size_t b = block_ptr_begin; b < block_ptr_end; ++b) {
		uint32_t block_ptr = this->GetInodeBlockAddr(inode, b);

		char buffer[1024]; // XXX: assuming block size is 1024 again
		ata_pio_read(this->lba + block_ptr / 512, block_size / 512, &buffer);
		while(off < block_size && n < count) {
			ptr[n++] = buffer[off++];
		}
		off = 0;
	}
}
<|endoftext|>