<commit_before>// This is free and unencumbered software released into the public domain.
// For more information, please refer to <http://unlicense.org/>

#include "report_table.h"

#include "models/base/helper.h"
#include "wx/clipbrd.h"
#include "wx/imaglist.h"

#include "../res/sort_arrow_up.xpm"
#include "../res/sort_arrow_down.xpm"

/// \par OVERVIEW
///
/// This struct contains all the control information for the
/// wxListCtrl::SortItems function, which is also passed onto the
/// wxListCompareFunction.
struct SortData {
  /// \var type
  ///   The sort type.
  SortOrderType type;

  /// \var index
  ///   The column index.
  int index;
};

/// \par OVERVIEW
///
/// This is the enumeration for the context menu.
enum {
  kCopyHeaders = 0,
  kCopyRow = 1,
  kCopyTable = 2
};

/// \brief This function is used by the wxListCtrl to sort items.
/// \param[in] item1
///   The first item to compare.
/// \param[in] item2
///   The second item to compare.
/// \param[in] sortData
///   The data/settings used to sort the listctrl. Column and whether
///   the sort is ascending/descending need to be detailed.
/// \return This function returns -1 if the first item is less than the second,
///   0 if they are equal, and 1 if the first is greater than the second one.
///   These values are used by wxListCtrl to sort the items.
/// This function uses the data associated with each listctrl item. See
/// wxListCtrl::SetItemData().
int wxCALLBACK wxListCompareFunction(wxIntPtr item1, wxIntPtr item2,
                                     wxIntPtr data_sort) {
  // gets sort column and order
  const SortData* data = (SortData*)data_sort;

  // gets string from row1
  const ReportRow* row1 = (ReportRow*)item1;
  const std::string& str1 = *std::next(row1->values.cbegin(), data->index);

  // gets string from row2
  const ReportRow* row2 = (ReportRow*)item2;
  const std::string& str2 = *std::next(row2->values.cbegin(), data->index);

  // attempts to compare strings as numbers
  int status;
  if (helper::IsNumeric(str1) && helper::IsNumeric(str2) == true) {
    // compares as numbers
    const double dbl1 = std::stod(str1);
    const double dbl2 = std::stod(str2);

    if (dbl1 == dbl2) {
      status = 0;
    } else if (dbl1 < dbl2) {
      status = -1;
    } else {
      status = 1;
    }
  } else {
    // compares as strings
    status = helper::CompareStrings(str1, str2);
  }

  // applies sort order
  if (data->type == SortOrderType::kAscending) {
    return status;
  } else {
    return -1 * status;
  }
}

BEGIN_EVENT_TABLE(ReportTable, wxPanel)
  EVT_LIST_COL_CLICK(wxID_ANY, ReportTable::OnColumnClick)
  EVT_LIST_COL_RIGHT_CLICK(wxID_ANY, ReportTable::OnColumnRightClick)
  EVT_LIST_ITEM_RIGHT_CLICK(wxID_ANY, ReportTable::OnItemRightClick)
  EVT_MENU(wxID_ANY, ReportTable::OnContextMenuSelect)
END_EVENT_TABLE()

ReportTable::ReportTable(wxWindow* parent) : wxPanel(parent, wxID_ANY) {
  // initializes members
  data_ = nullptr;
  index_selected_ = -1;
  index_sorted_ = -1;
  type_sort_ = SortOrderType::kNone;

  // initializes listctrl
  listctrl_ = new wxListCtrl(this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
                             wxLC_REPORT|wxLC_HRULES|wxLC_VRULES
                             |wxLC_SINGLE_SEL);
  wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
  sizer->Add(listctrl_, 1, wxEXPAND);
  SetSizer(sizer);

  // assigns images to listctrl
  wxImageList* images = new wxImageList(16, 16, true);
  images->Add(wxBitmap(sort_arrow_down_xpm), wxColour(255, 0, 0));
  images->Add(wxBitmap(sort_arrow_up_xpm), wxColour(255, 0, 0));
  listctrl_->AssignImageList(images, wxIMAGE_LIST_SMALL);
}

ReportTable::~ReportTable() {
}

const long ReportTable::IndexReportRow(const long& index_listctrl) {
  if (index_listctrl < 0) {
    return -1;
  } else if (listctrl_->GetItemCount() <= index_listctrl) {
    return -1;
  }

  // gets report data for selected index
  wxListItem item_selected;
  item_selected.SetId(index_listctrl);
  item_selected.SetMask(wxLIST_MASK_DATA);
  listctrl_->GetItem(item_selected);

  ReportRow* row_selected = (ReportRow*)item_selected.GetData();

  // searches report rows and compares memory address until a match is found
  for (auto iter = data_->rows.cbegin(); iter != data_->rows.cend(); iter++) {
    const ReportRow* row = &(*iter);

    // found a match, returns index
    if (row_selected == row) {
      return std::distance(data_->rows.cbegin(), iter);
    }
  }

  // nothing was found
  return -1;
}

void ReportTable::Refresh() {
  // helps reduce flicker
  listctrl_->Freeze();

  // initializes listctrl
  listctrl_->ClearAll();

  // inserts columns
  for (auto iter = data_->headers.cbegin(); iter != data_->headers.cend();
       iter++) {
    const std::string& str = *iter;
    const int i = std::distance(data_->headers.cbegin(), iter);
    listctrl_->InsertColumn(i, str, wxLIST_FORMAT_CENTER, 80);
  }

  // fills data
  for (auto iter = data_->rows.cbegin(); iter != data_->rows.cend(); iter++) {
    const ReportRow& row = *iter;
    const int i = std::distance(data_->rows.cbegin(), iter);

    // adds list item (row) to listctrl
    wxListItem item;
    item.SetId(i);
    item.SetData((long)&row);
    item.SetImage(-1);
    listctrl_->InsertItem(item);

    // fills remaining values for each column
    for (auto it = row.values.cbegin(); it != row.values.cend(); it++) {
      const std::string& str = *it;
      const int j = std::distance(row.values.cbegin(), it);

      // adds value to cell
      listctrl_->SetItem(i, j, str);
    }
  }

  // updates the column image and sorts
  if (listctrl_->GetColumnCount() <= index_sorted_) {
    index_sorted_ = -1;
  }

  // sorts
  ChangeColumnSortImage(index_sorted_, type_sort_);
  Sort();

  // selects item
  listctrl_->SetItemState(index_selected_, wxLIST_STATE_SELECTED,
                          wxLIST_STATE_SELECTED);

  // makes sure item is visible in refreshed table
  if ((0 < index_selected_) && (index_selected_ < listctrl_->GetItemCount())) {
    listctrl_->EnsureVisible(index_selected_);
  }

  listctrl_->Thaw();
}

const ReportData* ReportTable::data() const {
  return data_;
}

long ReportTable::index_selected() const {
  return index_selected_;
}

long ReportTable::index_sorted() const {
  return index_sorted_;
}

void ReportTable::set_data(const ReportData* data) {
  data_ = data;
}

void ReportTable::set_formatting_column(const int& column, const int& width,
                                        const wxListColumnFormat& align) {
  // checks if column exists
  if (column < 0 || listctrl_->GetColumnCount() - 1 < column) {
    return;
  }

  // modifies column formatting
  wxListItem item;
  listctrl_->GetColumn(column, item);

  item.SetWidth(width);
  item.SetAlign(align);
  listctrl_->SetColumn(column, item);
}

void ReportTable::set_index_selected(const long& index) {
  if (index < 0) {
    index_selected_ = -1;
  } else if (listctrl_->GetItemCount() <= index) {
    index_selected_ = -1;
  } else {
    index_selected_ = index;
  }
}

void ReportTable::set_index_sorted(const long& index) {
  if (index < 0) {
    index_sorted_ = -1;
  } else if (listctrl_->GetColumnCount() <= index) {
    index_sorted_ = -1;
  } else {
    index_sorted_ = index;
  }
}

void ReportTable::set_type_sort(const SortOrderType& type_sort) {
  type_sort_ = type_sort;
}

SortOrderType ReportTable::type_sort() const {
  return type_sort_;
}

void ReportTable::ChangeColumnSortImage(const int& index,
                                        const SortOrderType& type_sort) {
  if (index < 0) {
    return;
  }

  wxListItem item;
  item.SetMask(wxLIST_MASK_IMAGE);

  if (type_sort == SortOrderType::kAscending) {
    item.SetImage(0);
  } else if (type_sort == SortOrderType::kDescending) {
    item.SetImage(1);
  } else {
    item.SetImage(-1);
  }

  listctrl_->SetColumn(index, item);
}

void ReportTable::ClearListCtrl() {
  listctrl_->ClearAll();
}

std::string ReportTable::ClipboardStringHeaders() const {
  std::string str;
  const int kColumnMax = listctrl_->GetColumnCount() - 1;
  for (int index_column = 0; index_column <= kColumnMax; index_column++) {
    wxListItem item;
    listctrl_->GetColumn(index_column, item);
    str = str + item.GetText();

    // adds tab or new line character
    if (index_column == kColumnMax) {
      str = str + "\n";
    } else {
      str = str + "\t";
    }
  }

  return str;
}

std::string ReportTable::ClipboardStringRow(const int& index) const {
  // initializes
  std::string str;
  const int kColumnMax = listctrl_->GetColumnCount() - 1;

  // iterates over the number of columns
  for (int index_column = 0; index_column <= kColumnMax; index_column++) {
    // adds string from row/column index
    str = str + listctrl_->GetItemText(index, index_column);

    // adds tab or new line character
    if (index_column == kColumnMax) {
      str = str + "\n";
    } else {
      str = str + "\t";
    }
  }

  return str;
}

std::string ReportTable::ClipBoardStringTable() const {
  std::string str;
  const int kRowMax = listctrl_->GetItemCount() - 1;
  for (int index_row = 0; index_row <= kRowMax; index_row++) {
    str = str + ClipboardStringRow(index_row);
  }

  return str;
}

void ReportTable::CopyToClipboard(const std::string& str) {
  if (wxTheClipboard->Open()) {
    // creates a text data object to store clipboard information
    wxTextDataObject* data = new wxTextDataObject();
    data->SetText(str);

    // copies to the clipboard and closes
    wxTheClipboard->SetData(data);
    wxTheClipboard->Close();
  }
}

void ReportTable::OnColumnClick(wxListEvent& event) {
  // updates sorted column index
  const int index_sorted_old = index_sorted_;
  index_sorted_ = event.GetColumn();

  // updates sort order
  if (index_sorted_old == index_sorted_) {
    // inverses sort order if same column is selected
    if (type_sort_ == SortOrderType::kAscending) {
      type_sort_ = SortOrderType::kDescending;
    } else if (type_sort_ == SortOrderType::kDescending) {
      type_sort_ = SortOrderType::kAscending;
    }
  } else if (index_sorted_old == -1) {
    // initializes sort order if no columns were sorted before
    type_sort_ = SortOrderType::kAscending;
  }

  // changes column header images
  ChangeColumnSortImage(index_sorted_old, SortOrderType::kNone);
  ChangeColumnSortImage(index_sorted_, type_sort_);

  // sorts the listctrl
  Sort();
}

void ReportTable::OnColumnRightClick(wxListEvent& event) {
  // displays a context menu based on the item that was right clicked
  wxMenu menu;
  menu.Append(kCopyHeaders, "Copy Headers");
  menu.Append(kCopyTable, "Copy Table");

  // shows context menu
  // the event is caught by the the report table
  PopupMenu(&menu, event.GetPoint());

  // stops processing event (needed to allow pop-up menu to catch its event)
  event.Skip();
}

