<commit_before>/******************************************************************************\
* File:          lexers.cpp
* Purpose:       Implementation of wxExLexers classes
* Author:        Anton van Wezenbeek
* RCS-ID:        $Id$
*
* Copyright (c) 2008-2009 Anton van Wezenbeek
* All rights are reserved. Reproduction in whole or part is prohibited
* without the written consent of the copyright owner.
\******************************************************************************/

#include <wx/config.h>
#include <wx/stdpaths.h>
#include <wx/tokenzr.h>
#include <wx/stc/stc.h>
#include <wx/textfile.h>
#include <wx/extension/lexers.h>
#include <wx/extension/frd.h>
#include <wx/extension/util.h> // for wxExMatchesOneOf

wxExLexers* wxExLexers::m_Self = NULL;

wxExLexers::wxExLexers(const wxFileName& filename)
  : m_FileName(filename)
{
}

const wxString wxExLexers::ApplyMacro(const wxString& text) const
{
  if (text.IsNumber() || text.Contains(","))
  {
    return text;
  }

  std::map<wxString, wxString>::const_iterator it = m_Macros.find(text);

  if (it != m_Macros.end())
  {
    return it->second;
  }
  else
  {
    wxLogError(_("Undefined macro: %s"), text.c_str());
    return text;
  }
}

const wxString wxExLexers::BuildWildCards(const wxFileName& filename) const
{
  const wxString allfiles_wildcard =
    _("All Files") + wxString::Format(" (%s)|%s",
      wxFileSelectorDefaultWildcardStr,
      wxFileSelectorDefaultWildcardStr);

  wxString wildcards = allfiles_wildcard;

  // Build the wildcard string using all available lexers.
  for (
    std::map<wxString, wxExLexer>::const_iterator it = m_Lexers.begin();
    it != m_Lexers.end();
    ++it)
  {
    if (!it->second.m_Extensions.empty())
    {
      const wxString wildcard =
        it->second.GetScintillaLexer() +
        " (" + it->second.m_Extensions + ") |" +
        it->second.m_Extensions;

      if (wxExMatchesOneOf(filename, it->second.m_Extensions))
      {
        wildcards = wildcard + "|" + wildcards;
      }
      else
      {
        wildcards = wildcards + "|" + wildcard;
      }
    }
  }

  return wildcards;
}

const wxExLexer wxExLexers::FindByFileName(const wxFileName& filename) const
{
  if (!filename.IsOk())
  {
    return wxExLexer();
  }

  for (
    std::map<wxString, wxExLexer>::const_iterator it = m_Lexers.begin();
    it != m_Lexers.end();
    ++it)
  {
    if (wxExMatchesOneOf(filename, it->second.m_Extensions))
    {
      return it->second;
    }
  }

  return wxExLexer();
}

const wxExLexer wxExLexers::FindByName(
  const wxString& name,
  bool fail_if_not_found) const
{
  std::map<wxString, wxExLexer>::const_iterator it = m_Lexers.find(name);

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

  if (!m_Lexers.empty() && fail_if_not_found)
  {
    wxFAIL;
  }

  return wxExLexer();
}

const wxExLexer wxExLexers::FindByText(const wxString& text) const
{
  // Add automatic lexers if text starts with some special tokens.
  const wxString text_lowercase = text.Lower();

  if (text_lowercase.StartsWith("#") ||
      // .po files that do not have comment headers, start with msgid, so set them
      text_lowercase.StartsWith("msgid"))
  {
    return FindByName("bash", false); // don't show error
  }
  else if (text_lowercase.StartsWith("<html>") ||
           text_lowercase.StartsWith("<?php"))
  {
    return FindByName("hypertext", false); // don't show error
  }
  else if (text_lowercase.StartsWith("<?xml"))
  {
    return FindByName("xml", false); // don't show error
  }
  // cpp files like #include <map> really do not have a .h extension (e.g. /usr/include/c++/3.3.5/map)
  // so add here.
  else if (text_lowercase.StartsWith("//"))
  {
    return FindByName("cpp", false); // don't show error
  }

  return wxExLexer();
}

wxExLexers* wxExLexers::Get(bool createOnDemand)
{
  if (m_Self == NULL && createOnDemand)
  {
    m_Self = new wxExLexers(wxFileName(
#ifdef wxExUSE_PORTABLE
      wxPathOnly(wxStandardPaths::Get().GetExecutablePath())
#else
      wxStandardPaths::Get().GetUserDataDir()
#endif
      + wxFileName::GetPathSeparator() + "lexers.xml")
    );

    m_Self->Read();
  }

  return m_Self;
}

const wxString wxExLexers::GetLexerExtensions() const
{
  wxString text;

  for (
    std::map<wxString, wxExLexer>::const_iterator it = m_Lexers.begin();
    it != m_Lexers.end();
    ++it)
  {
    if (!it->second.m_Extensions.empty() &&
         it->second.m_Extensions != "*." + it->second.m_ScintillaLexer)
    {
      if (!text.empty())
      {
        text += wxExFindReplaceData::Get()->GetFieldSeparator();
      }

      text += it->second.m_Extensions;
    }
  }

  return text;
}

const wxString wxExLexers::ParseTagColourings(const wxXmlNode* node) const
{
  wxString text;

  wxXmlNode* child = node->GetChildren();

  while (child)
  {
    if (child->GetName() == "colouring")
    {
      wxString content = child->GetNodeContent().Strip(wxString::both);

      std::map<wxString, wxString>::const_iterator it = m_Macros.find(content);

      if (it != m_Macros.end())
      {
        content = it->second;
      }

      text +=
        ApplyMacro(
          child->GetAttribute("no", "0"))
        + "=" + content + wxTextFile::GetEOL();
    }
    else if (child->GetName() == "comment")
    {
      // Ignore comments.
    }
    else
    {
      wxLogError(_("Undefined colourings tag: %s on: %d"),
        child->GetName().c_str(), child->GetLineNumber());
    }

    child = child->GetNext();
  }

  return text;
}

void wxExLexers::ParseTagGlobal(const wxXmlNode* node)
{
  wxXmlNode* child = node->GetChildren();

  while (child)
  {
    if (child->GetName() == "comment")
    {
      // Ignore comments.
    }
    else if (child->GetName() == "hex")
    {
      m_StylesHex.push_back(
        ApplyMacro(child->GetAttribute("no", "0")) + "=" +
        child->GetNodeContent().Strip(wxString::both));
    }
    else if (child->GetName() == "indicator")
    {
      m_Indicators.insert(std::make_pair(
        atoi(ApplyMacro(child->GetAttribute("no", "0")).c_str()),
        atoi(child->GetNodeContent().Strip(wxString::both).c_str())));
    }
    else if (child->GetName() == "marker")
    {
      const wxExMarker marker(ParseTagMarker(
        ApplyMacro(child->GetAttribute("no", "0")),
        child->GetNodeContent().Strip(wxString::both)));

      if (marker.GetMarkerNumber() < wxSTC_STYLE_MAX &&
          marker.GetMarkerSymbol() < wxSTC_STYLE_MAX)
      {
        m_Markers.push_back(marker);
      }
      else
      {
        wxLogError(_("Illegal marker number: %d or symbol: %d on: %d"),
          marker.GetMarkerNumber(),
          marker.GetMarkerSymbol(),
          child->GetLineNumber());
      }
    }
    else if (child->GetName() == "properties")
    {
      m_GlobalProperties = ParseTagProperties(child);
    }
    else if (child->GetName() == "style")
    {
      const wxString attrib = ApplyMacro(child->GetAttribute("no", "0"));
      const wxString content = child->GetNodeContent().Strip(wxString::both);
      int attrib_no = atoi(attrib.c_str());

      if (attrib_no == wxSTC_STYLE_DEFAULT)
      {
        m_DefaultStyle = attrib + "=" + content;
      }
      else
      {
        m_Styles.push_back(attrib + "=" + content);
      }
    }
    else
    {
      wxLogError(_("Undefined global tag: %s on: %d"),
        child->GetName().c_str(), child->GetLineNumber());
    }

    child = child->GetNext();
  }
}

const wxExLexer wxExLexers::ParseTagLexer(const wxXmlNode* node) const
{
  wxExLexer lexer(node->GetAttribute("name", ""));
  lexer.m_Extensions = node->GetAttribute(
    "extensions",
    "*." + lexer.m_ScintillaLexer);

  wxXmlNode *child = node->GetChildren();

  while (child)
  {
    if (child->GetName() == "colourings")
    {
      lexer.m_Colourings = ParseTagColourings(child);
    }
    else if (child->GetName() == "keywords")
    {
      if (!lexer.SetKeywords(child->GetNodeContent().Strip(wxString::both)))
      {
        wxLogError(_("Keywords could not be set on: %d"), child->GetLineNumber());
      }
    }
    else if (child->GetName() == "properties")
    {
      lexer.m_Properties = ParseTagProperties(child);
    }
    else if (child->GetName() == "comments")
    {
      lexer.m_CommentBegin = child->GetAttribute("begin1", "");
      lexer.m_CommentEnd = child->GetAttribute("end1", "");
      lexer.m_CommentBegin2 = child->GetAttribute("begin2", "");
      lexer.m_CommentEnd2 = child->GetAttribute("end2", "");
    }
    else if (child->GetName() == "comment")
    {
      // Ignore comments.
    }
    else
    {
      wxLogError(_("Undefined lexer tag: %s on: %d"),
        child->GetName().c_str(), child->GetLineNumber());
    }

    child = child->GetNext();
  }

  return lexer;
}

void wxExLexers::ParseTagMacro(const wxXmlNode* node)
{
  wxXmlNode* child = node->GetChildren();

  while (child)
  {
    if (child->GetName() == "comment")
    {
      // Ignore comments.
    }
    else if (child->GetName() == "def")
    {
      const wxString attrib = child->GetAttribute("no", "0");
      const wxString content = child->GetNodeContent().Strip(wxString::both);
      m_Macros[attrib] = content;
    }
    else
    {
      wxLogError(_("Undefined macro tag: %s on: %d"),
        child->GetName().c_str(), child->GetLineNumber());
    }

    child = child->GetNext();
  }
}

const wxExMarker wxExLexers::ParseTagMarker(
  const wxString& number,
  const wxString& props) const
{
  wxStringTokenizer prop_fields(props, ",");

  const wxString symbol = ApplyMacro(prop_fields.GetNextToken());

  wxColour foreground;
  wxColour background;

  if (prop_fields.HasMoreTokens())
  {
    foreground = ApplyMacro(
      prop_fields.GetNextToken().Strip(wxString::both));

    if (prop_fields.HasMoreTokens())
    {
      background = ApplyMacro(
        prop_fields.GetNextToken().Strip(wxString::both));
    }
  }

  const int no = atoi(number.c_str());
  const int symbol_no = atoi(symbol.c_str());

  if (no <= wxSTC_MARKER_MAX && symbol_no <= wxSTC_MARKER_MAX)
  {
    return wxExMarker(no, symbol_no, foreground, background);
  }
  else
  {
    wxLogError(_("Illegal marker number: %d or symbol: %d"), no, symbol_no);
    return wxExMarker(0, 0, foreground, background);
  }
}

