<commit_before>/******************************************************************************\
* File:          textfile.cpp
* Purpose:       Implementation of class 'wxExTextFileWithListView'
* Author:        Anton van Wezenbeek
* RCS-ID:        $Id$
*
* Copyright (c) 1998-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/extension/report/textfile.h>
#include <wx/extension/app.h>
#include <wx/extension/report/defs.h>
#include <wx/extension/report/listview.h>
#include <wx/extension/report/frame.h>
#include <wx/extension/report/listitem.h>

wxExListViewWithFrame* wxExTextFileWithListView::m_Report = NULL;
wxExFrameWithHistory* wxExTextFileWithListView::m_Frame = NULL;

void SetItemColumnStatistics(
  wxExListItemWithFileName& item,
  const wxString& col,
  wxExStatistics<long>& stat)
{
  item.SetColumnText(
    col,
    wxString::Format("%ld", stat.Get(col)));
}

#if USE_EMBEDDED_SQL
wxExOTL wxExTextFileWithListView::m_otl;

class Recordset
{
public:
  Recordset(otl_connect* db, wxExTextFile* file)
    : m_db(db)
    , m_TextFile(file)
    , m_Records(0){}
  size_t GetRecords() const {return m_Records;};
  bool ExecQuery(const wxString& query);
  static const wxString QueryRunTimeText() {return "QUERY RUN TIME: ";};
private:
  void UpdateTextFileFromQuery();
  otl_connect* m_db;
  otl_stream m_stream;
  wxExTextFile* m_TextFile;
  wxString m_Query;
  size_t m_Records;
};
#endif

wxExTextFileWithListView::wxExTextFileWithListView(
  const wxExFileName& filename,
  const wxExTool& tool)
  : wxExTextFile(filename, tool, wxExApp::GetConfig())
#if USE_EMBEDDED_SQL
  , m_SQLResultsParsing(false)
#endif
{
}

#if USE_EMBEDDED_SQL
bool wxExTextFileWithListView::ParseComments()
{
  if (GetTool().GetId() == ID_TOOL_SQL || GetTool().GetId() == ID_TOOL_REPORT_SQL)
  {
    if (!m_SQLResultsParsing)
    {
      if (GetComments().substr(0, 4) == " SQL")
      {
        if (SetSQLQuery())
        {
          if (!ParseSQL())
          {
            return false;
          }
        }
      }
      else
      {
        ClearComments();
      }
    }
    else
    {
      if (GetTool().GetId() == ID_TOOL_REPORT_SQL &&
        GetComments().length() > Recordset::QueryRunTimeText().length() + 1 &&
        GetComments().substr(
          1,
          Recordset::QueryRunTimeText().length()) == Recordset::QueryRunTimeText())
      {
        const int start_of_runtime = Recordset::QueryRunTimeText().length() + 1;
        m_SQLQueryRunTime = GetComments().substr(start_of_runtime);
        Report();
      }

      if (GetComments().substr(0, 8) == " SQL END")
      {
        m_SQLResultsParsing = false;
      }

      ClearComments();
    }
  }

  return wxExTextFile::ParseComments();
}
#endif

#if USE_EMBEDDED_SQL
bool wxExTextFileWithListView::ParseSQL()
{
/*
 ; SQL # ..
 ;       .. #
<-- new data inserted by the recordset
 ; QUERY RUN TIME: 981201 150953
 ; USING DATABASE F\GAREX\CONFIG_MAIN.mdb
 new data
 ..
<-- end of new data
<-- old data starts here, will be deleted (the marker points to here)
 ; QUERY RUN TIME: 981201 150953
 ; USING DATABASE F\GAREX\CONFIG_MAIN.mdb
 old data
 ..
<-- end of old data
 ; SQL END (this statement triggers deletion)
*/
  if (GetTool().GetId() == ID_TOOL_SQL)
  {
    wxExApp::Log(
      _("File") + ": " + GetFileName().GetFullName() + " Query: " + wxExSkipWhiteSpace(m_SQLQuery));

    Recordset rs(&m_otl.GetConnect(), this);
    if (!rs.ExecQuery(m_SQLQuery))
    {
      return false;
    }

    const wxString msg = wxString::Format(_("Retrieved: %d records"), rs.GetRecords());
    wxExApp::Log(msg);
#if wxUSE_STATUSBAR
    wxExFrame::StatusText(msg);
#endif
  }

  // Test for SQL end statement.
  const size_t marker = GetCurrentLine();
  ClearComments();
  m_SQLResultsParsing = true;

  while (!Eof() && m_SQLResultsParsing)
  {
    if (!ParseLine(GetNextLine()))
    {
      return false;
    }
  }

  if (m_SQLResultsParsing)
  {
    wxLogError("Missing SQL END after query: " + wxExSkipWhiteSpace(m_SQLQuery));
    return false;
  }

  // Remove all old lines, except the last one containing the end statement.
  if (GetTool().GetId() == ID_TOOL_SQL)
  {
    for (size_t i = GetCurrentLine() - 1; i >= marker; i--)
    {
      RemoveLine(i);
    }

    GoToLine(marker);
  }

  GetStatisticElements().Inc(_("Actions Completed"));

  return true;
}
#endif

void wxExTextFileWithListView::Report()
{
  wxExListItemWithFileName item(m_Report, GetFileName().GetFullPath());
  item.Insert();

  const int line = (GetTool().GetId() == ID_TOOL_REPORT_REVISION ?
    GetCurrentLine():
    GetCurrentLine() + 1);

  item.SetColumnText(_("Line No"), wxString::Format("%d", line));

  switch (GetTool().GetId())
  {
  case ID_TOOL_REPORT_REPLACE:
    item.SetColumnText(_("Replaced"), wxExApp::GetConfig()->GetFindReplaceData()->GetReplaceString());
  case ID_TOOL_REPORT_FIND:
    item.SetColumnText(_("Line"), GetRCS().GetDescription().Strip(wxString::both));
    item.SetColumnText(_("Match"), wxExApp::GetConfig()->GetFindReplaceData()->GetFindString());
  break;

  case ID_TOOL_REPORT_REVISION:
    item.UpdateRevisionList(GetRCS());
  break;

#if USE_EMBEDDED_SQL
  case ID_TOOL_REPORT_SQL:
    item.SetColumnText(_("Query"), m_SQLQuery);
    item.SetColumnText(_("Run Time"), m_SQLQueryRunTime);
  break;
#endif

  default: wxFAIL;
  }
}

void wxExTextFileWithListView::ReportStatistics()
{
  if (GetTool().GetId() == ID_TOOL_REPORT_KEYWORD)
  {
    m_Report = m_Frame->Activate(
      wxExListViewFile::GetTypeTool(GetTool()),
      &GetFileName().GetLexer());

    if (m_Report == NULL)
    {
      wxFAIL;
      return;
    }
  }

  wxExListItemWithFileName item(m_Report, GetFileName().GetFullPath());
  item.Insert();

  switch (GetTool().GetId())
  {
  case ID_TOOL_REPORT_COUNT:
    SetItemColumnStatistics(item, _("Lines"), GetStatisticElements());
    SetItemColumnStatistics(item, _("Lines Of Code"), GetStatisticElements());
    SetItemColumnStatistics(item, _("Empty Lines"), GetStatisticElements());
    SetItemColumnStatistics(item, _("Words Of Code"), GetStatisticElements());
    SetItemColumnStatistics(item, _("Comments"), GetStatisticElements());
    SetItemColumnStatistics(item, _("Comment Size"), GetStatisticElements());
  break;

  case ID_TOOL_REPORT_KEYWORD:
  {
    long total = 0;
    for (size_t i = 0; i < GetFileName().GetLexer().GetKeywords().size(); i++)
    {
      const wxString name = m_Report->GetColumn(i + 1).GetText();
      const long value = GetStatisticKeywords().Get(name);
      item.SetColumnText(i + 1, wxString::Format("%ld", value));
      total += value;
    }
    item.SetColumnText(
      GetFileName().GetLexer().GetKeywords().size() + 1,
      wxString::Format("%ld", total));
  }
  break;

  default: wxFAIL;
  }
}

#if USE_EMBEDDED_SQL
bool wxExTextFileWithListView::SetSQLQuery()
{
  const size_t pos_start_of_query = GetComments().find('#');
  const size_t pos_end_of_query = GetComments().rfind('#');

  if (pos_start_of_query == wxString::npos ||
      pos_start_of_query == pos_end_of_query)
  {
    return false;
  }

  m_SQLQuery = GetComments().substr(
    pos_start_of_query + 1,
    pos_end_of_query - pos_start_of_query - 1);

  m_SQLQuery.Trim(false);
  m_SQLQuery.Trim(true);

  return true;
}
#endif

bool wxExTextFileWithListView::SetupTool(const wxExTool& tool)
{
#if USE_EMBEDDED_SQL
  if (tool.GetId() == ID_TOOL_SQL)
  {
    if (m_otl.IsConnected())
    {
      m_otl.Logoff();
    }

    // This is a static function, we cannot use this pointer.
    wxASSERT(wxTheApp != NULL);

    if (!m_otl.Logon(wxTheApp->GetTopWindow(), wxExApp::GetConfig()))
    {
      return false;
    }
  }
#endif

  if (tool.IsReportType())
  {
    wxASSERT(wxTheApp != NULL);
    wxWindow* window = wxTheApp->GetTopWindow();
    m_Frame = wxDynamicCast(window, wxExFrameWithHistory);

    if (m_Frame == NULL)
    {
      wxFAIL;
      return false;
    }

    if (tool.GetId() != ID_TOOL_REPORT_KEYWORD)
    {
      m_Report = m_Frame->Activate(wxExListViewFile::GetTypeTool(tool));

      if (m_Report == NULL)
      {
        wxFAIL;
        return false;
      }
    }
  }

  return true;
}

#if USE_EMBEDDED_SQL
bool Recordset::ExecQuery(const wxString& query)
{
  // If the query does not contain any space,
  // assume that it specifies an existing query in the database.
  // Otherwise the statement itself is a query, pass it through as specified.
  m_Query = (!query.Contains(" ") ? "SELECT * FROM " + query: query);

  try
  {
    m_stream.set_all_column_types(otl_all_num2str | otl_all_date2str);
    m_stream.open(1024, m_Query.c_str(), *m_db);
    UpdateTextFileFromQuery();
    return true;
  }
  catch (otl_exception& p)
  {
    wxTextEntryDialog(
      NULL,
      _("Error"),
      _("ODBC Error") + ":",
      p.msg,
      wxOK | wxCENTRE | wxTE_MULTILINE | wxRESIZE_BORDER).ShowModal();
    wxExApp::Log(p.msg);
    return false;
  }
}

