<commit_before>#include "doofit/plotting/Plot/PlotSimultaneous.h"

// STL
#include <vector>
#include <string>

// boost

// ROOT
#include "TList.h"
#include "TIterator.h"
#include "TCanvas.h"
#include "TPaveText.h"

// from RooFit
#include "RooSimultaneous.h"
#include "RooAbsData.h"
#include "RooAbsRealLValue.h"
#include "RooAbsCategoryLValue.h"
#include "RooCatType.h"
#include "RooDataHist.h"
#include "RooSuperCategory.h"
#include "RooCategory.h"

// from DooCore
#include "doocore/io/MsgStream.h"
#include "doocore/lutils/lutils.h"

// from Project

using namespace ROOT;
using namespace RooFit;
using namespace doocore::io;

namespace doofit {
namespace plotting {

PlotSimultaneous::PlotSimultaneous(const PlotConfig& cfg_plot, const RooAbsRealLValue& dimension, const RooAbsData& dataset, const RooSimultaneous& pdf, const std::vector<std::string>& components, const std::string& plot_name)
: Plot(cfg_plot, dimension, dataset, pdf, components, plot_name),
  components_regexps_(components)
{

}

void PlotSimultaneous::PlotHandler(ScaleType sc_y, std::string suffix) const {
  const RooSimultaneous& pdf = *dynamic_cast<const RooSimultaneous*>(pdf_);
  const RooAbsData& data     = *datasets_.front();
  RooAbsCategoryLValue& sim_cat = const_cast<RooAbsCategoryLValue&>(pdf.indexCat());
  TList* data_split = data.split(sim_cat);
  std::string plot_name;

  RooCatType* sim_cat_type = NULL;
  TIterator* sim_cat_type_iter = sim_cat.typeIterator();
  int num_slices = 0;
  while((sim_cat_type=dynamic_cast<RooCatType*>(sim_cat_type_iter->Next()))) {
    RooAbsPdf& sub_pdf = *(pdf.getPdf(sim_cat_type->GetName()));
    if (&sub_pdf != NULL) {
      RooAbsData& sub_data = *dynamic_cast<RooAbsData*>(data_split->FindObject(sim_cat_type->GetName()));

      sim_cat.setIndex(sim_cat_type->getVal());

      std::string cut_string = "";
      const RooSuperCategory* super_cat = dynamic_cast<const RooSuperCategory*>(&sim_cat);
      const RooCategory* std_cat        = dynamic_cast<const RooCategory*>(&sim_cat);
      if (super_cat != NULL) {
        RooLinkedListIter* it  = (RooLinkedListIter*)super_cat->inputCatList().createIterator();
        RooAbsArg*         arg = NULL;

        while ((arg=(RooAbsArg*)it->Next())) {
          RooCategory* cat = dynamic_cast<RooCategory*>(arg);
          if (cat != NULL) {
            if (cut_string.length() > 0) cut_string = cut_string + "&&";
            cut_string = cut_string + cat->GetName() + "==" + std::to_string(cat->getIndex());
          } else {
            serr << "Error in PlotSimultaneous::PlotHandler(...): Cannot handle category component " << arg->GetName() << endmsg;
          }
        }

        sdebug << "Cut string: " << cut_string << endmsg;

        delete it;
      } else if (std_cat != NULL) {
        cut_string = std::string(std_cat->GetName()) + "==" + std::to_string(std_cat->getIndex());
        sdebug << "Cut string: " << cut_string << endmsg;
      }

      RooAbsData& sub_data2 = data.reduce(Cut(cut_string.c_str()));
      sub_data.Print();
      sub_data2.Print();

      if (&sub_data == NULL) {
        serr << "PlotSimultaneous::PlotHandler(...): sub dataset for category " << sim_cat_type->GetName() << " empty. Will not plot. " << endmsg;
      } else {
        double min,max;
        RooRealVar var(dynamic_cast<const RooRealVar&>(dimension_));
        sub_data.getRange(var, min, max);
        //sdebug << "Range: " << min << "," << max << endmsg;

        //plot_name = std::string(dimension_.GetName()) + "_" + sim_cat_type->GetName();
        plot_name = plot_name_ + "_" + sim_cat_type->GetName();
        Plot plot(config_plot_, dimension_, sub_data, sub_pdf, components_regexps_, plot_name);
        plot.plot_args_ = this->plot_args_;
        plot.plot_range_ = this->plot_range_;

        // 20130905 FK: deactivated this manual setting of the plot range as it
        //              can dramatically increase plot time. Maybe need to
        //              rethink that later
        //plot.AddPlotArg(Range(min,max));

        // go through supplied cmd args and if necessary adapt ProjWData argument
        bool project_arg_found         = false;
        RooArgSet* set_project         = NULL;
        RooAbsData* data_reduced       = NULL;
        const RooAbsData* data_project = NULL;
        bool binned_projection         = false;
        for (std::vector<RooCmdArg>::iterator it = plot.plot_args_.begin();
             it != plot.plot_args_.end(); ++it) {
          if (std::string(it->GetName()) == "ProjData") {
            sinfo << "Found ProjWData() argument. Will change projection dataset accordingly." << endmsg;
            project_arg_found = true;
            binned_projection = it->getInt(0);

            // check for binned projection and if so generate binned dataset here to
            // accelerate projection
            if (binned_projection) {
              set_project = new RooArgSet(*dynamic_cast<const RooArgSet*>(it->getObject(0)));

              sinfo << " Binned projection is requested. Will generate a binned dataset to accelerate projection." << endmsg;

              data_reduced = sub_data.reduce(*set_project);
              std::string name_data_hist = std::string(sub_data.GetName()) + "_hist" + sim_cat_type->GetName();
              data_project = new RooDataHist(name_data_hist.c_str(), "binned projection dataset", *data_reduced->get(), *data_reduced);

              sinfo << " Created binned dataset with " << data_project->numEntries() << " bins." << endmsg;
            } else {
              data_project = &sub_data;
            }

            // create the new projection argument
            *it = ProjWData(*dynamic_cast<const RooArgSet*>(it->getObject(0)),
                            *data_project,
                            it->getInt(0));
          }
        }

        doocore::lutils::setStyle("LHCb");
        config_plot_.OnDemandOpenPlotStack();
        TCanvas c1("c1","c1",900,900);
        std::string label_text1 = std::string("Next plots: dimension ") + dimension_.GetName() + ", category " + sim_cat_type->GetName();
        std::string label_text2 = std::string(" (") + plot_name + ")";
        TPaveText label(0.1, 0.25, 0.9, 0.75);
        label.SetTextSize(0.03);
        label.AddText(label_text1.c_str());
        label.AddText(label_text2.c_str());
        label.SetLineWidth(0.0);
        label.SetTextAlign(13);
        label.SetFillColor(0);
        label.Draw();
        c1.Print(std::string(config_plot_.plot_directory()+"/pdf/AllPlots"+config_plot_.plot_appendix()+".pdf").c_str());

        plot.PlotHandler(sc_y, suffix);

        if (set_project != NULL) delete set_project;
        if (binned_projection) {
          delete data_project;
          delete data_reduced;
        }

        ++num_slices;
      }
    }
  }

  if (num_slices > 1) {
    TCanvas c1("c1","c1",900,900);
    std::string label_text1 = std::string("Next plots: dimension ") + dimension_.GetName() + ", summed all categories ";
    std::string label_text2 = std::string(" (") + plot_name + ")";
    TPaveText label(0.1, 0.25, 0.9, 0.75);
    label.SetTextSize(0.03);
    label.AddText(label_text1.c_str());
    label.AddText(label_text2.c_str());
    label.SetLineWidth(0.0);
    label.SetTextAlign(13);
    label.SetFillColor(0);
    label.Draw();
    c1.Print(std::string(config_plot_.plot_directory()+"/pdf/AllPlots"+config_plot_.plot_appendix()+".pdf").c_str());

    //  plot_name = std::string(dimension_.GetName()) + "_summed";
    plot_name = plot_name_ + "_summed";
    Plot plot(config_plot_, dimension_, data, *pdf_, components_regexps_, plot_name);
    plot.plot_args_ = this->plot_args_;
    plot.plot_range_ = this->plot_range_;

    // go through supplied cmd args and if necessary merge ProjWData arguments
    bool project_arg_found         = false;
    RooArgSet* set_project         = NULL;
    RooAbsData* data_reduced       = NULL;
    const RooAbsData* data_project = NULL;
    bool binned_projection         = false;
    for (std::vector<RooCmdArg>::iterator it = plot.plot_args_.begin();
         it != plot.plot_args_.end(); ++it) {
      if (std::string(it->GetName()) == "ProjData") {
        sinfo << "Found ProjWData() argument. Will join with " << sim_cat.GetName() << " on same dataset." << endmsg;
        project_arg_found = true;
        binned_projection = it->getInt(0);

        // copy argset for projection and add simultaneous category variables
        set_project = new RooArgSet(*dynamic_cast<const RooArgSet*>(it->getObject(0)));
        const RooSuperCategory* super_sim_cat = &dynamic_cast<const RooSuperCategory&>(sim_cat);
        if (super_sim_cat) {
          // The simultaneous category is a super category and will not be in the
          // supplied dataset. Add input categories instead.
          set_project->add(super_sim_cat->inputCatList());
        } else {
          set_project->add(sim_cat);
        }

        // check for binned projection and if so generate binned dataset here to
        // accelerate projection
        if (binned_projection) {
          sinfo << " Binned projection is requested. Will generate a binned dataset to accelerate projection." << endmsg;

          RooAbsData* data_proj = const_cast<RooAbsData*>(dynamic_cast<const RooAbsData*>(it->getObject(1)));
          std::string name_data_hist = std::string(data_proj->GetName()) + "_hist";
          data_reduced = data_proj->reduce(*set_project);
          data_project = new RooDataHist(name_data_hist.c_str(), "binned projection dataset", *data_reduced->get(), *data_reduced);

          sinfo << " Created binned dataset with " << data_project->numEntries() << " bins." << endmsg;
        } else {
          data_project = dynamic_cast<const RooAbsData*>(it->getObject(1));
        }

        // create the new projection argument
        *it = ProjWData(*set_project,
                        *data_project,
                        it->getInt(0));
      }
    }
    if (!project_arg_found) plot.AddPlotArg(ProjWData(sim_cat,data));

    plot.PlotHandler(sc_y, suffix);

    if (set_project != NULL) delete set_project;
    if (binned_projection) {
      delete data_reduced;
      delete data_project;
    }
  }

  TIter next(data_split);
  TObject *obj = NULL;
  while ((obj = next())) {
    delete obj;
  }
}

} // namespace plotting
} // namespace doofit
<commit_msg>PlotSimultaneous: Using hand-made sub datasets<commit_after>#include "doofit/plotting/Plot/PlotSimultaneous.h"