const wxString wxExLexers::ParseTagProperties(const wxXmlNode* node) const
{
  wxString text;

  wxXmlNode *child = node->GetChildren();

  while (child)
  {
    if (child->GetName() == "property")
    {
      text +=
        child->GetAttribute("name", "0") + "=" +
        child->GetNodeContent().Strip(wxString::both) + wxTextFile::GetEOL();
    }
    else if (child->GetName() == "comment")
    {
      // Ignore comments.
    }
    else
    {
      wxLogError(_("Undefined properties tag: %s on %d"),
        child->GetName().c_str(), child->GetLineNumber());
    }

    child = child->GetNext();
  }

  return text;
}

void wxExLexers::Read()
{
  // This test is to prevent showing an error if the lexers file does not exist,
  // as this is not required.
  if (!m_FileName.FileExists())
  {
    return;
  }

  wxXmlDocument doc;

  if (!doc.Load(m_FileName.GetFullPath()))
  {
    return;
  }

  // Initialize members.
  m_Indicators.clear();
  m_Lexers.clear();
  m_Markers.clear();
  m_SortedLexerNames.clear();
  m_Styles.clear();
  m_StylesHex.clear();

  wxXmlNode* child = doc.GetRoot()->GetChildren();

  while (child)
  {
    if (child->GetName() == "macro")
    {
      ParseTagMacro(child);
    }
    else if (child->GetName() == "global")
    {
      ParseTagGlobal(child);
    }
    else if (child->GetName() == "lexer")
    {
      const wxExLexer& lexer = ParseTagLexer(child);

      if (!lexer.GetScintillaLexer().empty())
      {
        if (lexer.GetScintillaLexer() == "hypertext")
        {
          // As our lexers.xml files cannot use xml comments,
          // add them here.
          wxExLexer l(lexer);
          l.m_CommentBegin = "<!--";
          l.m_CommentEnd = "-->";
          m_Lexers.insert(std::make_pair(lexer.GetScintillaLexer(), l));
        }
        else
        {
          m_Lexers.insert(std::make_pair(lexer.GetScintillaLexer(), lexer));
          m_SortedLexerNames.Add(lexer.GetScintillaLexer());
        }
      }
    }

    child = child->GetNext();
  }

  // Add the <none> lexer.
  m_SortedLexerNames.Add(_("<none>"));

  if (!wxConfigBase::Get()->Exists(_("In files")))
  {
    wxConfigBase::Get()->Write(_("In files"), GetLexerExtensions());
  }

  if (!wxConfigBase::Get()->Exists(_("Add what")))
  {
    wxConfigBase::Get()->Write(_("Add what"), GetLexerExtensions());
  }
}

wxExLexers* wxExLexers::Set(wxExLexers* lexers)
{
  wxExLexers* old = m_Self;
  m_Self = lexers;
  return old;
}

bool wxExLexers::ShowDialog(
  wxWindow* parent,
  wxString& lexer,
  const wxString& caption) const
{
  wxSingleChoiceDialog dlg(
    parent,
    _("Input") + ":",
    caption,
    m_SortedLexerNames);

  dlg.SetSelection(lexer.empty() ?
    m_SortedLexerNames.Index(_("<none>")):
    m_SortedLexerNames.Index(lexer));

  if (dlg.ShowModal() == wxID_CANCEL)
  {
    return false;
  }

  lexer = (dlg.GetSelection() == m_SortedLexerNames.Index(_("<none>")) ?
    wxEmptyString:
    FindByName(dlg.GetStringSelection()).GetScintillaLexer());

  return true;
}
<commit_msg>give error if macro already exists<commit_after>/******************************************************************************\
* File:          lexers.cpp
* Purpose:       Implementation of wxExLexers classes
* Author:        Anton van Wezenbeek
* RCS-ID:        $Id$
*
* Copyright (c) 2008-2009 Anton van Wezenbeek
* All rights are reserved. Reproduction in whole or part is prohibited
* without the written consent of the copyright owner.
\******************************************************************************/

#include <wx/config.h>
#include <wx/stdpaths.h>
#include <wx/tokenzr.h>
#include <wx/stc/stc.h>
#include <wx/textfile.h>
#include <wx/extension/lexers.h>
#include <wx/extension/frd.h>
#include <wx/extension/util.h> // for wxExMatchesOneOf

wxExLexers* wxExLexers::m_Self = NULL;

wxExLexers::wxExLexers(const wxFileName& filename)
  : m_FileName(filename)
{
}

const wxString wxExLexers::ApplyMacro(const wxString& text) const
{
  if (text.IsNumber() || text.Contains(","))
  {
    return text;
  }

  std::map<wxString, wxString>::const_iterator it = m_Macros.find(text);

  if (it != m_Macros.end())
  {
    return it->second;
  }
  else
  {
    wxLogError(_("Undefined macro: %s"), text.c_str());
    return text;
  }
}

const wxString wxExLexers::BuildWildCards(const wxFileName& filename) const
{
  const wxString allfiles_wildcard =
    _("All Files") + wxString::Format(" (%s)|%s",
      wxFileSelectorDefaultWildcardStr,
      wxFileSelectorDefaultWildcardStr);

  wxString wildcards = allfiles_wildcard;

  // Build the wildcard string using all available lexers.
  for (
    std::map<wxString, wxExLexer>::const_iterator it = m_Lexers.begin();
    it != m_Lexers.end();
    ++it)
  {
    if (!it->second.m_Extensions.empty())
    {
      const wxString wildcard =
        it->second.GetScintillaLexer() +
        " (" + it->second.m_Extensions + ") |" +
        it->second.m_Extensions;

      if (wxExMatchesOneOf(filename, it->second.m_Extensions))
      {
        wildcards = wildcard + "|" + wildcards;
      }
      else
      {
        wildcards = wildcards + "|" + wildcard;
      }
    }
  }

  return wildcards;
}

const wxExLexer wxExLexers::FindByFileName(const wxFileName& filename) const
{
  if (!filename.IsOk())
  {
    return wxExLexer();
  }

  for (
    std::map<wxString, wxExLexer>::const_iterator it = m_Lexers.begin();
    it != m_Lexers.end();
    ++it)
  {
    if (wxExMatchesOneOf(filename, it->second.m_Extensions))
    {
      return it->second;
    }
  }

  return wxExLexer();
}

const wxExLexer wxExLexers::FindByName(
  const wxString& name,
  bool fail_if_not_found) const
{
  std::map<wxString, wxExLexer>::const_iterator it = m_Lexers.find(name);

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

  if (!m_Lexers.empty() && fail_if_not_found)
  {
    wxFAIL;
  }

  return wxExLexer();
}

const wxExLexer wxExLexers::FindByText(const wxString& text) const
{
  // Add automatic lexers if text starts with some special tokens.
  const wxString text_lowercase = text.Lower();

  if (text_lowercase.StartsWith("#") ||
      // .po files that do not have comment headers, start with msgid, so set them
      text_lowercase.StartsWith("msgid"))
  {
    return FindByName("bash", false); // don't show error
  }
  else if (text_lowercase.StartsWith("<html>") ||
           text_lowercase.StartsWith("<?php"))
  {
    return FindByName("hypertext", false); // don't show error
  }
  else if (text_lowercase.StartsWith("<?xml"))
  {
    return FindByName("xml", false); // don't show error
  }
  // cpp files like #include <map> really do not have a .h extension (e.g. /usr/include/c++/3.3.5/map)
  // so add here.
  else if (text_lowercase.StartsWith("//"))
  {
    return FindByName("cpp", false); // don't show error
  }

  return wxExLexer();
}

wxExLexers* wxExLexers::Get(bool createOnDemand)
{
  if (m_Self == NULL && createOnDemand)
  {
    m_Self = new wxExLexers(wxFileName(
#ifdef wxExUSE_PORTABLE
      wxPathOnly(wxStandardPaths::Get().GetExecutablePath())
#else
      wxStandardPaths::Get().GetUserDataDir()
#endif
      + wxFileName::GetPathSeparator() + "lexers.xml")
    );

    m_Self->Read();
  }

  return m_Self;
}

const wxString wxExLexers::GetLexerExtensions() const
{
  wxString text;

  for (
    std::map<wxString, wxExLexer>::const_iterator it = m_Lexers.begin();
    it != m_Lexers.end();
    ++it)
  {
    if (!it->second.m_Extensions.empty() &&
         it->second.m_Extensions != "*." + it->second.m_ScintillaLexer)
    {
      if (!text.empty())
      {
        text += wxExFindReplaceData::Get()->GetFieldSeparator();
      }

      text += it->second.m_Extensions;
    }
  }

  return text;
}

const wxString wxExLexers::ParseTagColourings(const wxXmlNode* node) const
{
  wxString text;

  wxXmlNode* child = node->GetChildren();

  while (child)
  {
    if (child->GetName() == "colouring")
    {
      wxString content = child->GetNodeContent().Strip(wxString::both);

      std::map<wxString, wxString>::const_iterator it = m_Macros.find(content);

      if (it != m_Macros.end())
      {
        content = it->second;
      }

      text +=
        ApplyMacro(
          child->GetAttribute("no", "0"))
        + "=" + content + wxTextFile::GetEOL();
    }
    else if (child->GetName() == "comment")
    {
      // Ignore comments.
    }
    else
    {
      wxLogError(_("Undefined colourings tag: %s on: %d"),
        child->GetName().c_str(), child->GetLineNumber());
    }

    child = child->GetNext();
  }

  return text;
}

void wxExLexers::ParseTagGlobal(const wxXmlNode* node)
{
  wxXmlNode* child = node->GetChildren();

  while (child)
  {
    if (child->GetName() == "comment")
    {
      // Ignore comments.
    }
    else if (child->GetName() == "hex")
    {
      m_StylesHex.push_back(
        ApplyMacro(child->GetAttribute("no", "0")) + "=" +
        child->GetNodeContent().Strip(wxString::both));
    }
    else if (child->GetName() == "indicator")
    {
      m_Indicators.insert(std::make_pair(
        atoi(ApplyMacro(child->GetAttribute("no", "0")).c_str()),
        atoi(child->GetNodeContent().Strip(wxString::both).c_str())));
    }
    else if (child->GetName() == "marker")
    {
      const wxExMarker marker(ParseTagMarker(
        ApplyMacro(child->GetAttribute("no", "0")),
        child->GetNodeContent().Strip(wxString::both)));

      if (marker.GetMarkerNumber() < wxSTC_STYLE_MAX &&
          marker.GetMarkerSymbol() < wxSTC_STYLE_MAX)
      {
        m_Markers.push_back(marker);
      }
      else
      {
        wxLogError(_("Illegal marker number: %d or symbol: %d on: %d"),
          marker.GetMarkerNumber(),
          marker.GetMarkerSymbol(),
          child->GetLineNumber());
      }
    }
    else if (child->GetName() == "properties")
    {
      m_GlobalProperties = ParseTagProperties(child);
    }
    else if (child->GetName() == "style")
    {
      const wxString attrib = ApplyMacro(child->GetAttribute("no", "0"));
      const wxString content = child->GetNodeContent().Strip(wxString::both);
      int attrib_no = atoi(attrib.c_str());

      if (attrib_no == wxSTC_STYLE_DEFAULT)
      {
        m_DefaultStyle = attrib + "=" + content;
      }
      else
      {
        m_Styles.push_back(attrib + "=" + content);
      }
    }
    else
    {
      wxLogError(_("Undefined global tag: %s on: %d"),
        child->GetName().c_str(), child->GetLineNumber());
    }

    child = child->GetNext();
  }
}