void ReportTable::OnContextMenuSelect(wxCommandEvent& event) {
  // gets context menu selection and sends to handler function
  const int id_event = event.GetId();
  if (id_event == kCopyHeaders) {
    std::string str = ClipboardStringHeaders();
    CopyToClipboard(str);
  } else if (id_event == kCopyRow) {
    std::string str = ClipboardStringRow(index_selected_);
    CopyToClipboard(str);
  } else if (id_event == kCopyTable) {
    std::string str = ClipBoardStringTable();
    CopyToClipboard(str);
  }
}

void ReportTable::OnItemRightClick(wxListEvent& event) {
  // displays a context menu based on the item that was right clicked
  wxMenu menu;
  menu.Append(kCopyRow, "Copy Row");
  menu.Append(kCopyTable, "Copy Table");

  // shows context menu
  // the event is caught by the report table
  PopupMenu(&menu, event.GetPoint());

  // stops processing event (needed to allow pop-up menu to catch its event)
  event.Skip();
}

void ReportTable::Sort() {
  // checks if sort column is selected
  if (index_sorted_ < 0) {
    return;
  }

  // creates a struct to pass sorting parameters to compare function
  SortData data;
  data.index = index_sorted_;
  data.type = type_sort_;

  // temporarily casts the column number to the sort data parameter
  listctrl_->SortItems(wxListCompareFunction, (wxIntPtr)&data);
}
<commit_msg>Fixed bug for listctrl searching.<commit_after>// This is free and unencumbered software released into the public domain.
// For more information, please refer to <http://unlicense.org/>

#include "report_table.h"

#include "models/base/helper.h"
#include "wx/clipbrd.h"
#include "wx/imaglist.h"

#include "../res/sort_arrow_up.xpm"
#include "../res/sort_arrow_down.xpm"

/// \par OVERVIEW
///
/// This struct contains all the control information for the
/// wxListCtrl::SortItems function, which is also passed onto the
/// wxListCompareFunction.
struct SortData {
  /// \var type
  ///   The sort type.
  SortOrderType type;

  /// \var index
  ///   The column index.
  int index;
};

/// \par OVERVIEW
///
/// This is the enumeration for the context menu.
enum {
  kCopyHeaders = 0,
  kCopyRow = 1,
  kCopyTable = 2
};

/// \brief This function is used by the wxListCtrl to sort items.
/// \param[in] item1
///   The first item to compare.
/// \param[in] item2
///   The second item to compare.
/// \param[in] sortData
///   The data/settings used to sort the listctrl. Column and whether
///   the sort is ascending/descending need to be detailed.
/// \return This function returns -1 if the first item is less than the second,
///   0 if they are equal, and 1 if the first is greater than the second one.
///   These values are used by wxListCtrl to sort the items.
/// This function uses the data associated with each listctrl item. See
/// wxListCtrl::SetItemData().
int wxCALLBACK wxListCompareFunction(wxIntPtr item1, wxIntPtr item2,
                                     wxIntPtr data_sort) {
  // gets sort column and order
  const SortData* data = (SortData*)data_sort;

  // gets string from row1
  const ReportRow* row1 = (ReportRow*)item1;
  const std::string& str1 = *std::next(row1->values.cbegin(), data->index);

  // gets string from row2
  const ReportRow* row2 = (ReportRow*)item2;
  const std::string& str2 = *std::next(row2->values.cbegin(), data->index);

  // attempts to compare strings as numbers
  int status;
  if (helper::IsNumeric(str1) && helper::IsNumeric(str2) == true) {
    // compares as numbers
    const double dbl1 = std::stod(str1);
    const double dbl2 = std::stod(str2);

    if (dbl1 == dbl2) {
      status = 0;
    } else if (dbl1 < dbl2) {
      status = -1;
    } else {
      status = 1;
    }
  } else {
    // compares as strings
    status = helper::CompareStrings(str1, str2);
  }

  // applies sort order
  if (data->type == SortOrderType::kAscending) {
    return status;
  } else {
    return -1 * status;
  }
}

BEGIN_EVENT_TABLE(ReportTable, wxPanel)
  EVT_LIST_COL_CLICK(wxID_ANY, ReportTable::OnColumnClick)
  EVT_LIST_COL_RIGHT_CLICK(wxID_ANY, ReportTable::OnColumnRightClick)
  EVT_LIST_ITEM_RIGHT_CLICK(wxID_ANY, ReportTable::OnItemRightClick)
  EVT_MENU(wxID_ANY, ReportTable::OnContextMenuSelect)
END_EVENT_TABLE()

ReportTable::ReportTable(wxWindow* parent) : wxPanel(parent, wxID_ANY) {
  // initializes members
  data_ = nullptr;
  index_selected_ = -1;
  index_sorted_ = -1;
  type_sort_ = SortOrderType::kNone;

  // initializes listctrl
  listctrl_ = new wxListCtrl(this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
                             wxLC_REPORT|wxLC_HRULES|wxLC_VRULES
                             |wxLC_SINGLE_SEL);
  wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
  sizer->Add(listctrl_, 1, wxEXPAND);
  SetSizer(sizer);

  // assigns images to listctrl
  wxImageList* images = new wxImageList(16, 16, true);
  images->Add(wxBitmap(sort_arrow_down_xpm), wxColour(255, 0, 0));
  images->Add(wxBitmap(sort_arrow_up_xpm), wxColour(255, 0, 0));
  listctrl_->AssignImageList(images, wxIMAGE_LIST_SMALL);
}

ReportTable::~ReportTable() {
}

const long ReportTable::IndexReportRow(const long& index_listctrl) {
  if (index_listctrl < 0) {
    return -1;
  } else if (listctrl_->GetItemCount() <= index_listctrl) {
    return -1;
  }

  // gets report data for selected index
  wxListItem item_selected;
  item_selected.SetId(index_listctrl);
  item_selected.SetMask(wxLIST_MASK_DATA);
  const bool status = listctrl_->GetItem(item_selected);

  if (status == false) {
    wxLogMessage("Couldn't retrieve selected item from listctrl.");
  }

  ReportRow* row_selected = (ReportRow*)item_selected.GetData();

  // searches report rows and compares memory address until a match is found
  for (auto iter = data_->rows.cbegin(); iter != data_->rows.cend(); iter++) {
    const ReportRow* row = &(*iter);

    // found a match, returns index
    if (row_selected == row) {
      return std::distance(data_->rows.cbegin(), iter);
    }
  }

  // nothing was found
  return -1;
}

void ReportTable::Refresh() {
  // helps reduce flicker
  listctrl_->Freeze();

  // initializes listctrl
  listctrl_->ClearAll();

  // inserts columns
  for (auto iter = data_->headers.cbegin(); iter != data_->headers.cend();
       iter++) {
    const std::string& str = *iter;
    const int i = std::distance(data_->headers.cbegin(), iter);
    listctrl_->InsertColumn(i, str, wxLIST_FORMAT_CENTER, 80);
  }

  // fills data
  for (auto iter = data_->rows.cbegin(); iter != data_->rows.cend(); iter++) {
    const ReportRow& row = *iter;
    const int i = std::distance(data_->rows.cbegin(), iter);

    // adds list item (row) to listctrl
    wxListItem item;
    item.SetId(i);
    item.SetData((void*)&row);
    item.SetImage(-1);
    listctrl_->InsertItem(item);

    // fills remaining values for each column
    for (auto it = row.values.cbegin(); it != row.values.cend(); it++) {
      const std::string& str = *it;
      const int j = std::distance(row.values.cbegin(), it);

      // adds value to cell
      listctrl_->SetItem(i, j, str);
    }
  }

  // updates the column image and sorts
  if (listctrl_->GetColumnCount() <= index_sorted_) {
    index_sorted_ = -1;
  }

  // sorts
  ChangeColumnSortImage(index_sorted_, type_sort_);
  Sort();

  // selects item
  listctrl_->SetItemState(index_selected_, wxLIST_STATE_SELECTED,
                          wxLIST_STATE_SELECTED);

  // makes sure item is visible in refreshed table
  if ((0 < index_selected_) && (index_selected_ < listctrl_->GetItemCount())) {
    listctrl_->EnsureVisible(index_selected_);
  }

  listctrl_->Thaw();
}

const ReportData* ReportTable::data() const {
  return data_;
}

long ReportTable::index_selected() const {
  return index_selected_;
}

long ReportTable::index_sorted() const {
  return index_sorted_;
}

void ReportTable::set_data(const ReportData* data) {
  data_ = data;
}

void ReportTable::set_formatting_column(const int& column, const int& width,
                                        const wxListColumnFormat& align) {
  // checks if column exists
  if (column < 0 || listctrl_->GetColumnCount() - 1 < column) {
    return;
  }

  // modifies column formatting
  wxListItem item;
  listctrl_->GetColumn(column, item);

  item.SetWidth(width);
  item.SetAlign(align);
  listctrl_->SetColumn(column, item);
}

void ReportTable::set_index_selected(const long& index) {
  if (index < 0) {
    index_selected_ = -1;
  } else if (listctrl_->GetItemCount() <= index) {
    index_selected_ = -1;
  } else {
    index_selected_ = index;
  }
}

void ReportTable::set_index_sorted(const long& index) {
  if (index < 0) {
    index_sorted_ = -1;
  } else if (listctrl_->GetColumnCount() <= index) {
    index_sorted_ = -1;
  } else {
    index_sorted_ = index;
  }
}

void ReportTable::set_type_sort(const SortOrderType& type_sort) {
  type_sort_ = type_sort;
}

SortOrderType ReportTable::type_sort() const {
  return type_sort_;
}

void ReportTable::ChangeColumnSortImage(const int& index,
                                        const SortOrderType& type_sort) {
  if (index < 0) {
    return;
  }

  wxListItem item;
  item.SetMask(wxLIST_MASK_IMAGE);

  if (type_sort == SortOrderType::kAscending) {
    item.SetImage(0);
  } else if (type_sort == SortOrderType::kDescending) {
    item.SetImage(1);
  } else {
    item.SetImage(-1);
  }

  listctrl_->SetColumn(index, item);
}

void ReportTable::ClearListCtrl() {
  listctrl_->ClearAll();
}

std::string ReportTable::ClipboardStringHeaders() const {
  std::string str;
  const int kColumnMax = listctrl_->GetColumnCount() - 1;
  for (int index_column = 0; index_column <= kColumnMax; index_column++) {
    wxListItem item;
    listctrl_->GetColumn(index_column, item);
    str = str + item.GetText();

    // adds tab or new line character
    if (index_column == kColumnMax) {
      str = str + "\n";
    } else {
      str = str + "\t";
    }
  }

  return str;
}

std::string ReportTable::ClipboardStringRow(const int& index) const {
  // initializes
  std::string str;
  const int kColumnMax = listctrl_->GetColumnCount() - 1;

  // iterates over the number of columns
  for (int index_column = 0; index_column <= kColumnMax; index_column++) {
    // adds string from row/column index
    str = str + listctrl_->GetItemText(index, index_column);

    // adds tab or new line character
    if (index_column == kColumnMax) {
      str = str + "\n";
    } else {
      str = str + "\t";
    }
  }

  return str;
}