void Recordset::UpdateTextFileFromQuery()
{
  m_TextFile->GoToLine(m_TextFile->GetCurrentLine() + 1);
  m_TextFile->WriteComment(QueryRunTimeText() + wxDateTime::Now().Format(EX_TIMESTAMP_FORMAT));
  m_TextFile->WriteComment("USING ODBC DATABASE: " + wxExApp::GetConfig(_("Datasource")));

  // Get columns.
  int desc_len;
  m_stream.describe_select(desc_len);

   // Get all rows.
  while (!m_stream.eof())
  {
    m_Records++;
    wxString line;
    char rowstr[512];

    for (int n = 0; n < desc_len; n++)
    {
      m_stream >> rowstr;
      line += rowstr;

      if (n < desc_len - 1)
      {
        line += "\t";
      }
    }

    m_TextFile->InsertLine(line);
  }
}
#endif
<commit_msg>added include frd.h where needed<commit_after>/******************************************************************************\
* File:          textfile.cpp
* Purpose:       Implementation of class 'wxExTextFileWithListView'
* Author:        Anton van Wezenbeek
* RCS-ID:        $Id$
*
* Copyright (c) 1998-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/extension/report/textfile.h>
#include <wx/extension/app.h>
#include <wx/extension/frd.h>
#include <wx/extension/report/defs.h>
#include <wx/extension/report/listview.h>
#include <wx/extension/report/frame.h>
#include <wx/extension/report/listitem.h>

wxExListViewWithFrame* wxExTextFileWithListView::m_Report = NULL;
wxExFrameWithHistory* wxExTextFileWithListView::m_Frame = NULL;

void SetItemColumnStatistics(
  wxExListItemWithFileName& item,
  const wxString& col,
  wxExStatistics<long>& stat)
{
  item.SetColumnText(
    col,
    wxString::Format("%ld", stat.Get(col)));
}

#if USE_EMBEDDED_SQL
wxExOTL wxExTextFileWithListView::m_otl;

class Recordset
{
public:
  Recordset(otl_connect* db, wxExTextFile* file)
    : m_db(db)
    , m_TextFile(file)
    , m_Records(0){}
  size_t GetRecords() const {return m_Records;};
  bool ExecQuery(const wxString& query);
  static const wxString QueryRunTimeText() {return "QUERY RUN TIME: ";};
private:
  void UpdateTextFileFromQuery();
  otl_connect* m_db;
  otl_stream m_stream;
  wxExTextFile* m_TextFile;
  wxString m_Query;
  size_t m_Records;
};
#endif

wxExTextFileWithListView::wxExTextFileWithListView(
  const wxExFileName& filename,
  const wxExTool& tool)
  : wxExTextFile(filename, tool, wxExApp::GetConfig())
#if USE_EMBEDDED_SQL
  , m_SQLResultsParsing(false)
#endif
{
}

#if USE_EMBEDDED_SQL
bool wxExTextFileWithListView::ParseComments()
{
  if (GetTool().GetId() == ID_TOOL_SQL || GetTool().GetId() == ID_TOOL_REPORT_SQL)
  {
    if (!m_SQLResultsParsing)
    {
      if (GetComments().substr(0, 4) == " SQL")
      {
        if (SetSQLQuery())
        {
          if (!ParseSQL())
          {
            return false;
          }
        }
      }
      else
      {
        ClearComments();
      }
    }
    else
    {
      if (GetTool().GetId() == ID_TOOL_REPORT_SQL &&
        GetComments().length() > Recordset::QueryRunTimeText().length() + 1 &&
        GetComments().substr(
          1,
          Recordset::QueryRunTimeText().length()) == Recordset::QueryRunTimeText())
      {
        const int start_of_runtime = Recordset::QueryRunTimeText().length() + 1;
        m_SQLQueryRunTime = GetComments().substr(start_of_runtime);
        Report();
      }

      if (GetComments().substr(0, 8) == " SQL END")
      {
        m_SQLResultsParsing = false;
      }

      ClearComments();
    }
  }

  return wxExTextFile::ParseComments();
}
#endif

#if USE_EMBEDDED_SQL
bool wxExTextFileWithListView::ParseSQL()
{
/*
 ; SQL # ..
 ;       .. #
<-- new data inserted by the recordset
 ; QUERY RUN TIME: 981201 150953
 ; USING DATABASE F\GAREX\CONFIG_MAIN.mdb
 new data
 ..
<-- end of new data
<-- old data starts here, will be deleted (the marker points to here)
 ; QUERY RUN TIME: 981201 150953
 ; USING DATABASE F\GAREX\CONFIG_MAIN.mdb
 old data
 ..
<-- end of old data
 ; SQL END (this statement triggers deletion)
*/
  if (GetTool().GetId() == ID_TOOL_SQL)
  {
    wxExApp::Log(
      _("File") + ": " + GetFileName().GetFullName() + " Query: " + wxExSkipWhiteSpace(m_SQLQuery));

    Recordset rs(&m_otl.GetConnect(), this);
    if (!rs.ExecQuery(m_SQLQuery))
    {
      return false;
    }

    const wxString msg = wxString::Format(_("Retrieved: %d records"), rs.GetRecords());
    wxExApp::Log(msg);
#if wxUSE_STATUSBAR
    wxExFrame::StatusText(msg);
#endif
  }

  // Test for SQL end statement.
  const size_t marker = GetCurrentLine();
  ClearComments();
  m_SQLResultsParsing = true;

  while (!Eof() && m_SQLResultsParsing)
  {
    if (!ParseLine(GetNextLine()))
    {
      return false;
    }
  }

  if (m_SQLResultsParsing)
  {
    wxLogError("Missing SQL END after query: " + wxExSkipWhiteSpace(m_SQLQuery));
    return false;
  }

  // Remove all old lines, except the last one containing the end statement.
  if (GetTool().GetId() == ID_TOOL_SQL)
  {
    for (size_t i = GetCurrentLine() - 1; i >= marker; i--)
    {
      RemoveLine(i);
    }

    GoToLine(marker);
  }

  GetStatisticElements().Inc(_("Actions Completed"));

  return true;
}
#endif

void wxExTextFileWithListView::Report()
{
  wxExListItemWithFileName item(m_Report, GetFileName().GetFullPath());
  item.Insert();

  const int line = (GetTool().GetId() == ID_TOOL_REPORT_REVISION ?
    GetCurrentLine():
    GetCurrentLine() + 1);

  item.SetColumnText(_("Line No"), wxString::Format("%d", line));

  switch (GetTool().GetId())
  {
  case ID_TOOL_REPORT_REPLACE:
    item.SetColumnText(_("Replaced"), wxExApp::GetConfig()->GetFindReplaceData()->GetReplaceString());
  case ID_TOOL_REPORT_FIND:
    item.SetColumnText(_("Line"), GetRCS().GetDescription().Strip(wxString::both));
    item.SetColumnText(_("Match"), wxExApp::GetConfig()->GetFindReplaceData()->GetFindString());
  break;

  case ID_TOOL_REPORT_REVISION:
    item.UpdateRevisionList(GetRCS());
  break;

#if USE_EMBEDDED_SQL
  case ID_TOOL_REPORT_SQL:
    item.SetColumnText(_("Query"), m_SQLQuery);
    item.SetColumnText(_("Run Time"), m_SQLQueryRunTime);
  break;
#endif

  default: wxFAIL;
  }
}

void wxExTextFileWithListView::ReportStatistics()
{
  if (GetTool().GetId() == ID_TOOL_REPORT_KEYWORD)
  {
    m_Report = m_Frame->Activate(
      wxExListViewFile::GetTypeTool(GetTool()),
      &GetFileName().GetLexer());

    if (m_Report == NULL)
    {
      wxFAIL;
      return;
    }
  }

  wxExListItemWithFileName item(m_Report, GetFileName().GetFullPath());
  item.Insert();

  switch (GetTool().GetId())
  {
  case ID_TOOL_REPORT_COUNT:
    SetItemColumnStatistics(item, _("Lines"), GetStatisticElements());
    SetItemColumnStatistics(item, _("Lines Of Code"), GetStatisticElements());
    SetItemColumnStatistics(item, _("Empty Lines"), GetStatisticElements());
    SetItemColumnStatistics(item, _("Words Of Code"), GetStatisticElements());
    SetItemColumnStatistics(item, _("Comments"), GetStatisticElements());
    SetItemColumnStatistics(item, _("Comment Size"), GetStatisticElements());
  break;

  case ID_TOOL_REPORT_KEYWORD:
  {
    long total = 0;
    for (size_t i = 0; i < GetFileName().GetLexer().GetKeywords().size(); i++)
    {
      const wxString name = m_Report->GetColumn(i + 1).GetText();
      const long value = GetStatisticKeywords().Get(name);
      item.SetColumnText(i + 1, wxString::Format("%ld", value));
      total += value;
    }
    item.SetColumnText(
      GetFileName().GetLexer().GetKeywords().size() + 1,
      wxString::Format("%ld", total));
  }
  break;

  default: wxFAIL;
  }
}

#if USE_EMBEDDED_SQL
bool wxExTextFileWithListView::SetSQLQuery()
{
  const size_t pos_start_of_query = GetComments().find('#');
  const size_t pos_end_of_query = GetComments().rfind('#');

  if (pos_start_of_query == wxString::npos ||
      pos_start_of_query == pos_end_of_query)
  {
    return false;
  }

  m_SQLQuery = GetComments().substr(
    pos_start_of_query + 1,
    pos_end_of_query - pos_start_of_query - 1);

  m_SQLQuery.Trim(false);
  m_SQLQuery.Trim(true);

  return true;
}
#endif

bool wxExTextFileWithListView::SetupTool(const wxExTool& tool)
{
#if USE_EMBEDDED_SQL
  if (tool.GetId() == ID_TOOL_SQL)
  {
    if (m_otl.IsConnected())
    {
      m_otl.Logoff();
    }

    // This is a static function, we cannot use this pointer.
    wxASSERT(wxTheApp != NULL);

    if (!m_otl.Logon(wxTheApp->GetTopWindow(), wxExApp::GetConfig()))
    {
      return false;
    }
  }
#endif

  if (tool.IsReportType())
  {
    wxASSERT(wxTheApp != NULL);
    wxWindow* window = wxTheApp->GetTopWindow();
    m_Frame = wxDynamicCast(window, wxExFrameWithHistory);

    if (m_Frame == NULL)
    {
      wxFAIL;
      return false;
    }

    if (tool.GetId() != ID_TOOL_REPORT_KEYWORD)
    {
      m_Report = m_Frame->Activate(wxExListViewFile::GetTypeTool(tool));

      if (m_Report == NULL)
      {
        wxFAIL;
        return false;
      }
    }
  }

  return true;
}

#if USE_EMBEDDED_SQL
bool Recordset::ExecQuery(const wxString& query)
{
  // If the query does not contain any space,
  // assume that it specifies an existing query in the database.
  // Otherwise the statement itself is a query, pass it through as specified.
  m_Query = (!query.Contains(" ") ? "SELECT * FROM " + query: query);

  try
  {
    m_stream.set_all_column_types(otl_all_num2str | otl_all_date2str);
    m_stream.open(1024, m_Query.c_str(), *m_db);
    UpdateTextFileFromQuery();
    return true;
  }
  catch (otl_exception& p)
  {
    wxTextEntryDialog(
      NULL,
      _("Error"),
      _("ODBC Error") + ":",
      p.msg,
      wxOK | wxCENTRE | wxTE_MULTILINE | wxRESIZE_BORDER).ShowModal();
    wxExApp::Log(p.msg);
    return false;
  }
}

void Recordset::UpdateTextFileFromQuery()
{
  m_TextFile->GoToLine(m_TextFile->GetCurrentLine() + 1);
  m_TextFile->WriteComment(QueryRunTimeText() + wxDateTime::Now().Format(EX_TIMESTAMP_FORMAT));
  m_TextFile->WriteComment("USING ODBC DATABASE: " + wxExApp::GetConfig(_("Datasource")));

  // Get columns.
  int desc_len;
  m_stream.describe_select(desc_len);

   // Get all rows.
  while (!m_stream.eof())
  {
    m_Records++;
    wxString line;
    char rowstr[512];

    for (int n = 0; n < desc_len; n++)
    {
      m_stream >> rowstr;
      line += rowstr;

      if (n < desc_len - 1)
      {
        line += "\t";
      }
    }

    m_TextFile->InsertLine(line);
  }
}
#endif
<|endoftext|>