const wxExLexer wxExLexers::ParseTagLexer(const wxXmlNode* node) const
{
  wxExLexer lexer(node->GetAttribute("name", ""));
  lexer.m_Extensions = node->GetAttribute(
    "extensions",
    "*." + lexer.m_ScintillaLexer);

  wxXmlNode *child = node->GetChildren();

  while (child)
  {
    if (child->GetName() == "colourings")
    {
      lexer.m_Colourings = ParseTagColourings(child);
    }
    else if (child->GetName() == "keywords")
    {
      if (!lexer.SetKeywords(child->GetNodeContent().Strip(wxString::both)))
      {
        wxLogError(_("Keywords could not be set on: %d"), child->GetLineNumber());
      }
    }
    else if (child->GetName() == "properties")
    {
      lexer.m_Properties = ParseTagProperties(child);
    }
    else if (child->GetName() == "comments")
    {
      lexer.m_CommentBegin = child->GetAttribute("begin1", "");
      lexer.m_CommentEnd = child->GetAttribute("end1", "");
      lexer.m_CommentBegin2 = child->GetAttribute("begin2", "");
      lexer.m_CommentEnd2 = child->GetAttribute("end2", "");
    }
    else if (child->GetName() == "comment")
    {
      // Ignore comments.
    }
    else
    {
      wxLogError(_("Undefined lexer tag: %s on: %d"),
        child->GetName().c_str(), child->GetLineNumber());
    }

    child = child->GetNext();
  }

  return lexer;
}

void wxExLexers::ParseTagMacro(const wxXmlNode* node)
{
  wxXmlNode* child = node->GetChildren();

  while (child)
  {
    if (child->GetName() == "comment")
    {
      // Ignore comments.
    }
    else if (child->GetName() == "def")
    {
      const wxString attrib = child->GetAttribute("no", "0");
      const wxString content = child->GetNodeContent().Strip(wxString::both);

      std::map<wxString, wxString>::const_iterator it = m_Macros.find(attrib);

      if (it != m_Macros.end())
      {
        wxLogError(_("Macro: %s on line: already exists: %d"),
          attrib.c_str(), child->GetLineNumber());
      }
      else
      {
        m_Macros[attrib] = content;
      }
    }
    else
    {
      wxLogError(_("Undefined macro tag: %s on: %d"),
        child->GetName().c_str(), child->GetLineNumber());
    }

    child = child->GetNext();
  }
}

const wxExMarker wxExLexers::ParseTagMarker(
  const wxString& number,
  const wxString& props) const
{
  wxStringTokenizer prop_fields(props, ",");

  const wxString symbol = ApplyMacro(prop_fields.GetNextToken());

  wxColour foreground;
  wxColour background;

  if (prop_fields.HasMoreTokens())
  {
    foreground = ApplyMacro(
      prop_fields.GetNextToken().Strip(wxString::both));

    if (prop_fields.HasMoreTokens())
    {
      background = ApplyMacro(
        prop_fields.GetNextToken().Strip(wxString::both));
    }
  }

  const int no = atoi(number.c_str());
  const int symbol_no = atoi(symbol.c_str());

  if (no <= wxSTC_MARKER_MAX && symbol_no <= wxSTC_MARKER_MAX)
  {
    return wxExMarker(no, symbol_no, foreground, background);
  }
  else
  {
    wxLogError(_("Illegal marker number: %d or symbol: %d"), no, symbol_no);
    return wxExMarker(0, 0, foreground, background);
  }
}

const wxString wxExLexers::ParseTagProperties(const wxXmlNode* node) const
{
  wxString text;

  wxXmlNode *child = node->GetChildren();

  while (child)
  {
    if (child->GetName() == "property")
    {
      text +=
        child->GetAttribute("name", "0") + "=" +
        child->GetNodeContent().Strip(wxString::both) + wxTextFile::GetEOL();
    }
    else if (child->GetName() == "comment")
    {
      // Ignore comments.
    }
    else
    {
      wxLogError(_("Undefined properties tag: %s on %d"),
        child->GetName().c_str(), child->GetLineNumber());
    }

    child = child->GetNext();
  }

  return text;
}

void wxExLexers::Read()
{
  // This test is to prevent showing an error if the lexers file does not exist,
  // as this is not required.
  if (!m_FileName.FileExists())
  {
    return;
  }

  wxXmlDocument doc;

  if (!doc.Load(m_FileName.GetFullPath()))
  {
    return;
  }

  // Initialize members.
  m_Indicators.clear();
  m_Lexers.clear();
  m_Markers.clear();
  m_SortedLexerNames.clear();
  m_Styles.clear();
  m_StylesHex.clear();

  wxXmlNode* child = doc.GetRoot()->GetChildren();

  while (child)
  {
    if (child->GetName() == "macro")
    {
      ParseTagMacro(child);
    }
    else if (child->GetName() == "global")
    {
      ParseTagGlobal(child);
    }
    else if (child->GetName() == "lexer")
    {
      const wxExLexer& lexer = ParseTagLexer(child);

      if (!lexer.GetScintillaLexer().empty())
      {
        if (lexer.GetScintillaLexer() == "hypertext")
        {
          // As our lexers.xml files cannot use xml comments,
          // add them here.
          wxExLexer l(lexer);
          l.m_CommentBegin = "<!--";
          l.m_CommentEnd = "-->";
          m_Lexers.insert(std::make_pair(lexer.GetScintillaLexer(), l));
        }
        else
        {
          m_Lexers.insert(std::make_pair(lexer.GetScintillaLexer(), lexer));
          m_SortedLexerNames.Add(lexer.GetScintillaLexer());
        }
      }
    }

    child = child->GetNext();
  }

  // Add the <none> lexer.
  m_SortedLexerNames.Add(_("<none>"));

  if (!wxConfigBase::Get()->Exists(_("In files")))
  {
    wxConfigBase::Get()->Write(_("In files"), GetLexerExtensions());
  }

  if (!wxConfigBase::Get()->Exists(_("Add what")))
  {
    wxConfigBase::Get()->Write(_("Add what"), GetLexerExtensions());
  }
}

wxExLexers* wxExLexers::Set(wxExLexers* lexers)
{
  wxExLexers* old = m_Self;
  m_Self = lexers;
  return old;
}

bool wxExLexers::ShowDialog(
  wxWindow* parent,
  wxString& lexer,
  const wxString& caption) const
{
  wxSingleChoiceDialog dlg(
    parent,
    _("Input") + ":",
    caption,
    m_SortedLexerNames);

  dlg.SetSelection(lexer.empty() ?
    m_SortedLexerNames.Index(_("<none>")):
    m_SortedLexerNames.Index(lexer));

  if (dlg.ShowModal() == wxID_CANCEL)
  {
    return false;
  }

  lexer = (dlg.GetSelection() == m_SortedLexerNames.Index(_("<none>")) ?
    wxEmptyString:
    FindByName(dlg.GetStringSelection()).GetScintillaLexer());

  return true;
}
<|endoftext|>


<commit_before>/**
 *  Script.cpp
 *
 *  Implementation file for the script class
 *
 *  @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
 *  @copyright 2014 Copernica BV
 */

/**
 *  Dependencies
 */
#include "includes.h"
#include <mutex>

/**
 *  Open PHP namespace
 */
namespace Php {

/**
 *  Helper class to temporarily set compiler options
 *
 *  When an object is destructed, it automatically restored the previous compiler settings
 */
class CompilerOptions
{
private:
    /**
     *  The original compiler options
     *  @var int
     */
    zend_uint _original;

public:
    /**
     *  Constructor
     *  @param  options
     */
    CompilerOptions(zend_uint options)
    {
        // remember the old compiler options before we set temporary compile options
        _original = CG(compiler_options);

        // we're going to evaluate only once
        CG(compiler_options) = options;
    }

    /**
     *  Destructor
     */
    virtual ~CompilerOptions()
    {
        // restore original options
        CG(compiler_options) = _original;
    }
};

/**
 *  Helper class to store and restore the current opcode state
 *
 *  When we're going to execute a set of instructions, we need to store the
 *  current state of the Zend engine. After the instructions have been processed,
 *  we can switch back to the original instructions
 */
class ExecuteState
{
private:
    /**
     *  All the original settings
     */
    zend_op_array *_active_op_array;
    zval **_return_value_ptr_ptr;
    zend_op **_opline_ptr;
    int _interactive;

public:
    /**
     *  Constructor
     */
    ExecuteState()
    {
        // store all the original stuff
        _active_op_array = EG(active_op_array);
        _return_value_ptr_ptr = EG(return_value_ptr_ptr);
        _opline_ptr = EG(opline_ptr);
        _interactive = CG(interactive);
    }

    /**
     *  Destructor
     */
    virtual ~ExecuteState()
    {
        // restore all settings
        CG(interactive) = _interactive;
        EG(no_extensions) = 0;
        EG(opline_ptr) = _opline_ptr;
        EG(active_op_array) = _active_op_array;
        EG(return_value_ptr_ptr) = _return_value_ptr_ptr;
    }
};

/**
 *  Constructor
 *  @param  name        name of the script
 *  @param  script      actual PHP code
 *  @param  size        length of the string
 */
Script::Script(const char *name, const char *phpcode, size_t size)
{
    // Sadly, there is not a simple Zend function to compile a string into opcodes,
    // so we basically copy the code that we found in zend_execute_API.c inside
    // the zend_eval_stringl() function into this file here. However, the code
    // found there is full of zval manipulation, for which we can use the much
    // simpler Php::Value object
    Php::Value source(phpcode, size);

    // remember the old compiler options, and set new compiler options
    CompilerOptions options(ZEND_COMPILE_DEFAULT_FOR_EVAL);

    // we need the tsrm_ls variable
    TSRMLS_FETCH();

    // compile the string
    _opcodes = zend_compile_string(source._val, (char *)name TSRMLS_CC);
}

/**
 *  Destructor
 */
Script::~Script()
{
    // do nothing if there are no opcodes
    if (!_opcodes) return;

    // clean up opcodes
    destroy_op_array(_opcodes TSRMLS_CC);
    efree(_opcodes);
}

/**
 *  Execute a script
 *  @return Value
 */
Value Script::execute() const
{
    // if the script could not be compiled, we return null
    if (!_opcodes) return nullptr;

    // pointer that is going to hold the return value of the script
    zval *retval_ptr = nullptr;

    // the zend engine is probably already busy processing opcodes, so we store
    // the current execute state before we're going to switch the runtime to
    // our own set of opcodes
    ExecuteState oldstate;

    // old execute state has been saved (and will automatically be restured when
    // the oldstate is destructed), so we can now safely overwrite all the settings
    EG(return_value_ptr_ptr) = &retval_ptr;
    EG(active_op_array) = _opcodes;
    EG(no_extensions) = 1;
    if (!EG(active_symbol_table)) zend_rebuild_symbol_table(TSRMLS_C);
    CG(interactive) = 0;

    // this code was copied from zend_execute_API.c. this is what I think it does:
    // the zend_execute() call could result in all sort of disastrous things, one
    // of them is a full crash of the executing script. if that happens, the zend
    // engine does a long jump right up to some other point in the code. the
    // 'zend_try' and 'zend_catch' macros prevent this: they install a new
    // destination for the long jump, so that we can catch a failure
    zend_try
    {
        // execute the code
        zend_execute(_opcodes TSRMLS_CC);
    }
    zend_catch
    {
        // the code could not be executed, and the zend engine is in big
        // trouble now, in the original code the _opcodes are efree'd, but here
        // we can just as well continue with the real bailout (the zend_try/
        // zend_catch pair was maybe not even necessary???)
        zend_bailout();
    }
    zend_end_try();

    // we're ready if there is no return value
    if (!retval_ptr) return nullptr;

    // copy the pointer into a value object, and return that
    return retval_ptr;
}

/**
 *  End of namespace
 */
}