std::string ReportTable::ClipBoardStringTable() const {
  std::string str;
  const int kRowMax = listctrl_->GetItemCount() - 1;
  for (int index_row = 0; index_row <= kRowMax; index_row++) {
    str = str + ClipboardStringRow(index_row);
  }

  return str;
}

void ReportTable::CopyToClipboard(const std::string& str) {
  if (wxTheClipboard->Open()) {
    // creates a text data object to store clipboard information
    wxTextDataObject* data = new wxTextDataObject();
    data->SetText(str);

    // copies to the clipboard and closes
    wxTheClipboard->SetData(data);
    wxTheClipboard->Close();
  }
}

void ReportTable::OnColumnClick(wxListEvent& event) {
  // updates sorted column index
  const int index_sorted_old = index_sorted_;
  index_sorted_ = event.GetColumn();

  // updates sort order
  if (index_sorted_old == index_sorted_) {
    // inverses sort order if same column is selected
    if (type_sort_ == SortOrderType::kAscending) {
      type_sort_ = SortOrderType::kDescending;
    } else if (type_sort_ == SortOrderType::kDescending) {
      type_sort_ = SortOrderType::kAscending;
    }
  } else if (index_sorted_old == -1) {
    // initializes sort order if no columns were sorted before
    type_sort_ = SortOrderType::kAscending;
  }

  // changes column header images
  ChangeColumnSortImage(index_sorted_old, SortOrderType::kNone);
  ChangeColumnSortImage(index_sorted_, type_sort_);

  // sorts the listctrl
  Sort();
}

void ReportTable::OnColumnRightClick(wxListEvent& event) {
  // displays a context menu based on the item that was right clicked
  wxMenu menu;
  menu.Append(kCopyHeaders, "Copy Headers");
  menu.Append(kCopyTable, "Copy Table");

  // shows context menu
  // the event is caught by the the report table
  PopupMenu(&menu, event.GetPoint());

  // stops processing event (needed to allow pop-up menu to catch its event)
  event.Skip();
}

void ReportTable::OnContextMenuSelect(wxCommandEvent& event) {
  // gets context menu selection and sends to handler function
  const int id_event = event.GetId();
  if (id_event == kCopyHeaders) {
    std::string str = ClipboardStringHeaders();
    CopyToClipboard(str);
  } else if (id_event == kCopyRow) {
    std::string str = ClipboardStringRow(index_selected_);
    CopyToClipboard(str);
  } else if (id_event == kCopyTable) {
    std::string str = ClipBoardStringTable();
    CopyToClipboard(str);
  }
}

void ReportTable::OnItemRightClick(wxListEvent& event) {
  // displays a context menu based on the item that was right clicked
  wxMenu menu;
  menu.Append(kCopyRow, "Copy Row");
  menu.Append(kCopyTable, "Copy Table");

  // shows context menu
  // the event is caught by the report table
  PopupMenu(&menu, event.GetPoint());

  // stops processing event (needed to allow pop-up menu to catch its event)
  event.Skip();
}

void ReportTable::Sort() {
  // checks if sort column is selected
  if (index_sorted_ < 0) {
    return;
  }

  // creates a struct to pass sorting parameters to compare function
  SortData data;
  data.index = index_sorted_;
  data.type = type_sort_;

  // temporarily casts the column number to the sort data parameter
  listctrl_->SortItems(wxListCompareFunction, (wxIntPtr)&data);
}
<|endoftext|>


<commit_before>/* RTcmix  - Copyright (C) 2000  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/
#define MAIN
#include <pthread.h>
#include <ctype.h>
#include <math.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <iostream.h>
#include <signal.h>
#ifdef LINUX
   #include <sys/soundcard.h>
#endif
#ifdef SGI
   #include <dmedia/audio.h>
#endif
#include <globals.h>
#include <prototypes.h>
#include <ugens.h>
#include "../rtstuff/rt.h"
#include "sockdefs.h"
#include "defs.h"
#include "notetags.h"           // contains defs for note-tagging
#include "../H/dbug.h"

extern "C" {
   int ug_intro();
   void *yyparse();
   int profile();
   void rtprofile();
#ifdef SGI
   void flush_all_underflows_to_zero();
#endif
#ifdef LINUX
   void flush_fpe(int sig);
#endif
}

rt_item *rt_list;     /* can't put this in globals.h because of rt.h trouble */

int interactive;     /* used in y.tab.c - don't remove this! */
Tree program;

#define CMAX 16    /* allow up to 16 command line args to be passed to subs */
char *aargv[CMAX];
char name[NAMESIZE];
int aargc;

/* <yyin> is yacc's input file. If we leave it alone, stdin will be used. */
extern FILE *yyin;

/* --------------------------------------------------------- init_globals --- */
static void
init_globals()
{
   RTBUFSAMPS = 8192;           /* default, modifyable with rtsetparams */
   NCHANS = 2;

#ifdef LINUX
   for (int i = 0; i < MAXBUS; i++)
      in_port[i] = out_port[i] = 0;
#endif /* LINUX */
#ifdef SGI
   in_port = 0;
   out_port = 0;
#endif /* SGI */

   interactive = 1;
   rtInteractive = 0;
   noParse = 0;
   socknew = 0;
   rtsetparams_called = 0;

   audio_on = 0;
   audio_config = 1;
   play_audio = 1;              /* modified with set_option */
   full_duplex = 0;

   tags_on = 0;

   rtfileit = 0;                /* signal writing to soundfile */
   rtoutfile = 0;

   print_is_on = 1;

   Bus_Configed = NO;

   for (int i = 0; i < MAX_INPUT_FDS; i++)
      inputFileTable[i].fd = NO_FD;

   init_buf_ptrs();
}

/* ------------------------------------------------------- signal_handler --- */
static void
signal_handler(int signo)
{
#ifdef DBUG
   printf("Signal handler called (signo %d)\n", signo);
#endif

   if (rtsetparams_called) {
      close_audio_ports();
      rtreportstats();
      rtcloseout();
   }
   else
      closesf();

   exit(1);
}

/* ----------------------------------------------------------------- main --- */
int
main(int argc, char *argv[])
{
   int         i, j;
   int         retcode;                 /* for mutexes */
   char        *cp, *infile;
   pthread_t   sockitThread, inTraverseThread;

   init_globals();

#ifdef LINUX
   signal(SIGFPE, flush_fpe);          /* Install signal handler */
#endif
#ifdef SGI
   flush_all_underflows_to_zero();
#endif

   /* Call signal_handler on cntl-C. */
   if (signal(SIGINT, signal_handler) == SIG_ERR) {
      fprintf(stderr, "Error installing signal handler.\n");
      exit(1);
   }

   /* Copy command-line args, if any.
      Now, command-line args will be available to any subroutine
      in aargc; and char *aargv[], (both declared extern in ugens.h)
      parsing is exactly the same then as standard C routine.
      Maximum of CMAX arguments allowed.
   */
   for (j = 1; j < argc; j++)
      aargv[j - 1] = argv[j];
   aargc = argc;

   /* Banner */
   fprintf(stderr, " ---------> RTcmix/%s <----------\n", argv[0]);

   /* Process command line. */
   if (argc >= 2) {
      while ((*++argv)[0] == '-') {
         argc -= 1;             /* Take away two args */
         for (cp = argv[0] + 1; *cp; cp++) {
            switch (*cp) {      /* Grap options */
               case 'i':               /* for separate parseit thread */
                  rtInteractive = 1;
                  audio_config = 0;
                  break;
               case 'n':               /* for separate parseit thread */
                  noParse = 1;
                  break;
               case 's':               /* set up a socket offset */
                  socknew = atoi(*++argv);
                  fprintf(stderr, "listening on socket: %d\n",
                                                         MYPORT + socknew);
                  argc -= 1;
                  break;
               case 'c':     /* set up for continuous control (note tags on) */
                  tags_on = 1;
                  printf("rtupdates enabled\n");
                  curtag = 1;          /* "0" is reserved for all notes */
                  for (i = 0; i < MAXPUPS; i++)     /* initialize element 0 */
                     pupdatevals[0][i] = NOPUPDATE;
                  break;
               case 'f':     /* use file name arg instead of stdin as score */
                  infile = *++argv;
                  yyin = fopen(infile, "r+");
                  if (yyin == NULL) {
                     printf("Can't open %s\n", infile);
                     exit(1);
                  }
                  fprintf(stderr, "Using file %s\n", infile);
                  argc -= 1;
                  break;
               default:
                  printf("Don't know about option '%c'\n", *cp);
            }
         }
         if (argc == 1)
            break;
      }
   }

   ug_intro();                  /* introduce standard routines */
   profile();                   /* introduce user-written routines etc. */
   rtprofile();                 /* introduce real-time user-written routines */

   setbuf(stdout, NULL);        /*  Want to see stdout errors */

   /* In rtInteractive mode, we set up RTcmix to listen for score data
      over a socket, and then parse this, schedule instruments, and play
      them concurrently. The socket listening and parsing go in one
      thread, and the scheduler and instrument code go in another.

      When not in rtInteractive mode, RTcmix parses the score, schedules
      all instruments, and then plays them -- in that order. No threads.
   */
   if (rtInteractive) {

      fprintf(stdout, "rtInteractive mode set\n");

      /* Read an initialization score. */
      if (!noParse) {
         cout << "Parsing once ...\n";
         yyparse();
      }

      /* Create parsing thread. */
#ifdef DBUG
      fprintf(stdout, "creating sockit() thread\n");
#endif
      retcode = pthread_create(&sockitThread, NULL, sockit, "");
      if (retcode != 0) {
         fprintf(stderr, "sockit() thread create failed\n");
      }

      /* Create scheduling thread. */
#ifdef DBUG
      fprintf(stdout, "creating inTraverse() thread\n");
#endif
      retcode = pthread_create(&inTraverseThread, NULL, inTraverse, "");
      if (retcode != 0) {
         fprintf(stderr, "inTraverse() thread create failed\n");
      }

      /* Join scheduling thread. */
#ifdef DBUG
      fprintf(stdout, "joining inTraverse() thread\n");
#endif
      retcode = pthread_join(inTraverseThread, NULL);
      if (retcode != 0) {
         fprintf(stderr, "inTraverse() thread join failed\n");
      }

      /* Join parsing thread. */
#ifdef DBUG
      fprintf(stdout, "joining sockit() thread\n");
#endif
      retcode = pthread_join(sockitThread, NULL);
      if (retcode != 0) {
         fprintf(stderr, "sockit() thread join failed\n");
      }

   }
   else {
      yyparse();
      inTraverse(NULL);
   }

   closesf();

   return 0;
}

<commit_msg>Print version string in startup banner.<commit_after>/* RTcmix  - Copyright (C) 2000  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/
#define MAIN
#include <pthread.h>
#include <ctype.h>
#include <math.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <iostream.h>
#include <signal.h>
#ifdef LINUX
   #include <sys/soundcard.h>
#endif
#ifdef SGI
   #include <dmedia/audio.h>
#endif
#include <globals.h>
#include <prototypes.h>
#include <ugens.h>
#include <version.h>
#include "../rtstuff/rt.h"
#include "sockdefs.h"
#include "defs.h"
#include "notetags.h"           // contains defs for note-tagging
#include "../H/dbug.h"

extern "C" {
   int ug_intro();
   void *yyparse();
   int profile();
   void rtprofile();
#ifdef SGI
   void flush_all_underflows_to_zero();
#endif
#ifdef LINUX
   void flush_fpe(int sig);
#endif
}

rt_item *rt_list;     /* can't put this in globals.h because of rt.h trouble */