// STL
#include <vector>
#include <string>

// boost

// ROOT
#include "TList.h"
#include "TIterator.h"
#include "TCanvas.h"
#include "TPaveText.h"

// from RooFit
#include "RooSimultaneous.h"
#include "RooAbsData.h"
#include "RooAbsRealLValue.h"
#include "RooAbsCategoryLValue.h"
#include "RooCatType.h"
#include "RooDataHist.h"
#include "RooSuperCategory.h"
#include "RooCategory.h"

// from DooCore
#include "doocore/io/MsgStream.h"
#include "doocore/lutils/lutils.h"

// from Project

using namespace ROOT;
using namespace RooFit;
using namespace doocore::io;

namespace doofit {
namespace plotting {

PlotSimultaneous::PlotSimultaneous(const PlotConfig& cfg_plot, const RooAbsRealLValue& dimension, const RooAbsData& dataset, const RooSimultaneous& pdf, const std::vector<std::string>& components, const std::string& plot_name)
: Plot(cfg_plot, dimension, dataset, pdf, components, plot_name),
  components_regexps_(components)
{

}

void PlotSimultaneous::PlotHandler(ScaleType sc_y, std::string suffix) const {
  const RooSimultaneous& pdf = *dynamic_cast<const RooSimultaneous*>(pdf_);
  const RooAbsData& data     = *datasets_.front();
  RooAbsData& data_nonconst_fucking_roofit = const_cast<RooAbsData&>(data);
  RooAbsCategoryLValue& sim_cat = const_cast<RooAbsCategoryLValue&>(pdf.indexCat());
  //TList* data_split = data.split(sim_cat);
  std::string plot_name;

  RooCatType* sim_cat_type = NULL;
  TIterator* sim_cat_type_iter = sim_cat.typeIterator();
  int num_slices = 0;
  while((sim_cat_type=dynamic_cast<RooCatType*>(sim_cat_type_iter->Next()))) {
    RooAbsPdf& sub_pdf = *(pdf.getPdf(sim_cat_type->GetName()));
    if (&sub_pdf != NULL) {
      //RooAbsData& sub_data = *dynamic_cast<RooAbsData*>(data_split->FindObject(sim_cat_type->GetName()));

      sim_cat.setIndex(sim_cat_type->getVal());

      std::string cut_string = "";
      const RooSuperCategory* super_cat = dynamic_cast<const RooSuperCategory*>(&sim_cat);
      const RooCategory* std_cat        = dynamic_cast<const RooCategory*>(&sim_cat);
      if (super_cat != NULL) {
        RooLinkedListIter* it  = (RooLinkedListIter*)super_cat->inputCatList().createIterator();
        RooAbsArg*         arg = NULL;

        while ((arg=(RooAbsArg*)it->Next())) {
          RooCategory* cat = dynamic_cast<RooCategory*>(arg);
          if (cat != NULL) {
            if (cut_string.length() > 0) cut_string = cut_string + "&&";
            cut_string = cut_string + cat->GetName() + "==" + std::to_string(cat->getIndex());
          } else {
            serr << "Error in PlotSimultaneous::PlotHandler(...): Cannot handle category component " << arg->GetName() << endmsg;
          }
        }

        sdebug << "Cut string: " << cut_string << endmsg;

        delete it;
      } else if (std_cat != NULL) {
        cut_string = std::string(std_cat->GetName()) + "==" + std::to_string(std_cat->getIndex());
        sdebug << "Cut string: " << cut_string << endmsg;
      }

      RooAbsData* sub_data2 = data_nonconst_fucking_roofit.reduce(Cut(cut_string.c_str()));
      RooAbsData& sub_data = *sub_data2;

      if (&sub_data == NULL) {
        serr << "PlotSimultaneous::PlotHandler(...): sub dataset for category " << sim_cat_type->GetName() << " empty. Will not plot. " << endmsg;
      } else {
        double min,max;
        RooRealVar var(dynamic_cast<const RooRealVar&>(dimension_));
        sub_data.getRange(var, min, max);
        //sdebug << "Range: " << min << "," << max << endmsg;

        //plot_name = std::string(dimension_.GetName()) + "_" + sim_cat_type->GetName();
        plot_name = plot_name_ + "_" + sim_cat_type->GetName();
        Plot plot(config_plot_, dimension_, sub_data, sub_pdf, components_regexps_, plot_name);
        plot.plot_args_ = this->plot_args_;
        plot.plot_range_ = this->plot_range_;

        // 20130905 FK: deactivated this manual setting of the plot range as it
        //              can dramatically increase plot time. Maybe need to
        //              rethink that later
        //plot.AddPlotArg(Range(min,max));

        // go through supplied cmd args and if necessary adapt ProjWData argument
        bool project_arg_found         = false;
        RooArgSet* set_project         = NULL;
        RooAbsData* data_reduced       = NULL;
        const RooAbsData* data_project = NULL;
        bool binned_projection         = false;
        for (std::vector<RooCmdArg>::iterator it = plot.plot_args_.begin();
             it != plot.plot_args_.end(); ++it) {
          if (std::string(it->GetName()) == "ProjData") {
            sinfo << "Found ProjWData() argument. Will change projection dataset accordingly." << endmsg;
            project_arg_found = true;
            binned_projection = it->getInt(0);

            // check for binned projection and if so generate binned dataset here to
            // accelerate projection
            if (binned_projection) {
              set_project = new RooArgSet(*dynamic_cast<const RooArgSet*>(it->getObject(0)));

              sinfo << " Binned projection is requested. Will generate a binned dataset to accelerate projection." << endmsg;

              data_reduced = sub_data.reduce(*set_project);
              std::string name_data_hist = std::string(sub_data.GetName()) + "_hist" + sim_cat_type->GetName();
              data_project = new RooDataHist(name_data_hist.c_str(), "binned projection dataset", *data_reduced->get(), *data_reduced);

              sinfo << " Created binned dataset with " << data_project->numEntries() << " bins." << endmsg;
            } else {
              data_project = &sub_data;
            }

            // create the new projection argument
            *it = ProjWData(*dynamic_cast<const RooArgSet*>(it->getObject(0)),
                            *data_project,
                            it->getInt(0));
          }
        }

        doocore::lutils::setStyle("LHCb");
        config_plot_.OnDemandOpenPlotStack();
        TCanvas c1("c1","c1",900,900);
        std::string label_text1 = std::string("Next plots: dimension ") + dimension_.GetName() + ", category " + sim_cat_type->GetName();
        std::string label_text2 = std::string(" (") + plot_name + ")";
        TPaveText label(0.1, 0.25, 0.9, 0.75);
        label.SetTextSize(0.03);
        label.AddText(label_text1.c_str());
        label.AddText(label_text2.c_str());
        label.SetLineWidth(0.0);
        label.SetTextAlign(13);
        label.SetFillColor(0);
        label.Draw();
        c1.Print(std::string(config_plot_.plot_directory()+"/pdf/AllPlots"+config_plot_.plot_appendix()+".pdf").c_str());

        plot.PlotHandler(sc_y, suffix);

        if (set_project != NULL) delete set_project;
        if (binned_projection) {
          delete data_project;
          delete data_reduced;
        }

        ++num_slices;
      }

      if (sub_data2 != NULL) {
        delete sub_data2;
      }
    }
  }

  if (num_slices > 1) {
    TCanvas c1("c1","c1",900,900);
    std::string label_text1 = std::string("Next plots: dimension ") + dimension_.GetName() + ", summed all categories ";
    std::string label_text2 = std::string(" (") + plot_name + ")";
    TPaveText label(0.1, 0.25, 0.9, 0.75);
    label.SetTextSize(0.03);
    label.AddText(label_text1.c_str());
    label.AddText(label_text2.c_str());
    label.SetLineWidth(0.0);
    label.SetTextAlign(13);
    label.SetFillColor(0);
    label.Draw();
    c1.Print(std::string(config_plot_.plot_directory()+"/pdf/AllPlots"+config_plot_.plot_appendix()+".pdf").c_str());

    //  plot_name = std::string(dimension_.GetName()) + "_summed";
    plot_name = plot_name_ + "_summed";
    Plot plot(config_plot_, dimension_, data, *pdf_, components_regexps_, plot_name);
    plot.plot_args_ = this->plot_args_;
    plot.plot_range_ = this->plot_range_;

    // go through supplied cmd args and if necessary merge ProjWData arguments
    bool project_arg_found         = false;
    RooArgSet* set_project         = NULL;
    RooAbsData* data_reduced       = NULL;
    const RooAbsData* data_project = NULL;
    bool binned_projection         = false;
    for (std::vector<RooCmdArg>::iterator it = plot.plot_args_.begin();
         it != plot.plot_args_.end(); ++it) {
      if (std::string(it->GetName()) == "ProjData") {
        sinfo << "Found ProjWData() argument. Will join with " << sim_cat.GetName() << " on same dataset." << endmsg;
        project_arg_found = true;
        binned_projection = it->getInt(0);

        // copy argset for projection and add simultaneous category variables
        set_project = new RooArgSet(*dynamic_cast<const RooArgSet*>(it->getObject(0)));
        const RooSuperCategory* super_sim_cat = &dynamic_cast<const RooSuperCategory&>(sim_cat);
        if (super_sim_cat) {
          // The simultaneous category is a super category and will not be in the
          // supplied dataset. Add input categories instead.
          set_project->add(super_sim_cat->inputCatList());
        } else {
          set_project->add(sim_cat);
        }

        // check for binned projection and if so generate binned dataset here to
        // accelerate projection
        if (binned_projection) {
          sinfo << " Binned projection is requested. Will generate a binned dataset to accelerate projection." << endmsg;

          RooAbsData* data_proj = const_cast<RooAbsData*>(dynamic_cast<const RooAbsData*>(it->getObject(1)));
          std::string name_data_hist = std::string(data_proj->GetName()) + "_hist";
          data_reduced = data_proj->reduce(*set_project);
          data_project = new RooDataHist(name_data_hist.c_str(), "binned projection dataset", *data_reduced->get(), *data_reduced);

          sinfo << " Created binned dataset with " << data_project->numEntries() << " bins." << endmsg;
        } else {
          data_project = dynamic_cast<const RooAbsData*>(it->getObject(1));
        }

        // create the new projection argument
        *it = ProjWData(*set_project,
                        *data_project,
                        it->getInt(0));
      }
    }
    if (!project_arg_found) plot.AddPlotArg(ProjWData(sim_cat,data));

    plot.PlotHandler(sc_y, suffix);

    if (set_project != NULL) delete set_project;
    if (binned_projection) {
      delete data_reduced;
      delete data_project;
    }
  }

  TIter next(data_split);
  TObject *obj = NULL;
  while ((obj = next())) {
    delete obj;
  }
}

} // namespace plotting
} // namespace doofit
<|endoftext|>


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