<commit_msg>exception support for the Script class<commit_after>/**
 *  Script.cpp
 *
 *  Implementation file for the script class
 *
 *  @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
 *  @copyright 2014 Copernica BV
 */

/**
 *  Dependencies
 */
#include "includes.h"
#include <mutex>

/**
 *  Open PHP namespace
 */
namespace Php {

/**
 *  Helper class to temporarily set compiler options
 *
 *  When an object is destructed, it automatically restored the previous compiler settings
 */
class CompilerOptions
{
private:
    /**
     *  The original compiler options
     *  @var int
     */
    zend_uint _original;

public:
    /**
     *  Constructor
     *  @param  options
     */
    CompilerOptions(zend_uint options)
    {
        // remember the old compiler options before we set temporary compile options
        _original = CG(compiler_options);

        // we're going to evaluate only once
        CG(compiler_options) = options;
    }

    /**
     *  Destructor
     */
    virtual ~CompilerOptions()
    {
        // restore original options
        CG(compiler_options) = _original;
    }
};

/**
 *  Helper class to store and restore the current opcode state
 *
 *  When we're going to execute a set of instructions, we need to store the
 *  current state of the Zend engine. After the instructions have been processed,
 *  we can switch back to the original instructions
 */
class ExecuteState
{
private:
    /**
     *  All the original settings
     */
    zend_op_array *_active_op_array;
    zval **_return_value_ptr_ptr;
    zend_op **_opline_ptr;
    int _interactive;

public:
    /**
     *  Constructor
     */
    ExecuteState()
    {
        // store all the original stuff
        _active_op_array = EG(active_op_array);
        _return_value_ptr_ptr = EG(return_value_ptr_ptr);
        _opline_ptr = EG(opline_ptr);
        _interactive = CG(interactive);
    }

    /**
     *  Destructor
     */
    virtual ~ExecuteState()
    {
        // restore all settings
        CG(interactive) = _interactive;
        EG(no_extensions) = 0;
        EG(opline_ptr) = _opline_ptr;
        EG(active_op_array) = _active_op_array;
        EG(return_value_ptr_ptr) = _return_value_ptr_ptr;
    }
};

/**
 *  Constructor
 *  @param  name        name of the script
 *  @param  script      actual PHP code
 *  @param  size        length of the string
 */
Script::Script(const char *name, const char *phpcode, size_t size)
{
    // Sadly, there is not a simple Zend function to compile a string into opcodes,
    // so we basically copy the code that we found in zend_execute_API.c inside
    // the zend_eval_stringl() function into this file here. However, the code
    // found there is full of zval manipulation, for which we can use the much
    // simpler Php::Value object
    Php::Value source(phpcode, size);

    // remember the old compiler options, and set new compiler options
    CompilerOptions options(ZEND_COMPILE_DEFAULT_FOR_EVAL);

    // we need the tsrm_ls variable
    TSRMLS_FETCH();

    // compile the string
    _opcodes = zend_compile_string(source._val, (char *)name TSRMLS_CC);
}

/**
 *  Destructor
 */
Script::~Script()
{
    // do nothing if there are no opcodes
    if (!_opcodes) return;

    // clean up opcodes
    destroy_op_array(_opcodes TSRMLS_CC);
    efree(_opcodes);
}

/**
 *  Execute a script
 *  @return Value
 */
Value Script::execute() const
{
    // if the script could not be compiled, we return null
    if (!_opcodes) return nullptr;

    // pointer that is going to hold the return value of the script
    zval *retval_ptr = nullptr;

    // the zend engine is probably already busy processing opcodes, so we store
    // the current execute state before we're going to switch the runtime to
    // our own set of opcodes
    ExecuteState oldstate;

    // old execute state has been saved (and will automatically be restured when
    // the oldstate is destructed), so we can now safely overwrite all the settings
    EG(return_value_ptr_ptr) = &retval_ptr;
    EG(active_op_array) = _opcodes;
    EG(no_extensions) = 1;
    if (!EG(active_symbol_table)) zend_rebuild_symbol_table(TSRMLS_C);
    CG(interactive) = 0;

    // this code was copied from zend_execute_API.c. this is what I think it does:
    // the zend_execute() call could result in all sort of disastrous things, one
    // of them is a full crash of the executing script. if that happens, the zend
    // engine does a long jump right up to some other point in the code. the
    // 'zend_try' and 'zend_catch' macros prevent this: they install a new
    // destination for the long jump, so that we can catch a failure
    zend_try
    {
        // the current exception
        zval* oldException = EG(exception);

        // execute the code
        zend_execute(_opcodes TSRMLS_CC);

        // was an exception thrown inside the eval()'ed code? In that case we
        // throw a C++ new exception to give the C++ code the chance to catch it
        if (oldException != EG(exception) && EG(exception)) throw OrigException(EG(exception) TSRMLS_CC);
    }
    zend_catch
    {
        // the code could not be executed, and the zend engine is in big
        // trouble now, in the original code the _opcodes are efree'd, but here
        // we can just as well continue with the real bailout (the zend_try/
        // zend_catch pair was maybe not even necessary???)
        zend_bailout();
    }
    zend_end_try();

    // we're ready if there is no return value
    if (!retval_ptr) return nullptr;

    // copy the pointer into a value object, and return that
    return retval_ptr;
}

/**
 *  End of namespace
 */
}

<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkMinimumMaximumImageCalculatorTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 2001 Insight Consortium
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

 * The name of the Insight Consortium, nor the names of any consortium members,
   nor of any contributors, may be used to endorse or promote products derived
   from this software without specific prior written permission.

  * Modified source versions must be plainly marked as such, and must not be
    misrepresented as being the original software.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================*/

#include "itkImage.h"
#include "itkMinimumMaximumImageCalculator.h"
#include "itkSize.h"

typedef itk::Size<3>                                  SizeType;
typedef itk::Image<short, 3>                  ImageType;
typedef itk::MinimumMaximumImageCalculator<ImageType>  MinMaxCalculatorType;

/* Define the image size and physical coordinates */
SizeType size = {{20, 20, 20}};
double origin [3] = { 0.0, 0.0, 0.0};
double spacing[3] = { 1, 1 , 1};

int
main(int argc,char *argv[])
{
    int flag = 0;           /* Did this test program work? */

    std::cout << "Testing Minimum and Maximum Image Calulator:\n";

    /* Allocate a simple test image */
    ImageType::Pointer image = ImageType::New();
    ImageType::RegionType region;
    region.SetSize(size);
    image->SetLargestPossibleRegion(region);
    image->SetRequestedRegion(region);
    image->SetBufferedRegion(region);
    image->Allocate();

    /* Set origin and spacing of physical coordinates */
    image->SetOrigin(origin);
    image->SetSpacing(spacing);

    short minimum = -52;
    short maximum = 103;

    /* Initialize the image contents with the minimum value*/
    itk::Index<3> index;
    for (int slice = 0; slice < 20; slice++) {
        index[2] = slice;
        for (int row = 0; row <20; row++) {
            index[1] = row;
            for (int col = 0; col < 20; col++) {
                index[0] = col;
                image->SetPixel(index, minimum);
            }
        }
    }

    /* Set voxel (10,10,10) to maximum value*/
    index[0] = 10;
    index[1] = 10;
    index[2] = 10;
    image->SetPixel(index, maximum);

    /* Create and initialize the calculator */
    MinMaxCalculatorType::Pointer calculator = MinMaxCalculatorType::New();
    calculator->SetImage(image);

    calculator->Compute();

    /* Return minimum of intensity */
    short minimumResult = calculator->GetMinimum();
    std::cout << "The Minimum intensity value is : " << minimumResult << std::endl;

    if(minimumResult != minimum)
    {
       std::cout << "Minimum Value is wrong : " << minimumResult ;
       std::cout << " != " << minimum << std::endl;
       flag = 1;
    }

    /* Return maximum of intensity */
    short maximumResult = calculator->GetMaximum();
    std::cout << "The Maximum intensity value is : " << maximumResult << std::endl;

    if(maximumResult != maximum)
    {
       std::cout << "Maximum Value is wrong : " << maximumResult ;
       std::cout << " != " << maximum << std::endl;
       flag = 2;
    }

    /* Return results of test */
    if (flag != 0) {
        std::cout << "*** Some tests failed" << std::endl;
        return flag; }
    else {
        std::cout << "All tests successfully passed" << std::endl;
        return 0; }

}
<commit_msg>ENH: added print.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkMinimumMaximumImageCalculatorTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 2001 Insight Consortium
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

 * The name of the Insight Consortium, nor the names of any consortium members,
   nor of any contributors, may be used to endorse or promote products derived
   from this software without specific prior written permission.

  * Modified source versions must be plainly marked as such, and must not be
    misrepresented as being the original software.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================*/

#include "itkImage.h"
#include "itkMinimumMaximumImageCalculator.h"
#include "itkSize.h"

typedef itk::Size<3>                                  SizeType;
typedef itk::Image<short, 3>                  ImageType;
typedef itk::MinimumMaximumImageCalculator<ImageType>  MinMaxCalculatorType;

/* Define the image size and physical coordinates */
SizeType size = {{20, 20, 20}};
double origin [3] = { 0.0, 0.0, 0.0};
double spacing[3] = { 1, 1 , 1};

int
main(int argc,char *argv[])
{
    int flag = 0;           /* Did this test program work? */

    std::cout << "Testing Minimum and Maximum Image Calulator:\n";

    /* Allocate a simple test image */
    ImageType::Pointer image = ImageType::New();
    ImageType::RegionType region;
    region.SetSize(size);
    image->SetLargestPossibleRegion(region);
    image->SetRequestedRegion(region);
    image->SetBufferedRegion(region);
    image->Allocate();

    /* Set origin and spacing of physical coordinates */
    image->SetOrigin(origin);
    image->SetSpacing(spacing);

    short minimum = -52;
    short maximum = 103;

    /* Initialize the image contents with the minimum value*/
    itk::Index<3> index;
    for (int slice = 0; slice < 20; slice++) {
        index[2] = slice;
        for (int row = 0; row <20; row++) {
            index[1] = row;
            for (int col = 0; col < 20; col++) {
                index[0] = col;
                image->SetPixel(index, minimum);
            }
        }
    }

    /* Set voxel (10,10,10) to maximum value*/
    index[0] = 10;
    index[1] = 10;
    index[2] = 10;
    image->SetPixel(index, maximum);

    /* Create and initialize the calculator */
    MinMaxCalculatorType::Pointer calculator = MinMaxCalculatorType::New();
    calculator->SetImage(image);

    calculator->Compute();

    std::cout << "calculator: " << calculator;

    /* Return minimum of intensity */
    short minimumResult = calculator->GetMinimum();
    std::cout << "The Minimum intensity value is : " << minimumResult << std::endl;

    if(minimumResult != minimum)
    {
       std::cout << "Minimum Value is wrong : " << minimumResult ;
       std::cout << " != " << minimum << std::endl;
       flag = 1;
    }

    /* Return maximum of intensity */
    short maximumResult = calculator->GetMaximum();
    std::cout << "The Maximum intensity value is : " << maximumResult << std::endl;

    if(maximumResult != maximum)
    {
       std::cout << "Maximum Value is wrong : " << maximumResult ;
       std::cout << " != " << maximum << std::endl;
       flag = 2;
    }

    /* Return results of test */
    if (flag != 0) {
        std::cout << "*** Some tests failed" << std::endl;
        return flag; }
    else {
        std::cout << "All tests successfully passed" << std::endl;
        return 0; }

}
<|endoftext|>