int interactive;     /* used in y.tab.c - don't remove this! */
Tree program;

#define CMAX 16    /* allow up to 16 command line args to be passed to subs */
char *aargv[CMAX];
char name[NAMESIZE];
int aargc;

/* <yyin> is yacc's input file. If we leave it alone, stdin will be used. */
extern FILE *yyin;

/* --------------------------------------------------------- init_globals --- */
static void
init_globals()
{
   RTBUFSAMPS = 8192;           /* default, modifyable with rtsetparams */
   NCHANS = 2;

#ifdef LINUX
   for (int i = 0; i < MAXBUS; i++)
      in_port[i] = out_port[i] = 0;
#endif /* LINUX */
#ifdef SGI
   in_port = 0;
   out_port = 0;
#endif /* SGI */

   interactive = 1;
   rtInteractive = 0;
   noParse = 0;
   socknew = 0;
   rtsetparams_called = 0;

   audio_on = 0;
   audio_config = 1;
   play_audio = 1;              /* modified with set_option */
   full_duplex = 0;

   tags_on = 0;

   rtfileit = 0;                /* signal writing to soundfile */
   rtoutfile = 0;

   print_is_on = 1;

   Bus_Configed = NO;

   for (int i = 0; i < MAX_INPUT_FDS; i++)
      inputFileTable[i].fd = NO_FD;

   init_buf_ptrs();
}

/* ------------------------------------------------------- signal_handler --- */
static void
signal_handler(int signo)
{
#ifdef DBUG
   printf("Signal handler called (signo %d)\n", signo);
#endif

   if (rtsetparams_called) {
      close_audio_ports();
      rtreportstats();
      rtcloseout();
   }
   else
      closesf();

   exit(1);
}

/* ----------------------------------------------------------------- main --- */
int
main(int argc, char *argv[])
{
   int         i, j;
   int         retcode;                 /* for mutexes */
   char        *cp, *infile;
   pthread_t   sockitThread, inTraverseThread;

   init_globals();

#ifdef LINUX
   signal(SIGFPE, flush_fpe);          /* Install signal handler */
#endif
#ifdef SGI
   flush_all_underflows_to_zero();
#endif

   /* Call signal_handler on cntl-C. */
   if (signal(SIGINT, signal_handler) == SIG_ERR) {
      fprintf(stderr, "Error installing signal handler.\n");
      exit(1);
   }

   /* Copy command-line args, if any.
      Now, command-line args will be available to any subroutine
      in aargc; and char *aargv[], (both declared extern in ugens.h)
      parsing is exactly the same then as standard C routine.
      Maximum of CMAX arguments allowed.
   */
   for (j = 1; j < argc; j++)
      aargv[j - 1] = argv[j];
   aargc = argc;

   /* Banner */
   printf("--------> %s %s (%s) <--------\n",
                                      RTCMIX_NAME, RTCMIX_VERSION, argv[0]);

   /* Process command line. */
   if (argc >= 2) {
      while ((*++argv)[0] == '-') {
         argc -= 1;             /* Take away two args */
         for (cp = argv[0] + 1; *cp; cp++) {
            switch (*cp) {      /* Grap options */
               case 'i':               /* for separate parseit thread */
                  rtInteractive = 1;
                  audio_config = 0;
                  break;
               case 'n':               /* for separate parseit thread */
                  noParse = 1;
                  break;
               case 's':               /* set up a socket offset */
                  socknew = atoi(*++argv);
                  fprintf(stderr, "listening on socket: %d\n",
                                                         MYPORT + socknew);
                  argc -= 1;
                  break;
               case 'c':     /* set up for continuous control (note tags on) */
                  tags_on = 1;
                  printf("rtupdates enabled\n");
                  curtag = 1;          /* "0" is reserved for all notes */
                  for (i = 0; i < MAXPUPS; i++)     /* initialize element 0 */
                     pupdatevals[0][i] = NOPUPDATE;
                  break;
               case 'f':     /* use file name arg instead of stdin as score */
                  infile = *++argv;
                  yyin = fopen(infile, "r+");
                  if (yyin == NULL) {
                     printf("Can't open %s\n", infile);
                     exit(1);
                  }
                  fprintf(stderr, "Using file %s\n", infile);
                  argc -= 1;
                  break;
               default:
                  printf("Don't know about option '%c'\n", *cp);
            }
         }
         if (argc == 1)
            break;
      }
   }

   ug_intro();                  /* introduce standard routines */
   profile();                   /* introduce user-written routines etc. */
   rtprofile();                 /* introduce real-time user-written routines */

   setbuf(stdout, NULL);        /*  Want to see stdout errors */

   /* In rtInteractive mode, we set up RTcmix to listen for score data
      over a socket, and then parse this, schedule instruments, and play
      them concurrently. The socket listening and parsing go in one
      thread, and the scheduler and instrument code go in another.

      When not in rtInteractive mode, RTcmix parses the score, schedules
      all instruments, and then plays them -- in that order. No threads.
   */
   if (rtInteractive) {

      fprintf(stdout, "rtInteractive mode set\n");

      /* Read an initialization score. */
      if (!noParse) {
         cout << "Parsing once ...\n";
         yyparse();
      }

      /* Create parsing thread. */
#ifdef DBUG
      fprintf(stdout, "creating sockit() thread\n");
#endif
      retcode = pthread_create(&sockitThread, NULL, sockit, "");
      if (retcode != 0) {
         fprintf(stderr, "sockit() thread create failed\n");
      }

      /* Create scheduling thread. */
#ifdef DBUG
      fprintf(stdout, "creating inTraverse() thread\n");
#endif
      retcode = pthread_create(&inTraverseThread, NULL, inTraverse, "");
      if (retcode != 0) {
         fprintf(stderr, "inTraverse() thread create failed\n");
      }

      /* Join scheduling thread. */
#ifdef DBUG
      fprintf(stdout, "joining inTraverse() thread\n");
#endif
      retcode = pthread_join(inTraverseThread, NULL);
      if (retcode != 0) {
         fprintf(stderr, "inTraverse() thread join failed\n");
      }

      /* Join parsing thread. */
#ifdef DBUG
      fprintf(stdout, "joining sockit() thread\n");
#endif
      retcode = pthread_join(sockitThread, NULL);
      if (retcode != 0) {
         fprintf(stderr, "sockit() thread join failed\n");
      }

   }
   else {
      yyparse();
      inTraverse(NULL);
   }

   closesf();

   return 0;
}

<|endoftext|>


<commit_before>/* RTcmix  - Copyright (C) 2000  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/
#define MAIN
#include <globals.h>
#include <pthread.h>
#include <ctype.h>
#include <math.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <iostream.h>
extern "C" {
#include "../H/ugens.h"
}

#include "../rtstuff/rt.h"

#include "sockdefs.h"  // Also includes defs.h
#include "notetags.h" // contains defs for note-tagging

#include "../H/dbug.h"

#ifdef SGI
	#include <dmedia/audio.h>
#endif
#ifdef LINUX
	#include <sys/soundcard.h>
	#include <signal.h>
#endif

extern "C" {
	int ug_intro();
	void *yyparse();
	int profile();
	void *sockit();
	Tree exct(Tree);
	int closesf();
#ifdef SGI
	void flush_all_underflows_to_zero();
#endif
#ifdef LINUX
	void flush_fpe (int sig);
#endif
}

rt_item *rt_list;   /* can't put this in globals.h because of rt.h trouble */

extern "C" void rtprofile();
extern "C" void *inTraverse();
extern "C" void *yTraverse();
extern "C" void *traverse();
extern "C" void *rtsendsamps();

int interactive;
Tree     program;
#define CMAX 16     /* allow up to 16 command line args to be passed to subs */
int aargc;
char *aargv[CMAX];  /* this are declared in ugens.h */
char name[NAMESIZE];/* to store file name found by card scanner, accessed by
                       m_open in sound.c */
FILE *fp;

// ***************************************************************************

main(int argc, char *argv[])
{
	int	i,j;
	char    *cp,*infile;
	int retcode;  // for mutexes

	/* threads */
	pthread_t sockitThread, inTraverseThread;

	// Set up buffer sizes
	// These can be changed with rtsetparams

	play_audio = 1; // modified with audio_set
	RTBUFSAMPS = 8192; // default, modifyable with rtsetparams
	MAXBUF = NCHANS*RTBUFSAMPS;
	in_port = 0;
	out_port = 0;

	interactive = 1;		/* default is interactive mode */
	rtInteractive = 0;	/* we set this with command-line option -r now */
	oldSched = 0;
	noParse = 0;
	socknew = 0;
	audio_on = 0;
	audio_config = 1;
	tags_on = 0;
	full_duplex = 0;
	in_port = 0;
	out_port = 0;
   rtfileit = 0;        /* signal writing to soundfile */
	rtoutfile = 0;
	rtoutswap = 0;
	print_is_on = 1;

#ifdef DBUG
	printf("main():  MAXBUF = %d\n",MAXBUF);
#endif
	/*	THE FOLLOWING FUNCTION IS SGI ONLY
		set the special "flush zero" but (FS, bit 24) in the
		Control Status Register of the FPU of R4k and beyond
		so that the result of any underflowing operation will
		be clamped to zero, and no exception of any kind will
		be generated on the CPU.  This has no effect on an R3000.
	*/
#ifdef SGI
	flush_all_underflows_to_zero();
#endif
#ifdef LINUX
	/* THE FOLLOWING FUNCTION TRIES TO DO THE SAME THING */
	/* Install signal handler */
	signal(SIGFPE,flush_fpe);
#endif

	/* copy command-line args, if any*/
	for(j = 1; j < argc; j++)
		aargv[j - 1] = argv[j];
	aargc = argc;
	/* Now, command-line args will be available to any subroutine
	   in aargc; and char *aargv[], (both declared extern in ugens.h)
	   parsing is exactly the same then as standard C routine.
	   Maximum of CMAX arguments allowed. */

	fprintf(stderr," ---------> RTcmix/%s <----------\n",argv[0]);

	/*
	 * "Introduce" functions and stuff to program
	 */
	fp = NULL;

	if(argc >= 2) {
	while((*++argv)[0] == '-') {
		argc -= 1; /* Take away two args */
		for(cp = argv[0]+1; *cp; cp++) {
			switch(*cp) { /* Grap options */
			case 'i':  /* This for separate parseit thread */
			  rtInteractive = 1;
			  audio_config = 0;
			  break;
			case 'n':  /* This for separate parseit thread */
			  noParse = 1;
			  break;
			case 'o':  /* Use the old scheduler */
			  oldSched = 1;
			  break;
                        case 's': // set up a socket offset
			  socknew = atoi(*++argv);
			  fprintf(stderr,"listening on socket: %d\n",MYPORT+socknew);
			  argc -= 1;
			  break;
			case 'c': // set up for continuous control (note tags on)
				tags_on = 1;
				printf("rtupdates enabled\n");
				curtag = 1; // "0" is reserved for all notes
				for (i = 0; i < MAXPUPS; i++)  // initialize element 0
					pupdatevals[0][i] = NOPUPDATE;
				break;
			case 'f':
			  infile = *++argv;
			  fp = fopen(infile,"r+");
			  if(fp == NULL) {
			    printf("Can't open %s\n",infile);
			    exit(-1);
			  }
			  fprintf(stderr,"Using file %s\n",infile);
			  break;
			default:
				printf("don't know about option %c\n",*cp);
			}
		}
	        if(argc == 1) break;
		}
	}

	ug_intro();	/* introduce standard routines */
	profile();	/* introduce user-written routines etc. */
        rtprofile();	/* introduce real-time user-written routines */

	setbuf(stdout, NULL);	/*  Want to see stdout errors	*/

        if (rtInteractive) {
	  fprintf(stdout,"rtInteractive mode set\n");
	}

	/* Temporary ... just to get inits! */
        if (rtInteractive) {
	  /* Create the threads *************************/
	  /**********************************************/

	  /* Parsing threads ****************************/

	  if (!noParse) {
	    cout << "Parsing once ...\n";
	    yyparse();  /* a hack to read initialization scorefile */
	  }
	  fprintf(stdout,"creating sockit() thread\n");
	  retcode = pthread_create(&sockitThread, NULL, sockit, "");
	  if (retcode != 0) {
	    fprintf(stderr,"sockit() thread create failed\n");
	  }

	  /* Scheduling threads *************************/

	  fprintf(stdout,"creating inTraverse() thread\n");
	  retcode = pthread_create(&inTraverseThread, NULL, inTraverse, "");
	  if (retcode != 0) {
	    fprintf(stderr,"inTraverse() thread create failed\n");
	  }

	  /* Join the threads ****************************/
	  /***********************************************/

	  /* Scheduling threads ****************************/

	  fprintf(stdout,"joining inTraverse() thread\n");
	  retcode = pthread_join (inTraverseThread, NULL);
	  if (retcode != 0) {
	    fprintf(stderr,"inTraverse() thread join failed\n");
	  }

	  /* Parsing threads ****************************/

	  fprintf(stdout,"joining sockit() thread\n");
	  retcode = pthread_join (sockitThread, NULL);
	  if (retcode != 0) {
	    fprintf(stderr,"sockit() thread join failed\n");
	  }

	}
	else if (oldSched) {
	  cout << "Using old style parser\n";
	  yyparse();
	  traverse();  /* play instruments on the heap */
	}
	else {
	  yyparse();
	  inTraverse();
	}

#ifdef SGI
	if (out_port) while (ALgetfilled(out_port) > 0) {};
#endif
	closesf();
	fprintf(stderr,"--------->Goodbye<---------");
}