<commit_before>/*
MIT License

Copyright (c) 2016 ME_Kun_Han

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

#include "rs_kernel_buffer.h"
#include "rs_protocol_rtmp.h"

using namespace std;

c0c1::c0c1()
{

}

c0c1::~c0c1()
{

}

int c0c1::initialize()
{
    int ret =ERROR_SUCCESS;

    version = 0x03;
    timestamp = (uint32_t)rs_get_system_time_ms();
    zero = 0;
    random_data = rs_get_random(1528);
    return ret;
}

int c0c1::initialize(std::string buf)
{
    int ret = ERROR_SUCCESS;

    if (buf.size() < 1537) {
        ret = ERROR_RTMP_PROTOCOL_C0C1_LENGTH_ERROR;
        return ret;
    }

    RsBufferLittleEndian buffer;
    buffer.write_bytes(buf.c_str(), (int)buf.size());

    if (buffer.read_1_byte() != 0x03) {
        ret = ERROR_RTMP_PROTOCOL_VERSION_ERROR;
        return ret;
    }

    timestamp = buffer.read_4_byte();
    zero = buffer.read_4_byte();
    if (zero != 0) {
        ret = ERROR_RTMP_PROTOCOL_C0C1_ZERO_NOT_ZERO;
        return ret;
    }

    random_data = buffer.read_bytes(1528);

    return ret;
}

string c0c1::dumps()
{
    RsBufferLittleEndian buf;

    buf.write_1_byte(version);
    buf.write_4_byte(timestamp);
    buf.write_4_byte(zero);
    buf.write_bytes(random_data);

    return string(buf.dumps());
}

c2::c2()
{

}

c2::~c2()
{

}

int c2::initialize()
{
    int ret = ERROR_SUCCESS;
    timestamp = (uint32_t)rs_get_system_time_ms();
    timestamp2 = 0;
    random_data = rs_get_random(1528);
    return ret;
}

int c2::initialize(uint32_t ts, string rd)
{
    int ret = ERROR_SUCCESS;

    timestamp = (uint32_t)rs_get_system_time_ms();
    timestamp2 = ts;
    random_data = rd;

    return ret;
}

string c2::dumps()
{
    RsBufferLittleEndian buf;

    buf.write_4_byte(timestamp);
    buf.write_4_byte(timestamp2);
    buf.write_bytes(random_data);

    return string(buf.dumps());
}

RsRtmpChunkMessage::RsRtmpChunkMessage()
{
}

RsRtmpChunkMessage::~RsRtmpChunkMessage()
{
}

int RsRtmpChunkMessage::type_0_decode(IRsReaderWriter reader, uint32_t cs)
{
    int ret = ERROR_SUCCESS;
    bool has_extended_timestamp = false;
    string buf;

    assert(fmt == 0);
    // read timestamp
    if ((ret = reader.read(buf, 3)) != ERROR_SUCCESS) {
        cout << "read timestamp failed. ret=" << ret << endl;
        return ret;
    }
    timestamp = RsBufferLittleEndian::convert_3bytes_into_uint32(buf);
    buf.clear();

    if (timestamp > 16777215) {
        has_extended_timestamp = true;
    }

    // read message length
    if ((ret = reader.read(buf, 3)) != ERROR_SUCCESS) {
        cout << "read message length failed. ret=" << ret << endl;
        return ret;
    }

    message_length = RsBufferLittleEndian::convert_3bytes_into_uint32(buf);
    buf.clear();

    // read message type
    if ((ret = reader.read(buf, 1)) != ERROR_SUCCESS) {
        cout << "read message type failed. ret=" << ret << endl;
        return ret;
    }

    message_type = (uint8_t) buf.c_str()[0];
    buf.clear();

    // read message stream id
    if ((ret = reader.read(buf, 4)) != ERROR_SUCCESS) {
        cout << "read message stream id failed. ret=" << ret << endl;
        return ret;
    }

    message_stream_id = RsBufferLittleEndian::convert_4bytes_into_uint32(buf);
    buf.clear();

    // read extened timestamp if there it is
    if (has_extended_timestamp) {
        if ((ret = reader.read(buf, 4)) != ERROR_SUCCESS) {
            cout << "read extended timestamp failed. ret=" << ret << endl;
            return ret;
        }

        extended_timestamp = RsBufferLittleEndian::convert_4bytes_into_uint32(buf);
        buf.clear();
    }

    // read payload
    int length = message_length > chunk_size ? chunk_size : message_length;
    if ((ret = reader.read(buf, length)) != ERROR_SUCCESS) {
        cout << "read message payload failed. ret=" << ret << endl;
        return ret;
    }
    chunk_data = buf;

    return ERROR_SUCCESS;
}

int RsRtmpChunkMessage::type_1_decode()
{
    return ERROR_SUCCESS;
}

int RsRtmpChunkMessage::type_2_decode()
{
    return ERROR_SUCCESS;
}

int RsRtmpChunkMessage::type_3_decode(IRsReaderWriter reader, uint32_t size)
{
    int ret = ERROR_SUCCESS;

    if ((ret = reader.read(chunk_data, size)) != ERROR_SUCCESS) {
        cout << "read chunk data from reader failed. ret=" << ret << endl;
    }

    return ret;
}

int RsRtmpChunkMessage::initialize(IRsReaderWriter reader, uint32_t cs, uint32_t payload_length, uint64_t pre_timestamp)
{
    int ret = ERROR_SUCCESS;
    chunk_size = cs;

    // read basic header
    string buf;
    if ((ret = reader.read(buf, 1) != ERROR_SUCCESS)) {
        cout << "read fmt failed. ret=" << ret << endl;
        return ret;
    }
    fmt = uint8_t(buf.c_str()[0] & 0xc0);

    int tmp = buf.c_str()[0] & 0x3f;
    if (tmp > 1) {
        cs_id = uint8_t(tmp);
    }

    if (tmp == 0) {
        buf.clear();
        if ((ret = reader.read(buf, 1)) != ERROR_SUCCESS) {
            cout << "read 1 byte failed. ret=" << ret << endl;
            return ret;
        }
        cs_id = 64 + uint8_t(buf.c_str()[0]);
    }

    if (tmp == 1) {
        buf.clear();
        if ((ret = reader.read(buf, 2)) != ERROR_SUCCESS) {
            cout << "read 2 bytes failed. ret=" << ret << endl;
            return ret;
        }

        cs_id = (uint32_t) (64 + uint8_t(buf.c_str()[0]) + 256 * uint8_t(buf.c_str()[1]));
    }
    // read message header
    switch (fmt) {
        case 0:
            return type_0_decode(reader, cs);
        case 1:
            return type_1_decode();
        case 2:
            return type_2_decode();
        case 3:
            return type_3_decode(reader, cs < payload_length ? cs : payload_length);
        default:
            cout << "the fmt should be 0, 1, 2, 3, now is " << fmt << endl;
            ret = ERROR_RTMP_PROTOCOL_CHUNK_MESSAGE_FMT_ERROR;
            return ret;
    }
}

string RsRtmpChunkMessage::dumps()
{
    RsBufferLittleEndian msg;

    return string(msg.dumps());
}

vector<RsRtmpChunkMessage*> RsRtmpChunkMessage::create_chunk_messages(uint8_t fmt, string msg, uint8_t msg_type, uint32_t msg_stream_id)
{
    vector<RsRtmpChunkMessage*> msgs;

    return msgs;
}
<commit_msg>refine code<commit_after>/*
MIT License

Copyright (c) 2016 ME_Kun_Han

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

#include "rs_kernel_buffer.h"
#include "rs_protocol_rtmp.h"

using namespace std;
#define CHUNK_MESSAGE_TIMESTAMP_MAX 16777215

c0c1::c0c1()
{

}

c0c1::~c0c1()
{

}

int c0c1::initialize()
{
    int ret =ERROR_SUCCESS;

    version = 0x03;
    timestamp = (uint32_t)rs_get_system_time_ms();
    zero = 0;
    random_data = rs_get_random(1528);
    return ret;
}

int c0c1::initialize(std::string buf)
{
    int ret = ERROR_SUCCESS;

    if (buf.size() < 1537) {
        ret = ERROR_RTMP_PROTOCOL_C0C1_LENGTH_ERROR;
        return ret;
    }

    RsBufferLittleEndian buffer;
    buffer.write_bytes(buf.c_str(), (int)buf.size());

    if (buffer.read_1_byte() != 0x03) {
        ret = ERROR_RTMP_PROTOCOL_VERSION_ERROR;
        return ret;
    }

    timestamp = buffer.read_4_byte();
    zero = buffer.read_4_byte();
    if (zero != 0) {
        ret = ERROR_RTMP_PROTOCOL_C0C1_ZERO_NOT_ZERO;
        return ret;
    }

    random_data = buffer.read_bytes(1528);

    return ret;
}

string c0c1::dumps()
{
    RsBufferLittleEndian buf;

    buf.write_1_byte(version);
    buf.write_4_byte(timestamp);
    buf.write_4_byte(zero);
    buf.write_bytes(random_data);

    return string(buf.dumps());
}

c2::c2()
{

}

c2::~c2()
{

}

int c2::initialize()
{
    int ret = ERROR_SUCCESS;
    timestamp = (uint32_t)rs_get_system_time_ms();
    timestamp2 = 0;
    random_data = rs_get_random(1528);
    return ret;
}

int c2::initialize(uint32_t ts, string rd)
{
    int ret = ERROR_SUCCESS;

    timestamp = (uint32_t)rs_get_system_time_ms();
    timestamp2 = ts;
    random_data = rd;

    return ret;
}

string c2::dumps()
{
    RsBufferLittleEndian buf;

    buf.write_4_byte(timestamp);
    buf.write_4_byte(timestamp2);
    buf.write_bytes(random_data);

    return string(buf.dumps());
}

RsRtmpChunkMessage::RsRtmpChunkMessage()
{
}

RsRtmpChunkMessage::~RsRtmpChunkMessage()
{
}

int RsRtmpChunkMessage::type_0_decode(IRsReaderWriter reader, uint32_t cs)
{
    int ret = ERROR_SUCCESS;
    bool has_extended_timestamp = false;
    string buf;

    assert(fmt == 0);
    // read timestamp
    if ((ret = reader.read(buf, 3)) != ERROR_SUCCESS) {
        cout << "read timestamp failed. ret=" << ret << endl;
        return ret;
    }
    timestamp = RsBufferLittleEndian::convert_3bytes_into_uint32(buf);
    buf.clear();

    if (timestamp > CHUNK_MESSAGE_TIMESTAMP_MAX) {
        has_extended_timestamp = true;
    }

    // read message length
    if ((ret = reader.read(buf, 3)) != ERROR_SUCCESS) {
        cout << "read message length failed. ret=" << ret << endl;
        return ret;
    }

    message_length = RsBufferLittleEndian::convert_3bytes_into_uint32(buf);
    buf.clear();

    // read message type
    if ((ret = reader.read(buf, 1)) != ERROR_SUCCESS) {
        cout << "read message type failed. ret=" << ret << endl;
        return ret;
    }

    message_type = (uint8_t) buf.c_str()[0];
    buf.clear();

    // read message stream id
    if ((ret = reader.read(buf, 4)) != ERROR_SUCCESS) {
        cout << "read message stream id failed. ret=" << ret << endl;
        return ret;
    }

    message_stream_id = RsBufferLittleEndian::convert_4bytes_into_uint32(buf);
    buf.clear();

    // read extened timestamp if there it is
    if (has_extended_timestamp) {
        if ((ret = reader.read(buf, 4)) != ERROR_SUCCESS) {
            cout << "read extended timestamp failed. ret=" << ret << endl;
            return ret;
        }

        extended_timestamp = RsBufferLittleEndian::convert_4bytes_into_uint32(buf);
        buf.clear();
    }

    // read payload
    int length = message_length > chunk_size ? chunk_size : message_length;
    if ((ret = reader.read(buf, length)) != ERROR_SUCCESS) {
        cout << "read message payload failed. ret=" << ret << endl;
        return ret;
    }
    chunk_data = buf;

    return ERROR_SUCCESS;
}

int RsRtmpChunkMessage::type_1_decode()
{
    return ERROR_SUCCESS;
}

int RsRtmpChunkMessage::type_2_decode()
{
    return ERROR_SUCCESS;
}

int RsRtmpChunkMessage::type_3_decode(IRsReaderWriter reader, uint32_t size)
{
    int ret = ERROR_SUCCESS;

    if ((ret = reader.read(chunk_data, size)) != ERROR_SUCCESS) {
        cout << "read chunk data from reader failed. ret=" << ret << endl;
    }

    return ret;
}

int RsRtmpChunkMessage::initialize(IRsReaderWriter reader, uint32_t cs, uint32_t payload_length, uint64_t pre_timestamp)
{
    int ret = ERROR_SUCCESS;
    chunk_size = cs;

    // read basic header
    string buf;
    if ((ret = reader.read(buf, 1) != ERROR_SUCCESS)) {
        cout << "read fmt failed. ret=" << ret << endl;
        return ret;
    }
    fmt = uint8_t(buf.c_str()[0] & 0xc0);

    int tmp = buf.c_str()[0] & 0x3f;
    if (tmp > 1) {
        cs_id = uint8_t(tmp);
    }

    if (tmp == 0) {
        buf.clear();
        if ((ret = reader.read(buf, 1)) != ERROR_SUCCESS) {
            cout << "read 1 byte failed. ret=" << ret << endl;
            return ret;
        }
        cs_id = 64 + uint8_t(buf.c_str()[0]);
    }

    if (tmp == 1) {
        buf.clear();
        if ((ret = reader.read(buf, 2)) != ERROR_SUCCESS) {
            cout << "read 2 bytes failed. ret=" << ret << endl;
            return ret;
        }

        cs_id = (uint32_t) (64 + uint8_t(buf.c_str()[0]) + 256 * uint8_t(buf.c_str()[1]));
    }
    // read message header
    switch (fmt) {
        case 0:
            return type_0_decode(reader, cs);
        case 1:
            return type_1_decode();
        case 2:
            return type_2_decode();
        case 3:
            return type_3_decode(reader, cs < payload_length ? cs : payload_length);
        default:
            cout << "the fmt should be 0, 1, 2, 3, now is " << fmt << endl;
            ret = ERROR_RTMP_PROTOCOL_CHUNK_MESSAGE_FMT_ERROR;
            return ret;
    }
}

string RsRtmpChunkMessage::dumps()
{
    RsBufferLittleEndian msg;

    return string(msg.dumps());
}

vector<RsRtmpChunkMessage*> RsRtmpChunkMessage::create_chunk_messages(uint8_t fmt, string msg, uint8_t msg_type, uint32_t msg_stream_id)
{
    vector<RsRtmpChunkMessage*> msgs;

    return msgs;
}
<|endoftext|>


<commit_before>// RUN: %clangxx -fsanitize=function %s -O3 -g -o %t
// RUN: %run %t 2>&1 | FileCheck %s
// Verify that we can disable symbolization if needed:
// RUN: UBSAN_OPTIONS=symbolize=0 ASAN_OPTIONS=symbolize=0 %run %t 2>&1 | FileCheck %s --check-prefix=NOSYM

// -fsanitize=function is unsupported on Darwin yet.
// XFAIL: darwin

#include <stdint.h>

void f() {}

void g(int x) {}

int main(void) {
  // CHECK: runtime error: call to function f() through pointer to incorrect function type 'void (*)(int)'
  // CHECK-NEXT: function.cpp:8: note: f() defined here
  // NOSYM: runtime error: call to function (unknown) through pointer to incorrect function type 'void (*)(int)'
  // NOSYM-NEXT: ({{.*}}+0x{{.*}}): note: (unknown) defined here
  reinterpret_cast<void (*)(int)>(reinterpret_cast<uintptr_t>(f))(42);

  // CHECK-NOT: runtime error: call to function g
  reinterpret_cast<void (*)(int)>(reinterpret_cast<uintptr_t>(g))(42);
}
<commit_msg>[ubsan] Follow-up for r216263: fix the expected line number.<commit_after>// RUN: %clangxx -fsanitize=function %s -O3 -g -o %t
// RUN: %run %t 2>&1 | FileCheck %s
// Verify that we can disable symbolization if needed:
// RUN: UBSAN_OPTIONS=symbolize=0 ASAN_OPTIONS=symbolize=0 %run %t 2>&1 | FileCheck %s --check-prefix=NOSYM

// -fsanitize=function is unsupported on Darwin yet.
// XFAIL: darwin

#include <stdint.h>

void f() {}

void g(int x) {}

int main(void) {
  // CHECK: runtime error: call to function f() through pointer to incorrect function type 'void (*)(int)'
  // CHECK-NEXT: function.cpp:11: note: f() defined here
  // NOSYM: runtime error: call to function (unknown) through pointer to incorrect function type 'void (*)(int)'
  // NOSYM-NEXT: ({{.*}}+0x{{.*}}): note: (unknown) defined here
  reinterpret_cast<void (*)(int)>(reinterpret_cast<uintptr_t>(f))(42);

  // CHECK-NOT: runtime error: call to function g
  reinterpret_cast<void (*)(int)>(reinterpret_cast<uintptr_t>(g))(42);
}
<|endoftext|>


<commit_before>/*
 * opencog/util/Config.cc
 *
 * Copyright (C) 2008 by Singularity Institute for Artificial Intelligence
 * All Rights Reserved
 *
 * Written by Gustavo Gama <gama@vettalabs.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "Config.h"

#include <fstream>
#include <sstream>
#include <cstdio>
#include <cstdlib>

#include <errno.h>

#include <opencog/util/platform.h>
#include <opencog/util/exceptions.h>

using namespace opencog;
using namespace std;

// returns a string with leading/trailing characters of a set stripped
static char const* blank_chars = " \t\f\v\n\r";
static string strip(string const& str)
{
    string::size_type const first = str.find_first_not_of(blank_chars);
    return (first == string::npos) ? string() : str.substr(first, str.find_last_not_of(blank_chars) - first + 1);
}

Config::~Config()
{
}

Config::Config()
{
    reset();
}

void Config::reset()
{
    table.clear();
    // load default configuration
    for (unsigned int i = 0; DEFAULT()[i] != ""; i += 2) {
        if (table.find(DEFAULT()[i]) == table.end()) {
            table[DEFAULT()[i]] = DEFAULT()[i + 1];
        }
    }
}

// constructor
void Config::load(const char* filename)
{
    // quit if no explicit filename was supplied
    if (filename == NULL) return;

    // reset to default values
    reset();

    // finally, read and process the config file
    ifstream fin(filename);
    if (!fin || !fin.good() || !fin.is_open()) throw IOException(TRACE_INFO, "[ERROR] unable to open file \"%s\"", filename);

    string line;
    string name;
    string value;
    unsigned int line_number = 0;

    while (++line_number, fin.good() && getline(fin, line)) {
        string::size_type idx;
        // find comment and discard the rest of the line
        if ((idx = line.find('#')) != string::npos) {
            line.replace(idx, line.size() - idx, "");
        }
        // search for the '=' character
        if ((idx = line.find('=')) != string::npos) {
            // select name and value
            name  = line.substr(0, idx);
            value = line.substr(idx + 1);
            // strip them
            name  = strip(name);
            value = strip(value);
            // finally, store the entries
            table[name] = value;
        } else if (line.find_first_not_of(blank_chars) != string::npos) {
            throw InvalidParamException(TRACE_INFO, "[ERROR] invalid configuration entry (line %d)", line_number);
        }
    }
    fin.close();
}

const bool Config::has(const string &name) const
{
    return (table.find(name) != table.end());
}

const string& Config::get(const string &name) const
{
    map<string, string>::const_iterator it = table.find(name);
    if (it == table.end()) throw InvalidParamException(TRACE_INFO, "[ERROR] parameter not found (%s)", name.c_str());
    return it->second;
}

const string& Config::operator[](const string &name) const
{
    return get(name);
}

int Config::get_int(const string &name) const
{
    int int_val;
    errno = 0;
    int_val = strtol(get(name).c_str(), NULL, 0);
    if (errno != 0) throw InvalidParamException(TRACE_INFO, "[ERROR] invalid integer parameter (%s)", name.c_str());
    return int_val;
}

double Config::get_double(const string &name) const
{
    double int_val;
    errno = 0;
    int_val = strtod(get(name).c_str(), NULL);
    if (errno != 0) throw InvalidParamException(TRACE_INFO, "[ERROR] invalid double parameter (%s: %s)", name.c_str(), get(name).c_str());
    return int_val;
}

bool Config::get_bool(const string &name) const
{
    if (strcasecmp(get(name).c_str(), "true") == 0) return true;
    else if (strcasecmp(get(name).c_str(), "false") == 0) return false;
    else throw InvalidParamException(TRACE_INFO, "[ERROR] invalid double parameter (%s: %s)", name.c_str(), get(name).c_str());
}

std::string Config::to_string() const
{
    std::ostringstream oss;
    oss << "{\"";
    for (map<string, string>::const_iterator it = table.begin(); it != table.end(); ++it) {
        if (it != table.begin()) oss << "\", \"";
        oss << it->first << "\" => \"" << it->second;
    }
    oss << "\"}";
    return oss.str();
}

// create and return the single instance
Config& opencog::config()
{
    static Config instance;
    return instance;
}
<commit_msg>Strip double quotes from configuration files. This allows us to use spaces on the property values.<commit_after>/*
 * opencog/util/Config.cc
 *
 * Copyright (C) 2008 by Singularity Institute for Artificial Intelligence
 * All Rights Reserved
 *
 * Written by Gustavo Gama <gama@vettalabs.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "Config.h"

#include <fstream>
#include <sstream>
#include <cstdio>
#include <cstdlib>

#include <errno.h>

#include <opencog/util/platform.h>
#include <opencog/util/exceptions.h>

using namespace opencog;
using namespace std;

// returns a string with leading/trailing characters of a set stripped
static char const* blank_chars = " \t\f\v\n\r";
static string strip(string const& str, char const *strip_chars = blank_chars)
{
    string::size_type const first = str.find_first_not_of(strip_chars);
    return (first == string::npos) ? string() : str.substr(first, str.find_last_not_of(strip_chars) - first + 1);
}

Config::~Config()
{
}

Config::Config()
{
    reset();
}

void Config::reset()
{
    table.clear();
    // load default configuration
    for (unsigned int i = 0; DEFAULT()[i] != ""; i += 2) {
        if (table.find(DEFAULT()[i]) == table.end()) {
            table[DEFAULT()[i]] = DEFAULT()[i + 1];
        }
    }
}

// constructor
void Config::load(const char* filename)
{
    // quit if no explicit filename was supplied
    if (filename == NULL) return;

    // reset to default values
    reset();

    // finally, read and process the config file
    ifstream fin(filename);
    if (!fin || !fin.good() || !fin.is_open()) throw IOException(TRACE_INFO, "[ERROR] unable to open file \"%s\"", filename);

    string line;
    string name;
    string value;
    unsigned int line_number = 0;

    while (++line_number, fin.good() && getline(fin, line)) {
        string::size_type idx;
        // find comment and discard the rest of the line
        if ((idx = line.find('#')) != string::npos) {
            line.replace(idx, line.size() - idx, "");
        }
        // search for the '=' character
        if ((idx = line.find('=')) != string::npos) {
            // select name and value
            name  = line.substr(0, idx);
            value = line.substr(idx + 1);
            // strip them
            name  = strip(name);
            value = strip(value);
            value = strip(value, "\"");
            // finally, store the entries
            table[name] = value;
        } else if (line.find_first_not_of(blank_chars) != string::npos) {
            throw InvalidParamException(TRACE_INFO, "[ERROR] invalid configuration entry (line %d)", line_number);
        }
    }
    fin.close();
}

const bool Config::has(const string &name) const
{
    return (table.find(name) != table.end());
}

const string& Config::get(const string &name) const
{
    map<string, string>::const_iterator it = table.find(name);
    if (it == table.end()) throw InvalidParamException(TRACE_INFO, "[ERROR] parameter not found (%s)", name.c_str());
    return it->second;
}

const string& Config::operator[](const string &name) const
{
    return get(name);
}

int Config::get_int(const string &name) const
{
    int int_val;
    errno = 0;
    int_val = strtol(get(name).c_str(), NULL, 0);
    if (errno != 0) throw InvalidParamException(TRACE_INFO, "[ERROR] invalid integer parameter (%s)", name.c_str());
    return int_val;
}

double Config::get_double(const string &name) const
{
    double int_val;
    errno = 0;
    int_val = strtod(get(name).c_str(), NULL);
    if (errno != 0) throw InvalidParamException(TRACE_INFO, "[ERROR] invalid double parameter (%s: %s)", name.c_str(), get(name).c_str());
    return int_val;
}

bool Config::get_bool(const string &name) const
{
    if (strcasecmp(get(name).c_str(), "true") == 0) return true;
    else if (strcasecmp(get(name).c_str(), "false") == 0) return false;
    else throw InvalidParamException(TRACE_INFO, "[ERROR] invalid double parameter (%s: %s)", name.c_str(), get(name).c_str());
}

std::string Config::to_string() const
{
    std::ostringstream oss;
    oss << "{\"";
    for (map<string, string>::const_iterator it = table.begin(); it != table.end(); ++it) {
        if (it != table.begin()) oss << "\", \"";
        oss << it->first << "\" => \"" << it->second;
    }
    oss << "\"}";
    return oss.str();
}

// create and return the single instance
Config& opencog::config()
{
    static Config instance;
    return instance;
}
<|endoftext|>


<commit_before>/*-------------------------------------------------------------------------
 * drawElements Quality Program Tester Core
 * ----------------------------------------
 *
 * Copyright (c) 2016 The Khronos Group Inc.
 *
 * 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.
 *
 *//*!
 * \file
 * \brief X11 using XCB utilities.
 *//*--------------------------------------------------------------------*/