#include "grilodatasource.h"
#include "grilomedia.h"
#include "grilomodel.h"
#include "griloregistry.h"
#include <QDebug>

#include <QTimerEvent>

static void fill_key_id(gpointer data, gpointer user_data) {
  QVariantList *varList = static_cast<QVariantList *>(user_data);
  varList->append(GriloDataSource::MetadataKeys(GRLPOINTER_TO_KEYID(data)));
}

GriloDataSource::GriloDataSource(QObject *parent) :
  QObject(parent),
  m_opId(0),
  m_registry(0),
  m_count(0),
  m_skip(0),
  m_insertIndex(0),
  m_updateScheduled(false) {

  m_metadataKeys << Title;
  m_typeFilter << None;
}

GriloDataSource::~GriloDataSource() {
  cancelRefresh();
  m_models.clear();
}

const QList<GriloMedia *> *GriloDataSource::media() const {
  return &m_media;
}

void GriloDataSource::addModel(GriloModel *model) {
  if (m_models.indexOf(model) == -1) {
    m_models << model;
  }
}

void GriloDataSource::removeModel(GriloModel *model) {
  if (int index = m_models.indexOf(model) != -1) {
    m_models.removeAt(index);
  }
}

void GriloDataSource::prefill(GriloModel *model) {
  if (m_media.isEmpty()) {
    return;
  }

  model->beginInsertRows(QModelIndex(), 0, m_media.size() - 1);
  model->endInsertRows();

  emit model->countChanged();
}

void GriloDataSource::addMedia(GrlMedia *media) {
  GriloMedia *wrappedMedia = 0;

  if (m_insertIndex < m_media.count()) {
      wrappedMedia = m_hash.value(QString::fromUtf8(grl_media_get_id(media)), 0);
  }

  if (wrappedMedia) {
      // If the media was already queried by a previous fetch update its position and refresh
      // the data instead of creating another item.
      bool dataChanged = false;
      int index = m_media.indexOf(wrappedMedia);
      if (index == m_insertIndex) {
         dataChanged = true;
      } else if (index != -1) {
          dataChanged = true;
        foreach (GriloModel *model, m_models) {
          model->beginMoveRows(QModelIndex(), index, index, QModelIndex(), m_insertIndex);
        }
        m_media.move(index, m_insertIndex);
        foreach (GriloModel *model, m_models) {
          model->endMoveRows();
        }
      }

      if (dataChanged) {
        wrappedMedia->setMedia(media);
        foreach (GriloModel *model, m_models) {
          QModelIndex modelIndex = model->index(m_insertIndex, 0);
          model->dataChanged(modelIndex, modelIndex);
        }
        ++m_insertIndex;
        return;
      }
  }

  wrappedMedia = new GriloMedia(media);

  foreach (GriloModel *model, m_models) {
    model->beginInsertRows(QModelIndex(), m_insertIndex, m_insertIndex);
  }

  m_media.insert(m_insertIndex, wrappedMedia);
  ++m_insertIndex;

  QString id = wrappedMedia->id();
  if (!id.isEmpty()) {
    m_hash.insert(id, wrappedMedia);
  }

  foreach (GriloModel *model, m_models) {
    model->endInsertRows();
    emit model->countChanged();
  }

}

void GriloDataSource::removeMedia(GrlMedia *media) {
  QString id = QString::fromUtf8(grl_media_get_id(media));

  if (id.isEmpty() || !m_hash.contains(id)) {
    // We really cannot do much.
    return;
  }

  GriloMedia *wrapper = m_hash[id];
  int index = m_media.indexOf(wrapper);
  if (index < m_insertIndex) {
    --m_insertIndex;
  }

  // remove from models:
  foreach (GriloModel *model, m_models) {
    model->beginRemoveRows(QModelIndex(), index, index);
  }

  // remove from hash
  m_hash.take(id);

  // remove from list
  m_media.takeAt(index);

  // destroy
  wrapper->deleteLater();

  foreach (GriloModel *model, m_models) {
    model->endRemoveRows();
    emit model->countChanged();
  }
}

void GriloDataSource::clearMedia() {
  if (m_media.isEmpty()) {
    return;
  }

  int size = m_media.size();

  foreach (GriloModel *model, m_models) {
    model->beginRemoveRows(QModelIndex(), 0, size - 1);
  }

  qDeleteAll(m_media);
  m_media.clear();
  m_hash.clear();

  foreach (GriloModel *model, m_models) {
    model->endRemoveRows();
    emit model->countChanged();
  }
}

GriloRegistry *GriloDataSource::registry() const {
  return m_registry;
}

void GriloDataSource::setRegistry(GriloRegistry *registry) {
  // Registry change is not allowed for now.

  if (!m_registry && registry != m_registry) {

    m_registry = registry;

    QObject::connect(m_registry, SIGNAL(availableSourcesChanged()),
		     this, SLOT(availableSourcesChanged()));
    QObject::connect(m_registry, SIGNAL(contentChanged(QString,GrlSourceChangeType,GPtrArray*)),
             this, SLOT(contentChanged(QString,GrlSourceChangeType,GPtrArray*)));

    emit registryChanged();
  }
}

int GriloDataSource::count() const {
  return m_count;
}

void GriloDataSource::setCount(int count) {
  if (m_count != count) {
    m_count = count;
    emit countChanged();
  }
}

int GriloDataSource::skip() const {
  return m_skip;
}

void GriloDataSource::setSkip(int skip) {
  if (m_skip != skip) {
    m_skip = skip;
    emit skipChanged();
  }
}

QVariantList GriloDataSource::metadataKeys() const {
  return m_metadataKeys;
}

void GriloDataSource::setMetadataKeys(const QVariantList& keys) {
  if (m_metadataKeys != keys) {
    m_metadataKeys = keys;
    emit metadataKeysChanged();
  }
}

QVariantList GriloDataSource::typeFilter() const {
  return m_typeFilter;
}

void GriloDataSource::setTypeFilter(const QVariantList& filter) {
  if (m_typeFilter != filter) {
    m_typeFilter = filter;
    emit typeFilterChanged();
  }
}

GrlOperationOptions *GriloDataSource::operationOptions(GrlSource *src, const OperationType& type) {
  GrlCaps *caps = NULL;

  if (src) {
    caps = grl_source_get_caps(src, (GrlSupportedOps)type);
  }

  GrlOperationOptions *options = grl_operation_options_new(caps);

  grl_operation_options_set_flags(options, GRL_RESOLVE_IDLE_RELAY); // TODO: hardcoded
  grl_operation_options_set_skip(options, m_skip);

  if (m_count != 0) {
    grl_operation_options_set_count(options, m_count);
  }

  int typeFilter = 0;
  foreach (const QVariant& var, m_typeFilter) {
    if (var.canConvert<int>()) {
      typeFilter |= var.toInt();
    }
  }

  grl_operation_options_set_type_filter(options, (GrlTypeFilter)typeFilter);

  return options;
}

GList *GriloDataSource::keysAsList() {
  // TODO: Check why using  grl_metadata_key_list_new() produces a symbol error.
  GList *keys = NULL;

  foreach (const QVariant& var, m_metadataKeys) {
    if (var.canConvert<int>()) {
      keys = g_list_append(keys, GRLKEYID_TO_POINTER(var.toInt()));
    }
  }

  return keys;
}

void GriloDataSource::cancelRefresh() {
  if (m_opId != 0) {
    grl_operation_cancel(m_opId);
    m_opId = 0;
  }

  m_insertIndex = 0;
  m_updateScheduled = false;
  m_updateTimer.stop();
}

void GriloDataSource::grilo_source_result_cb(GrlSource *source, guint op_id,
					     GrlMedia *media, guint remaining,
					     gpointer user_data, const GError *error) {

  Q_UNUSED(source);

  // We get an error if the operation has been canceled:
  if (error) {
    if (error->domain != GRL_CORE_ERROR || error->code != GRL_CORE_ERROR_OPERATION_CANCELLED) {
      // TODO: error reporting?
      qCritical() << "Operation failed" << error->message;
    }
  }

  GriloDataSource *that = static_cast<GriloDataSource *>(user_data);

  if (that->m_opId != op_id) {
    qWarning() << "Got results belonging to an unknown browse id";

    if (media) {
      g_object_unref(media);
    }

    return;
  }

  if (media) {
    that->addMedia(media);
  }

  if (remaining == 0) {
    emit that->finished();
    that->m_opId = 0;

    if (that->m_updateScheduled) {
      that->m_updateTimer.start(100, that);
    }

    // If there are items from a previous fetch still remaining remove them.
    if (that->m_insertIndex < that->m_media.count()) {
      foreach (GriloModel *model, that->m_models) {
        model->beginRemoveRows(QModelIndex(), that->m_insertIndex, that->m_media.count() - 1);
      }
      while (that->m_media.count() > that->m_insertIndex) {
          GriloMedia *media = that->m_media.takeLast();
          that->m_hash.remove(media->id());
          delete media;
      }
      foreach (GriloModel *model, that->m_models) {
        model->endRemoveRows();
        emit model->countChanged();
      }
    }
  }
}

void GriloDataSource::contentChanged(const QString &source, GrlSourceChangeType change_type,
                            GPtrArray *changed_media)
{
    Q_UNUSED(source);
    Q_UNUSED(change_type);
    Q_UNUSED(changed_media);
}

void GriloDataSource::updateContent(GrlSourceChangeType change_type, GPtrArray *changed_media)
{
    switch (change_type) {
    case GRL_CONTENT_CHANGED:
    case GRL_CONTENT_ADDED:
      if (!m_updateScheduled) {
        m_updateScheduled = true;
        if (m_opId == 0) {
          m_updateTimer.start(100, this);
        }
      }
      break;
    case GRL_CONTENT_REMOVED:
      for (uint i = 0; i < changed_media->len; ++i) {
          removeMedia((GrlMedia *)g_ptr_array_index(changed_media, i));
      }
      break;
    default:
      break;
    }
}

QVariantList GriloDataSource::listToVariantList(const GList *keys) const {
  QVariantList varList;

  g_list_foreach(const_cast<GList *>(keys), fill_key_id, &varList);

  return varList;
}