<commit_msg>Break global inits into a separate function. Init new audio bus buffer arrays. Got rid of <interactive> variable (no longer used anywhere that I could find). Other minor cleanups.<commit_after>/* RTcmix  - Copyright (C) 2000  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/
#define MAIN
#include <globals.h>
#include <pthread.h>
#include <ctype.h>
#include <math.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <iostream.h>
extern "C" {
#include "../H/ugens.h"
}

#include "../rtstuff/rt.h"

#include "sockdefs.h"  // Also includes defs.h
#include "notetags.h" // contains defs for note-tagging

#include "../H/dbug.h"

#ifdef SGI
	#include <dmedia/audio.h>
#endif
#ifdef LINUX
	#include <sys/soundcard.h>
	#include <signal.h>
#endif

extern "C" {
	int ug_intro();
	void *yyparse();
	int profile();
	void *sockit();
	Tree exct(Tree);
	int closesf();
#ifdef SGI
	void flush_all_underflows_to_zero();
#endif
#ifdef LINUX
	void flush_fpe (int sig);
#endif
}

rt_item *rt_list;   /* can't put this in globals.h because of rt.h trouble */

extern "C" void rtprofile();
extern "C" void *inTraverse();
extern "C" void *yTraverse();
extern "C" void *traverse();
extern "C" void *rtsendsamps();

Tree     program;
#define CMAX 16     /* allow up to 16 command line args to be passed to subs */
int aargc;
char *aargv[CMAX];  /* this are declared in ugens.h */
char name[NAMESIZE];/* to store file name found by card scanner, accessed by
                       m_open in sound.c */
FILE *fp;

// ***************************************************************************

static void
init_globals()
{
	// Set up buffer sizes
	// These can be changed with rtsetparams

	RTBUFSAMPS = 8192; // default, modifyable with rtsetparams
// FIXME: NCHANS hasn't even been inited yet!
	MAXBUF = NCHANS * RTBUFSAMPS;
#ifdef DBUG
	printf("init_globals():  MAXBUF = %d\n", MAXBUF);
#endif

	in_port = 0;
	out_port = 0;

	rtInteractive = 0;	/* we set this with command-line option -r now */
	oldSched = 0;
	noParse = 0;
	socknew = 0;

	audio_on = 0;
	audio_config = 1;
	play_audio = 1;      /* modified with set_option */
	full_duplex = 0;

	tags_on = 0;

   rtfileit = 0;        /* signal writing to soundfile */
	rtoutfile = 0;
	rtoutswap = 0;

	print_is_on = 1;

	rtInputIndex = -1;

	init_buf_ptrs();
}

main(int argc, char *argv[])
{
	int	i,j;
	char    *cp,*infile;
	int retcode;  // for mutexes

	/* threads */
	pthread_t sockitThread, inTraverseThread;

#ifdef SGI
	flush_all_underflows_to_zero();
#endif
#ifdef LINUX
	/* Install signal handler */
	signal(SIGFPE, flush_fpe);
#endif

	/* copy command-line args, if any*/
	for(j = 1; j < argc; j++)
		aargv[j - 1] = argv[j];
	aargc = argc;
	/* Now, command-line args will be available to any subroutine
	   in aargc; and char *aargv[], (both declared extern in ugens.h)
	   parsing is exactly the same then as standard C routine.
	   Maximum of CMAX arguments allowed. */

	fprintf(stderr," ---------> RTcmix/%s <----------\n",argv[0]);

	/*
	 * "Introduce" functions and stuff to program
	 */
	fp = NULL;

	if(argc >= 2) {
	while((*++argv)[0] == '-') {
		argc -= 1; /* Take away two args */
		for(cp = argv[0]+1; *cp; cp++) {
			switch(*cp) { /* Grap options */
			case 'i':  /* This for separate parseit thread */
			  rtInteractive = 1;
			  audio_config = 0;
			  break;
			case 'n':  /* This for separate parseit thread */
			  noParse = 1;
			  break;
			case 'o':  /* Use the old scheduler */
			  oldSched = 1;
			  break;
                        case 's': // set up a socket offset
			  socknew = atoi(*++argv);
			  fprintf(stderr,"listening on socket: %d\n",MYPORT+socknew);
			  argc -= 1;
			  break;
			case 'c': // set up for continuous control (note tags on)
				tags_on = 1;
				printf("rtupdates enabled\n");
				curtag = 1; // "0" is reserved for all notes
				for (i = 0; i < MAXPUPS; i++)  // initialize element 0
					pupdatevals[0][i] = NOPUPDATE;
				break;
			case 'f':
			  infile = *++argv;
			  fp = fopen(infile,"r+");
			  if(fp == NULL) {
			    printf("Can't open %s\n",infile);
			    exit(-1);
			  }
			  fprintf(stderr,"Using file %s\n",infile);
			  break;
			default:
				printf("don't know about option %c\n",*cp);
			}
		}
	        if(argc == 1) break;
		}
	}

	ug_intro();	/* introduce standard routines */
	profile();	/* introduce user-written routines etc. */
        rtprofile();	/* introduce real-time user-written routines */

	setbuf(stdout, NULL);	/*  Want to see stdout errors	*/

        if (rtInteractive) {
	  fprintf(stdout,"rtInteractive mode set\n");
	}

	/* Temporary ... just to get inits! */
        if (rtInteractive) {
	  /* Create the threads *************************/
	  /**********************************************/

	  /* Parsing threads ****************************/

	  if (!noParse) {
	    cout << "Parsing once ...\n";
	    yyparse();  /* a hack to read initialization scorefile */
	  }
	  fprintf(stdout,"creating sockit() thread\n");
	  retcode = pthread_create(&sockitThread, NULL, sockit, "");
	  if (retcode != 0) {
	    fprintf(stderr,"sockit() thread create failed\n");
	  }

	  /* Scheduling threads *************************/

	  fprintf(stdout,"creating inTraverse() thread\n");
	  retcode = pthread_create(&inTraverseThread, NULL, inTraverse, "");
	  if (retcode != 0) {
	    fprintf(stderr,"inTraverse() thread create failed\n");
	  }

	  /* Join the threads ****************************/
	  /***********************************************/

	  /* Scheduling threads ****************************/

	  fprintf(stdout,"joining inTraverse() thread\n");
	  retcode = pthread_join (inTraverseThread, NULL);
	  if (retcode != 0) {
	    fprintf(stderr,"inTraverse() thread join failed\n");
	  }

	  /* Parsing threads ****************************/

	  fprintf(stdout,"joining sockit() thread\n");
	  retcode = pthread_join (sockitThread, NULL);
	  if (retcode != 0) {
	    fprintf(stderr,"sockit() thread join failed\n");
	  }

	}
	else if (oldSched) {
	  cout << "Using old style parser\n";
	  yyparse();
	  traverse();  /* play instruments on the heap */
	}
	else {
	  yyparse();
	  inTraverse();
	}

#ifdef SGI
	if (out_port) while (ALgetfilled(out_port) > 0) {};
#endif
	closesf();
}

<|endoftext|>


<commit_before>#include <algorithm>
#include <functional>
#include <cctype>
#include <locale>

std::wstring trim_left(std::wstring s) {
	s.erase(
		s.begin(),
		std::find_if(
			s.begin(),
			s.end(),
			std::not1(std::ptr_fun<int, int>(std::isspace))));
	return s;
}