<commit_before>// Test the mmap_limit_mb flag.
//
// RUN: %clangxx_asan -O2 %s -o %t
// RUN: %run %t 100 16
// RUN: %run %t 100 1000000
// RUN: env ASAN_OPTIONS=mmap_limit_mb=500 %run %t 50 16
// RUN: env ASAN_OPTIONS=mmap_limit_mb=500 %run %t 50 1000000
// RUN: env ASAN_OPTIONS=mmap_limit_mb=500 not %run %t 500 16 2>&1 | FileCheck %s
// RUN: env ASAN_OPTIONS=mmap_limit_mb=500 not %run %t 500 1000000 2>&1 | FileCheck %s
// XFAIL: arm-linux-gnueabi

#include <assert.h>
#include <stdlib.h>
#include <stdio.h>

#include <algorithm>
#include <vector>

int main(int argc, char **argv) {
  assert(argc == 3);
  long total_mb = atoi(argv[1]);
  long allocation_size = atoi(argv[2]);
  fprintf(stderr, "total_mb: %zd allocation_size: %zd\n", total_mb,
          allocation_size);
  std::vector<char *> v;
  for (long total = total_mb << 20; total > 0; total -= allocation_size)
    v.push_back(new char[allocation_size]);
  for (std::vector<char *>::const_iterator it = v.begin(); it != v.end(); ++it)
    delete[](*it);
  fprintf(stderr, "PASS\n");
  // CHECK: total_mmaped{{.*}}mmap_limit_mb
  return 0;
}
<commit_msg>[asan] Tune down mmap_limit_mb test.<commit_after>// Test the mmap_limit_mb flag.
//
// RUN: %clangxx_asan -O2 %s -o %t
// RUN: %run %t 20 16
// RUN: %run %t 30 1000000
// RUN: env ASAN_OPTIONS=mmap_limit_mb=150 %run %t 20 16
// RUN: env ASAN_OPTIONS=mmap_limit_mb=150 %run %t 20 1000000
// RUN: env ASAN_OPTIONS=mmap_limit_mb=150 not %run %t 500 16 2>&1 | FileCheck %s
// RUN: env ASAN_OPTIONS=mmap_limit_mb=150 not %run %t 500 1000000 2>&1 | FileCheck %s
// XFAIL: arm-linux-gnueabi

#include <assert.h>
#include <stdlib.h>
#include <stdio.h>

#include <algorithm>
#include <vector>