void GriloDataSource::timerEvent(QTimerEvent *event) {
  if (event->timerId() == m_updateTimer.timerId()) {
    m_updateTimer.stop();
    emit contentUpdated();
  }
}
<commit_msg>[datasource] Callback returns immediately on canceled refresh<commit_after>/*!
 *
 * Copyright (C) 2012 Jolla Ltd.
 *
 * Contact: Mohammed Hassan <mohammed.hassan@jollamobile.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "grilodatasource.h"
#include "grilomedia.h"
#include "grilomodel.h"
#include "griloregistry.h"
#include <QDebug>

#include <QTimerEvent>

static void fill_key_id(gpointer data, gpointer user_data) {
  QVariantList *varList = static_cast<QVariantList *>(user_data);
  varList->append(GriloDataSource::MetadataKeys(GRLPOINTER_TO_KEYID(data)));
}

GriloDataSource::GriloDataSource(QObject *parent) :
  QObject(parent),
  m_opId(0),
  m_registry(0),
  m_count(0),
  m_skip(0),
  m_insertIndex(0),
  m_updateScheduled(false) {

  m_metadataKeys << Title;
  m_typeFilter << None;
}

GriloDataSource::~GriloDataSource() {
  cancelRefresh();
  m_models.clear();
}

const QList<GriloMedia *> *GriloDataSource::media() const {
  return &m_media;
}

void GriloDataSource::addModel(GriloModel *model) {
  if (m_models.indexOf(model) == -1) {
    m_models << model;
  }
}

void GriloDataSource::removeModel(GriloModel *model) {
  if (int index = m_models.indexOf(model) != -1) {
    m_models.removeAt(index);
  }
}

void GriloDataSource::prefill(GriloModel *model) {
  if (m_media.isEmpty()) {
    return;
  }

  model->beginInsertRows(QModelIndex(), 0, m_media.size() - 1);
  model->endInsertRows();

  emit model->countChanged();
}

void GriloDataSource::addMedia(GrlMedia *media) {
  GriloMedia *wrappedMedia = 0;

  if (m_insertIndex < m_media.count()) {
      wrappedMedia = m_hash.value(QString::fromUtf8(grl_media_get_id(media)), 0);
  }

  if (wrappedMedia) {
      // If the media was already queried by a previous fetch update its position and refresh
      // the data instead of creating another item.
      bool dataChanged = false;
      int index = m_media.indexOf(wrappedMedia);
      if (index == m_insertIndex) {
         dataChanged = true;
      } else if (index != -1) {
          dataChanged = true;
        foreach (GriloModel *model, m_models) {
          model->beginMoveRows(QModelIndex(), index, index, QModelIndex(), m_insertIndex);
        }
        m_media.move(index, m_insertIndex);
        foreach (GriloModel *model, m_models) {
          model->endMoveRows();
        }
      }

      if (dataChanged) {
        wrappedMedia->setMedia(media);
        foreach (GriloModel *model, m_models) {
          QModelIndex modelIndex = model->index(m_insertIndex, 0);
          model->dataChanged(modelIndex, modelIndex);
        }
        ++m_insertIndex;
        return;
      }
  }

  wrappedMedia = new GriloMedia(media);

  foreach (GriloModel *model, m_models) {
    model->beginInsertRows(QModelIndex(), m_insertIndex, m_insertIndex);
  }

  m_media.insert(m_insertIndex, wrappedMedia);
  ++m_insertIndex;

  QString id = wrappedMedia->id();
  if (!id.isEmpty()) {
    m_hash.insert(id, wrappedMedia);
  }

  foreach (GriloModel *model, m_models) {
    model->endInsertRows();
    emit model->countChanged();
  }

}

void GriloDataSource::removeMedia(GrlMedia *media) {
  QString id = QString::fromUtf8(grl_media_get_id(media));

  if (id.isEmpty() || !m_hash.contains(id)) {
    // We really cannot do much.
    return;
  }

  GriloMedia *wrapper = m_hash[id];
  int index = m_media.indexOf(wrapper);
  if (index < m_insertIndex) {
    --m_insertIndex;
  }

  // remove from models:
  foreach (GriloModel *model, m_models) {
    model->beginRemoveRows(QModelIndex(), index, index);
  }

  // remove from hash
  m_hash.take(id);

  // remove from list
  m_media.takeAt(index);

  // destroy
  wrapper->deleteLater();

  foreach (GriloModel *model, m_models) {
    model->endRemoveRows();
    emit model->countChanged();
  }
}

void GriloDataSource::clearMedia() {
  if (m_media.isEmpty()) {
    return;
  }

  int size = m_media.size();

  foreach (GriloModel *model, m_models) {
    model->beginRemoveRows(QModelIndex(), 0, size - 1);
  }

  qDeleteAll(m_media);
  m_media.clear();
  m_hash.clear();

  foreach (GriloModel *model, m_models) {
    model->endRemoveRows();
    emit model->countChanged();
  }
}

GriloRegistry *GriloDataSource::registry() const {
  return m_registry;
}

void GriloDataSource::setRegistry(GriloRegistry *registry) {
  // Registry change is not allowed for now.

  if (!m_registry && registry != m_registry) {

    m_registry = registry;

    QObject::connect(m_registry, SIGNAL(availableSourcesChanged()),
		     this, SLOT(availableSourcesChanged()));
    QObject::connect(m_registry, SIGNAL(contentChanged(QString,GrlSourceChangeType,GPtrArray*)),
             this, SLOT(contentChanged(QString,GrlSourceChangeType,GPtrArray*)));

    emit registryChanged();
  }
}

int GriloDataSource::count() const {
  return m_count;
}

void GriloDataSource::setCount(int count) {
  if (m_count != count) {
    m_count = count;
    emit countChanged();
  }
}

int GriloDataSource::skip() const {
  return m_skip;
}

void GriloDataSource::setSkip(int skip) {
  if (m_skip != skip) {
    m_skip = skip;
    emit skipChanged();
  }
}

QVariantList GriloDataSource::metadataKeys() const {
  return m_metadataKeys;
}

void GriloDataSource::setMetadataKeys(const QVariantList& keys) {
  if (m_metadataKeys != keys) {
    m_metadataKeys = keys;
    emit metadataKeysChanged();
  }
}

QVariantList GriloDataSource::typeFilter() const {
  return m_typeFilter;
}

void GriloDataSource::setTypeFilter(const QVariantList& filter) {
  if (m_typeFilter != filter) {
    m_typeFilter = filter;
    emit typeFilterChanged();
  }
}

GrlOperationOptions *GriloDataSource::operationOptions(GrlSource *src, const OperationType& type) {
  GrlCaps *caps = NULL;

  if (src) {
    caps = grl_source_get_caps(src, (GrlSupportedOps)type);
  }

  GrlOperationOptions *options = grl_operation_options_new(caps);

  grl_operation_options_set_flags(options, GRL_RESOLVE_IDLE_RELAY); // TODO: hardcoded
  grl_operation_options_set_skip(options, m_skip);

  if (m_count != 0) {
    grl_operation_options_set_count(options, m_count);
  }

  int typeFilter = 0;
  foreach (const QVariant& var, m_typeFilter) {
    if (var.canConvert<int>()) {
      typeFilter |= var.toInt();
    }
  }

  grl_operation_options_set_type_filter(options, (GrlTypeFilter)typeFilter);

  return options;
}

GList *GriloDataSource::keysAsList() {
  // TODO: Check why using  grl_metadata_key_list_new() produces a symbol error.
  GList *keys = NULL;

  foreach (const QVariant& var, m_metadataKeys) {
    if (var.canConvert<int>()) {
      keys = g_list_append(keys, GRLKEYID_TO_POINTER(var.toInt()));
    }
  }

  return keys;
}

void GriloDataSource::cancelRefresh() {
  if (m_opId != 0) {
    grl_operation_cancel(m_opId);
    m_opId = 0;
  }

  m_insertIndex = 0;
  m_updateScheduled = false;
  m_updateTimer.stop();
}

void GriloDataSource::grilo_source_result_cb(GrlSource *source, guint op_id,
					     GrlMedia *media, guint remaining,
					     gpointer user_data, const GError *error) {

  Q_UNUSED(source);

  // We get an error if the operation has been canceled:
  if (error) {
    if (error->domain != GRL_CORE_ERROR || error->code != GRL_CORE_ERROR_OPERATION_CANCELLED) {
      // TODO: error reporting?
      qCritical() << "Operation failed" << error->message;
    } else {
      // Cancelled operation notification. Nothing else to be done.
      return;
    }
  }

  GriloDataSource *that = static_cast<GriloDataSource *>(user_data);

  if (that->m_opId != op_id) {
    qWarning() << "Got results belonging to an unknown browse id";

    if (media) {
      g_object_unref(media);
    }

    return;
  }

  if (media) {
    that->addMedia(media);
  }

  if (remaining == 0) {
    emit that->finished();
    that->m_opId = 0;

    if (that->m_updateScheduled) {
      that->m_updateTimer.start(100, that);
    }

    // If there are items from a previous fetch still remaining remove them.
    if (that->m_insertIndex < that->m_media.count()) {
      foreach (GriloModel *model, that->m_models) {
        model->beginRemoveRows(QModelIndex(), that->m_insertIndex, that->m_media.count() - 1);
      }
      while (that->m_media.count() > that->m_insertIndex) {
          GriloMedia *media = that->m_media.takeLast();
          that->m_hash.remove(media->id());
          delete media;
      }
      foreach (GriloModel *model, that->m_models) {
        model->endRemoveRows();
        emit model->countChanged();
      }
    }
  }
}

void GriloDataSource::contentChanged(const QString &source, GrlSourceChangeType change_type,
                            GPtrArray *changed_media)
{
    Q_UNUSED(source);
    Q_UNUSED(change_type);
    Q_UNUSED(changed_media);
}

void GriloDataSource::updateContent(GrlSourceChangeType change_type, GPtrArray *changed_media)
{
    switch (change_type) {
    case GRL_CONTENT_CHANGED:
    case GRL_CONTENT_ADDED:
      if (!m_updateScheduled) {
        m_updateScheduled = true;
        if (m_opId == 0) {
          m_updateTimer.start(100, this);
        }
      }
      break;
    case GRL_CONTENT_REMOVED:
      for (uint i = 0; i < changed_media->len; ++i) {
          removeMedia((GrlMedia *)g_ptr_array_index(changed_media, i));
      }
      break;
    default:
      break;
    }
}

QVariantList GriloDataSource::listToVariantList(const GList *keys) const {
  QVariantList varList;

  g_list_foreach(const_cast<GList *>(keys), fill_key_id, &varList);

  return varList;
}

void GriloDataSource::timerEvent(QTimerEvent *event) {
  if (event->timerId() == m_updateTimer.timerId()) {
    m_updateTimer.stop();
    emit contentUpdated();
  }
}
<|endoftext|>


<commit_before>#include <sys/types.h>
#include <sys/errno.h>
#include <sys/uio.h>
#include <fcntl.h>
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>

#include <map>
#include <vector>

#include <common/buffer.h>
#include <common/endian.h>

#include <xcodec/xcodec.h>

#define	XCDUMP_IOVEC_SIZE	(IOV_MAX)

static void dump(int, int);
static bool fill(int, Buffer *);
static void flush(int, Buffer *);
static void process_files(int, char *[]);
static void usage(void);

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

	while ((ch = getopt(argc, argv, "?")) != -1) {
		switch (ch) {
		case '?':
		default:
			usage();
		}
	}
	argc -= optind;
	argv += optind;

	process_files(argc, argv);

	return (0);
}

static void
dump(int ifd, int ofd)
{
	Buffer input, output;

	while (fill(ifd, &input)) {
		BufferSegment *seg;
		uint64_t hash;
		size_t inlen;
		uint8_t ch;

		inlen = input.length();
		while (inlen != 0) {
			ch = input.peek();

			while (!XCODEC_CHAR_SPECIAL(ch)) {
				inlen--;
				input.skip(1);
				output.append("<literal />\n");

				if (inlen == 0)
					break;

				ch = input.peek();
			}

			ASSERT(inlen == input.length());

			if (inlen == 0)
				break;

			switch (ch) {
			case XCODEC_HASHREF_CHAR:
				if (inlen < 9)
					break;

				input.moveout((uint8_t *)&hash, 1, sizeof hash);
				hash = LittleEndian::decode(hash);

				output.append("<hash-reference />\n");
				output.append("<window-declare />\n");
				inlen -= 9;
				continue;

			case XCODEC_ESCAPE_CHAR:
				if (inlen < 2)
					break;
				input.skip(1);
				output.append("<escape />\n");
				input.skip(1);
				inlen -= 2;
				continue;

			case XCODEC_DECLARE_CHAR:
				if (inlen < 9 + XCODEC_SEGMENT_LENGTH)
					break;

				input.moveout((uint8_t *)&hash, 1, sizeof hash);
				hash = LittleEndian::decode(hash);

				input.copyout(&seg, XCODEC_SEGMENT_LENGTH);
				input.skip(XCODEC_SEGMENT_LENGTH);

				output.append("<hash-declare />\n");
				output.append("<window-declare />\n");

				seg->unref();
				inlen -= 9 + XCODEC_SEGMENT_LENGTH;
				continue;

			case XCODEC_BACKREF_CHAR:
				if (inlen < 2)
					break;
				input.skip(1);
				ch = input.peek();
				input.skip(1);

				output.append("<window-reference />\n");

				inlen -= 2;
				continue;

			default:
				NOTREACHED();
			}
			break;
		}

		flush(ofd, &output);
	}
	ASSERT(input.empty());
	ASSERT(output.empty());
}

static bool
fill(int fd, Buffer *input)
{
	BufferSegment *segments[XCDUMP_IOVEC_SIZE];
	struct iovec iov[XCDUMP_IOVEC_SIZE];
	BufferSegment *seg;
	ssize_t len;
	unsigned i;

	for (i = 0; i < XCDUMP_IOVEC_SIZE; i++) {
		seg = new BufferSegment();
		iov[i].iov_base = seg->head();
		iov[i].iov_len = BUFFER_SEGMENT_SIZE;
		segments[i] = seg;
	}

	len = readv(fd, iov, XCDUMP_IOVEC_SIZE);
	if (len == -1)
		HALT("/fill") << "read failed.";
	for (i = 0; i < XCDUMP_IOVEC_SIZE; i++) {
		seg = segments[i];
		if (len > 0) {
			if (len > BUFFER_SEGMENT_SIZE) {
				seg->set_length(BUFFER_SEGMENT_SIZE);
				len -= BUFFER_SEGMENT_SIZE;
			} else {
				seg->set_length((size_t)len);
				len = 0;
			}
			input->append(seg);
		}
		seg->unref();
	}
	if (input->empty())
		return (false);
	return (true);
}

static void
flush(int fd, Buffer *output)
{
	ssize_t len;

	if (fd == -1) {
		output->clear();
		return;
	}

	for (;;) {
		Buffer::SegmentIterator iter = output->segments();
		if (iter.end())
			break;

		const BufferSegment *seg = *iter;

		len = write(fd, seg->data(), seg->length());
		if (len != (ssize_t)seg->length())
			HALT("/output") << "write failed.";
		output->skip((size_t)len);
	}
	ASSERT(output->empty());
}

static void
process_files(int argc, char *argv[])
{
	int ifd, ofd;

	if (argc == 0) {
		ifd = STDIN_FILENO;
		ofd = STDOUT_FILENO;

		dump(ifd, ofd);
	} else {
		while (argc--) {
			const char *file = *argv++;

			ifd = open(file, O_RDONLY);
			ASSERT(ifd != -1);
			ofd = STDOUT_FILENO;

			dump(ifd, ofd);
		}
	}
}

static void
usage(void)
{
	fprintf(stderr,
"usage: xcdump [file ...]\n");
	exit(1);
}
<commit_msg>o) Add verbosity levels, at 1+, display hashes and single characters, at 2+,    display hexdumps of entire segments in hash declarations.<commit_after>#include <sys/types.h>
#include <sys/errno.h>
#include <sys/uio.h>
#include <fcntl.h>
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>

#include <map>
#include <vector>

#include <common/buffer.h>
#include <common/endian.h>

#include <xcodec/xcodec.h>

#define	XCDUMP_IOVEC_SIZE	(IOV_MAX)

static int dump_verbosity;

static void bhexdump(Buffer *, const uint8_t *, size_t);
static void bprintf(Buffer *, const char *, ...);
static void dump(int, int);
static bool fill(int, Buffer *);
static void flush(int, Buffer *);
static void process_files(int, char *[]);
static void usage(void);

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

	while ((ch = getopt(argc, argv, "?v")) != -1) {
		switch (ch) {
		case 'v':
			dump_verbosity++;
			break;
		case '?':
		default:
			usage();
		}
	}
	argc -= optind;
	argv += optind;

	process_files(argc, argv);

	return (0);
}

static void
bhexdump(Buffer *output, const uint8_t *data, size_t len)
{
	while (len--)
		bprintf(output, "%02x", *data++);
}

static void
bprintf(Buffer *output, const char *fmt, ...)
{
	char buf[65536];
	va_list ap;

	va_start(ap, fmt);
	vsnprintf(buf, sizeof buf, fmt, ap);
	va_end(ap);

	output->append(std::string(buf));
}

static void
dump(int ifd, int ofd)
{
	Buffer input, output;

	while (fill(ifd, &input)) {
		BufferSegment *seg;
		uint64_t hash;
		size_t inlen;
		uint8_t ch;

		inlen = input.length();
		while (inlen != 0) {
			ch = input.peek();

			while (!XCODEC_CHAR_SPECIAL(ch)) {
				inlen--;
				input.skip(1);
				bprintf(&output, "<literal");
				if (dump_verbosity > 0)
					bprintf(&output, " character=\"0x%02x\"", ch);
				bprintf(&output, "/>\n");

				if (inlen == 0)
					break;

				ch = input.peek();
			}

			ASSERT(inlen == input.length());

			if (inlen == 0)
				break;

			switch (ch) {
			case XCODEC_HASHREF_CHAR:
				if (inlen < 9)
					break;

				input.moveout((uint8_t *)&hash, 1, sizeof hash);
				hash = LittleEndian::decode(hash);

				bprintf(&output, "<hash-reference");
				if (dump_verbosity > 0)
					bprintf(&output, " hash=\"0x%016jx\"", (uintmax_t)hash);
				bprintf(&output, "/>\n");
				inlen -= 9;
				continue;

			case XCODEC_ESCAPE_CHAR:
				if (inlen < 2)
					break;
				input.skip(1);
				ch = input.peek();
				bprintf(&output, "<escape");
				if (dump_verbosity > 0)
					bprintf(&output, " character=\"0x%02x\"", ch);
				bprintf(&output, "/>\n");
				input.skip(1);
				inlen -= 2;
				continue;

			case XCODEC_DECLARE_CHAR:
				if (inlen < 9 + XCODEC_SEGMENT_LENGTH)
					break;

				input.moveout((uint8_t *)&hash, 1, sizeof hash);
				hash = LittleEndian::decode(hash);

				input.copyout(&seg, XCODEC_SEGMENT_LENGTH);
				input.skip(XCODEC_SEGMENT_LENGTH);

				bprintf(&output, "<hash-declare");
				if (dump_verbosity > 0) {
					bprintf(&output, " hash=\"0x%016jx\"", (uintmax_t)hash);
					if (dump_verbosity > 1) {
						bprintf(&output, " data=\"");
						bhexdump(&output, seg->data(), seg->length());
						bprintf(&output, "\"");
					}
				}
				bprintf(&output, "/>\n");

				seg->unref();
				inlen -= 9 + XCODEC_SEGMENT_LENGTH;
				continue;

			case XCODEC_BACKREF_CHAR:
				if (inlen < 2)
					break;
				input.skip(1);
				ch = input.peek();
				input.skip(1);

				bprintf(&output, "<back-reference");
				if (dump_verbosity > 0)
					bprintf(&output, " offset=\"%u\"", ch);
				bprintf(&output, "/>\n");

				inlen -= 2;
				continue;

			default:
				NOTREACHED();
			}
			break;
		}

		flush(ofd, &output);
	}
	ASSERT(input.empty());
	ASSERT(output.empty());
}

static bool
fill(int fd, Buffer *input)
{
	BufferSegment *segments[XCDUMP_IOVEC_SIZE];
	struct iovec iov[XCDUMP_IOVEC_SIZE];
	BufferSegment *seg;
	ssize_t len;
	unsigned i;

	for (i = 0; i < XCDUMP_IOVEC_SIZE; i++) {
		seg = new BufferSegment();
		iov[i].iov_base = seg->head();
		iov[i].iov_len = BUFFER_SEGMENT_SIZE;
		segments[i] = seg;
	}

	len = readv(fd, iov, XCDUMP_IOVEC_SIZE);
	if (len == -1)
		HALT("/fill") << "read failed.";
	for (i = 0; i < XCDUMP_IOVEC_SIZE; i++) {
		seg = segments[i];
		if (len > 0) {
			if (len > BUFFER_SEGMENT_SIZE) {
				seg->set_length(BUFFER_SEGMENT_SIZE);
				len -= BUFFER_SEGMENT_SIZE;
			} else {
				seg->set_length((size_t)len);
				len = 0;
			}
			input->append(seg);
		}
		seg->unref();
	}
	if (input->empty())
		return (false);
	return (true);
}

static void
flush(int fd, Buffer *output)
{
	ssize_t len;

	if (fd == -1) {
		output->clear();
		return;
	}

	for (;;) {
		Buffer::SegmentIterator iter = output->segments();
		if (iter.end())
			break;

		const BufferSegment *seg = *iter;

		len = write(fd, seg->data(), seg->length());
		if (len != (ssize_t)seg->length())
			HALT("/output") << "write failed.";
		output->skip((size_t)len);
	}
	ASSERT(output->empty());
}

static void
process_files(int argc, char *argv[])
{
	int ifd, ofd;

	if (argc == 0) {
		ifd = STDIN_FILENO;
		ofd = STDOUT_FILENO;

		dump(ifd, ofd);
	} else {
		while (argc--) {
			const char *file = *argv++;

			ifd = open(file, O_RDONLY);
			ASSERT(ifd != -1);
			ofd = STDOUT_FILENO;

			dump(ifd, ofd);
		}
	}
}

static void
usage(void)
{
	fprintf(stderr,
"usage: xcdump [-v] [file ...]\n");
	exit(1);
}
<|endoftext|>


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

extern int gTypesToTest;
extern bool gTestReadWrite;

extern int test_read_image_set_1D( cl_device_id device, cl_context context, cl_command_queue queue, cl_image_format *format, image_sampler_data *imageSampler, ExplicitType outputType );
extern int test_read_image_set_1D_buffer( cl_device_id device, cl_context context, cl_command_queue queue, cl_image_format *format, image_sampler_data *imageSampler, ExplicitType outputType );
extern int test_read_image_set_2D( cl_device_id device, cl_context context, cl_command_queue queue, cl_image_format *format, image_sampler_data *imageSampler, ExplicitType outputType );
extern int test_read_image_set_3D( cl_device_id device, cl_context context, cl_command_queue queue, cl_image_format *format, image_sampler_data *imageSampler, ExplicitType outputType );
extern int test_read_image_set_1D_array( cl_device_id device, cl_context context, cl_command_queue queue, cl_image_format *format, image_sampler_data *imageSampler, ExplicitType outputType );
extern int test_read_image_set_2D_array( cl_device_id device, cl_context context, cl_command_queue queue, cl_image_format *format, image_sampler_data *imageSampler, ExplicitType outputType );

int test_read_image_type( cl_device_id device, cl_context context, cl_command_queue queue, cl_image_format *format,
                          image_sampler_data *imageSampler, ExplicitType outputType, cl_mem_object_type imageType )
{
    int ret = 0;
    imageSampler->addressing_mode = CL_ADDRESS_NONE;

    print_read_header( format, imageSampler, false );

    gTestCount++;

    switch (imageType)
    {
        case CL_MEM_OBJECT_IMAGE1D:
            ret = test_read_image_set_1D( device, context, queue, format, imageSampler, outputType );
            break;
        case CL_MEM_OBJECT_IMAGE1D_BUFFER:
            ret += test_read_image_set_1D_buffer( device, context, queue, format, imageSampler, outputType );
            break;
        case CL_MEM_OBJECT_IMAGE2D:
            ret = test_read_image_set_2D( device, context, queue, format, imageSampler, outputType );
            break;
        case CL_MEM_OBJECT_IMAGE3D:
            ret = test_read_image_set_3D( device, context, queue, format, imageSampler, outputType );
            break;
        case CL_MEM_OBJECT_IMAGE1D_ARRAY:
            ret = test_read_image_set_1D_array( device, context, queue, format, imageSampler, outputType );
            break;
        case CL_MEM_OBJECT_IMAGE2D_ARRAY:
            ret = test_read_image_set_2D_array( device, context, queue, format, imageSampler, outputType );
            break;
    }

    if ( ret != 0 )
    {
        gFailCount++;
        log_error( "FAILED: " );
        print_read_header( format, imageSampler, true );
        log_info( "\n" );
    }
    return ret;
}

int test_read_image_formats( cl_device_id device, cl_context context, cl_command_queue queue, cl_image_format *formatList, bool *filterFlags, unsigned int numFormats,
                             image_sampler_data *imageSampler, ExplicitType outputType, cl_mem_object_type imageType )
{
    int ret = 0;
    imageSampler->normalized_coords = false;
    log_info( "read_image (%s coords, %s results) *****************************\n",
              "integer", get_explicit_type_name( outputType ) );

    for ( unsigned int i = 0; i < numFormats; i++ )
    {
        if ( filterFlags[i] )
            continue;

        cl_image_format &imageFormat = formatList[ i ];

        ret |= test_read_image_type( device, context, queue, &imageFormat, imageSampler, outputType, imageType );
    }
    return ret;
}

int test_image_set( cl_device_id device, cl_context context, cl_command_queue queue, cl_mem_object_type imageType )
{
    int ret = 0;
    static int printedFormatList = -1;

    // Grab the list of supported image formats
    cl_image_format *formatList;
    bool *filterFlags;
    unsigned int numFormats;

    if (gTestReadWrite && checkForReadWriteImageSupport(device))
    {
        return TEST_SKIPPED_ITSELF;
    }

    // This flag is only for querying the list of supported formats
    // The flag for creating image will be set explicitly in test functions
    cl_mem_flags flags = (gTestReadWrite)? CL_MEM_KERNEL_READ_AND_WRITE : CL_MEM_READ_ONLY;

    if ( get_format_list( context, imageType, formatList, numFormats, flags ) )
        return -1;

    filterFlags = new bool[ numFormats ];
    if ( filterFlags == NULL )
    {
        log_error( "ERROR: Out of memory allocating filter flags list!\n" );
        return -1;
    }
    memset( filterFlags, 0, sizeof( bool ) * numFormats );

    // First time through, we'll go ahead and print the formats supported, regardless of type
    if ( printedFormatList != (int)imageType )
    {
        log_info( "---- Supported %s read formats for this device ---- \n", convert_image_type_to_string(imageType) );
        for ( unsigned int f = 0; f < numFormats; f++ )
            log_info( "  %-7s %-24s %d\n", GetChannelOrderName( formatList[ f ].image_channel_order ),
                      GetChannelTypeName( formatList[ f ].image_channel_data_type ),
                      (int)get_format_channel_count( &formatList[ f ] ) );
        log_info( "------------------------------------------- \n" );
        printedFormatList = imageType;
    }

    image_sampler_data imageSampler;

    for (auto test : imageTestTypes)
    {
        if (gTypesToTest & test.type)
        {
            if (filter_formats(formatList, filterFlags, numFormats,
                               test.channelTypes)
                == 0)
            {
                log_info("No formats supported for %s type\n", test.name);
            }
            else
            {
                imageSampler.filter_mode = CL_FILTER_NEAREST;
                ret += test_read_image_formats(
                    device, context, queue, formatList, filterFlags, numFormats,
                    &imageSampler, test.explicitType, imageType);
            }
        }
    }

    delete[] filterFlags;
    delete[] formatList;

    return ret;
}
<commit_msg>Fix samplerlessReads read_write (#329) (#1016)<commit_after>//
// Copyright (c) 2017 The Khronos Group Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "../testBase.h"
#include "../common.h"

extern int gTypesToTest;
extern bool gTestReadWrite;

extern int test_read_image_set_1D( cl_device_id device, cl_context context, cl_command_queue queue, cl_image_format *format, image_sampler_data *imageSampler, ExplicitType outputType );
extern int test_read_image_set_1D_buffer( cl_device_id device, cl_context context, cl_command_queue queue, cl_image_format *format, image_sampler_data *imageSampler, ExplicitType outputType );
extern int test_read_image_set_2D( cl_device_id device, cl_context context, cl_command_queue queue, cl_image_format *format, image_sampler_data *imageSampler, ExplicitType outputType );
extern int test_read_image_set_3D( cl_device_id device, cl_context context, cl_command_queue queue, cl_image_format *format, image_sampler_data *imageSampler, ExplicitType outputType );
extern int test_read_image_set_1D_array( cl_device_id device, cl_context context, cl_command_queue queue, cl_image_format *format, image_sampler_data *imageSampler, ExplicitType outputType );
extern int test_read_image_set_2D_array( cl_device_id device, cl_context context, cl_command_queue queue, cl_image_format *format, image_sampler_data *imageSampler, ExplicitType outputType );

int test_read_image_type( cl_device_id device, cl_context context, cl_command_queue queue, cl_image_format *format,
                          image_sampler_data *imageSampler, ExplicitType outputType, cl_mem_object_type imageType )
{
    int ret = 0;
    imageSampler->addressing_mode = CL_ADDRESS_NONE;

    print_read_header( format, imageSampler, false );

    gTestCount++;

    switch (imageType)
    {
        case CL_MEM_OBJECT_IMAGE1D:
            ret = test_read_image_set_1D( device, context, queue, format, imageSampler, outputType );
            break;
        case CL_MEM_OBJECT_IMAGE1D_BUFFER:
            ret += test_read_image_set_1D_buffer( device, context, queue, format, imageSampler, outputType );
            break;
        case CL_MEM_OBJECT_IMAGE2D:
            ret = test_read_image_set_2D( device, context, queue, format, imageSampler, outputType );
            break;
        case CL_MEM_OBJECT_IMAGE3D:
            ret = test_read_image_set_3D( device, context, queue, format, imageSampler, outputType );
            break;
        case CL_MEM_OBJECT_IMAGE1D_ARRAY:
            ret = test_read_image_set_1D_array( device, context, queue, format, imageSampler, outputType );
            break;
        case CL_MEM_OBJECT_IMAGE2D_ARRAY:
            ret = test_read_image_set_2D_array( device, context, queue, format, imageSampler, outputType );
            break;
    }

    if ( ret != 0 )
    {
        gFailCount++;
        log_error( "FAILED: " );
        print_read_header( format, imageSampler, true );
        log_info( "\n" );
    }
    return ret;
}

int test_read_image_formats( cl_device_id device, cl_context context, cl_command_queue queue, cl_image_format *formatList, bool *filterFlags, unsigned int numFormats,
                             image_sampler_data *imageSampler, ExplicitType outputType, cl_mem_object_type imageType )
{
    int ret = 0;
    imageSampler->normalized_coords = false;
    log_info( "read_image (%s coords, %s results) *****************************\n",
              "integer", get_explicit_type_name( outputType ) );

    for ( unsigned int i = 0; i < numFormats; i++ )
    {
        if ( filterFlags[i] )
            continue;

        cl_image_format &imageFormat = formatList[ i ];

        ret |= test_read_image_type( device, context, queue, &imageFormat, imageSampler, outputType, imageType );
    }
    return ret;
}

int test_image_set( cl_device_id device, cl_context context, cl_command_queue queue, cl_mem_object_type imageType )
{
    int ret = 0;
    static int printedFormatList = -1;

    // Grab the list of supported image formats
    cl_image_format *formatList;
    unsigned int numFormats;

    if (gTestReadWrite && checkForReadWriteImageSupport(device))
    {
        return TEST_SKIPPED_ITSELF;
    }

    cl_image_format *readOnlyFormats;
    unsigned int numReadOnlyFormats;

    if (get_format_list(context, imageType, readOnlyFormats, numReadOnlyFormats,
                        CL_MEM_READ_ONLY))
        return -1;

    if (gTestReadWrite)
    {
        cl_image_format *readWriteFormats;
        unsigned int numReadWriteFormats;

        if (get_format_list(context, imageType, readWriteFormats,
                            numReadWriteFormats, CL_MEM_KERNEL_READ_AND_WRITE))
            return -1;

        numFormats = numReadOnlyFormats;
        formatList = new cl_image_format[numFormats];
        unsigned int k = 0;

        // Keep only intersecting formats with read only and read write flags
        for (unsigned int i = 0; i < numReadOnlyFormats; i++)
        {
            for (unsigned int j = 0; j < numReadWriteFormats; j++)
            {
                if (readOnlyFormats[i].image_channel_data_type
                        == readWriteFormats[j].image_channel_data_type
                    && readOnlyFormats[i].image_channel_order
                        == readWriteFormats[j].image_channel_order)
                {
                    formatList[k].image_channel_data_type =
                        readOnlyFormats[i].image_channel_data_type;
                    formatList[k].image_channel_order =
                        readOnlyFormats[i].image_channel_order;
                    k++;
                    break;
                }
            }
        }

        numFormats = k;

        delete[] readOnlyFormats;
        delete[] readWriteFormats;
    }
    else
    {
        numFormats = numReadOnlyFormats;
        formatList = readOnlyFormats;
    }

    bool *filterFlags = new bool[numFormats];
    if ( filterFlags == NULL )
    {
        log_error( "ERROR: Out of memory allocating filter flags list!\n" );
        return -1;
    }
    memset( filterFlags, 0, sizeof( bool ) * numFormats );

    // First time through, we'll go ahead and print the formats supported, regardless of type
    if ( printedFormatList != (int)imageType )
    {
        log_info( "---- Supported %s read formats for this device ---- \n", convert_image_type_to_string(imageType) );
        for ( unsigned int f = 0; f < numFormats; f++ )
            log_info( "  %-7s %-24s %d\n", GetChannelOrderName( formatList[ f ].image_channel_order ),
                      GetChannelTypeName( formatList[ f ].image_channel_data_type ),
                      (int)get_format_channel_count( &formatList[ f ] ) );
        log_info( "------------------------------------------- \n" );
        printedFormatList = imageType;
    }

    image_sampler_data imageSampler;

    for (auto test : imageTestTypes)
    {
        if (gTypesToTest & test.type)
        {
            if (filter_formats(formatList, filterFlags, numFormats,
                               test.channelTypes)
                == 0)
            {
                log_info("No formats supported for %s type\n", test.name);
            }
            else
            {
                imageSampler.filter_mode = CL_FILTER_NEAREST;
                ret += test_read_image_formats(
                    device, context, queue, formatList, filterFlags, numFormats,
                    &imageSampler, test.explicitType, imageType);
            }
        }
    }

    delete[] filterFlags;
    delete[] formatList;

    return ret;
}
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2004-2019 musikcube team
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//    * Redistributions of source code must retain the above copyright notice,
//      this list of conditions and the following disclaimer.
//
//    * Redistributions in binary form must reproduce the above copyright
//      notice, this list of conditions and the following disclaimer in the
//      documentation and/or other materials provided with the distribution.
//
//    * Neither the name of the author nor the names of other contributors may
//      be used to endorse or promote products derived from this software
//      without specific prior written permission.
//
// 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 COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////

#include "pch.hpp"
#include <core/support/Common.h>
#include <core/config.h>
#include <utf8/utf8.h>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <functional>
#include <vector>
#include <string>
#include <cctype>
#include <algorithm>

#ifdef WIN32
    #include <shellapi.h>
#elif __APPLE__
    #include <mach-o/dyld.h>
#else
    #include <sys/types.h>
    #include <unistd.h>
    #include <sys/stat.h>
    #include <limits.h>
#endif

// given the #ifdef/#else above, the following is not required.
// Nor it is the #if FreeBSD below.
#ifdef __OpenBSD__
	#include <sys/types.h>
	#include <sys/sysctl.h>
	#include <unistd.h>
	#include <limits.h>
#endif

#ifdef __FreeBSD__
    #include <sys/types.h>
    #include <sys/sysctl.h>
#endif

static std::string GetHomeDirectory() {
    std::string directory;

#ifdef WIN32
    DWORD bufferSize = GetEnvironmentVariable(L"APPDATA", 0, 0);
    wchar_t *buffer = new wchar_t[bufferSize + 2];
    GetEnvironmentVariable(L"APPDATA", buffer, bufferSize);
    directory.assign(u16to8(buffer));
    delete[] buffer;
#else
    directory = std::string(std::getenv("HOME"));
#endif

    return directory;
}

static std::string getDataDirectoryRoot() {
#ifdef WIN32
    return GetHomeDirectory();
#else
    return GetHomeDirectory() + "/.config";
#endif
}

static inline void silentDelete(const std::string fn) {
    boost::system::error_code ec;
    boost::filesystem::remove(boost::filesystem::path(fn), ec);
}

namespace musik { namespace core {

    std::string GetPluginDirectory() {
        std::string path(GetApplicationDirectory());
        path.append("/plugins/");
        return path;
    }

    std::string GetApplicationDirectory() {
        std::string result;

        #ifdef WIN32
            wchar_t widePath[2048];
            int length = GetModuleFileName(NULL, widePath, 2048);
            if (length != 0 && length < 2048) {
                result.assign(GetPath(u16to8(widePath).c_str()));
            }
        #elif __APPLE__
            char pathbuf[PATH_MAX + 1];
            uint32_t bufsize = sizeof(pathbuf);
            _NSGetExecutablePath(pathbuf, &bufsize);
            result.assign(pathbuf);
            size_t last = result.find_last_of("/");
            result = result.substr(0, last); /* remove filename component */
        #else
            char pathbuf[PATH_MAX + 1] = { 0 };

            #ifdef __FreeBSD__
                int mib[4];
                mib[0] = CTL_KERN;
                mib[1] = KERN_PROC;
                mib[2] = KERN_PROC_PATHNAME;
                mib[3] = -1;
                size_t bufsize = sizeof(pathbuf);
                sysctl(mib, 4, pathbuf, &bufsize, nullptr, 0);
            #elif defined  __OpenBSD__
			    int mib[4];
			    char **argv;
			    size_t len = ARG_MAX;

			    mib[0] = CTL_KERN;
			    mib[1] = KERN_PROC_ARGS;
			    mib[2] = getpid();
			    mib[3] = KERN_PROC_ARGV;

			    argv = new char*[len];
			    if (sysctl(mib, 4, argv, &len, nullptr, 0) < 0) abort();

			    boost::filesystem::path command = boost::filesystem::system_complete(argv[0]);
			    realpath(command.c_str(), pathbuf);
			    delete[] argv;
	        #endif

            result.assign(pathbuf);
            size_t last = result.find_last_of("/");
            result = result.substr(0, last); /* remove filename component */
        #endif

        return result;
    }

    std::string GetHomeDirectory() {
        std::string directory;

    #ifdef WIN32
        DWORD bufferSize = GetEnvironmentVariable(L"USERPROFILE", 0, 0);
        wchar_t *buffer = new wchar_t[bufferSize + 2];
        GetEnvironmentVariable(L"USERPROFILE", buffer, bufferSize);
        directory.assign(u16to8(buffer));
        delete[] buffer;
    #else
        directory = std::string(std::getenv("HOME"));
    #endif

        return directory;
    }

    std::string GetDataDirectory(bool create) {
        std::string directory = getDataDirectoryRoot() + std::string("/musikcube/");

        if (create) {
            try {
                boost::filesystem::path path(directory);
                if (!boost::filesystem::exists(path)) {
                    boost::filesystem::create_directories(path);
                }
            }
            catch (...) {
                /* ugh, fixme */
            }
        }

        return directory;
    }

    std::string GetPath(const std::string &sFile) {
        std::string sPath;
        int length;

    #ifdef WIN32
        wchar_t widePath[2048];
        wchar_t *szFile = NULL;

        length = GetFullPathName(u8to16(sFile).c_str(), 2048, widePath, &szFile);
        if(length != 0 && length < 2048) {
            sPath.assign(u16to8(widePath).c_str());
            if(szFile!=0) {
                std::string sTheFile = u16to8(szFile);
                sPath.assign(sPath.substr(0,length-sTheFile.length()));
            }
        }
        else {
            sPath.assign(sFile);
        }
     #else
        char* szDir;
        sPath.assign(getcwd((char*)szDir, (size_t) length));
     #endif

        return sPath;
    }

    int64_t Checksum(char *data,unsigned int bytes) {
        int64_t sum = 0;
        for(unsigned int i = 0; i < bytes; ++i) {
            char ch = *(data + i);
            sum += (int64_t) ch;
        }
        return sum;
    }

    size_t CopyString(const std::string& src, char* dst, size_t size) {
        size_t len = src.size() + 1; /* space for the null terminator */
        if (dst) {
            size_t copied = src.copy(dst, size - 1);
            dst[copied] = '\0';
            return copied + 1;
        }
        return len;
    }

    bool FileToByteArray(const std::string& path, char** target, int& size, bool nullTerminate) {
    #ifdef WIN32
        std::wstring u16fn = u8to16(path);
        FILE* file = _wfopen(u16fn.c_str(), L"rb");
    #else
        FILE* file = fopen(path.c_str(), "rb");
    #endif

        *target = nullptr;
        size = 0;

        if (!file) {
            return false;
        }

        bool success = false;

        if (fseek(file, 0L, SEEK_END) == 0) {
            long fileSize = ftell(file);
            if (fileSize == -1) {
                goto close_and_return;
            }

            if (fseek(file, 0L, SEEK_SET) != 0) {
                goto close_and_return;
            }

            *target = (char*)malloc(sizeof(char) * (fileSize + (nullTerminate ? 1 : 0)));
            size = fread(*target, sizeof(char), fileSize, file);

            if (size == fileSize) {
                if (nullTerminate) {
                    (*target)[size] = 0;
                }

                success = true;
            }
        }

    close_and_return:
        fclose(file);

        if (!success) {
            free(*target);
        }

        return success;
    }

    std::string NormalizeDir(std::string path) {
        path = boost::filesystem::path(path).make_preferred().string();

        std::string sep(1, boost::filesystem::path::preferred_separator);
        if (path.size() && path.substr(path.size() - 1, 1) != sep) {
            path += sep;
        }

        return path;
    }

    void ReplaceAll(std::string& input, const std::string& find, const std::string& replace) {
        size_t pos = input.find(find);
        while (pos != std::string::npos) {
            input.replace(pos, find.size(), replace);
            pos = input.find(find, pos + replace.size());
        }
    }

    std::string Trim(const std::string& str) {
        std::string s(str);
        s.erase(s.begin(), std::find_if(s.begin(), s.end(),
            std::not1(std::ptr_fun<int, int>(std::isspace))));
        s.erase(std::find_if(s.rbegin(), s.rend(),
            std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
        return s;
    }

    std::vector<std::string> Split(
        const std::string& in, const std::string& delim)
    {
        std::vector<std::string> result;
        size_t last = 0, next = 0;
        while ((next = in.find(delim, last)) != std::string::npos) {
            result.push_back(std::move(Trim(in.substr(last, next - last))));
            last = next + 1;
        }
        result.push_back(std::move(Trim(in.substr(last))));
        return result;
    }

    void OpenFile(const std::string& path) {
    #ifdef WIN32
        ShellExecuteA(nullptr, nullptr, path.c_str(), nullptr, nullptr, SW_SHOWNORMAL);
    #elif __APPLE__
        std::string command = "open '" + path + "' > /dev/null 2> /dev/null";
        system(command.c_str());
    #else
        std::string command = "xdg-open '" + path + "' > /dev/null 2> /dev/null";
        system(command.c_str());
    #endif
    }

    bool CopyFile(const std::string& from, const std::string& to) {
        if (from.size() && to.size() && from != to) {
            std::ifstream in(from);
            if (in.is_open()) {
                std::ofstream out(to);
                if (out.is_open()) {
                    out << in.rdbuf();
                    return true;
                }
            }
        }
        return false;
    }

} }
<commit_msg>restore accidentally removed Linux #ifdef case<commit_after>//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2004-2019 musikcube team
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//    * Redistributions of source code must retain the above copyright notice,
//      this list of conditions and the following disclaimer.
//
//    * Redistributions in binary form must reproduce the above copyright
//      notice, this list of conditions and the following disclaimer in the
//      documentation and/or other materials provided with the distribution.
//
//    * Neither the name of the author nor the names of other contributors may
//      be used to endorse or promote products derived from this software
//      without specific prior written permission.
//
// 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 COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////