std::wstring trim_right(std::wstring s) {
	s.erase(
		std::find_if(
			s.rbegin(),
			s.rend(),
			std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
	return s;
}

std::wstring trim(std::wstring s) {
	return trim_left(trim_right(s));
}
<commit_msg>Replace ptr_fun with lambdas<commit_after>#include <algorithm>
#include <functional>
#include <cctype>
#include <locale>

std::wstring trim_left(std::wstring s) {
	s.erase(
		s.begin(),
		std::find_if(
			s.begin(),
			s.end(),
			[](const auto& c) {
				return !std::isspace(c);
			}
		)
	);
	return s;
}

std::wstring trim_right(std::wstring s) {
	s.erase(
		std::find_if(
			s.rbegin(),
			s.rend(),
			[](const auto& c) {
				return !std::isspace(c);
			}
		).base(), s.end()
	);
	return s;
}

std::wstring trim(std::wstring s) {
	return trim_left(trim_right(s));
}
<|endoftext|>


<commit_before>
#include"somocluWrap.h"
#include <cmath>
#include <iostream>
#include <string.h>

using namespace std;
void trainWrapper(float *data, int data_length,
                  unsigned int nEpoch,
                  unsigned int nSomX, unsigned int nSomY,
                  unsigned int nDimensions, unsigned int nVectors,
                  unsigned int radius0, unsigned int radiusN,
                  string radiusCooling,
                  float scale0, float scaleN,
                  string scaleCooling, unsigned int snapshots,
                  unsigned int kernelType, string mapType,
                  string initialCodebookFilename,
                  float *codebook, int codebook_size,
                  int *globalBmus, int globalBmus_size,
                  float *uMatrix, int uMatrix_size)
{
  ///
  /// Codebook
  ///

  int itask = 0;
  svm_node ** sparseData = NULL;
  core_data coreData;
  coreData.codebook_size = nSomY*nSomX*nDimensions;
  coreData.codebook = new float[coreData.codebook_size];
  coreData.globalBmus = NULL;
  coreData.uMatrix = NULL;
  unsigned int nVectorsPerRank = nVectors;
  coreData.globalBmus_size = nVectorsPerRank*int(ceil(nVectors/(double)nVectorsPerRank))*2;
  if (itask == 0) {
      coreData.globalBmus = new int[coreData.globalBmus_size];

      if (initialCodebookFilename.empty()){
          initializeCodebook(0, coreData.codebook, nSomX, nSomY, nDimensions);
      } else {
          unsigned int nSomXY = 0;
          unsigned int tmpNDimensions = 0;
          delete [] coreData.codebook;
          coreData.codebook = readMatrix(initialCodebookFilename, nSomXY, tmpNDimensions);
          if (tmpNDimensions != nDimensions) {
              cerr << "Dimension of initial codebook does not match data!\n";
              my_abort(5);
          } else if (nSomXY / nSomY != nSomX) {
              cerr << "Dimension of initial codebook does not match specified SOM grid!\n";
              my_abort(6);
          }
          cout << "Read initial codebook: " << initialCodebookFilename << "\n";
      }
  }
  ///
  /// Parameters for SOM
  ///
  if (radius0 == 0) {
      radius0 = nSomX / 2.0f;              /// init radius for updating neighbors
  }
  if (radiusN == 0) {
      radiusN = 1;
  }
  if (scale0 == 0) {
    scale0 = 1.0;
  }

  unsigned int currentEpoch = 0;             /// 0...nEpoch-1

  ///
  /// Training
  ///

  while ( currentEpoch < nEpoch ) {

      coreData = trainOneEpoch(itask, data, sparseData,
                               coreData, nEpoch, currentEpoch,
                               snapshots > 0,
                               nSomX, nSomY,
                               nDimensions, nVectors,
                               nVectorsPerRank,
                               radius0, radiusN,
                               radiusCooling,
                               scale0, scaleN,
                               scaleCooling,
                               kernelType, mapType);

      currentEpoch++;
    }

  if (itask == 0) {
      ///
      /// Save U-mat
      ///
      coreData.uMatrix = calculateUMatrix(coreData.codebook, nSomX, nSomY, nDimensions, mapType);
      coreData.uMatrix_size = nSomX * nSomY;
  }
  memcpy(codebook, coreData.codebook, sizeof(float) *  codebook_size);
  memcpy(globalBmus, coreData.globalBmus, sizeof(int) *  globalBmus_size);
  memcpy(uMatrix, coreData.uMatrix, sizeof(float) *  uMatrix_size);
  //cd = &coreData;
 // return coreData;

}
<commit_msg>fix delete 	modified:   somocluWrap.cpp<commit_after>
#include"somocluWrap.h"
#include <cmath>
#include <iostream>
#include <string.h>

using namespace std;
void trainWrapper(float *data, int data_length,
                  unsigned int nEpoch,
                  unsigned int nSomX, unsigned int nSomY,
                  unsigned int nDimensions, unsigned int nVectors,
                  unsigned int radius0, unsigned int radiusN,
                  string radiusCooling,
                  float scale0, float scaleN,
                  string scaleCooling, unsigned int snapshots,
                  unsigned int kernelType, string mapType,
                  string initialCodebookFilename,
                  float *codebook, int codebook_size,
                  int *globalBmus, int globalBmus_size,
                  float *uMatrix, int uMatrix_size)
{
  ///
  /// Codebook
  ///

  int itask = 0;
  svm_node ** sparseData = NULL;
  core_data coreData;
  coreData.codebook_size = nSomY*nSomX*nDimensions;
  coreData.codebook = new float[coreData.codebook_size];
  coreData.globalBmus = NULL;
  coreData.uMatrix = NULL;
  unsigned int nVectorsPerRank = nVectors;
  coreData.globalBmus_size = nVectorsPerRank*int(ceil(nVectors/(double)nVectorsPerRank))*2;
  if (itask == 0) {
      coreData.globalBmus = new int[coreData.globalBmus_size];

      if (initialCodebookFilename.empty()){
          initializeCodebook(0, coreData.codebook, nSomX, nSomY, nDimensions);
      } else {
          unsigned int nSomXY = 0;
          unsigned int tmpNDimensions = 0;
          delete [] coreData.codebook;
          coreData.codebook = readMatrix(initialCodebookFilename, nSomXY, tmpNDimensions);
          if (tmpNDimensions != nDimensions) {
              cerr << "Dimension of initial codebook does not match data!\n";
              my_abort(5);
          } else if (nSomXY / nSomY != nSomX) {
              cerr << "Dimension of initial codebook does not match specified SOM grid!\n";
              my_abort(6);
          }
          cout << "Read initial codebook: " << initialCodebookFilename << "\n";
      }
  }
  ///
  /// Parameters for SOM
  ///
  if (radius0 == 0) {
      radius0 = nSomX / 2.0f;              /// init radius for updating neighbors
  }
  if (radiusN == 0) {
      radiusN = 1;
  }
  if (scale0 == 0) {
    scale0 = 1.0;
  }

  unsigned int currentEpoch = 0;             /// 0...nEpoch-1

  ///
  /// Training
  ///

  while ( currentEpoch < nEpoch ) {

      coreData = trainOneEpoch(itask, data, sparseData,
                               coreData, nEpoch, currentEpoch,
                               snapshots > 0,
                               nSomX, nSomY,
                               nDimensions, nVectors,
                               nVectorsPerRank,
                               radius0, radiusN,
                               radiusCooling,
                               scale0, scaleN,
                               scaleCooling,
                               kernelType, mapType);

      currentEpoch++;
    }

  if (itask == 0) {
      ///
      /// Save U-mat
      ///
      coreData.uMatrix = calculateUMatrix(coreData.codebook, nSomX, nSomY, nDimensions, mapType);
      coreData.uMatrix_size = nSomX * nSomY;
  }
  memcpy(codebook, coreData.codebook, sizeof(float) *  codebook_size);
  delete [] coreData.codebook;
  memcpy(globalBmus, coreData.globalBmus, sizeof(int) *  globalBmus_size);
  delete [] coreData.globalBmus;
  memcpy(uMatrix, coreData.uMatrix, sizeof(float) *  uMatrix_size);
  delete [] coreData.uMatrix;
  //cd = &coreData;
 // return coreData;

}
<|endoftext|>


<commit_before>/**
 * \file stringutils.hpp
 * \brief stringutils header file.
 */

#ifndef STRINGUTILS_HPP_INCLUDED
#define STRINGUTILS_HPP_INCLUDED

#include <string>

namespace stringutils
{
    std::string shift(const std::string& str, int i);

    std::string uppercase(const std::string& str);

    bool is_all_unique(const std::string& str);
}

#endif // STRINGUTILS_HPP_INCLUDED
<commit_msg>added docs<commit_after>/**
 * \file stringutils.hpp
 * \brief stringutils header file.
 */

#ifndef STRINGUTILS_HPP_INCLUDED
#define STRINGUTILS_HPP_INCLUDED

#include <string>

namespace stringutils
{
    /**
     * \brief Circular shift (rotate) of string.
     * \param str Reference to string shift.
     * \param i How many times to shif the string.
              Negative values indicate left shift, positives right shift.
     * \return A copy of the original string, shifted.
     */
    std::string shift(const std::string& str, int i);

    /**
     * \brief Copies a string and converts the copy to uppercase.
     * \param str Reference to string to convert.
     * \return Uppercase copy of the original string.
     */
    std::string uppercase(const std::string& str);

    /**
     * \brief Checks if string contains all unique characters (no duplicates).
     * \param str Reference to string to check for uniqueness.
     * \return true if all unique, else false.
     */
    bool is_all_unique(const std::string& str);
}

#endif // STRINGUTILS_HPP_INCLUDED
<|endoftext|>


<commit_before>/*
 * This file is part of Clockwork.
 *
 * Copyright (c) 2013-2016 Jeremy Othieno.
 *
 * The MIT License (MIT)
 * 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 CLOCKWORK_ERROR_HH
#define CLOCKWORK_ERROR_HH

namespace clockwork {
/**
 *
 */
enum class Error {
	None,
	FileNotAccessible,
	InvalidQmlContext,
	Unknown,
};
} // namespace clockwork

#endif // CLOCKWORK_ERROR_HH
<commit_msg>Document the Error enumeration<commit_after>/*
 * This file is part of Clockwork.
 *
 * Copyright (c) 2013-2016 Jeremy Othieno.
 *
 * The MIT License (MIT)
 * 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 CLOCKWORK_ERROR_HH
#define CLOCKWORK_ERROR_HH

namespace clockwork {
/**
 * An enumeration of available system errors.
 */
enum class Error {
	None,
	FileNotAccessible,
	InvalidQmlContext,
	Unknown,
};
} // namespace clockwork

#endif // CLOCKWORK_ERROR_HH
<|endoftext|>


<commit_before>#include "common/config.h"
#include "common/signal.h"
#include "global/signal_handler.h"

#include "test/unit.h"

#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>

static volatile sig_atomic_t got_sigusr1 = 0;

static void handle_sigusr1(int signo)
{
  got_sigusr1 = 1;
}

TEST(SignalApi, SimpleInstall)
{
  install_sighandler(SIGUSR1, handle_sigusr1, 0);
}

TEST(SignalApi, SimpleInstallAndTest)
{
  install_sighandler(SIGUSR1, handle_sigusr1, 0);

  // blocked signal should not be delievered until we call sigsuspend()
  sigset_t old_sigset;
  block_signals(NULL, &old_sigset);

  int ret = kill(getpid(), SIGUSR1);
  ASSERT_EQ(ret, 0);
  ASSERT_EQ(got_sigusr1, 0);

  sigset_t mask;
  sigemptyset(&mask);
  sigdelset(&mask, SIGUSR1);
  ret = sigsuspend(&mask);
  if (ret == -1)
    ret = errno;
  ASSERT_EQ(ret, EINTR);
  ASSERT_EQ(got_sigusr1, 1);
  unblock_all_signals(&old_sigset);
}

TEST(SignalEffects, ErrnoTest1)
{
}
<commit_msg>signals unit test: fix<commit_after>#include "common/config.h"
#include "common/signal.h"
#include "global/signal_handler.h"

#include "test/unit.h"

#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>

static volatile sig_atomic_t got_sigusr1 = 0;

static void handle_sigusr1(int signo)
{
  got_sigusr1 = 1;
}

TEST(SignalApi, SimpleInstall)
{
  install_sighandler(SIGPIPE, handle_sigusr1, 0);
}

TEST(SignalApi, SimpleInstallAndTest)
{
  install_sighandler(SIGPIPE, handle_sigusr1, 0);

  // SIGPIPE starts out blocked
  int ret = kill(getpid(), SIGPIPE);
  ASSERT_EQ(ret, 0);
  ASSERT_EQ(got_sigusr1, 0);

  // handle SIGPIPE
  sigset_t mask;
  sigemptyset(&mask);
  ret = sigsuspend(&mask);
  if (ret == -1)
    ret = errno;

  // we should have gotten it
  ASSERT_EQ(ret, EINTR);
  ASSERT_EQ(got_sigusr1, 1);
}