#include "tcuX11Xcb.hpp"
#include "deMemory.h"

namespace tcu
{
namespace x11
{

XcbDisplay::XcbDisplay (EventState& platform, const char* name)
	: DisplayBase	(platform)
{
	m_connection						= xcb_connect(name, NULL);
	const xcb_setup_t		*setup		= xcb_get_setup(m_connection);
	xcb_screen_iterator_t	iterator	= xcb_setup_roots_iterator(setup);
	m_screen							= iterator.data;
}

XcbDisplay::~XcbDisplay (void)
{
	xcb_disconnect (m_connection);
}

void XcbDisplay::processEvents (void)
{
	xcb_generic_event_t *ev;
	while ((ev = xcb_poll_for_event(m_connection)))
	{
		deFree(ev);
		/* Manage your event */
	}
}

XcbWindow::XcbWindow (XcbDisplay& display, int width, int height, xcb_visualid_t* visual)
	: WindowBase	()
	, m_display		(display)
{
	xcb_connection_t*	connection = m_display.getConnection();
	uint32_t			values[2];
	m_window	= xcb_generate_id(connection);
	m_colormap	= xcb_generate_id(connection);

	if (visual == DE_NULL)
		visual = &m_display.getScreen()->root_visual;

	values[0] = m_display.getScreen()->white_pixel;
	values[1] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_PROPERTY_CHANGE;

	xcb_create_window	(
							connection,								// Connection
							XCB_COPY_FROM_PARENT,					// depth (same as root)
							m_window,								// window Id
							display.getScreen()->root,				// parent window
							0, 0,									// x, y
							static_cast<uint16_t >(width),			// width
							static_cast<uint16_t >(height),			// height
							10,										// border_width
							XCB_WINDOW_CLASS_INPUT_OUTPUT,			// class
							*visual,								// visual
							XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK,	// masks
							values									//not used yet
						);

	xcb_create_colormap	(
							connection,
							XCB_COLORMAP_ALLOC_NONE,
							m_colormap,
							m_window,
							*visual
						);

	xcb_alloc_color_reply_t* rep = xcb_alloc_color_reply(connection, xcb_alloc_color(connection, m_colormap, 65535, 0, 0), NULL);
	deFree(rep);
	xcb_flush (connection);
}

XcbWindow::~XcbWindow (void)
{
	xcb_flush (m_display.getConnection());
	xcb_free_colormap(m_display.getConnection(), m_colormap);
	xcb_destroy_window(m_display.getConnection(), m_window);
}

void XcbWindow::setVisibility (bool visible)
{
	if (visible == m_visible)
		return;

	if (visible)
		 xcb_map_window(m_display.getConnection(), m_window);
	else
		xcb_unmap_window(m_display.getConnection(), m_window);

	m_visible = visible;
	xcb_flush (m_display.getConnection());

}

void XcbWindow::processEvents (void)
{
	// A bit of a hack, since we don't really handle all the events.
	m_display.processEvents();
}

void XcbWindow::getDimensions (int* width, int* height) const
{
	xcb_get_geometry_reply_t *geom;
	geom = xcb_get_geometry_reply(m_display.getConnection(), xcb_get_geometry(m_display.getConnection(), m_window), NULL);
	*height = static_cast<int>(geom->height);
	*width = static_cast<int>(geom->width);
	deFree(geom);
}

void XcbWindow::setDimensions (int width, int height)
{
	const uint32_t		values[]	= {static_cast<uint32_t >(width), static_cast<uint32_t >(height)};
	xcb_void_cookie_t	result;
	xcb_connection_t*	display		= m_display.getConnection();
	result = xcb_configure_window(display, m_window, XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, values);
	DE_ASSERT(DE_NULL == xcb_request_check(display,result));
	xcb_flush (display);

	for(;;)
	{
		xcb_generic_event_t*	event = xcb_poll_for_event(display);
		int						w, h;
		if(event != DE_NULL)
		{
			if (XCB_PROPERTY_NOTIFY == (event->response_type & ~0x80))
			{
				deFree(event);
				break;
			}
			deFree(event);
		}
		getDimensions (&w,&h);
		if (h==height || w==width)
			break;
	}
}

} // xcb
} // tcu
<commit_msg>Fix XCB window dimensions setter<commit_after>/*-------------------------------------------------------------------------
 * drawElements Quality Program Tester Core
 * ----------------------------------------
 *
 * Copyright (c) 2016 The Khronos Group Inc.
 *
 * 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.
 *
 *//*!
 * \file
 * \brief X11 using XCB utilities.
 *//*--------------------------------------------------------------------*/