#include "pch.hpp"
#include <core/support/Common.h>
#include <core/config.h>
#include <utf8/utf8.h>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <functional>
#include <vector>
#include <string>
#include <cctype>
#include <algorithm>

#ifdef WIN32
    #include <shellapi.h>
#elif __APPLE__
    #include <mach-o/dyld.h>
#else
    #include <sys/types.h>
    #include <unistd.h>
    #include <sys/stat.h>
    #include <limits.h>
#endif

// given the #ifdef/#else above, the following is not required.
// Nor it is the #if FreeBSD below.
#ifdef __OpenBSD__
	#include <sys/types.h>
	#include <sys/sysctl.h>
	#include <unistd.h>
	#include <limits.h>
#endif

#ifdef __FreeBSD__
    #include <sys/types.h>
    #include <sys/sysctl.h>
#endif

static std::string GetHomeDirectory() {
    std::string directory;

#ifdef WIN32
    DWORD bufferSize = GetEnvironmentVariable(L"APPDATA", 0, 0);
    wchar_t *buffer = new wchar_t[bufferSize + 2];
    GetEnvironmentVariable(L"APPDATA", buffer, bufferSize);
    directory.assign(u16to8(buffer));
    delete[] buffer;
#else
    directory = std::string(std::getenv("HOME"));
#endif

    return directory;
}