TEST(SignalEffects, ErrnoTest1)
{
}
<|endoftext|>


<commit_before>/*
c++: 23
package_definitions: true
deps:
    - pub.egorpugin.primitives.sw.main
*/

#include <primitives/hash.h>
#include <primitives/sw/main.h>
#include <bits/stdc++.h>
using namespace std;

size_t find_closing_curly_bracket(auto &&s) {
    auto it = s.begin();
    size_t n = 0;
    while (*it) {
        if (*it == '{') ++n;
        else if (*it == '}' && !--n)
            return distance(s.begin(), it);
        ++it;
    }
    return -1;
}

int main(int argc, char *argv[]) {
    regex r_datafile{R"xxx(\\begin\{datafile\}\{(.*?)\})xxx"};
    regex r_input{R"xxx(\\\input\{(.*?)\})xxx"};
    regex r_include{R"xxx(\\\include\{(.*?)\})xxx"};
    smatch m;
    path fn = argv[1];
    ofstream ofile{argv[2]};
    ofstream dfile{argv[3]};
    dfile << "$(TMPFILE).tex :";
    auto lines = split_lines(read_file(fn), true);
    int nline = 0;
    for (auto it = lines.begin(); it != lines.end();) {
        ++nline;
        auto &s = *it++;
        if (0) {
        } else if (regex_match(s, m, r_input) || regex_match(s, m, r_include)) {
            auto fn = m[1].str();
            auto lines2 = split_lines(read_file(fn), true);
            it = lines.insert(it, lines2.begin(), lines2.end());
            dfile << " " << fn;
            continue;
        } else if (s == "\\question") {
            ofile << "%#line " << nline << " " << fn << "\n";
            ofile << "\\question{" << *it++ << "}" << "\n";
            ofile << "\\begin{enumerate}[label={\\asbuk*)}]" << "\n";
            while (*it != "")
                ofile << "\\item " << *it++ << "\n";
            ofile << "\\end{enumerate}" << "\n";
            ofile << "\n";
        } else if (s == "\\table") {
            static const regex r_multicolumn{R"xxx(\\\multicolumn\{(\d+)\})xxx"};
            static const regex r_label{R"xxx(\\\label\{(.*?)\})xxx"};
            bool bold_table_headers = false;
            optional<string> caption;
            optional<string> label;
            int ncols = 0;
            Strings table;
            while (*it != "\\endtable") {
                auto &s = *it;
                if (s == "\\boldheaders" || s == "\\жирныезаголовки") {
                    bold_table_headers = true;
                } else if (regex_match(s, m, r_label)) {
                    label = s;
                } else if (!caption) {
                    caption = s;
                } else if (s.starts_with("%")) {
                } else {
                    table.push_back(s);
                    ncols = max<int>(ncols, ranges::count(s, ';') + 1);
                }
                ++it;
            }
            ++it;
            ofile << "%#line " << nline << " " << fn << "\n";
            ofile << "\\begin{table}[ht!]" << "\n";
            if (label)
                ofile << *label << "\n";
            if (caption || label) {
                ofile << "\\caption{";
                if (caption)
                    ofile << *caption;
                if (label)
                    ofile << *label;
                ofile << "}" << "\n";
            }
            ofile << "\\centering" << "\n";
            ofile << "\\begin{tabularx}{\\textwidth}{|";
            auto headers = split_string(table[0], ";", true);
            for (int i = 0; i < ncols; ++i) {
                if (i < headers.size() && !headers[i].empty() && headers[i][0] == '{') {
                    ofile << headers[i].substr(1, find_closing_curly_bracket(headers[i]) - 1);
                } else {
                    ofile << "X";
                    //ofile << "p{" << (1.0 / ncols) << "\\textwidth}";
                }
                ofile << "|";
            }
            ofile << "}" << "\n";
            ofile << "\\hline" << "\n";
            for (int str = 0; auto &&s : table) {
                auto cols = split_string(s, ";", true);
                for (int i = 0, imulticol = 0; i < ncols; ++i, ++imulticol) {
                    if (i < cols.size()) {
                        bool multicolumn = regex_search(cols[i], m, r_multicolumn);
                        if (bold_table_headers && !multicolumn && str == 0)
                            ofile << "\\textbf{";
                        if (str == 0 && i < headers.size() && !headers[i].empty() && headers[i][0] == '{') {
                            ofile << cols[i].substr(find_closing_curly_bracket(cols[i]) + 1);
                        } else {
                            ofile << cols[i];
                        }
                        if (bold_table_headers && !multicolumn && str == 0)
                            ofile << "}";
                        if (multicolumn) {
                            imulticol += stoi(m[1].str()) - 1;
                        }
                    }
                    if (imulticol < ncols - 1)
                        ofile << " & ";
                }
                ofile << "\\\\\\hline\n";
                ++str;
            }
            ofile << "\\end{tabularx}" << "\n";
            ofile << "\\end{table}" << "\n";
            //ofile << "\n";
        } else if (regex_match(s, m, r_datafile)) {
            auto fn = m[1].str();
            string s;
            while (*it++ != "\\end{datafile}")
                s += s + "\n";
            write_file_if_different(fn, s);
        } else if (s == "\\items") {
            ofile << "%#line " << nline << " " << fn << "\n";
            ofile << "\\begin{itemize}" << "\n";
            while (*it != "")
                ofile << "\\item " << *it++ << "\n";
            ofile << "\\end{itemize}" << "\n";
            ofile << "\n";
        } else if (s == "\\enum") {
            ofile << "%#line " << nline << " " << fn << "\n";
            ofile << "\\begin{enumerate}" << "\n";
            while (*it != "")
                ofile << "\\item " << *it++ << "\n";
            ofile << "\\end{enumerate}" << "\n";
            ofile << "\n";
        // cpp (only with includes and inside main)
        // cppraw (no includes)
        // cppsw (with primitives.sw.main)
        } else if (s == "\\cppmain") {
            string s = R"xxx(
#include <bits/stdc++.h>
using namespace std;

int main(int argc, char *argv[]) {
            )xxx";
            while (*it != "\\endcppmain")
                s += *it++ + "\n";
            ++it;
            s += "}\n";
            const auto base = fs::temp_directory_path() / sha1(s);
            auto fn = path{base} += ".cpp";
            auto out = base;
            auto stdo = path{base} += ".out";
            if (!fs::exists(stdo)) {
                write_file_if_different(fn, s);
                {
                    string cmd = "g++ -std=c++23 " + fn.string() + " -o " + base.string();
                    if (system(cmd.c_str()))
                        throw SW_RUNTIME_ERROR("build error");
                }
                {
                    string cmd = base.string() + " > " + stdo.string();
                    if (system(cmd.c_str()))
                        throw SW_RUNTIME_ERROR("run error");
                }
            }
            auto lines2 = split_lines(read_file(stdo), true);
            it = lines.insert(it, lines2.begin(), lines2.end());
        } else {
            ofile << s << "\n";
        }
    }
    return 0;
}
<commit_msg>[texpp] Update.<commit_after>/*
c++: 23
package_definitions: true
deps:
    - pub.egorpugin.primitives.sw.main
*/

#include <primitives/hash.h>
#include <primitives/sw/main.h>
#include <bits/stdc++.h>
using namespace std;

size_t find_closing_curly_bracket(auto &&s) {
    auto it = s.begin();
    size_t n = 0;
    while (*it) {
        if (*it == '{') ++n;
        else if (*it == '}' && !--n)
            return distance(s.begin(), it);
        ++it;
    }
    return -1;
}

int main(int argc, char *argv[]) {
    regex r_datafile{R"xxx(\\begin\{datafile\}\{(.*?)\})xxx"};
    regex r_input{R"xxx(\\\input\{(.*?)\})xxx"};
    regex r_include{R"xxx(\\\include\{(.*?)\})xxx"};
    smatch m;
    path fn = argv[1];
    ofstream ofile{argv[2]};
    ofstream dfile{argv[3]};
    dfile << "$(TMPFILE).tex :";
    auto lines = split_lines(read_file(fn), true);
    // preprocessor step
    for (auto it = lines.begin(); it != lines.end();) {
        auto &s = *it++;
        if (0) {
        } else if (regex_match(s, m, r_input) || regex_match(s, m, r_include)) {
            auto fn = m[1].str();
            auto lines2 = split_lines(read_file(fn), true);
            s = "%" + s;
            it = lines.insert(it, lines2.begin(), lines2.end());
            dfile << " " << fn;
            continue;
        }
    }
    // remove %commented lines
    for (auto it = lines.begin(); it != lines.end();) {
        if (it->starts_with('%'))
            it = lines.erase(it);
        else
            ++it;
    }
    int nline = 0;
    for (auto it = lines.begin(); it != lines.end();) {
        ++nline;
        auto &s = *it++;
        if (0) {
        } else if (s == "\\question") {
            ofile << "%#line " << nline << " " << fn << "\n";
            ofile << "\\question{" << *it++ << "}" << "\n";
            ofile << "\\begin{enumerate}[label={\\asbuk*)}]" << "\n";
            while (*it != "")
                ofile << "\\item " << *it++ << "\n";
            ofile << "\\end{enumerate}" << "\n";
            ofile << "\n";
        } else if (s == "\\table") {
            static const regex r_multicolumn{R"xxx(\\\multicolumn\{(\d+)\})xxx"};
            static const regex r_label{R"xxx(\\\label\{(.*?)\})xxx"};
            bool bold_table_headers = false;
            optional<string> caption;
            optional<string> label;
            int ncols = 0;
            Strings table;
            while (*it != "\\endtable") {
                auto &s = *it;
                if (s == "\\boldheaders" || s == "\\жирныезаголовки") {
                    bold_table_headers = true;
                } else if (regex_match(s, m, r_label)) {
                    label = s;
                } else if (!caption) {
                    caption = s;
                } else if (s.starts_with("%")) {
                } else {
                    table.push_back(s);
                    ncols = max<int>(ncols, ranges::count(s, ';') + 1);
                }
                ++it;
            }
            ++it;
            ofile << "%#line " << nline << " " << fn << "\n";
            ofile << "\\begin{table}[ht!]" << "\n";
            if (label)
                ofile << *label << "\n";
            if (caption || label) {
                ofile << "\\caption{";
                if (caption)
                    ofile << *caption;
                if (label)
                    ofile << *label;
                ofile << "}" << "\n";
            }
            ofile << "\\centering" << "\n";
            ofile << "\\begin{tabularx}{\\textwidth}{|";
            auto headers = split_string(table[0], ";", true);
            for (int i = 0; i < ncols; ++i) {
                if (i < headers.size() && !headers[i].empty() && headers[i][0] == '{') {
                    ofile << headers[i].substr(1, find_closing_curly_bracket(headers[i]) - 1);
                } else {
                    ofile << "X";
                    //ofile << "p{" << (1.0 / ncols) << "\\textwidth}";
                }
                ofile << "|";
            }
            ofile << "}" << "\n";
            ofile << "\\hline" << "\n";
            for (int str = 0; auto &&s : table) {
                auto cols = split_string(s, ";", true);
                for (int i = 0, imulticol = 0; i < ncols; ++i, ++imulticol) {
                    if (i < cols.size()) {
                        bool multicolumn = regex_search(cols[i], m, r_multicolumn);
                        if (bold_table_headers && !multicolumn && str == 0)
                            ofile << "\\textbf{";
                        if (str == 0 && i < headers.size() && !headers[i].empty() && headers[i][0] == '{') {
                            ofile << cols[i].substr(find_closing_curly_bracket(cols[i]) + 1);
                        } else {
                            ofile << cols[i];
                        }
                        if (bold_table_headers && !multicolumn && str == 0)
                            ofile << "}";
                        if (multicolumn) {
                            imulticol += stoi(m[1].str()) - 1;
                        }
                    }
                    if (imulticol < ncols - 1)
                        ofile << " & ";
                }
                ofile << "\\\\\\hline\n";
                ++str;
            }
            ofile << "\\end{tabularx}" << "\n";
            ofile << "\\end{table}" << "\n";
            //ofile << "\n";
        } else if (regex_match(s, m, r_datafile)) {
            auto fn = m[1].str();
            string s;
            while (*it++ != "\\end{datafile}")
                s += s + "\n";
            write_file_if_different(fn, s);
        } else if (s == "\\items") {
            ofile << "%#line " << nline << " " << fn << "\n";
            ofile << "\\begin{itemize}" << "\n";
            while (*it != "")
                ofile << "\\item " << *it++ << "\n";
            ofile << "\\end{itemize}" << "\n";
            ofile << "\n";
        } else if (s == "\\enum") {
            ofile << "%#line " << nline << " " << fn << "\n";
            ofile << "\\begin{enumerate}" << "\n";
            while (*it != "")
                ofile << "\\item " << *it++ << "\n";
            ofile << "\\end{enumerate}" << "\n";
            ofile << "\n";
        // cpp (only with includes and inside main)
        // cppraw (no includes)
        // cppsw (with primitives.sw.main)
        } else if (s == "\\cppmain") {
            string s = R"xxx(
#include <bits/stdc++.h>
using namespace std;

int main(int argc, char *argv[]) {
            )xxx";
            while (*it != "\\endcppmain")
                s += *it++ + "\n";
            ++it;
            s += "}\n";
            const auto base = fs::temp_directory_path() / sha1(s);
            auto fn = path{base} += ".cpp";
            auto out = base;
            auto stdo = path{base} += ".out";
            if (!fs::exists(stdo)) {
                write_file_if_different(fn, s);
                {
                    string cmd = "g++ -std=c++23 " + fn.string() + " -o " + base.string();
                    if (system(cmd.c_str()))
                        throw SW_RUNTIME_ERROR("build error");
                }
                {
                    string cmd = base.string() + " > " + stdo.string();
                    if (system(cmd.c_str()))
                        throw SW_RUNTIME_ERROR("run error");
                }
            }
            auto lines2 = split_lines(read_file(stdo), true);
            it = lines.insert(it, lines2.begin(), lines2.end());
        } else {
            ofile << s << "\n";
        }
    }
    return 0;
}
<|endoftext|>