int main(int argc, char **argv) {
  assert(argc == 3);
  long total_mb = atoi(argv[1]);
  long allocation_size = atoi(argv[2]);
  fprintf(stderr, "total_mb: %zd allocation_size: %zd\n", total_mb,
          allocation_size);
  std::vector<char *> v;
  for (long total = total_mb << 20; total > 0; total -= allocation_size)
    v.push_back(new char[allocation_size]);
  for (std::vector<char *>::const_iterator it = v.begin(); it != v.end(); ++it)
    delete[](*it);
  fprintf(stderr, "PASS\n");
  // CHECK: total_mmaped{{.*}}mmap_limit_mb
  return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2011 The Native Client Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "native_client/tests/ppapi_test_lib/get_browser_interface.h"
#include "native_client/tests/ppapi_test_lib/test_interface.h"
#include "native_client/src/shared/platform/nacl_check.h"
#include "ppapi/c/ppb_core.h"
#include "ppapi/c/ppb_file_system.h"
#include "ppapi/c/ppb_url_request_info.h"
#include "ppapi/c/pp_errors.h"

namespace {

void OpenCallback(void* /*data*/, int32_t /*result*/) {
}

const PP_FileSystemType kFileSystemTypes[] = {
  PP_FILESYSTEMTYPE_EXTERNAL,
  PP_FILESYSTEMTYPE_LOCALPERSISTENT,
  PP_FILESYSTEMTYPE_LOCALTEMPORARY
};

const size_t kNumFileSystemTypes =
    sizeof(kFileSystemTypes) / sizeof(kFileSystemTypes[0]);

void TestCreate() {
  PP_Resource file_system = kInvalidResource;
  const PPB_FileSystem* ppb_file_system = PPBFileSystem();
  // Test to see if PPB_FileSystem::Create returns PP_Resource value of 0
  // if the instance parameter is invalid.
  file_system = ppb_file_system->Create(kInvalidInstance,
                                        PP_FILESYSTEMTYPE_EXTERNAL);
  EXPECT(file_system == kInvalidResource);
  file_system = ppb_file_system->Create(kInvalidInstance,
                                        PP_FILESYSTEMTYPE_LOCALPERSISTENT);
  EXPECT(file_system == kInvalidResource);
  file_system = ppb_file_system->Create(kInvalidInstance,
                                        PP_FILESYSTEMTYPE_LOCALTEMPORARY);
  EXPECT(file_system == kInvalidResource);

  // Test for failure when an invalid file system type is requested.
  file_system = ppb_file_system->Create(pp_instance(),
                                        PP_FILESYSTEMTYPE_INVALID);
  EXPECT(file_system == kInvalidResource);

  // Test to see if PPB_FileSystem::Create returns a valid PP_Resource
  // value when given a valid PP_Instance value parameter.  Test for all
  // three file system types PPB_FileSystem supports.
  for (size_t i = 0; i < kNumFileSystemTypes; ++i) {
    file_system = ppb_file_system->Create(pp_instance(), kFileSystemTypes[i]);
    EXPECT(file_system != kInvalidResource);
    PPBCore()->ReleaseResource(file_system);
  }
  TEST_PASSED;
}

void TestIsFileSystem() {
  const PPB_Core* ppb_core = PPBCore();
  const PPB_FileSystem* ppb_file_system = PPBFileSystem();
  PP_Resource file_system = kInvalidResource;
  PP_Bool is_file_system = PP_FALSE;

  // Test fail for invalid resource.
  EXPECT(ppb_file_system->IsFileSystem(kInvalidResource) != PP_TRUE);

  // Test pass for the different valid system types, and test fail against a
  // resource that has been released.
  for (size_t i = 0; i < kNumFileSystemTypes; ++i) {
    file_system = ppb_file_system->Create(pp_instance(), kFileSystemTypes[i]);
    CHECK(file_system != kInvalidResource);

    is_file_system = ppb_file_system->IsFileSystem(file_system);
    ppb_core->ReleaseResource(file_system);

    EXPECT(is_file_system == PP_TRUE);

    is_file_system = ppb_file_system->IsFileSystem(file_system);
    EXPECT(is_file_system == PP_FALSE);
  }

  // Test fail against a non-filesystem resource.
  PP_Resource url_request_info = PPBURLRequestInfo()->Create(pp_instance());
  CHECK(url_request_info != kInvalidResource);
  is_file_system = ppb_file_system->IsFileSystem(url_request_info);
  ppb_core->ReleaseResource(url_request_info);
  EXPECT(is_file_system == PP_FALSE);

  TEST_PASSED;
}

void TestOpen() {
  const PPB_Core* ppb_core = PPBCore();
  const PPB_FileSystem* ppb_file_system = PPBFileSystem();
  PP_Resource file_system = kInvalidResource;
  PP_CompletionCallback nop_callback =
      MakeTestableCompletionCallback("NopCallback", OpenCallback);
  PP_CompletionCallback open_callback =
      MakeTestableCompletionCallback("OpenCallback", OpenCallback, NULL);
  int32_t pp_error = PP_ERROR_FAILED;
  int64_t kSize = 1024;  // Dummy value.

  // Test to make sure opening an invalid file system fails.
  pp_error = ppb_file_system->Open(kInvalidResource, kSize, nop_callback);
  EXPECT(pp_error == PP_ERROR_BADRESOURCE);

  // Test to make sure external file system is not supported.
  // TODO(sanga): Once Chrome supports external file systems, change this test
  // to reflect the change.
  file_system = ppb_file_system->Create(pp_instance(),
                                        PP_FILESYSTEMTYPE_EXTERNAL);
  pp_error = ppb_file_system->Open(file_system, kSize, nop_callback);
  ppb_core->ReleaseResource(file_system);
  EXPECT(pp_error == PP_ERROR_FAILED);

  // Test local temporary and local persistant file systems.
  for (size_t i = 1; i < kNumFileSystemTypes; ++i) {
#ifdef __native_client__
    // Test fail for blocking open.
    //
    // Only conduct this test with nexe.  Trusted ppapi plugin does not work
    // with synchronous Open call.
    // See http://code.google.com/p/chromium/issues/detail?id=78449
    file_system = ppb_file_system->Create(pp_instance(), kFileSystemTypes[i]);
    pp_error = ppb_file_system->Open(file_system, kSize,
                                     PP_BlockUntilComplete());
    ppb_core->ReleaseResource(file_system);
    EXPECT(pp_error == PP_ERROR_BADARGUMENT);
#endif

    // Test success for asynchronous open.
    file_system = ppb_file_system->Create(pp_instance(), kFileSystemTypes[i]);
    pp_error = ppb_file_system->Open(file_system, kSize, open_callback);
    ppb_core->ReleaseResource(file_system);
    EXPECT(pp_error == PP_OK_COMPLETIONPENDING);
    open_callback =
        MakeTestableCompletionCallback("OpenCallback", OpenCallback);

    // Test fail for multiple opens.
    file_system = ppb_file_system->Create(pp_instance(), kFileSystemTypes[i]);
    pp_error = ppb_file_system->Open(file_system, kSize, open_callback);
    CHECK(pp_error == PP_OK_COMPLETIONPENDING);  // Previously tested.
    pp_error = ppb_file_system->Open(file_system, kSize, nop_callback);
    ppb_core->ReleaseResource(file_system);
    // TODO(polina, sanga): take out PP_ERROR_FAILED when chrome is fixed.
    EXPECT(pp_error == PP_ERROR_FAILED || pp_error == PP_ERROR_INPROGRESS);
  }
  TEST_PASSED;
}

void TestGetType() {
  const PPB_Core* ppb_core = PPBCore();
  const PPB_FileSystem* ppb_file_system = PPBFileSystem();
  PP_Resource file_system = kInvalidResource;
  PP_FileSystemType type = PP_FILESYSTEMTYPE_INVALID;

  // Test for invalid resource.
  EXPECT(PP_FILESYSTEMTYPE_INVALID == ppb_file_system->GetType(0));

  // Test pass for the different valid system types.
  for (size_t i = 0; i < kNumFileSystemTypes; ++i) {
    file_system = ppb_file_system->Create(pp_instance(), kFileSystemTypes[i]);
    CHECK(file_system != kInvalidResource);

    type = ppb_file_system->GetType(file_system);
    ppb_core->ReleaseResource(file_system);

    EXPECT(type == kFileSystemTypes[i]);
  }

  // Test fail against a non-filesystem resource.
  PP_Resource url_request_info = PPBURLRequestInfo()->Create(pp_instance());
  CHECK(url_request_info != kInvalidResource);
  type = ppb_file_system->GetType(url_request_info);
  ppb_core->ReleaseResource(url_request_info);
  EXPECT(type == PP_FILESYSTEMTYPE_INVALID);

  TEST_PASSED;
}

}  // namespace

void SetupTests() {
  RegisterTest("TestCreate", TestCreate);
  RegisterTest("TestIsFileSystem", TestIsFileSystem);
  RegisterTest("TestOpen", TestOpen);
  RegisterTest("TestGetType", TestGetType);
}

void SetupPluginInterfaces() {
  /* No PPP interface to test. */
}
<commit_msg>Made a fix so TestOpen does not release the file system right after calling Open, instead passing the resource as user data to the open callback to be released.<commit_after>// Copyright (c) 2011 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.

#include "native_client/tests/ppapi_test_lib/get_browser_interface.h"
#include "native_client/tests/ppapi_test_lib/test_interface.h"
#include "native_client/src/shared/platform/nacl_check.h"
#include "ppapi/c/ppb_core.h"
#include "ppapi/c/ppb_file_system.h"
#include "ppapi/c/ppb_url_request_info.h"
#include "ppapi/c/pp_errors.h"

namespace {

struct OpenCallbackData {
  explicit OpenCallbackData(PP_Resource file_system)
      : file_system(file_system) {}

  PP_Resource file_system;
};

void OpenCallback(void* data, int32_t result) {
  EXPECT(result == PP_OK);
  OpenCallbackData* callback_data = reinterpret_cast<OpenCallbackData*>(data);
  PPBCore()->ReleaseResource(callback_data->file_system);
  delete callback_data;
}

const PP_FileSystemType kFileSystemTypes[] = {
  PP_FILESYSTEMTYPE_EXTERNAL,
  PP_FILESYSTEMTYPE_LOCALPERSISTENT,
  PP_FILESYSTEMTYPE_LOCALTEMPORARY
};

const size_t kNumFileSystemTypes =
    sizeof(kFileSystemTypes) / sizeof(kFileSystemTypes[0]);

void TestCreate() {
  PP_Resource file_system = kInvalidResource;
  const PPB_FileSystem* ppb_file_system = PPBFileSystem();
  // Test to see if PPB_FileSystem::Create returns PP_Resource value of 0
  // if the instance parameter is invalid.
  file_system = ppb_file_system->Create(kInvalidInstance,
                                        PP_FILESYSTEMTYPE_EXTERNAL);
  EXPECT(file_system == kInvalidResource);
  file_system = ppb_file_system->Create(kInvalidInstance,
                                        PP_FILESYSTEMTYPE_LOCALPERSISTENT);
  EXPECT(file_system == kInvalidResource);
  file_system = ppb_file_system->Create(kInvalidInstance,
                                        PP_FILESYSTEMTYPE_LOCALTEMPORARY);
  EXPECT(file_system == kInvalidResource);

  // Test for failure when an invalid file system type is requested.
  file_system = ppb_file_system->Create(pp_instance(),
                                        PP_FILESYSTEMTYPE_INVALID);
  EXPECT(file_system == kInvalidResource);

  // Test to see if PPB_FileSystem::Create returns a valid PP_Resource
  // value when given a valid PP_Instance value parameter.  Test for all
  // three file system types PPB_FileSystem supports.
  for (size_t i = 0; i < kNumFileSystemTypes; ++i) {
    file_system = ppb_file_system->Create(pp_instance(), kFileSystemTypes[i]);
    EXPECT(file_system != kInvalidResource);
    PPBCore()->ReleaseResource(file_system);
  }
  TEST_PASSED;
}

void TestIsFileSystem() {
  const PPB_Core* ppb_core = PPBCore();
  const PPB_FileSystem* ppb_file_system = PPBFileSystem();
  PP_Resource file_system = kInvalidResource;
  PP_Bool is_file_system = PP_FALSE;

  // Test fail for invalid resource.
  EXPECT(ppb_file_system->IsFileSystem(kInvalidResource) != PP_TRUE);

  // Test pass for the different valid system types, and test fail against a
  // resource that has been released.
  for (size_t i = 0; i < kNumFileSystemTypes; ++i) {
    file_system = ppb_file_system->Create(pp_instance(), kFileSystemTypes[i]);
    CHECK(file_system != kInvalidResource);

    is_file_system = ppb_file_system->IsFileSystem(file_system);
    ppb_core->ReleaseResource(file_system);

    EXPECT(is_file_system == PP_TRUE);

    is_file_system = ppb_file_system->IsFileSystem(file_system);
    EXPECT(is_file_system == PP_FALSE);
  }

  // Test fail against a non-filesystem resource.
  PP_Resource url_request_info = PPBURLRequestInfo()->Create(pp_instance());
  CHECK(url_request_info != kInvalidResource);
  is_file_system = ppb_file_system->IsFileSystem(url_request_info);
  ppb_core->ReleaseResource(url_request_info);
  EXPECT(is_file_system == PP_FALSE);

  TEST_PASSED;
}

void TestOpen() {
  const PPB_Core* ppb_core = PPBCore();
  const PPB_FileSystem* ppb_file_system = PPBFileSystem();
  static PP_Resource file_system = kInvalidResource;
  PP_CompletionCallback nop_callback =
      MakeTestableCompletionCallback("NopCallback", OpenCallback);
  int32_t pp_error = PP_ERROR_FAILED;
  int64_t kSize = 1024;  // Dummy value.

  // Test to make sure opening an invalid file system fails.
  pp_error = ppb_file_system->Open(kInvalidResource, kSize, nop_callback);
  EXPECT(pp_error == PP_ERROR_BADRESOURCE);

  // Test to make sure external file system is not supported.
  // TODO(sanga): Once Chrome supports external file systems, change this test
  // to reflect the change.
  file_system = ppb_file_system->Create(pp_instance(),
                                        PP_FILESYSTEMTYPE_EXTERNAL);
  pp_error = ppb_file_system->Open(file_system, kSize, nop_callback);
  ppb_core->ReleaseResource(file_system);
  EXPECT(pp_error == PP_ERROR_FAILED);

  // Test local temporary and local persistant file systems.
  for (size_t i = 1; i < kNumFileSystemTypes; ++i) {
#ifdef __native_client__
    // Test fail for blocking open.
    //
    // Only conduct this test with nexe.  Trusted ppapi plugin does not work
    // with synchronous Open call.
    // See http://code.google.com/p/chromium/issues/detail?id=78449
    file_system = ppb_file_system->Create(pp_instance(), kFileSystemTypes[i]);
    pp_error = ppb_file_system->Open(file_system, kSize,
                                     PP_BlockUntilComplete());
    ppb_core->ReleaseResource(file_system);
    EXPECT(pp_error == PP_ERROR_BADARGUMENT);
#endif

    // Test success for asynchronous open.
    file_system = ppb_file_system->Create(pp_instance(), kFileSystemTypes[i]);
    OpenCallbackData* callback_data = new OpenCallbackData(file_system);
    PP_CompletionCallback open_callback = MakeTestableCompletionCallback(
        "OpenCallback", OpenCallback, callback_data);
    pp_error = ppb_file_system->Open(file_system, kSize, open_callback);
    EXPECT(pp_error == PP_OK_COMPLETIONPENDING);

    // Test fail for multiple opens.
    file_system = ppb_file_system->Create(pp_instance(), kFileSystemTypes[i]);
    callback_data = new OpenCallbackData(file_system);
    open_callback = MakeTestableCompletionCallback(
        "OpenCallback", OpenCallback, callback_data);
    pp_error = ppb_file_system->Open(file_system, kSize, open_callback);
    CHECK(pp_error == PP_OK_COMPLETIONPENDING);  // Previously tested.
    pp_error = ppb_file_system->Open(file_system, kSize, nop_callback);
    EXPECT(pp_error == PP_ERROR_INPROGRESS);
  }
  TEST_PASSED;
}

void TestGetType() {
  const PPB_Core* ppb_core = PPBCore();
  const PPB_FileSystem* ppb_file_system = PPBFileSystem();
  PP_Resource file_system = kInvalidResource;
  PP_FileSystemType type = PP_FILESYSTEMTYPE_INVALID;

  // Test for invalid resource.
  EXPECT(PP_FILESYSTEMTYPE_INVALID == ppb_file_system->GetType(0));

  // Test pass for the different valid system types.
  for (size_t i = 0; i < kNumFileSystemTypes; ++i) {
    file_system = ppb_file_system->Create(pp_instance(), kFileSystemTypes[i]);
    CHECK(file_system != kInvalidResource);

    type = ppb_file_system->GetType(file_system);
    ppb_core->ReleaseResource(file_system);

    EXPECT(type == kFileSystemTypes[i]);
  }

  // Test fail against a non-filesystem resource.
  PP_Resource url_request_info = PPBURLRequestInfo()->Create(pp_instance());
  CHECK(url_request_info != kInvalidResource);
  type = ppb_file_system->GetType(url_request_info);
  ppb_core->ReleaseResource(url_request_info);
  EXPECT(type == PP_FILESYSTEMTYPE_INVALID);

  TEST_PASSED;
}

}  // namespace

void SetupTests() {
  RegisterTest("TestCreate", TestCreate);
  RegisterTest("TestIsFileSystem", TestIsFileSystem);
  RegisterTest("TestOpen", TestOpen);
  RegisterTest("TestGetType", TestGetType);
}

void SetupPluginInterfaces() {
  /* No PPP interface to test. */
}
<|endoftext|>


<commit_before>/**********************************************************************
 * File:        serialis.cpp  (Formerly serialmac.h)
 * Description: Inline routines and macros for serialisation functions
 * Author:      Phil Cheatle
 *
 * (C) Copyright 1990, Hewlett-Packard Ltd.
 ** 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 "errcode.h"
#include <tesseract/helpers.h>  // for ReverseN
#include "serialis.h"
#include <cstdio>

namespace tesseract {

// The default FileReader loads the whole file into the vector of char,
// returning false on error.
bool LoadDataFromFile(const char* filename, std::vector<char>* data) {
  bool result = false;
  FILE* fp = fopen(filename, "rb");
  if (fp != nullptr) {
    fseek(fp, 0, SEEK_END);
    auto size = std::ftell(fp);
    fseek(fp, 0, SEEK_SET);
    // Trying to open a directory on Linux sets size to LONG_MAX. Catch it here.
    if (size > 0 && size < LONG_MAX) {
      // reserve an extra byte in case caller wants to append a '\0' character
      data->reserve(size + 1);
      data->resize(size); // TODO: optimize no init
      result = static_cast<long>(fread(&(*data)[0], 1, size, fp)) == size;
    }
    fclose(fp);
  }
  return result;
}

// The default FileWriter writes the vector of char to the filename file,
// returning false on error.
bool SaveDataToFile(const std::vector<char>& data, const char* filename) {
  FILE* fp = fopen(filename, "wb");
  if (fp == nullptr) {
    return false;
  }
  bool result =
      static_cast<int>(fwrite(&data[0], 1, data.size(), fp)) == data.size();
  fclose(fp);
  return result;
}

bool DeSerialize(FILE* fp, char* data, size_t n) {
  return fread(data, sizeof(*data), n, fp) == n;
}

bool DeSerialize(FILE* fp, float* data, size_t n) {
  return fread(data, sizeof(*data), n, fp) == n;
}

bool DeSerialize(FILE* fp, int8_t* data, size_t n) {
  return fread(data, sizeof(*data), n, fp) == n;
}

bool DeSerialize(FILE* fp, int16_t* data, size_t n) {
  return fread(data, sizeof(*data), n, fp) == n;
}

bool DeSerialize(FILE* fp, int32_t* data, size_t n) {
  return fread(data, sizeof(*data), n, fp) == n;
}

bool DeSerialize(FILE* fp, uint8_t* data, size_t n) {
  return fread(data, sizeof(*data), n, fp) == n;
}

bool DeSerialize(FILE* fp, uint16_t* data, size_t n) {
  return fread(data, sizeof(*data), n, fp) == n;
}

bool DeSerialize(FILE* fp, uint32_t* data, size_t n) {
  return fread(data, sizeof(*data), n, fp) == n;
}

bool Serialize(FILE* fp, const char* data, size_t n) {
  return fwrite(data, sizeof(*data), n, fp) == n;
}

bool Serialize(FILE* fp, const float* data, size_t n) {
  return fwrite(data, sizeof(*data), n, fp) == n;
}

bool Serialize(FILE* fp, const int8_t* data, size_t n) {
  return fwrite(data, sizeof(*data), n, fp) == n;
}

bool Serialize(FILE* fp, const int16_t* data, size_t n) {
  return fwrite(data, sizeof(*data), n, fp) == n;
}

bool Serialize(FILE* fp, const int32_t* data, size_t n) {
  return fwrite(data, sizeof(*data), n, fp) == n;
}

bool Serialize(FILE* fp, const uint8_t* data, size_t n) {
  return fwrite(data, sizeof(*data), n, fp) == n;
}

bool Serialize(FILE* fp, const uint16_t* data, size_t n) {
  return fwrite(data, sizeof(*data), n, fp) == n;
}

bool Serialize(FILE* fp, const uint32_t* data, size_t n) {
  return fwrite(data, sizeof(*data), n, fp) == n;
}

TFile::TFile()
    : data_(nullptr),
      offset_(0),
      data_is_owned_(false),
      is_writing_(false),
      swap_(false) {}

TFile::~TFile() {
  if (data_is_owned_)
    delete data_;
}

bool TFile::DeSerialize(std::vector<char>& data) {
  uint32_t size;
  if (!DeSerialize(&size)) {
    return false;
  }
  // TODO: optimize.
  data.resize(size);
  return DeSerialize(&data[0], data.size());
}

bool TFile::DeSerialize(char* buffer, size_t count) {
  return FRead(buffer, sizeof(*buffer), count) == count;
}

bool TFile::DeSerialize(double* buffer, size_t count) {
  return FReadEndian(buffer, sizeof(*buffer), count) == count;
}

bool TFile::DeSerialize(float* buffer, size_t count) {
  return FReadEndian(buffer, sizeof(*buffer), count) == count;
}

bool TFile::DeSerialize(int8_t* buffer, size_t count) {
  return FRead(buffer, sizeof(*buffer), count) == count;
}

bool TFile::DeSerialize(int16_t* buffer, size_t count) {
  return FReadEndian(buffer, sizeof(*buffer), count) == count;
}

bool TFile::DeSerialize(int32_t* buffer, size_t count) {
  return FReadEndian(buffer, sizeof(*buffer), count) == count;
}

bool TFile::DeSerialize(int64_t* buffer, size_t count) {
  return FReadEndian(buffer, sizeof(*buffer), count) == count;
}

bool TFile::DeSerialize(uint8_t* buffer, size_t count) {
  return FRead(buffer, sizeof(*buffer), count) == count;
}

bool TFile::DeSerialize(uint16_t* buffer, size_t count) {
  return FReadEndian(buffer, sizeof(*buffer), count) == count;
}

bool TFile::DeSerialize(uint32_t* buffer, size_t count) {
  return FReadEndian(buffer, sizeof(*buffer), count) == count;
}

bool TFile::DeSerialize(uint64_t* buffer, size_t count) {
  return FReadEndian(buffer, sizeof(*buffer), count) == count;
}

bool TFile::Serialize(const std::vector<char>& data) {
  uint32_t size = data.size();
  if (!Serialize(&size)) {
    return false;
  }
  return Serialize(&data[0], size);
}

bool TFile::Serialize(const char* buffer, size_t count) {
  return FWrite(buffer, sizeof(*buffer), count) == count;
}

bool TFile::Serialize(const double* buffer, size_t count) {
  return FWrite(buffer, sizeof(*buffer), count) == count;
}

bool TFile::Serialize(const float* buffer, size_t count) {
  return FWrite(buffer, sizeof(*buffer), count) == count;
}

bool TFile::Serialize(const int8_t* buffer, size_t count) {
  return FWrite(buffer, sizeof(*buffer), count) == count;
}

bool TFile::Serialize(const int16_t* buffer, size_t count) {
  return FWrite(buffer, sizeof(*buffer), count) == count;
}

bool TFile::Serialize(const int32_t* buffer, size_t count) {
  return FWrite(buffer, sizeof(*buffer), count) == count;
}

bool TFile::Serialize(const int64_t* buffer, size_t count) {
  return FWrite(buffer, sizeof(*buffer), count) == count;
}

bool TFile::Serialize(const uint8_t* buffer, size_t count) {
  return FWrite(buffer, sizeof(*buffer), count) == count;
}

bool TFile::Serialize(const uint16_t* buffer, size_t count) {
  return FWrite(buffer, sizeof(*buffer), count) == count;
}

bool TFile::Serialize(const uint32_t* buffer, size_t count) {
  return FWrite(buffer, sizeof(*buffer), count) == count;
}

bool TFile::Serialize(const uint64_t* buffer, size_t count) {
  return FWrite(buffer, sizeof(*buffer), count) == count;
}

bool TFile::Skip(size_t count) {
  offset_ += count;
  return true;
}

bool TFile::Open(const char* filename, FileReader reader) {
  if (!data_is_owned_) {
    data_ = new std::vector<char>;
    data_is_owned_ = true;
  }
  offset_ = 0;
  is_writing_ = false;
  swap_ = false;
  if (reader == nullptr)
    return LoadDataFromFile(filename, data_);
  else
    return (*reader)(filename, data_);
}

bool TFile::Open(const char* data, int size) {
  offset_ = 0;
  if (!data_is_owned_) {
    data_ = new std::vector<char>;
    data_is_owned_ = true;
  }
  is_writing_ = false;
  swap_ = false;
  data_->resize(size); // TODO: optimize no init
  memcpy(&(*data_)[0], data, size);
  return true;
}

bool TFile::Open(FILE* fp, int64_t end_offset) {
  offset_ = 0;
  auto current_pos = std::ftell(fp);
  if (current_pos < 0) {
    // ftell failed.
    return false;
  }
  if (end_offset < 0) {
    if (fseek(fp, 0, SEEK_END))
      return false;
    end_offset = ftell(fp);
    if (fseek(fp, current_pos, SEEK_SET))
      return false;
  }
  int size = end_offset - current_pos;
  is_writing_ = false;
  swap_ = false;
  if (!data_is_owned_) {
    data_ = new std::vector<char>;
    data_is_owned_ = true;
  }
  data_->resize(size); // TODO: optimize no init
  return static_cast<int>(fread(&(*data_)[0], 1, size, fp)) == size;
}

char* TFile::FGets(char* buffer, int buffer_size) {
  ASSERT_HOST(!is_writing_);
  int size = 0;
  while (size + 1 < buffer_size && offset_ < data_->size()) {
    buffer[size++] = (*data_)[offset_++];
    if ((*data_)[offset_ - 1] == '\n') break;
  }
  if (size < buffer_size) buffer[size] = '\0';
  return size > 0 ? buffer : nullptr;
}

int TFile::FReadEndian(void* buffer, size_t size, int count) {
  int num_read = FRead(buffer, size, count);
  if (swap_) {
    char* char_buffer = static_cast<char*>(buffer);
    for (int i = 0; i < num_read; ++i, char_buffer += size) {
      ReverseN(char_buffer, size);
    }
  }
  return num_read;
}

int TFile::FRead(void* buffer, size_t size, int count) {
  ASSERT_HOST(!is_writing_);
  ASSERT_HOST(size > 0);
  ASSERT_HOST(count >= 0);
  size_t required_size;
  if (SIZE_MAX / size <= count) {
    // Avoid integer overflow.
    required_size = data_->size() - offset_;
  } else {
    required_size = size * count;
    if (data_->size() - offset_ < required_size) {
      required_size = data_->size() - offset_;
    }
  }
  if (required_size > 0 && buffer != nullptr)
    memcpy(buffer, &(*data_)[offset_], required_size);
  offset_ += required_size;
  return required_size / size;
}

void TFile::Rewind() {
  ASSERT_HOST(!is_writing_);
  offset_ = 0;
}

void TFile::OpenWrite(std::vector<char>* data) {
  offset_ = 0;
  if (data != nullptr) {
    if (data_is_owned_) delete data_;
    data_ = data;
    data_is_owned_ = false;
  } else if (!data_is_owned_) {
    data_ = new std::vector<char>;
    data_is_owned_ = true;
  }
  is_writing_ = true;
  swap_ = false;
  data_->resize(0);
}

bool TFile::CloseWrite(const char* filename, FileWriter writer) {
  ASSERT_HOST(is_writing_);
  if (writer == nullptr)
    return SaveDataToFile(*data_, filename);
  else
    return (*writer)(*data_, filename);
}

int TFile::FWrite(const void* buffer, size_t size, int count) {
  ASSERT_HOST(is_writing_);
  ASSERT_HOST(size > 0);
  ASSERT_HOST(count >= 0);
  ASSERT_HOST(SIZE_MAX / size > count);
  size_t total = size * count;
  const char* buf = static_cast<const char*>(buffer);
  // This isn't very efficient, but memory is so fast compared to disk
  // that it is relatively unimportant, and very simple.
  for (size_t i = 0; i < total; ++i)
    data_->push_back(buf[i]);
  return count;
}

}  // namespace tesseract.
<commit_msg>Fix TFile::DeSerialize, TFile::Serialize for empty vectors<commit_after>/**********************************************************************
 * File:        serialis.cpp  (Formerly serialmac.h)
 * Description: Inline routines and macros for serialisation functions
 * Author:      Phil Cheatle
 *
 * (C) Copyright 1990, Hewlett-Packard Ltd.
 ** 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 "errcode.h"
#include <tesseract/helpers.h>  // for ReverseN
#include "serialis.h"
#include <cstdio>

namespace tesseract {

// The default FileReader loads the whole file into the vector of char,
// returning false on error.
bool LoadDataFromFile(const char* filename, std::vector<char>* data) {
  bool result = false;
  FILE* fp = fopen(filename, "rb");
  if (fp != nullptr) {
    fseek(fp, 0, SEEK_END);
    auto size = std::ftell(fp);
    fseek(fp, 0, SEEK_SET);
    // Trying to open a directory on Linux sets size to LONG_MAX. Catch it here.
    if (size > 0 && size < LONG_MAX) {
      // reserve an extra byte in case caller wants to append a '\0' character
      data->reserve(size + 1);
      data->resize(size); // TODO: optimize no init
      result = static_cast<long>(fread(&(*data)[0], 1, size, fp)) == size;
    }
    fclose(fp);
  }
  return result;
}

// The default FileWriter writes the vector of char to the filename file,
// returning false on error.
bool SaveDataToFile(const std::vector<char>& data, const char* filename) {
  FILE* fp = fopen(filename, "wb");
  if (fp == nullptr) {
    return false;
  }
  bool result =
      static_cast<int>(fwrite(&data[0], 1, data.size(), fp)) == data.size();
  fclose(fp);
  return result;
}

bool DeSerialize(FILE* fp, char* data, size_t n) {
  return fread(data, sizeof(*data), n, fp) == n;
}

bool DeSerialize(FILE* fp, float* data, size_t n) {
  return fread(data, sizeof(*data), n, fp) == n;
}

bool DeSerialize(FILE* fp, int8_t* data, size_t n) {
  return fread(data, sizeof(*data), n, fp) == n;
}

bool DeSerialize(FILE* fp, int16_t* data, size_t n) {
  return fread(data, sizeof(*data), n, fp) == n;
}

bool DeSerialize(FILE* fp, int32_t* data, size_t n) {
  return fread(data, sizeof(*data), n, fp) == n;
}

bool DeSerialize(FILE* fp, uint8_t* data, size_t n) {
  return fread(data, sizeof(*data), n, fp) == n;
}

bool DeSerialize(FILE* fp, uint16_t* data, size_t n) {
  return fread(data, sizeof(*data), n, fp) == n;
}

bool DeSerialize(FILE* fp, uint32_t* data, size_t n) {
  return fread(data, sizeof(*data), n, fp) == n;
}

bool Serialize(FILE* fp, const char* data, size_t n) {
  return fwrite(data, sizeof(*data), n, fp) == n;
}

bool Serialize(FILE* fp, const float* data, size_t n) {
  return fwrite(data, sizeof(*data), n, fp) == n;
}

bool Serialize(FILE* fp, const int8_t* data, size_t n) {
  return fwrite(data, sizeof(*data), n, fp) == n;
}

bool Serialize(FILE* fp, const int16_t* data, size_t n) {
  return fwrite(data, sizeof(*data), n, fp) == n;
}

bool Serialize(FILE* fp, const int32_t* data, size_t n) {
  return fwrite(data, sizeof(*data), n, fp) == n;
}

bool Serialize(FILE* fp, const uint8_t* data, size_t n) {
  return fwrite(data, sizeof(*data), n, fp) == n;
}

bool Serialize(FILE* fp, const uint16_t* data, size_t n) {
  return fwrite(data, sizeof(*data), n, fp) == n;
}

bool Serialize(FILE* fp, const uint32_t* data, size_t n) {
  return fwrite(data, sizeof(*data), n, fp) == n;
}

TFile::TFile()
    : data_(nullptr),
      offset_(0),
      data_is_owned_(false),
      is_writing_(false),
      swap_(false) {}

TFile::~TFile() {
  if (data_is_owned_)
    delete data_;
}

bool TFile::DeSerialize(std::vector<char>& data) {
  uint32_t size;
  if (!DeSerialize(&size)) {
    return false;
  } else if (size > 0) {
    // TODO: optimize.
    data.resize(size);
    return DeSerialize(&data[0], data.size());
  }
  data.clear();
  return true;
}

bool TFile::DeSerialize(char* buffer, size_t count) {
  return FRead(buffer, sizeof(*buffer), count) == count;
}

bool TFile::DeSerialize(double* buffer, size_t count) {
  return FReadEndian(buffer, sizeof(*buffer), count) == count;
}

bool TFile::DeSerialize(float* buffer, size_t count) {
  return FReadEndian(buffer, sizeof(*buffer), count) == count;
}

bool TFile::DeSerialize(int8_t* buffer, size_t count) {
  return FRead(buffer, sizeof(*buffer), count) == count;
}

bool TFile::DeSerialize(int16_t* buffer, size_t count) {
  return FReadEndian(buffer, sizeof(*buffer), count) == count;
}

bool TFile::DeSerialize(int32_t* buffer, size_t count) {
  return FReadEndian(buffer, sizeof(*buffer), count) == count;
}

bool TFile::DeSerialize(int64_t* buffer, size_t count) {
  return FReadEndian(buffer, sizeof(*buffer), count) == count;
}

bool TFile::DeSerialize(uint8_t* buffer, size_t count) {
  return FRead(buffer, sizeof(*buffer), count) == count;
}

bool TFile::DeSerialize(uint16_t* buffer, size_t count) {
  return FReadEndian(buffer, sizeof(*buffer), count) == count;
}

bool TFile::DeSerialize(uint32_t* buffer, size_t count) {
  return FReadEndian(buffer, sizeof(*buffer), count) == count;
}

bool TFile::DeSerialize(uint64_t* buffer, size_t count) {
  return FReadEndian(buffer, sizeof(*buffer), count) == count;
}

bool TFile::Serialize(const std::vector<char>& data) {
  uint32_t size = data.size();
  if (!Serialize(&size)) {
    return false;
  } else if (size > 0) {
  return Serialize(&data[0], size);
  }
  return true;
}

bool TFile::Serialize(const char* buffer, size_t count) {
  return FWrite(buffer, sizeof(*buffer), count) == count;
}

bool TFile::Serialize(const double* buffer, size_t count) {
  return FWrite(buffer, sizeof(*buffer), count) == count;
}

bool TFile::Serialize(const float* buffer, size_t count) {
  return FWrite(buffer, sizeof(*buffer), count) == count;
}

bool TFile::Serialize(const int8_t* buffer, size_t count) {
  return FWrite(buffer, sizeof(*buffer), count) == count;
}

bool TFile::Serialize(const int16_t* buffer, size_t count) {
  return FWrite(buffer, sizeof(*buffer), count) == count;
}

bool TFile::Serialize(const int32_t* buffer, size_t count) {
  return FWrite(buffer, sizeof(*buffer), count) == count;
}

bool TFile::Serialize(const int64_t* buffer, size_t count) {
  return FWrite(buffer, sizeof(*buffer), count) == count;
}

bool TFile::Serialize(const uint8_t* buffer, size_t count) {
  return FWrite(buffer, sizeof(*buffer), count) == count;
}

bool TFile::Serialize(const uint16_t* buffer, size_t count) {
  return FWrite(buffer, sizeof(*buffer), count) == count;
}

bool TFile::Serialize(const uint32_t* buffer, size_t count) {
  return FWrite(buffer, sizeof(*buffer), count) == count;
}

bool TFile::Serialize(const uint64_t* buffer, size_t count) {
  return FWrite(buffer, sizeof(*buffer), count) == count;
}

bool TFile::Skip(size_t count) {
  offset_ += count;
  return true;
}

bool TFile::Open(const char* filename, FileReader reader) {
  if (!data_is_owned_) {
    data_ = new std::vector<char>;
    data_is_owned_ = true;
  }
  offset_ = 0;
  is_writing_ = false;
  swap_ = false;
  if (reader == nullptr)
    return LoadDataFromFile(filename, data_);
  else
    return (*reader)(filename, data_);
}

bool TFile::Open(const char* data, int size) {
  offset_ = 0;
  if (!data_is_owned_) {
    data_ = new std::vector<char>;
    data_is_owned_ = true;
  }
  is_writing_ = false;
  swap_ = false;
  data_->resize(size); // TODO: optimize no init
  memcpy(&(*data_)[0], data, size);
  return true;
}

bool TFile::Open(FILE* fp, int64_t end_offset) {
  offset_ = 0;
  auto current_pos = std::ftell(fp);
  if (current_pos < 0) {
    // ftell failed.
    return false;
  }
  if (end_offset < 0) {
    if (fseek(fp, 0, SEEK_END))
      return false;
    end_offset = ftell(fp);
    if (fseek(fp, current_pos, SEEK_SET))
      return false;
  }
  int size = end_offset - current_pos;
  is_writing_ = false;
  swap_ = false;
  if (!data_is_owned_) {
    data_ = new std::vector<char>;
    data_is_owned_ = true;
  }
  data_->resize(size); // TODO: optimize no init
  return static_cast<int>(fread(&(*data_)[0], 1, size, fp)) == size;
}

char* TFile::FGets(char* buffer, int buffer_size) {
  ASSERT_HOST(!is_writing_);
  int size = 0;
  while (size + 1 < buffer_size && offset_ < data_->size()) {
    buffer[size++] = (*data_)[offset_++];
    if ((*data_)[offset_ - 1] == '\n') break;
  }
  if (size < buffer_size) buffer[size] = '\0';
  return size > 0 ? buffer : nullptr;
}

int TFile::FReadEndian(void* buffer, size_t size, int count) {
  int num_read = FRead(buffer, size, count);
  if (swap_) {
    char* char_buffer = static_cast<char*>(buffer);
    for (int i = 0; i < num_read; ++i, char_buffer += size) {
      ReverseN(char_buffer, size);
    }
  }
  return num_read;
}

int TFile::FRead(void* buffer, size_t size, int count) {
  ASSERT_HOST(!is_writing_);
  ASSERT_HOST(size > 0);
  ASSERT_HOST(count >= 0);
  size_t required_size;
  if (SIZE_MAX / size <= count) {
    // Avoid integer overflow.
    required_size = data_->size() - offset_;
  } else {
    required_size = size * count;
    if (data_->size() - offset_ < required_size) {
      required_size = data_->size() - offset_;
    }
  }
  if (required_size > 0 && buffer != nullptr)
    memcpy(buffer, &(*data_)[offset_], required_size);
  offset_ += required_size;
  return required_size / size;
}

void TFile::Rewind() {
  ASSERT_HOST(!is_writing_);
  offset_ = 0;
}

void TFile::OpenWrite(std::vector<char>* data) {
  offset_ = 0;
  if (data != nullptr) {
    if (data_is_owned_) delete data_;
    data_ = data;
    data_is_owned_ = false;
  } else if (!data_is_owned_) {
    data_ = new std::vector<char>;
    data_is_owned_ = true;
  }
  is_writing_ = true;
  swap_ = false;
  data_->resize(0);
}

bool TFile::CloseWrite(const char* filename, FileWriter writer) {
  ASSERT_HOST(is_writing_);
  if (writer == nullptr)
    return SaveDataToFile(*data_, filename);
  else
    return (*writer)(*data_, filename);
}

int TFile::FWrite(const void* buffer, size_t size, int count) {
  ASSERT_HOST(is_writing_);
  ASSERT_HOST(size > 0);
  ASSERT_HOST(count >= 0);
  ASSERT_HOST(SIZE_MAX / size > count);
  size_t total = size * count;
  const char* buf = static_cast<const char*>(buffer);
  // This isn't very efficient, but memory is so fast compared to disk
  // that it is relatively unimportant, and very simple.
  for (size_t i = 0; i < total; ++i)
    data_->push_back(buf[i]);
  return count;
}

}  // namespace tesseract.
<|endoftext|>