static std::string getDataDirectoryRoot() {
#ifdef WIN32
    return GetHomeDirectory();
#else
    return GetHomeDirectory() + "/.config";
#endif
}

static inline void silentDelete(const std::string fn) {
    boost::system::error_code ec;
    boost::filesystem::remove(boost::filesystem::path(fn), ec);
}

namespace musik { namespace core {

    std::string GetPluginDirectory() {
        std::string path(GetApplicationDirectory());
        path.append("/plugins/");
        return path;
    }

    std::string GetApplicationDirectory() {
        std::string result;

        #ifdef WIN32
            wchar_t widePath[2048];
            int length = GetModuleFileName(NULL, widePath, 2048);
            if (length != 0 && length < 2048) {
                result.assign(GetPath(u16to8(widePath).c_str()));
            }
        #elif __APPLE__
            char pathbuf[PATH_MAX + 1];
            uint32_t bufsize = sizeof(pathbuf);
            _NSGetExecutablePath(pathbuf, &bufsize);
            result.assign(pathbuf);
            size_t last = result.find_last_of("/");
            result = result.substr(0, last); /* remove filename component */
        #else
            char pathbuf[PATH_MAX + 1] = { 0 };

            #ifdef __FreeBSD__
                int mib[4];
                mib[0] = CTL_KERN;
                mib[1] = KERN_PROC;
                mib[2] = KERN_PROC_PATHNAME;
                mib[3] = -1;
                size_t bufsize = sizeof(pathbuf);
                sysctl(mib, 4, pathbuf, &bufsize, nullptr, 0);
            #elif defined  __OpenBSD__
			    int mib[4];
			    char **argv;
			    size_t len = ARG_MAX;

			    mib[0] = CTL_KERN;
			    mib[1] = KERN_PROC_ARGS;
			    mib[2] = getpid();
			    mib[3] = KERN_PROC_ARGV;

			    argv = new char*[len];
			    if (sysctl(mib, 4, argv, &len, nullptr, 0) < 0) abort();

			    boost::filesystem::path command = boost::filesystem::system_complete(argv[0]);
			    realpath(command.c_str(), pathbuf);
			    delete[] argv;
            #else
                std::string pathToProc = u8fmt("/proc/%d/exe", (int) getpid());
                readlink(pathToProc.c_str(), pathbuf, PATH_MAX);
	    #endif

            result.assign(pathbuf);
            size_t last = result.find_last_of("/");
            result = result.substr(0, last); /* remove filename component */
        #endif

        return result;
    }