#include "tcuX11Xcb.hpp"
#include "deMemory.h"

namespace tcu
{
namespace x11
{

XcbDisplay::XcbDisplay (EventState& platform, const char* name)
	: DisplayBase	(platform)
{
	m_connection						= xcb_connect(name, NULL);
	const xcb_setup_t		*setup		= xcb_get_setup(m_connection);
	xcb_screen_iterator_t	iterator	= xcb_setup_roots_iterator(setup);
	m_screen							= iterator.data;
}

XcbDisplay::~XcbDisplay (void)
{
	xcb_disconnect (m_connection);
}

void XcbDisplay::processEvents (void)
{
	xcb_generic_event_t *ev;
	while ((ev = xcb_poll_for_event(m_connection)))
	{
		deFree(ev);
		/* Manage your event */
	}
}

XcbWindow::XcbWindow (XcbDisplay& display, int width, int height, xcb_visualid_t* visual)
	: WindowBase	()
	, m_display		(display)
{
	xcb_connection_t*	connection = m_display.getConnection();
	uint32_t			values[2];
	m_window	= xcb_generate_id(connection);
	m_colormap	= xcb_generate_id(connection);

	if (visual == DE_NULL)
		visual = &m_display.getScreen()->root_visual;

	values[0] = m_display.getScreen()->white_pixel;
	values[1] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_PROPERTY_CHANGE;

	xcb_create_window	(
							connection,								// Connection
							XCB_COPY_FROM_PARENT,					// depth (same as root)
							m_window,								// window Id
							display.getScreen()->root,				// parent window
							0, 0,									// x, y
							static_cast<uint16_t >(width),			// width
							static_cast<uint16_t >(height),			// height
							10,										// border_width
							XCB_WINDOW_CLASS_INPUT_OUTPUT,			// class
							*visual,								// visual
							XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK,	// masks
							values									//not used yet
						);

	xcb_create_colormap	(
							connection,
							XCB_COLORMAP_ALLOC_NONE,
							m_colormap,
							m_window,
							*visual
						);

	xcb_alloc_color_reply_t* rep = xcb_alloc_color_reply(connection, xcb_alloc_color(connection, m_colormap, 65535, 0, 0), NULL);
	deFree(rep);
	xcb_flush (connection);
}

XcbWindow::~XcbWindow (void)
{
	xcb_flush (m_display.getConnection());
	xcb_free_colormap(m_display.getConnection(), m_colormap);
	xcb_destroy_window(m_display.getConnection(), m_window);
}

void XcbWindow::setVisibility (bool visible)
{
	if (visible == m_visible)
		return;

	if (visible)
		 xcb_map_window(m_display.getConnection(), m_window);
	else
		xcb_unmap_window(m_display.getConnection(), m_window);

	m_visible = visible;
	xcb_flush (m_display.getConnection());

}

void XcbWindow::processEvents (void)
{
	// A bit of a hack, since we don't really handle all the events.
	m_display.processEvents();
}

void XcbWindow::getDimensions (int* width, int* height) const
{
	xcb_get_geometry_reply_t *geom;
	geom = xcb_get_geometry_reply(m_display.getConnection(), xcb_get_geometry(m_display.getConnection(), m_window), NULL);
	*height = static_cast<int>(geom->height);
	*width = static_cast<int>(geom->width);
	deFree(geom);
}

void XcbWindow::setDimensions (int width, int height)
{
	const uint32_t		values[]	= {static_cast<uint32_t >(width), static_cast<uint32_t >(height)};
	xcb_void_cookie_t	result;
	xcb_connection_t*	display		= m_display.getConnection();
	result = xcb_configure_window(display, m_window, XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, values);
	DE_ASSERT(DE_NULL == xcb_request_check(display,result));
	xcb_flush (display);

	for(;;)
	{
		xcb_generic_event_t*	event = xcb_poll_for_event(display);
		int						w, h;
		if(event != DE_NULL)
		{
			if (XCB_PROPERTY_NOTIFY == (event->response_type & ~0x80))
			{
				const xcb_property_notify_event_t* pnEvent = (xcb_property_notify_event_t*)event;
				if (pnEvent->atom == XCB_ATOM_RESOLUTION)
				{
					deFree(event);
					break;
				}
			}
			deFree(event);
		}
		getDimensions (&w,&h);
		if (h==height || w==width)
			break;
	}
}

} // xcb
} // tcu
<|endoftext|>


<commit_before>#include <algorithm>
#include <iostream>
#include <list>
#include <cppunit/TestCase.h>
#include <cppunit/ui/text/TextTestRunner.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/TestResult.h>
#include <cppunit/TestResultCollector.h>
#include <cppunit/BriefTestProgressListener.h>
#include <cppunit/CompilerOutputter.h>
#include "Test.h"

/*
 * This file handles all the general functions needed to run unit tests.
 */

CPPUNIT_TEST_SUITE_REGISTRATION(Test);  // Add test suites. Repeat for additional new test suites
                                        // This could be used to add performance tests as well

compiler::Backend backend = compiler::Backend::PPRINTER;    // Standard compiler if no other valid is set

int main(int argc, char* argv[]){

    // Set the target compiler
    if (strcmp(argv[1], "c") == 0) {    // Set compiler to c
#ifdef CCPP
        cout << "Backend: C" << endl;
        backend = compiler::Backend::C;
#else
        cout << "Unsupported: C - Defaulting to Pretty Printer" << endl;
#endif
    } else if (strcmp(argv[1], "p") == 0) { // Set compiler to c parallel
#ifdef CCPP
        cout << "Backend: C Parallel" << endl;
        backend = compiler::Backend::CPAR;
#else
        cout << "Unsupported: C Parallel - Defaulting to Pretty Printer" << endl;
#endif
    } else if (strcmp(argv[1], "l") == 0) { // Set compiler to llvm
#ifdef CLLVM
        cout << "Backend: LLVM" << endl;
        backend = compiler::Backend::LLVM;
#else
        cout << "Unsupported: LLVM - Defaulting to Pretty Printer" << endl;
#endif
    } else if (strcmp(argv[1], "h") == 0) { // set compiler to haskell
#ifdef CHASKELL
        cout << "Backend: Haskell" << endl;
        backend = compiler::Backend::HASKELL;
#else
        cout << "Unsupported: Haskell - Defaulting to Pretty Printer" << endl;
#endif
    } else if (strcmp(argv[1], "a") == 0) { // set compiler to gnu asm
#ifdef CGNUASM
        cout << "Backend: Gnu Asm" << endl;
        backend = compiler::Backend::GNUASM;
#else
        cout << "Unsupported: Gnu Asm - Defaulting to Pretty Printer" << endl;
#endif
    }

    // CPPUNIT stuff
    // It just have to be there. Dont mind it.
    CPPUNIT_NS::TestResult test_result;

    CPPUNIT_NS::TestResultCollector collector;
    test_result.addListener(&collector);

    CPPUNIT_NS::BriefTestProgressListener progress;
    test_result.addListener (&progress);

    CPPUNIT_NS::TestRunner testrunner;
    testrunner.addTest (CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest ());
    testrunner.run(test_result);

    CPPUNIT_NS::CompilerOutputter compileroutputter(&collector, std::cerr);
    compileroutputter.write ();

    return collector.wasSuccessful() ? 0 : 1;
}

// Not used, but CppUnit require it
void Test::setUp() {
    // First test setup
}

// Not used, but CppUnit require it
void Test::tearDown() {
    // Final test cleanup
}

// Compiles the input program using the given sourcefile and the preset compiler target
bool Test::compileChecker(std::string name) {
    int compStatus;     // Stores the return code from the compiler

    try {
        compiler::Compiler compiler;

        std::vector<std::string> in;
        string file = "";

        // Split input to individual files.
        // Better alternative to function overloading for different number of arguments,
        // and easier than stdarg or creating a vector for every single test.
        for (char c : name) {
            if (c == ' ') {
                in.push_back(file);
                file.clear();
            } else {
                file += c;
                file = file;
            }
        }

        // Push last file to input vector
        if (file.length() > 0) {
            in.push_back(file);
        }

        // Set output files
        switch (backend) {
            case compiler::Backend::C:
            case compiler::Backend::CPP:
            case compiler::Backend::CPAR:
                compiler.setOutput("out.c");
                compiler.setHeaderOutput("test.h");
                break;
            case compiler::Backend::LLVM:
                compiler.setOutput("out.ll");
                compiler.Silent = true;
                break;
            default:
                break;
        }

        compiler.setBackend(backend);
        compStatus = compiler.compile(in);  // Run compiler
    }
    catch (...) {   // The compiler should never throw an error
                    // Special message if it is the case
                    // Cant handle serious exceptions such as Abort SegFault.
        CPPUNIT_ASSERT_MESSAGE("Exception Thrown In Compiler", false);
        return false;
    }

    if (compStatus != 0) {  // For the future, consider returning the errorcode to the user
        return false;
    } else {
        return true;
    }
}

// Run the code after compiled
// Run separate function for each supported target language
// Only currently relevant languages available
bool Test::executeChecker(std::string args, std::string expectedOutput) {
    if (backend == compiler::Backend::CPP
        || backend == compiler::Backend::CPAR
        || backend == compiler::Backend::C) {
        return executeCPP(args, expectedOutput);
    } else if (backend == compiler::Backend::LLVM) {
        return executeLLVM(args, expectedOutput);
    } else {
        return false;
    }
}

// Wrapper for when not using input arguments in the test
bool Test::executeChecker(std::string expectedOutput) {
    return executeChecker("", expectedOutput);
}