<commit_before>#include "../base.hpp"

// Higher weights are higher.
// Primarily used as a set able to get the k-th element

struct Treap {
    Treap *lson = NULL, *rson = NULL;
    ll val;
    int weight;
    int size = 0;

    Treap(ll _val) : val(_val), weight(rand()), size(1) {}

    ~Treap() {
        delete lson;
        delete rson;
    }

    void setSon(bool right, Treap *newSon) {
        Treap *&upd = right ? (rson) : (lson);
        upd = newSon;
        size = 1 + (lson ? (lson->size) : 0) + (rson ? (rson->size) : 0);
    }
};

Treap* merge(Treap *l, Treap *r) {
    if (!l) return r;
    if (!r) return l;
    if (l->weight > r->weight) {
        l->setSon(true, merge(l->rson, r));
        return l;
    } else {
        r->setSon(false, merge(l, r->lson));
        return r;
    }
}

pair<Treap*, Treap*> split(Treap *a, ll val) {
    if (!a) return {NULL, NULL};
    if (a->val <= val) {
        pair<Treap*, Treap*> res = split(a->rson, val);
        a->setSon(true, res.first);
        return {a, res.second};
    } else {
        pair<Treap*, Treap*> res = split(a->lson, val);
        a->setSon(false, res.second);
        return {res.first, a};
    }
}

void insert(Treap *&a, ll val) {
    if (!a) {
        a = new Treap(val);
    } else {
        pair<Treap*, Treap*> spl = split(a, val);
        a = merge(spl.first, new Treap(val));
        a = merge(a, spl.second);
    }
}

// TODO: works only for integers; all elements in the treap must be unique
void erase(Treap *&a, ll val) {
	pair <Treap *, Treap *> spl = split(a, val);
	pair <Treap *, Treap *> spl2 = split(spl.first, --val);
	assert(spl2.second->size == 1);
	delete spl2.second;
	a = merge(spl2.first, spl.second);
}

ll getKth(Treap *a, int k) { //zero-indexed
    int lsize = (a->lson ? (a->lson->size) : 0);
    if (lsize == k) {
        return a->val;
    } else if (lsize > k) {
        return getKth(a->lson, k);
    } else {
        assert(a->rson); //when k >= size
        return getKth(a->rson, k - lsize - 1);
    }
}

int indexOf(Treap *a, ll val) {
    if (!a) return -1;
    int lsize = (a->lson ? (a->lson->size) : 0);
    if (a->val == val) {
        return lsize;
    } else if (val < a->val) {
        return indexOf(a->lson, val);
    } else {
        int res = indexOf(a->rson, val);
        if (res == -1) return -1;
        else return res + lsize + 1;
    }
}
<commit_msg>Treap: odrekurzit funkce pro k-tý prvek<commit_after>#include "../base.hpp"

// Higher weights are higher.
// Primarily used as a set able to get the k-th element

#define SIZE(t) ((t) ? (t)->size : 0)

struct Treap {
    Treap *lson = NULL, *rson = NULL;
    ll val;
    int weight;
    int size = 0;

    Treap(ll _val) : val(_val), weight(rand()), size(1) {}

    ~Treap() {
        delete lson;
        delete rson;
    }

    void setSon(bool right, Treap *newSon) {
        Treap *&upd = right ? (rson) : (lson);
        upd = newSon;
        size = 1 + SIZE(lson) + SIZE(rson);
    }
};

Treap* merge(Treap *l, Treap *r) {
    if (!l) return r;
    if (!r) return l;
    if (l->weight > r->weight) {
        l->setSon(true, merge(l->rson, r));
        return l;
    } else {
        r->setSon(false, merge(l, r->lson));
        return r;
    }
}

pair<Treap*, Treap*> split(Treap *a, ll val) {
    if (!a) return {NULL, NULL};
    if (a->val <= val) {
        pair<Treap*, Treap*> res = split(a->rson, val);
        a->setSon(true, res.first);
        return {a, res.second};
    } else {
        pair<Treap*, Treap*> res = split(a->lson, val);
        a->setSon(false, res.second);
        return {res.first, a};
    }
}

void insert(Treap *&a, ll val) {
    if (!a) {
        a = new Treap(val);
    } else {
        pair<Treap*, Treap*> spl = split(a, val);
        a = merge(spl.first, new Treap(val));
        a = merge(a, spl.second);
    }
}

// TODO: works only for integers; all elements in the treap must be unique
void erase(Treap *&a, ll val) {
	pair <Treap *, Treap *> spl = split(a, val);
	pair <Treap *, Treap *> spl2 = split(spl.first, --val);
	assert(spl2.second->size == 1);
	delete spl2.second;
	a = merge(spl2.first, spl.second);
}

ll getKth(Treap *a, int k) { //zero-indexed
    assert(k < a->size);
    while (true) {
        int lsize = SIZE(a->lson);
        if (lsize == k)
            return a->val;
        else if (lsize > k)
            a = a->lson;
        else
            a = a->rson, k -= lsize + 1;
    }
}

int indexOf(Treap *a, ll val) {
    int res = 0;
    while (true) {
        if (!a) return -1;
        int lsize = SIZE(a->lson);
        if (a->val == val)
            return res + lsize;
        else if (val < a->val)
            a = a->lson;
        else
            res += lsize + 1, a = a->rson;
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright 2007-2020 CM4all GmbH
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once

#include "util/Compiler.h"

#include <boost/intrusive/slist.hpp>

/**
 * List of key/value pairs.
 */
class KeyValueList {
public:
	struct Item : boost::intrusive::slist_base_hook<boost::intrusive::link_mode<boost::intrusive::normal_link>> {
		const char *key, *value;

		Item(const char *_key, const char *_value)
			:key(_key), value(_value) {}
	};

private:
	typedef boost::intrusive::slist<Item,
					boost::intrusive::constant_time_size<false>> List;

	typedef List::const_iterator const_iterator;

	List list;

public:
	KeyValueList() = default;
	KeyValueList(const KeyValueList &) = delete;
	KeyValueList(KeyValueList &&src) {
		list.swap(src.list);
	}

	template<typename Alloc>
	KeyValueList(Alloc &&alloc, const KeyValueList &src) {
		for (const auto &i : src)
			Add(alloc, alloc.Dup(i.key), alloc.Dup(i.value));
	}

	KeyValueList &operator=(KeyValueList &&src) {
		list.swap(src.list);
		return *this;
	}

	const_iterator begin() const {
		return list.begin();
	}

	const_iterator end() const {
		return list.end();
	}

	gcc_pure
	bool IsEmpty() const {
		return list.empty();
	}

	void Clear() {
		list.clear();
	}

	template<typename Alloc>
	void Add(Alloc &&alloc, const char *key, const char *value) {
		auto item = alloc.template New<Item>(key, value);
		list.push_front(*item);
	}

	void Reverse() {
		list.reverse();
	}
};
<commit_msg>util/kvlist: add `noexcept`<commit_after>/*
 * Copyright 2007-2020 CM4all GmbH
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once

#include "util/Compiler.h"

#include <boost/intrusive/slist.hpp>

/**
 * List of key/value pairs.
 */
class KeyValueList {
public:
	struct Item : boost::intrusive::slist_base_hook<boost::intrusive::link_mode<boost::intrusive::normal_link>> {
		const char *key, *value;

		Item(const char *_key, const char *_value) noexcept
			:key(_key), value(_value) {}
	};

private:
	typedef boost::intrusive::slist<Item,
					boost::intrusive::constant_time_size<false>> List;

	typedef List::const_iterator const_iterator;

	List list;

public:
	KeyValueList() = default;
	KeyValueList(const KeyValueList &) = delete;
	KeyValueList(KeyValueList &&src) noexcept {
		list.swap(src.list);
	}

	template<typename Alloc>
	KeyValueList(Alloc &&alloc, const KeyValueList &src) noexcept {
		for (const auto &i : src)
			Add(alloc, alloc.Dup(i.key), alloc.Dup(i.value));
	}

	KeyValueList &operator=(KeyValueList &&src) noexcept {
		list.swap(src.list);
		return *this;
	}

	const_iterator begin() const noexcept {
		return list.begin();
	}

	const_iterator end() const noexcept {
		return list.end();
	}

	gcc_pure
	bool IsEmpty() const noexcept {
		return list.empty();
	}

	void Clear() noexcept {
		list.clear();
	}

	template<typename Alloc>
	void Add(Alloc &&alloc, const char *key, const char *value) noexcept {
		auto item = alloc.template New<Item>(key, value);
		list.push_front(*item);
	}

	void Reverse() noexcept {
		list.reverse();
	}
};
<|endoftext|>