    std::string GetHomeDirectory() {
        std::string directory;

    #ifdef WIN32
        DWORD bufferSize = GetEnvironmentVariable(L"USERPROFILE", 0, 0);
        wchar_t *buffer = new wchar_t[bufferSize + 2];
        GetEnvironmentVariable(L"USERPROFILE", buffer, bufferSize);
        directory.assign(u16to8(buffer));
        delete[] buffer;
    #else
        directory = std::string(std::getenv("HOME"));
    #endif

        return directory;
    }

    std::string GetDataDirectory(bool create) {
        std::string directory = getDataDirectoryRoot() + std::string("/musikcube/");

        if (create) {
            try {
                boost::filesystem::path path(directory);
                if (!boost::filesystem::exists(path)) {
                    boost::filesystem::create_directories(path);
                }
            }
            catch (...) {
                /* ugh, fixme */
            }
        }

        return directory;
    }

    std::string GetPath(const std::string &sFile) {
        std::string sPath;
        int length;

    #ifdef WIN32
        wchar_t widePath[2048];
        wchar_t *szFile = NULL;

        length = GetFullPathName(u8to16(sFile).c_str(), 2048, widePath, &szFile);
        if(length != 0 && length < 2048) {
            sPath.assign(u16to8(widePath).c_str());
            if(szFile!=0) {
                std::string sTheFile = u16to8(szFile);
                sPath.assign(sPath.substr(0,length-sTheFile.length()));
            }
        }
        else {
            sPath.assign(sFile);
        }
     #else
        char* szDir;
        sPath.assign(getcwd((char*)szDir, (size_t) length));
     #endif

        return sPath;
    }