// Used for testing the generated c code
bool Test::executeCPP(std::string args, std::string expectedOutput) {
    int status;

    // Compile program using system c compiler
    if (backend == compiler::Backend::CPP || backend == compiler::Backend::C) {    // Sequential compiler
        status = system("cc out.c -o prog");
    } else if (backend == compiler::Backend::CPAR) {    // Parallel compiler
        status = system("cc out.c context.c print.c queue.c runtime.c task.c -o prog -lpthread");
    } else{
        CPPUNIT_ASSERT_MESSAGE("Unsupported backend detected wrong place", false);
    }

    if (status != 0) {
        CPPUNIT_ASSERT_MESSAGE("C Compiler Error", false);  // If this happens, yell a the
    }                                                       // C code generator

    // SOURCE: http://stackoverflow.com/questions/478898/how-to-execute-a-command-and-get-output-of-command-within-c
    // Used to read from outputstream for the program

    // build the command line command
    std::string argBuilder = "./prog " + args;
    char* arg = (char*) argBuilder.c_str();

    std::shared_ptr<FILE> pipe(popen(arg,"r"), pclose);
    if (!pipe) {
        CPPUNIT_ASSERT_MESSAGE("could not open pipe", false);
        return false;
    }
    std::string res = "";
    char buffer[128];

    while(!feof(pipe.get())) {
        if (fgets(buffer, 128, pipe.get()) != NULL) {
            res += buffer;
        }
    }

    // Compare the output from the program to the expected output
    // If the outputs are equal, the program executed correctly
    // (as in it gave the correct output to the correct input)
    if (res.compare(expectedOutput) != 0) {
        // If fail, first clear last test output, then return
        std::string resTemp = "result differ from expected\nResult   => ";
        resTemp += res;
        resTemp += "\nExpected => ";
        resTemp += expectedOutput;

        CPPUNIT_ASSERT_MESSAGE(resTemp, false);

        remove("out.c");
        remove("test.h");
        remove("prog");
        return false;
    } else {
        // If successful, first clear last test output
        remove("out.c");
        remove("test.h");
        remove("prog");
        return true;
    }
}

bool Test::executeLLVM(std::string Args, std::string ExpectedOutput) {
    std::shared_ptr<FILE> Pipe(popen((string("lli out.ll ") + Args).c_str(), "r"), pclose);
    if (!Pipe) {
        CPPUNIT_ASSERT_MESSAGE("could not open pipe", false);
        return false;
    }

    std::string Res = "";
    char Buffer[128];
    while(!feof(Pipe.get())) {
        if (fgets(Buffer, 128, Pipe.get()) != NULL) {
            Res += Buffer;
        }
    }

    // Compare the output from the program to the expected output
    // If the outputs are equal, the program executed correctly
    // (as in it gave the correct output to the correct input)
    if (Res.compare(ExpectedOutput) != 0) {
        // If fail, first clear last test output, then return
        std::string Msg = "Result differ from expected:\nResult   => " + Res + "\nExpected => " + ExpectedOutput;

        CPPUNIT_ASSERT_MESSAGE(Msg, false);

        remove("out.ll");
        return false;
    } else {
        remove("out.ll");
        return true;
    }
}<commit_msg>tests: fixed building maybe<commit_after>#include <algorithm>
#include <iostream>
#include <list>
#include <cppunit/TestCase.h>
#include <cppunit/ui/text/TextTestRunner.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/TestResult.h>
#include <cppunit/TestResultCollector.h>
#include <cppunit/BriefTestProgressListener.h>
#include <cppunit/CompilerOutputter.h>
#include "Test.h"

/*
 * This file handles all the general functions needed to run unit tests.
 */

CPPUNIT_TEST_SUITE_REGISTRATION(Test);  // Add test suites. Repeat for additional new test suites
                                        // This could be used to add performance tests as well

compiler::Backend backend = compiler::Backend::PPRINTER;    // Standard compiler if no other valid is set

int main(int argc, char* argv[]){

    // Set the target compiler
    if (strcmp(argv[1], "c") == 0) {    // Set compiler to c
#ifdef CCPP
        cout << "Backend: C" << endl;
        backend = compiler::Backend::C;
#else
        cout << "Unsupported: C - Defaulting to Pretty Printer" << endl;
#endif
    } else if (strcmp(argv[1], "p") == 0) { // Set compiler to c parallel
#ifdef CCPP
        cout << "Backend: C Parallel" << endl;
        backend = compiler::Backend::CPAR;
#else
        cout << "Unsupported: C Parallel - Defaulting to Pretty Printer" << endl;
#endif
    } else if (strcmp(argv[1], "l") == 0) { // Set compiler to llvm
#ifdef CLLVM
        cout << "Backend: LLVM" << endl;
        backend = compiler::Backend::LLVM;
#else
        cout << "Unsupported: LLVM - Defaulting to Pretty Printer" << endl;
#endif
    } else if (strcmp(argv[1], "h") == 0) { // set compiler to haskell
#ifdef CHASKELL
        cout << "Backend: Haskell" << endl;
        backend = compiler::Backend::HASKELL;
#else
        cout << "Unsupported: Haskell - Defaulting to Pretty Printer" << endl;
#endif
    } else if (strcmp(argv[1], "a") == 0) { // set compiler to gnu asm
#ifdef CGNUASM
        cout << "Backend: Gnu Asm" << endl;
        backend = compiler::Backend::GNUASM;
#else
        cout << "Unsupported: Gnu Asm - Defaulting to Pretty Printer" << endl;
#endif
    }

    // CPPUNIT stuff
    // It just have to be there. Dont mind it.
    CPPUNIT_NS::TestResult test_result;

    CPPUNIT_NS::TestResultCollector collector;
    test_result.addListener(&collector);

    CPPUNIT_NS::BriefTestProgressListener progress;
    test_result.addListener (&progress);

    CPPUNIT_NS::TestRunner testrunner;
    testrunner.addTest (CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest ());
    testrunner.run(test_result);

    CPPUNIT_NS::CompilerOutputter compileroutputter(&collector, std::cerr);
    compileroutputter.write ();

    return collector.wasSuccessful() ? 0 : 1;
}

// Not used, but CppUnit require it
void Test::setUp() {
    // First test setup
}

// Not used, but CppUnit require it
void Test::tearDown() {
    // Final test cleanup
}

// Compiles the input program using the given sourcefile and the preset compiler target
bool Test::compileChecker(std::string name) {
    int compStatus;     // Stores the return code from the compiler

    try {
        compiler::Compiler compiler;

        std::vector<std::string> in;
        string file = "";

        // Split input to individual files.
        // Better alternative to function overloading for different number of arguments,
        // and easier than stdarg or creating a vector for every single test.
        for (char c : name) {
            if (c == ' ') {
                in.push_back(file);
                file.clear();
            } else {
                file += c;
                file = file;
            }
        }

        // Push last file to input vector
        if (file.length() > 0) {
            in.push_back(file);
        }

        // Set output files
        switch (backend) {
            case compiler::Backend::C:
            case compiler::Backend::CPAR:
                compiler.setOutput("out.c");
                compiler.setHeaderOutput("test.h");
                break;
            case compiler::Backend::LLVM:
                compiler.setOutput("out.ll");
                compiler.Silent = true;
                break;
            default:
                break;
        }

        compiler.setBackend(backend);
        compStatus = compiler.compile(in);  // Run compiler
    }
    catch (...) {   // The compiler should never throw an error
                    // Special message if it is the case
                    // Cant handle serious exceptions such as Abort SegFault.
        CPPUNIT_ASSERT_MESSAGE("Exception Thrown In Compiler", false);
        return false;
    }

    if (compStatus != 0) {  // For the future, consider returning the errorcode to the user
        return false;
    } else {
        return true;
    }
}

// Run the code after compiled
// Run separate function for each supported target language
// Only currently relevant languages available
bool Test::executeChecker(std::string args, std::string expectedOutput) {
    if (backend == compiler::Backend::CPAR
        || backend == compiler::Backend::C) {
        return executeCPP(args, expectedOutput);
    } else if (backend == compiler::Backend::LLVM) {
        return executeLLVM(args, expectedOutput);
    } else {
        return false;
    }
}

// Wrapper for when not using input arguments in the test
bool Test::executeChecker(std::string expectedOutput) {
    return executeChecker("", expectedOutput);
}

// Used for testing the generated c code
bool Test::executeCPP(std::string args, std::string expectedOutput) {
    int status;

    // Compile program using system c compiler
    if (backend == compiler::Backend::C) {    // Sequential compiler
        status = system("cc out.c -o prog");
    } else if (backend == compiler::Backend::CPAR) {    // Parallel compiler
        status = system("cc out.c context.c print.c queue.c runtime.c task.c -o prog -lpthread");
    } else{
        CPPUNIT_ASSERT_MESSAGE("Unsupported backend detected wrong place", false);
    }

    if (status != 0) {
        CPPUNIT_ASSERT_MESSAGE("C Compiler Error", false);  // If this happens, yell a the
    }                                                       // C code generator

    // SOURCE: http://stackoverflow.com/questions/478898/how-to-execute-a-command-and-get-output-of-command-within-c
    // Used to read from outputstream for the program

    // build the command line command
    std::string argBuilder = "./prog " + args;
    char* arg = (char*) argBuilder.c_str();

    std::shared_ptr<FILE> pipe(popen(arg,"r"), pclose);
    if (!pipe) {
        CPPUNIT_ASSERT_MESSAGE("could not open pipe", false);
        return false;
    }
    std::string res = "";
    char buffer[128];

    while(!feof(pipe.get())) {
        if (fgets(buffer, 128, pipe.get()) != NULL) {
            res += buffer;
        }
    }

    // Compare the output from the program to the expected output
    // If the outputs are equal, the program executed correctly
    // (as in it gave the correct output to the correct input)
    if (res.compare(expectedOutput) != 0) {
        // If fail, first clear last test output, then return
        std::string resTemp = "result differ from expected\nResult   => ";
        resTemp += res;
        resTemp += "\nExpected => ";
        resTemp += expectedOutput;

        CPPUNIT_ASSERT_MESSAGE(resTemp, false);

        remove("out.c");
        remove("test.h");
        remove("prog");
        return false;
    } else {
        // If successful, first clear last test output
        remove("out.c");
        remove("test.h");
        remove("prog");
        return true;
    }
}

bool Test::executeLLVM(std::string Args, std::string ExpectedOutput) {
    std::shared_ptr<FILE> Pipe(popen((string("lli out.ll ") + Args).c_str(), "r"), pclose);
    if (!Pipe) {
        CPPUNIT_ASSERT_MESSAGE("could not open pipe", false);
        return false;
    }

    std::string Res = "";
    char Buffer[128];
    while(!feof(Pipe.get())) {
        if (fgets(Buffer, 128, Pipe.get()) != NULL) {
            Res += Buffer;
        }
    }

    // Compare the output from the program to the expected output
    // If the outputs are equal, the program executed correctly
    // (as in it gave the correct output to the correct input)
    if (Res.compare(ExpectedOutput) != 0) {
        // If fail, first clear last test output, then return
        std::string Msg = "Result differ from expected:\nResult   => " + Res + "\nExpected => " + ExpectedOutput;

        CPPUNIT_ASSERT_MESSAGE(Msg, false);

        remove("out.ll");
        return false;
    } else {
        remove("out.ll");
        return true;
    }
}<|endoftext|>


<commit_before>/*
 * The MIT License
 *
 * Copyright 2017-2018 Norwegian University of Technology
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING  FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#ifndef FMICPP_MODELVARIABLES_HPP
#define FMICPP_MODELVARIABLES_HPP

#include <vector>
#include <memory>
#include <boost/property_tree/ptree.hpp>
#include <fmicpp/fmi2/xml/ScalarVariable.hpp>

using boost::property_tree::ptree;

namespace fmicpp::fmi2::xml {

struct ModelVariables : public std::vector<std::unique_ptr<ScalarVariable>> {

        void load(const ptree &node);

        ScalarVariable& getByName(const std::string name);
        ScalarVariable& getByValueReference(const fmi2ValueReference vr);

    };

}

#endif //FMICPP_MODELVARIABLES_HPP
<commit_msg>indent line<commit_after>/*
 * The MIT License
 *
 * Copyright 2017-2018 Norwegian University of Technology
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING  FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#ifndef FMICPP_MODELVARIABLES_HPP
#define FMICPP_MODELVARIABLES_HPP

#include <vector>
#include <memory>
#include <boost/property_tree/ptree.hpp>
#include <fmicpp/fmi2/xml/ScalarVariable.hpp>

using boost::property_tree::ptree;

namespace fmicpp::fmi2::xml {

    struct ModelVariables : public std::vector<std::unique_ptr<ScalarVariable>> {

        void load(const ptree &node);

        ScalarVariable& getByName(const std::string name);
        ScalarVariable& getByValueReference(const fmi2ValueReference vr);

    };

}

#endif //FMICPP_MODELVARIABLES_HPP
<|endoftext|>


<commit_before>/****************************************************************/
/*               DO NOT MODIFY THIS HEADER                      */
/* MOOSE - Multiphysics Object Oriented Simulation Environment  */
/*                                                              */
/*           (c) 2010 Battelle Energy Alliance, LLC             */
/*                   ALL RIGHTS RESERVED                        */
/*                                                              */
/*          Prepared by Battelle Energy Alliance, LLC           */
/*            Under Contract No. DE-AC07-05ID14517              */
/*            With the U. S. Department of Energy               */
/*                                                              */
/*            See COPYRIGHT for full restrictions               */
/****************************************************************/

#include "ConvectiveFluxBC.h"

template<>
InputParameters validParams<ConvectiveFluxBC>()
{
  InputParameters params = validParams<IntegratedBC>();
  params.set<Real>("rate")=7500;
  params.set<Real>("initial")=500;
  params.set<Real>("final")=500;
  params.set<Real>("duration")=0.0;
  return params;
}

ConvectiveFluxBC::ConvectiveFluxBC(const std::string & name, InputParameters parameters) :
    IntegratedBC(name, parameters),
    _initial(getParam<Real>("initial")),
    _final(getParam<Real>("final")),
    _rate(getParam<Real>("rate")),
    _duration(getParam<Real>("duration"))
{}

Real
ConvectiveFluxBC::computeQpResidual()
{
  Real value;

  if(_t < _duration)
    value = _initial + (_final-_initial) * std::sin((0.5/_duration) * libMesh::pi * _t);
  else
    value = _final;

  return -(_test[_i][_qp]*_rate*(value - _u[_qp]));
}

Real
ConvectiveFluxBC::computeQpJacobian()
{
  return -(_test[_i][_qp]*_rate*(-_phi[_j][_qp]));
}
<commit_msg>Improve Jacobian<commit_after>/****************************************************************/
/*               DO NOT MODIFY THIS HEADER                      */
/* MOOSE - Multiphysics Object Oriented Simulation Environment  */
/*                                                              */
/*           (c) 2010 Battelle Energy Alliance, LLC             */
/*                   ALL RIGHTS RESERVED                        */
/*                                                              */
/*          Prepared by Battelle Energy Alliance, LLC           */
/*            Under Contract No. DE-AC07-05ID14517              */
/*            With the U. S. Department of Energy               */
/*                                                              */
/*            See COPYRIGHT for full restrictions               */
/****************************************************************/

#include "ConvectiveFluxBC.h"

template<>
InputParameters validParams<ConvectiveFluxBC>()
{
  InputParameters params = validParams<IntegratedBC>();
  params.set<Real>("rate")=7500;
  params.set<Real>("initial")=500;
  params.set<Real>("final")=500;
  params.set<Real>("duration")=0.0;
  return params;
}

ConvectiveFluxBC::ConvectiveFluxBC(const std::string & name, InputParameters parameters) :
    IntegratedBC(name, parameters),
    _initial(getParam<Real>("initial")),
    _final(getParam<Real>("final")),
    _rate(getParam<Real>("rate")),
    _duration(getParam<Real>("duration"))
{}

Real
ConvectiveFluxBC::computeQpResidual()
{
  Real value;

  if(_t < _duration)
    value = _initial + (_final-_initial) * std::sin((0.5/_duration) * libMesh::pi * _t);
  else
    value = _final;

  return -(_test[_i][_qp]*_rate*(value - _u[_qp]));
}

Real
ConvectiveFluxBC::computeQpJacobian()
{
  return -(_test[_i][_qp]*_rate*(-_phi[_j][_qp]));
}
<|endoftext|>


<commit_before>#include <stan/math.hpp>
#include <stan/math/mix/mat.hpp>
#include <gtest/gtest.h>
#include <test/unit/util.hpp>
#include <test/unit/math/rev/mat/fun/util.hpp>
#include <iostream>
#include <limits>
#include <sstream>
#include <vector>

std::ostringstream msgs;

struct f1 {
  template <typename T1, typename T2>
  inline typename stan::return_type<T1, T2>::type operator()(
      const T1& x, const T1& xc, const std::vector<T2>& theta,
      const std::vector<double>& x_r, const std::vector<int>& x_i,
      std::ostream& msgs) const {
    return exp(x) + theta[0];
  }
};

struct f2 {
  template <typename T1, typename T2>
  inline typename stan::return_type<T1, T2>::type operator()(
      const T1& x, const T1& xc, const std::vector<T2>& theta,
      const std::vector<double>& x_r, const std::vector<int>& x_i,
      std::ostream& msgs) const {
    return exp(theta[0] * cos(2 * 3.141593 * x)) + theta[0];
  }
};

struct f3 {
  template <typename T1, typename T2>
  inline typename stan::return_type<T1, T2>::type operator()(
      const T1& x, const T1& xc, const std::vector<T2>& theta,
      const std::vector<double>& x_r, const std::vector<int>& x_i,
      std::ostream& msgs) const {
    return exp(x) + pow(theta[0], x_r[0]) + 2 * pow(theta[1], x_r[1])
           + 2 * theta[2];
  }
};

struct f4 {
  template <typename T1, typename T2>
  inline typename stan::return_type<T1, T2>::type operator()(
      const T1& x, const T1& xc, const std::vector<T2>& theta,
      const std::vector<double>& x_r, const std::vector<int>& x_i,
      std::ostream& msgs) const {
    return exp(-x) / sqrt(x);
  }
};

struct f5 {
  template <typename T1, typename T2>
  inline typename stan::return_type<T1, T2>::type operator()(
      const T1& x, const T1& xc, const std::vector<T2>& theta,
      const std::vector<double>& x_r, const std::vector<int>& x_i,
      std::ostream& msgs) const {
    return exp(-theta[0] * x) / sqrt(theta[1] * x);
  }
};

struct f6 {
  template <typename T1, typename T2>
  inline typename stan::return_type<T1, T2>::type operator()(
      const T1& x, const T1& xc, const std::vector<T2>& theta,
      const std::vector<double>& x_r, const std::vector<int>& x_i,
      std::ostream& msgs) const {
    return sqrt(x / (1 - theta[0] * x * x));
  }
};

struct f7 {
  template <typename T1, typename T2>
  inline typename stan::return_type<T1, T2>::type operator()(
      const T1& x, const T1& xc, const std::vector<T2>& theta,
      const std::vector<double>& x_r, const std::vector<int>& x_i,
      std::ostream& msgs) const {
    return exp(-theta[0] * x);
  }
};

struct f8 {
  template <typename T1, typename T2>
  inline typename stan::return_type<T1, T2>::type operator()(
      const T1& x, const T1& xc, const std::vector<T2>& theta,
      const std::vector<double>& x_r, const std::vector<int>& x_i,
      std::ostream& msgs) const {
    return exp(theta[0] * x);
  }
};

struct f9 {
  template <typename T1, typename T2>
  inline typename stan::return_type<T1, T2>::type operator()(
      const T1& x, const T1& xc, const std::vector<T2>& theta,
      const std::vector<double>& x_r, const std::vector<int>& x_i,
      std::ostream& msgs) const {
    return exp(-pow(x - x_r[0], x_i[0]) / pow(x_r[1], x_i[0]));
  }
};

struct f10 {
  template <typename T1, typename T2>
  inline typename stan::return_type<T1, T2>::type operator()(
      const T1& x, const T1& xc, const std::vector<T2>& theta,
      const std::vector<double>& x_r, const std::vector<int>& x_i,
      std::ostream& msgs) const {
    return 1 / (1 + pow(x, x_i[0]) / x_r[0]);
  }
};

struct f11 {
  template <typename T1, typename T2>
  inline typename stan::return_type<T1, T2>::type operator()(
      const T1& x, const T1& xc, const std::vector<T2>& theta,
      const std::vector<double>& x_r, const std::vector<int>& x_i,
      std::ostream& msgs) const {
    return pow(x, theta[0] - 1.0)
           * pow((x > 0.5) ? xc : (1 - x), theta[1] - 1.0);
  }
};

/*
 * test_derivatives is a helper function to make it easy to test the
 * integrate_1d function.
 *
 * It takes in a callable function object, integration limits, parameters, real
 * and integer data. It integrates the provided function and compares the
 * computed integral and gradients against the provided integral value (val) and
 * gradients (grad).
 *
 * The prototype for f is:
 *   struct f10 {
 *     template <typename T1, typename T2>
 *     inline typename stan::return_type<T1, T2>::type operator()(
 *         const T1& x, const std::vector<T2>& theta, const std::vector<double>&
 * x_r, const std::vector<int>& x_i, std::ostream& msgs) const {
 *     }
 *  };
 *
 * @tparam F Type of f
 * @param f a functor with signature given above
 * @param a lower limit of integration
 * @param b upper limit of integration
 * @param param parameters to be passed to f (should be
 * std::vector<stan::math::var>)
 * @param x_r real data to be passed to f (should be std::vector<double>)
 * @param x_i integer data to be passed to f (should be std::vector<int>)
 * @param val correct value of integral
 * @param grad correct value of gradients
 */
template <typename F>
void test_derivatives(const F& f, double a, double b,
                      std::vector<double> thetas,
                      const std::vector<double>& x_r,
                      const std::vector<int>& x_i, double val,
                      std::vector<double> grad) {
  using stan::math::var;

  std::vector<double> tolerances = {1e-4, 1e-6, 1e-8};

  for (auto tolerance : tolerances) {
    // Reset autodiff stack
    stan::math::recover_memory();
    // Convert parameters into vars for actual calls
    std::vector<var> theta_vars(thetas.size());
    for (size_t i = 0; i < thetas.size(); ++i) {
      theta_vars[i] = thetas[i];
    }

    var integral = stan::math::integrate_1d(f, a, b, theta_vars, x_r, x_i, msgs,
                                            tolerance);
    std::vector<double> computed_grad;
    integral.grad(theta_vars, computed_grad);
    EXPECT_LE(std::abs(val - integral.val()), tolerance);
    for (size_t i = 0; i < grad.size(); ++i) {
      EXPECT_LE(std::abs(grad[i] - computed_grad[i]), tolerance);
    }
  }
}

TEST(StanMath_integrate_1d, TestDerivatives) {
  // Easy integrals
  test_derivatives(f1{}, 0.2, 0.7, {0.75}, {}, {},
                   0.7923499493102901 + 0.5 * 0.75, {0.5});
  test_derivatives(f2{}, 0.0, 1.0, {0.5}, {}, {}, 1.56348343527304,
                   {1.25789445875152});
  test_derivatives(f1{}, 0.0, 0.0, {0.75}, {}, {}, 0.0, {0.0});
  test_derivatives(f2{}, 1.0, 1.0, {0.5}, {}, {}, 0.0, {0.0});
  // Zero crossing integral + test x_r
  test_derivatives(f3{}, -1.0, 1.0, {0.5, 1.75, 3.9}, {2.5, 3.0}, {},
                   2.350402387287579 + 2.0 * pow(0.5, 2.5)
                       + 4.0 * pow(1.75, 3.0) + 4.0 * 3.9,
                   {5 * pow(0.5, 1.5), 12 * 1.75 * 1.75, 4.0});
  // Tricky integral from Boost docs + limit at infinity + no gradients
  test_derivatives(f4{}, 0.0, std::numeric_limits<double>::infinity(), {}, {},
                   {}, 1.772453850905516, {});
  // Tricky integral from Boost docs + limit at infinity with gradients
  test_derivatives(f5{}, 0.0, std::numeric_limits<double>::infinity(),
                   {0.5, 3.0}, {}, {}, 1.772453850905516 / sqrt(0.5 * 3.0),
                   {-1.772453850905516 * 3.0 / (2 * pow(0.5 * 3.0, 1.5)),
                    -1.772453850905516 * 0.5 / (2 * pow(0.5 * 3.0, 1.5))});
  // Tricky integral from Boost docs
  // test_derivatives(f6{}, 0.0, 1.0, {0.75}, {}, {}, 0.851926727945904,
  //                  {0.4814066053874294});
  // Zero crossing integral + limit at infinity
  test_derivatives(f7{}, -5.0, std::numeric_limits<double>::infinity(), {1.5},
                   {}, {}, 1205.361609637375, {5223.23364176196});
  // Zero crossing integral + limit at negative infinity
  test_derivatives(f8{}, -std::numeric_limits<double>::infinity(), 5.0, {1.5},
                   {}, {}, 1205.361609637375, {5223.23364176196});
  // Both limits at infinity + test x_r/x_i + no gradients
  test_derivatives(f9{}, -std::numeric_limits<double>::infinity(),
                   std::numeric_limits<double>::infinity(), {}, {5.0, 1.7}, {2},
                   3.013171546539377, {});
  // Both limits at infinity + test x_r/x_i + no gradients
  test_derivatives(f10{}, -std::numeric_limits<double>::infinity(),
                   std::numeric_limits<double>::infinity(), {}, {1.7}, {4},
                   2.536571480364399, {});
  // Various integrals of beta function
  test_derivatives(f11{}, 0.0, 1.0, {0.1, 0.1}, {}, {}, 19.71463948905016,
                   {-101.229055967892, -101.229055967892});
  test_derivatives(f11{}, 0.0, 1.0, {0.5, 0.51}, {}, {}, 3.098843783331868,
                   {-4.346514423368675, -4.196150770134913});
  test_derivatives(f11{}, 0.0, 1.0, {0.51, 0.5}, {}, {}, 3.098843783331868,
                   {-4.196150770134913, -4.346514423368675});
  test_derivatives(f11{}, 0.0, 1.0, {5.0, 3.0}, {}, {}, 0.00952380952380952,
                   {-0.004852607709750566, -0.01040816326530613});
  test_derivatives(f11{}, 0.0, 1.0, {3.0, 5.0}, {}, {}, 0.00952380952380952,
                   {-0.01040816326530613, -0.004852607709750566});
}
<commit_msg>add Gaussian integral with var sigma<commit_after>#include <gtest/gtest.h>
#include <iostream>
#include <limits>
#include <sstream>
#include <stan/math.hpp>
#include <stan/math/mix/mat.hpp>
#include <test/unit/math/rev/mat/fun/util.hpp>
#include <test/unit/util.hpp>
#include <vector>