    int64_t Checksum(char *data,unsigned int bytes) {
        int64_t sum = 0;
        for(unsigned int i = 0; i < bytes; ++i) {
            char ch = *(data + i);
            sum += (int64_t) ch;
        }
        return sum;
    }

    size_t CopyString(const std::string& src, char* dst, size_t size) {
        size_t len = src.size() + 1; /* space for the null terminator */
        if (dst) {
            size_t copied = src.copy(dst, size - 1);
            dst[copied] = '\0';
            return copied + 1;
        }
        return len;
    }

    bool FileToByteArray(const std::string& path, char** target, int& size, bool nullTerminate) {
    #ifdef WIN32
        std::wstring u16fn = u8to16(path);
        FILE* file = _wfopen(u16fn.c_str(), L"rb");
    #else
        FILE* file = fopen(path.c_str(), "rb");
    #endif

        *target = nullptr;
        size = 0;

        if (!file) {
            return false;
        }

        bool success = false;

        if (fseek(file, 0L, SEEK_END) == 0) {
            long fileSize = ftell(file);
            if (fileSize == -1) {
                goto close_and_return;
            }

            if (fseek(file, 0L, SEEK_SET) != 0) {
                goto close_and_return;
            }

            *target = (char*)malloc(sizeof(char) * (fileSize + (nullTerminate ? 1 : 0)));
            size = fread(*target, sizeof(char), fileSize, file);

            if (size == fileSize) {
                if (nullTerminate) {
                    (*target)[size] = 0;
                }

                success = true;
            }
        }

    close_and_return:
        fclose(file);

        if (!success) {
            free(*target);
        }

        return success;
    }

    std::string NormalizeDir(std::string path) {
        path = boost::filesystem::path(path).make_preferred().string();

        std::string sep(1, boost::filesystem::path::preferred_separator);
        if (path.size() && path.substr(path.size() - 1, 1) != sep) {
            path += sep;
        }

        return path;
    }

    void ReplaceAll(std::string& input, const std::string& find, const std::string& replace) {
        size_t pos = input.find(find);
        while (pos != std::string::npos) {
            input.replace(pos, find.size(), replace);
            pos = input.find(find, pos + replace.size());
        }
    }

    std::string Trim(const std::string& str) {
        std::string s(str);
        s.erase(s.begin(), std::find_if(s.begin(), s.end(),
            std::not1(std::ptr_fun<int, int>(std::isspace))));
        s.erase(std::find_if(s.rbegin(), s.rend(),
            std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
        return s;
    }

    std::vector<std::string> Split(
        const std::string& in, const std::string& delim)
    {
        std::vector<std::string> result;
        size_t last = 0, next = 0;
        while ((next = in.find(delim, last)) != std::string::npos) {
            result.push_back(std::move(Trim(in.substr(last, next - last))));
            last = next + 1;
        }
        result.push_back(std::move(Trim(in.substr(last))));
        return result;
    }

    void OpenFile(const std::string& path) {
    #ifdef WIN32
        ShellExecuteA(nullptr, nullptr, path.c_str(), nullptr, nullptr, SW_SHOWNORMAL);
    #elif __APPLE__
        std::string command = "open '" + path + "' > /dev/null 2> /dev/null";
        system(command.c_str());
    #else
        std::string command = "xdg-open '" + path + "' > /dev/null 2> /dev/null";
        system(command.c_str());
    #endif
    }

    bool CopyFile(const std::string& from, const std::string& to) {
        if (from.size() && to.size() && from != to) {
            std::ifstream in(from);
            if (in.is_open()) {
                std::ofstream out(to);
                if (out.is_open()) {
                    out << in.rdbuf();
                    return true;
                }
            }
        }
        return false;
    }

} }
<|endoftext|>