std::ostringstream msgs;

struct f1 {
  template <typename T1, typename T2>
  inline typename stan::return_type<T1, T2>::type
  operator()(const T1 &x, const T1 &xc, const std::vector<T2> &theta,
             const std::vector<double> &x_r, const std::vector<int> &x_i,
             std::ostream &msgs) const {
    return exp(x) + theta[0];
  }
};

struct f2 {
  template <typename T1, typename T2>
  inline typename stan::return_type<T1, T2>::type
  operator()(const T1 &x, const T1 &xc, const std::vector<T2> &theta,
             const std::vector<double> &x_r, const std::vector<int> &x_i,
             std::ostream &msgs) const {
    return exp(theta[0] * cos(2 * 3.141593 * x)) + theta[0];
  }
};

struct f3 {
  template <typename T1, typename T2>
  inline typename stan::return_type<T1, T2>::type
  operator()(const T1 &x, const T1 &xc, const std::vector<T2> &theta,
             const std::vector<double> &x_r, const std::vector<int> &x_i,
             std::ostream &msgs) const {
    return exp(x) + pow(theta[0], x_r[0]) + 2 * pow(theta[1], x_r[1]) +
           2 * theta[2];
  }
};

struct f4 {
  template <typename T1, typename T2>
  inline typename stan::return_type<T1, T2>::type
  operator()(const T1 &x, const T1 &xc, const std::vector<T2> &theta,
             const std::vector<double> &x_r, const std::vector<int> &x_i,
             std::ostream &msgs) const {
    return exp(-x) / sqrt(x);
  }
};

struct f5 {
  template <typename T1, typename T2>
  inline typename stan::return_type<T1, T2>::type
  operator()(const T1 &x, const T1 &xc, const std::vector<T2> &theta,
             const std::vector<double> &x_r, const std::vector<int> &x_i,
             std::ostream &msgs) const {
    return exp(-theta[0] * x) / sqrt(theta[1] * x);
  }
};

struct f6 {
  template <typename T1, typename T2>
  inline typename stan::return_type<T1, T2>::type
  operator()(const T1 &x, const T1 &xc, const std::vector<T2> &theta,
             const std::vector<double> &x_r, const std::vector<int> &x_i,
             std::ostream &msgs) const {
    return sqrt(x / (1 - theta[0] * x * x));
  }
};

struct f7 {
  template <typename T1, typename T2>
  inline typename stan::return_type<T1, T2>::type
  operator()(const T1 &x, const T1 &xc, const std::vector<T2> &theta,
             const std::vector<double> &x_r, const std::vector<int> &x_i,
             std::ostream &msgs) const {
    return exp(-theta[0] * x);
  }
};

struct f8 {
  template <typename T1, typename T2>
  inline typename stan::return_type<T1, T2>::type
  operator()(const T1 &x, const T1 &xc, const std::vector<T2> &theta,
             const std::vector<double> &x_r, const std::vector<int> &x_i,
             std::ostream &msgs) const {
    return exp(theta[0] * x);
  }
};

struct f9 {
  template <typename T1, typename T2>
  inline typename stan::return_type<T1, T2>::type
  operator()(const T1 &x, const T1 &xc, const std::vector<T2> &theta,
             const std::vector<double> &x_r, const std::vector<int> &x_i,
             std::ostream &msgs) const {
    return exp(-pow(x - x_r[0], x_i[0]) / pow(x_r[1], x_i[0]));
  }
};

struct f10 {
  template <typename T1, typename T2>
  inline typename stan::return_type<T1, T2>::type
  operator()(const T1 &x, const T1 &xc, const std::vector<T2> &theta,
             const std::vector<double> &x_r, const std::vector<int> &x_i,
             std::ostream &msgs) const {
    return 1 / (1 + pow(x, x_i[0]) / x_r[0]);
  }
};

struct f11 {
  template <typename T1, typename T2>
  inline typename stan::return_type<T1, T2>::type
  operator()(const T1 &x, const T1 &xc, const std::vector<T2> &theta,
             const std::vector<double> &x_r, const std::vector<int> &x_i,
             std::ostream &msgs) const {
    return pow(x, theta[0] - 1.0) *
           pow((x > 0.5) ? xc : (1 - x), theta[1] - 1.0);
  }
};

struct f12 {
  template <typename T1, typename T2>
  inline typename stan::return_type<T1, T2>::type
  operator()(const T1 &x, const T1 &xc, const std::vector<T2> &theta,
             const std::vector<double> &x_r, const std::vector<int> &x_i,
             std::ostream &msgs) const {
    T2 sigma = theta[0];
    return exp(-0.5 * stan::math::square(x / sigma)) /
           (sigma * sqrt(2.0 * stan::math::pi()));
  }
};

/*
 * test_derivatives is a helper function to make it easy to test the
 * integrate_1d function.
 *
 * It takes in a callable function object, integration limits, parameters, real
 * and integer data. It integrates the provided function and compares the
 * computed integral and gradients against the provided integral value (val) and
 * gradients (grad).
 *
 * The prototype for f is:
 *   struct f10 {
 *     template <typename T1, typename T2>
 *     inline typename stan::return_type<T1, T2>::type operator()(
 *         const T1& x, const std::vector<T2>& theta, const std::vector<double>&
 * x_r, const std::vector<int>& x_i, std::ostream& msgs) const {
 *     }
 *  };
 *
 * @tparam F Type of f
 * @param f a functor with signature given above
 * @param a lower limit of integration
 * @param b upper limit of integration
 * @param param parameters to be passed to f (should be
 * std::vector<stan::math::var>)
 * @param x_r real data to be passed to f (should be std::vector<double>)
 * @param x_i integer data to be passed to f (should be std::vector<int>)
 * @param val correct value of integral
 * @param grad correct value of gradients
 */
template <typename F>
void test_derivatives(const F &f, double a, double b,
                      std::vector<double> thetas,
                      const std::vector<double> &x_r,
                      const std::vector<int> &x_i, double val,
                      std::vector<double> grad) {
  using stan::math::var;

  std::vector<double> tolerances = {1e-4, 1e-6, 1e-8};

  for (auto tolerance : tolerances) {
    // Reset autodiff stack
    stan::math::recover_memory();
    // Convert parameters into vars for actual calls
    std::vector<var> theta_vars(thetas.size());
    for (size_t i = 0; i < thetas.size(); ++i) {
      theta_vars[i] = thetas[i];
    }

    var integral = stan::math::integrate_1d(f, a, b, theta_vars, x_r, x_i, msgs,
                                            tolerance);
    std::vector<double> computed_grad;
    integral.grad(theta_vars, computed_grad);
    EXPECT_LE(std::abs(val - integral.val()), tolerance);
    for (size_t i = 0; i < grad.size(); ++i) {
      EXPECT_LE(std::abs(grad[i] - computed_grad[i]), tolerance);
    }
  }
}

TEST(StanMath_integrate_1d, TestDerivatives) {
  // Easy integrals
  test_derivatives(f1{}, 0.2, 0.7, {0.75}, {}, {},
                   0.7923499493102901 + 0.5 * 0.75, {0.5});
  test_derivatives(f2{}, 0.0, 1.0, {0.5}, {}, {}, 1.56348343527304,
                   {1.25789445875152});
  test_derivatives(f1{}, 0.0, 0.0, {0.75}, {}, {}, 0.0, {0.0});
  test_derivatives(f2{}, 1.0, 1.0, {0.5}, {}, {}, 0.0, {0.0});
  // Zero crossing integral + test x_r
  test_derivatives(f3{}, -1.0, 1.0, {0.5, 1.75, 3.9}, {2.5, 3.0}, {},
                   2.350402387287579 + 2.0 * pow(0.5, 2.5) +
                       4.0 * pow(1.75, 3.0) + 4.0 * 3.9,
                   {5 * pow(0.5, 1.5), 12 * 1.75 * 1.75, 4.0});
  // Tricky integral from Boost docs + limit at infinity + no gradients
  test_derivatives(f4{}, 0.0, std::numeric_limits<double>::infinity(), {}, {},
                   {}, 1.772453850905516, {});
  // Tricky integral from Boost docs + limit at infinity with gradients
  test_derivatives(f5{}, 0.0, std::numeric_limits<double>::infinity(),
                   {0.5, 3.0}, {}, {}, 1.772453850905516 / sqrt(0.5 * 3.0),
                   {-1.772453850905516 * 3.0 / (2 * pow(0.5 * 3.0, 1.5)),
                    -1.772453850905516 * 0.5 / (2 * pow(0.5 * 3.0, 1.5))});
  // Tricky integral from Boost docs
  // test_derivatives(f6{}, 0.0, 1.0, {0.75}, {}, {}, 0.851926727945904,
  //                  {0.4814066053874294});
  // Zero crossing integral + limit at infinity
  test_derivatives(f7{}, -5.0, std::numeric_limits<double>::infinity(), {1.5},
                   {}, {}, 1205.361609637375, {5223.23364176196});
  // Zero crossing integral + limit at negative infinity
  test_derivatives(f8{}, -std::numeric_limits<double>::infinity(), 5.0, {1.5},
                   {}, {}, 1205.361609637375, {5223.23364176196});
  // Both limits at infinity + test x_r/x_i + no gradients
  test_derivatives(f9{}, -std::numeric_limits<double>::infinity(),
                   std::numeric_limits<double>::infinity(), {}, {5.0, 1.7}, {2},
                   3.013171546539377, {});
  // Both limits at infinity + test x_r/x_i + no gradients
  test_derivatives(f10{}, -std::numeric_limits<double>::infinity(),
                   std::numeric_limits<double>::infinity(), {}, {1.7}, {4},
                   2.536571480364399, {});
  // Various integrals of beta function
  test_derivatives(f11{}, 0.0, 1.0, {0.1, 0.1}, {}, {}, 19.71463948905016,
                   {-101.229055967892, -101.229055967892});
  test_derivatives(f11{}, 0.0, 1.0, {0.5, 0.51}, {}, {}, 3.098843783331868,
                   {-4.346514423368675, -4.196150770134913});
  test_derivatives(f11{}, 0.0, 1.0, {0.51, 0.5}, {}, {}, 3.098843783331868,
                   {-4.196150770134913, -4.346514423368675});
  test_derivatives(f11{}, 0.0, 1.0, {5.0, 3.0}, {}, {}, 0.00952380952380952,
                   {-0.004852607709750566, -0.01040816326530613});
  test_derivatives(f11{}, 0.0, 1.0, {3.0, 5.0}, {}, {}, 0.00952380952380952,
                   {-0.01040816326530613, -0.004852607709750566});

  test_derivatives(f12{}, -std::numeric_limits<double>::infinity(),
                   std::numeric_limits<double>::infinity(), {1}, {}, {}, 1.0,
                   {0});
}
<|endoftext|>