<commit_before>//
//  src/misc/flags.cc
//  tbd
//
//  Created by inoahdev on 7/10/17.
//  Copyright © 2017 inoahdev. All rights reserved.
//

#include <cerrno>

#include <cstdint>
#include <cstdio>

#include <cstdlib>
#include <cstring>

#include "flags.h"

flags::flags(flags_integer_t length)
: length(length) {
    const auto bit_size = this->bit_size();
    if (length > bit_size) {
        auto size = (size_t)((double)length / (double)bit_size) + 1;
        auto allocation_size = sizeof(flags_integer_t) * size;

        bits.pointer = (flags_integer_t *)calloc(1, allocation_size);

        if (!bits.pointer) {
            fprintf(stderr, "Failed to allocate data of size (%ld), failing with error (%s)\n", size, strerror(errno));
            exit(1);
        }
    }
}

flags::flags(const flags &flags) {
    const auto bit_size = this->bit_size();
    if (length > bit_size) {
        auto size = (size_t)((double)length / (double)bit_size) + 1;
        auto allocation_size = sizeof(flags_integer_t) * size;

        bits.pointer = (flags_integer_t *)malloc(allocation_size);
        if (!bits.pointer) {
            fprintf(stderr, "Failed to allocate data of size (%ld), failing with error (%s)\n", size, strerror(errno));
            exit(1);
        }

        memcpy(bits.pointer, flags.bits.pointer, allocation_size);
    } else {
        bits.integer = flags.bits.integer;
    }
}

flags::~flags() {
    if (length > bit_size()) {
        free(bits.pointer);
    }
}

void flags::cast(flags_integer_t index, bool flag) noexcept {
    if (index > length - 1) {
        fprintf(stderr, "INTERNAL: Casting bit at index %llu from buffer with bits-length %llu", index, length);
        exit(1);
    }

    const auto bit_size = this->bit_size();
    if (length > bit_size) {
        auto location = (flags_integer_t)((double)(index + 1) / (double)bit_size);
        auto pointer = (flags_integer_t *)((flags_integer_t)bits.pointer + (sizeof(flags_integer_t) * location));

        index -= bit_size * location;

        if (flag) {
            *pointer |= (flags_integer_t)1 << index;
        } else {
            *pointer &= ~((flags_integer_t)1 << index);
        }
    } else {
        if (flag) {
            bits.integer |= (flags_integer_t)1 << index;
        } else {
            bits.integer &= ~((flags_integer_t)1 << index);
        }
    }
}

bool flags::at(flags_integer_t index) const noexcept {
    if (index > length - 1) {
        fprintf(stderr, "INTERNAL: Accessing bit at index %llu from buffer with bits-length %llu", index, length);
        exit(1);
    }

    auto flags = bits.integer;
    const auto bit_size = this->bit_size();

    if (length > bit_size) {
        auto location = (flags_integer_t)((double)(index + 1) / (double)bit_size);
        auto pointer = (flags_integer_t *)((flags_integer_t)bits.pointer + (sizeof(flags_integer_t) * location));

        index -= bit_size * location;
        flags = *pointer;
    }

    return flags & ((flags_integer_t)1 << index);
}

bool flags::operator==(const flags &flags) const noexcept {
    if (length != flags.length) {
        return false;
    }

    if (length > bit_size()) {
        return memcmp(bits.pointer, flags.bits.pointer, length);
    } else {
        return bits.integer == flags.bits.integer;
    }
}
<commit_msg>Fix bug causing multiple groups of reexports and symbols to be outputted<commit_after>//
//  src/misc/flags.cc
//  tbd
//
//  Created by inoahdev on 7/10/17.
//  Copyright © 2017 inoahdev. All rights reserved.
//

#include <cerrno>

#include <cstdint>
#include <cstdio>

#include <cstdlib>
#include <cstring>

#include "flags.h"

flags::flags(flags_integer_t length)
: length(length) {
    const auto bit_size = this->bit_size();
    if (length > bit_size) {
        auto size = (size_t)((double)length / (double)bit_size) + 1;
        auto allocation_size = sizeof(flags_integer_t) * size;

        bits.pointer = (flags_integer_t *)calloc(1, allocation_size);

        if (!bits.pointer) {
            fprintf(stderr, "Failed to allocate data of size (%ld), failing with error (%s)\n", size, strerror(errno));
            exit(1);
        }
    }
}

flags::flags(const flags &flags) :
length(flags.length) {
    const auto bit_size = this->bit_size();
    if (length > bit_size) {
        auto size = (size_t)((double)length / (double)bit_size) + 1;
        auto allocation_size = sizeof(flags_integer_t) * size;

        bits.pointer = (flags_integer_t *)malloc(allocation_size);
        if (!bits.pointer) {
            fprintf(stderr, "Failed to allocate data of size (%ld), failing with error (%s)\n", size, strerror(errno));
            exit(1);
        }

        memcpy(bits.pointer, flags.bits.pointer, allocation_size);
    } else {
        bits.integer = flags.bits.integer;
    }
}

flags::~flags() {
    if (length > bit_size()) {
        free(bits.pointer);
    }
}

void flags::cast(flags_integer_t index, bool flag) noexcept {
    if (index > length - 1) {
        fprintf(stderr, "INTERNAL: Casting bit at index %llu from buffer with bits-length %llu", index, length);
        exit(1);
    }

    const auto bit_size = this->bit_size();
    if (length > bit_size) {
        auto location = (flags_integer_t)((double)(index + 1) / (double)bit_size);
        auto pointer = (flags_integer_t *)((flags_integer_t)bits.pointer + (sizeof(flags_integer_t) * location));

        index -= bit_size * location;

        if (flag) {
            *pointer |= (flags_integer_t)1 << index;
        } else {
            *pointer &= ~((flags_integer_t)1 << index);
        }
    } else {
        if (flag) {
            bits.integer |= (flags_integer_t)1 << index;
        } else {
            bits.integer &= ~((flags_integer_t)1 << index);
        }
    }
}

bool flags::at(flags_integer_t index) const noexcept {
    if (index > length - 1) {
        fprintf(stderr, "INTERNAL: Accessing bit at index %llu from buffer with bits-length %llu", index, length);
        exit(1);
    }

    auto flags = bits.integer;
    const auto bit_size = this->bit_size();

    if (length > bit_size) {
        auto location = (flags_integer_t)((double)(index + 1) / (double)bit_size);
        auto pointer = (flags_integer_t *)((flags_integer_t)bits.pointer + (sizeof(flags_integer_t) * location));

        index -= bit_size * location;
        flags = *pointer;
    }

    return flags & ((flags_integer_t)1 << index);
}

bool flags::operator==(const flags &flags) const noexcept {
    if (length != flags.length) {
        return false;
    }

    if (length > bit_size()) {
        return memcmp(bits.pointer, flags.bits.pointer, length);
    } else {
        return bits.integer == flags.bits.integer;
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// 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 "libshaderc_util/counting_includer.h"

#include <gmock/gmock.h>
#include <thread>

namespace {

// A trivial implementation of CountingIncluder's virtual methods, so tests can
// instantiate.
class ConcreteCountingIncluder : public shaderc_util::CountingIncluder {
 public:
  virtual glslang::TShader::Includer::IncludeResult* include_delegate(
      const char* requested, const char* requestor, IncludeType,
      size_t) override {
    const char kError[] = "Unexpected #include";
    return new glslang::TShader::Includer::IncludeResult{
        "", kError, strlen(kError), nullptr};
  }
  virtual void release_delegate(
      glslang::TShader::Includer::IncludeResult* include_result) override {
    delete include_result;
  }
};

TEST(CountingIncluderTest, InitialCount) {
  EXPECT_EQ(0, ConcreteCountingIncluder().num_include_directives());
}

TEST(CountingIncluderTest, OneIncludeLocal) {
  ConcreteCountingIncluder includer;
  includer.includeLocal("random file name", "from me", 0);
  EXPECT_EQ(1, includer.num_include_directives());
}

TEST(CountingIncluderTest, TwoIncludesAnyIncludeType) {
  ConcreteCountingIncluder includer;
  includer.includeSystem("name1", "from me", 0);
  includer.includeLocal("name2", "me", 0);
  EXPECT_EQ(2, includer.num_include_directives());
}

TEST(CountingIncluderTest, ManyIncludes) {
  ConcreteCountingIncluder includer;
  for (int i = 0; i < 100; ++i) {
    includer.includeLocal("filename", "from me", i);
    includer.includeSystem("filename", "from me", i);
  }
  EXPECT_EQ(200, includer.num_include_directives());
}

#ifndef SHADERC_DISABLE_THREADED_TESTS
TEST(CountingIncluderTest, ThreadedIncludes) {
  ConcreteCountingIncluder includer;
  std::thread t1(
      [&includer]() { includer.includeLocal("name1", "me", 0); });
  std::thread t2(
      [&includer]() { includer.includeSystem("name2", "me", 1); });
  std::thread t3(
      [&includer]() { includer.includeLocal("name3", "me", 2); });
  t1.join();
  t2.join();
  t3.join();
  EXPECT_EQ(3, includer.num_include_directives());
}
#endif // SHADERC_DISABLE_THREADED_TESTS

}  // anonymous namespace
<commit_msg>Avoid mem leaks in counting includer test<commit_after>// Copyright 2015 The Shaderc Authors. All rights reserved.
//
// 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 "libshaderc_util/counting_includer.h"

#include <thread>
#include <vector>

#include <gmock/gmock.h>

namespace {

// A trivial implementation of CountingIncluder's virtual methods, so tests can
// instantiate.
class ConcreteCountingIncluder : public shaderc_util::CountingIncluder {
 public:
  using IncludeResult = glslang::TShader::Includer::IncludeResult;
  ~ConcreteCountingIncluder() {
    // Avoid leaks.
    for (auto result : results_) {
      release_delegate(result);
    }
  }
  virtual IncludeResult* include_delegate(
      const char* requested, const char* requestor, IncludeType,
      size_t) override {
    const char kError[] = "Unexpected #include";
    results_.push_back(new IncludeResult{"", kError, strlen(kError), nullptr});
    return results_.back();
  }
  virtual void release_delegate(IncludeResult* include_result) override {
    delete include_result;
  }

 private:
  // All the results we've returned so far.
  std::vector<IncludeResult*> results_;
};

TEST(CountingIncluderTest, InitialCount) {
  EXPECT_EQ(0, ConcreteCountingIncluder().num_include_directives());
}

TEST(CountingIncluderTest, OneIncludeLocal) {
  ConcreteCountingIncluder includer;
  includer.includeLocal("random file name", "from me", 0);
  EXPECT_EQ(1, includer.num_include_directives());
}

TEST(CountingIncluderTest, TwoIncludesAnyIncludeType) {
  ConcreteCountingIncluder includer;
  includer.includeSystem("name1", "from me", 0);
  includer.includeLocal("name2", "me", 0);
  EXPECT_EQ(2, includer.num_include_directives());
}

TEST(CountingIncluderTest, ManyIncludes) {
  ConcreteCountingIncluder includer;
  for (int i = 0; i < 100; ++i) {
    includer.includeLocal("filename", "from me", i);
    includer.includeSystem("filename", "from me", i);
  }
  EXPECT_EQ(200, includer.num_include_directives());
}

#ifndef SHADERC_DISABLE_THREADED_TESTS
TEST(CountingIncluderTest, ThreadedIncludes) {
  ConcreteCountingIncluder includer;
  std::thread t1(
      [&includer]() { includer.includeLocal("name1", "me", 0); });
  std::thread t2(
      [&includer]() { includer.includeSystem("name2", "me", 1); });
  std::thread t3(
      [&includer]() { includer.includeLocal("name3", "me", 2); });
  t1.join();
  t2.join();
  t3.join();
  EXPECT_EQ(3, includer.num_include_directives());
}
#endif // SHADERC_DISABLE_THREADED_TESTS

}  // anonymous namespace
<|endoftext|>


<commit_before>/****************************************************************************
** Meta object code from reading C++ file 'CQMainWindow.h'
**
** Created: Fri Sep 13 22:07:43 2013
**      by: The Qt Meta Object Compiler version 63 (Qt 4.8.1)
**
** WARNING! All changes made in this file will be lost!
*****************************************************************************/

#include "CQMainWindow.h"
#if !defined(Q_MOC_OUTPUT_REVISION)
#error "The header file 'CQMainWindow.h' doesn't include <QObject>."
#elif Q_MOC_OUTPUT_REVISION != 63
#error "This file was generated using the moc from 4.8.1. It"
#error "cannot be used with the include files from this version of Qt."
#error "(The moc has changed too much.)"
#endif

QT_BEGIN_MOC_NAMESPACE
static const uint qt_meta_data_CQMainWindow[] = {

 // content:
       6,       // revision
       0,       // classname
       0,    0, // classinfo
       0,    0, // methods
       0,    0, // properties
       0,    0, // enums/sets
       0,    0, // constructors
       0,       // flags
       0,       // signalCount

       0        // eod
};

static const char qt_meta_stringdata_CQMainWindow[] = {
    "CQMainWindow\0"
};

void CQMainWindow::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
    Q_UNUSED(_o);
    Q_UNUSED(_id);
    Q_UNUSED(_c);
    Q_UNUSED(_a);
}

const QMetaObjectExtraData CQMainWindow::staticMetaObjectExtraData = {
    0,  qt_static_metacall
};

const QMetaObject CQMainWindow::staticMetaObject = {
    { &QMainWindow::staticMetaObject, qt_meta_stringdata_CQMainWindow,
      qt_meta_data_CQMainWindow, &staticMetaObjectExtraData }
};

#ifdef Q_NO_DATA_RELOCATION
const QMetaObject &CQMainWindow::getStaticMetaObject() { return staticMetaObject; }
#endif //Q_NO_DATA_RELOCATION

const QMetaObject *CQMainWindow::metaObject() const
{
    return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;
}

void *CQMainWindow::qt_metacast(const char *_clname)
{
    if (!_clname) return 0;
    if (!strcmp(_clname, qt_meta_stringdata_CQMainWindow))
        return static_cast<void*>(const_cast< CQMainWindow*>(this));
    return QMainWindow::qt_metacast(_clname);
}

int CQMainWindow::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
    _id = QMainWindow::qt_metacall(_c, _id, _a);
    if (_id < 0)
        return _id;
    return _id;
}
QT_END_MOC_NAMESPACE
<commit_msg>new files<commit_after><|endoftext|>


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

#include <wx/extension/configdialog.h>
#include <wx/filetool/filetool.h>

/// Offers a find combobox that allows yuo to find text
/// on a current STC on an ftFrame.
class ftFind : public wxComboBox
{
public:
  /// Constructor. Fills the combobox box with values from FindReplace from config.
  ftFind(
    wxWindow* parent,
    ftFrame* frame,
    wxWindowID id = wxID_ANY,
    const wxPoint& pos = wxDefaultPosition,
    const wxSize& size = wxDefaultSize);
private:
  void OnCommand(wxCommandEvent& event);
  void OnKey(wxKeyEvent& event);
  ftFrame* m_Frame;

  DECLARE_EVENT_TABLE()
};

bool ftCompareFile(const wxFileName& file1, const wxFileName& file2)
{
  const wxString comparator = exApp::GetConfig(_("Comparator"));

  if (comparator.empty())
  {
    wxLogMessage(_("Please add a comparator"));
    return false;
  }

  const wxString arguments =
     (file1.GetModificationTime() < file2.GetModificationTime()) ?
       "\"" + file1.GetFullPath() + "\" \"" + file2.GetFullPath() + "\"":
       "\"" + file2.GetFullPath() + "\" \"" + file1.GetFullPath() + "\"";

  if (wxExecute(comparator + " " + arguments) == 0)
  {
    return false;
  }

  const wxString msg = _("Compared") + ": " + arguments;
  exApp::Log(msg);
  exFrame::StatusText(msg);

  return true;
}

void ftFindInFiles(ftFrame* frame, bool replace)
{
  std::vector<exConfigItem> v;
  v.push_back(exConfigItem(_("Find what"), CONFIG_COMBOBOX, wxEmptyString, true));
  if (replace) v.push_back(exConfigItem(_("Replace with"), CONFIG_COMBOBOX));
  v.push_back(exConfigItem(_("In files"), CONFIG_COMBOBOX, wxEmptyString, true));
  v.push_back(exConfigItem(_("In folder"), CONFIG_COMBOBOXDIR, wxEmptyString, true));
  v.push_back(exConfigItem());
  v.push_back(exConfigItem(exApp::GetConfig()->GetFindReplaceData()->GetInfo()));

  if (exConfigDialog(NULL,
    exApp::GetConfig(),
    v,
    (replace ? _("Replace In Files"): _("Find In Files"))).ShowModal() == wxID_CANCEL)
  {
    return;
  }

  ftListView* output =
    frame->Activate(replace ? ftListView::LIST_REPLACE : ftListView::LIST_FIND);
  if (output == NULL) return;

  const exTool tool =
    (replace ?
       ID_TOOL_REPORT_REPLACE:
       ID_TOOL_REPORT_FIND);

  if (!ftTextFile::SetupTool(tool))
  {
    return;
  }

  exApp::Log(exApp::GetConfig()->GetFindReplaceData()->GetText(replace));

  ftDir dir(
    output,
    exApp::GetConfig(_("In folder")),
    exApp::GetConfig(_("In files")));

  dir.RunTool(tool);
  dir.GetStatistics().Log(tool);
}

bool ftFindOtherFileName(
  const wxFileName& filename,
  ftListView* listview,
  wxFileName* lastfile)
{
  /* Add the base version if present. E.g.
  fullpath: F:\CCIS\v990308\com\atis\atis-ctrl\atis-ctrl.cc
  base:  F:\CCIS\
  append:   \com\atis\atis-ctrl\atis-ctrl.cc
  */
  const wxString fullpath = filename.GetFullPath();

  wxRegEx reg("[/|\\][a-z-]*[0-9]+\\.?[0-9]*\\.?[0-9]*\\.?[0-9]*");

  if (!reg.Matches(fullpath.Lower()))
  {
    exFrame::StatusText(_("No version information found"));
    return false;
  }

  size_t start, len;
  if (!reg.GetMatch(&start, &len))
  {
    exFrame::StatusText("No match after all");
    return false;
  }

  wxString base = fullpath.substr(0, start);
  if (!wxEndsWithPathSeparator(base))
  {
    base += wxFileName::GetPathSeparator();
  }

  wxDir dir(base);

  if (!dir.IsOpened())
  {
    exFrame::StatusText("Could not open base dir: " + base);
    return false;
  }

  wxString filename_string;
  bool cont = dir.GetFirst(&filename_string, wxEmptyString, wxDIR_DIRS); // only get dirs

  wxDateTime lastmodtime((time_t)0);
  const wxString append = fullpath.substr(start + len);

  bool found = false;

  // TODO: Use a thread for this.
  while (cont)
  {
    wxFileName fn(base + filename_string + append);

    if (fn.FileExists() &&
        fn.GetPath().CmpNoCase(filename.GetPath()) != 0 &&
        fn.GetModificationTime() != filename.GetModificationTime())
    {
      found = true;

      if (listview == NULL && lastfile == NULL)
      {
        // We are only interested in return value, so speed it up.
        return true;
      }

      if (listview != NULL)
      {
        ftListItem item(listview, fn.GetFullPath());
        item.Insert();
      }

      if (lastfile != NULL)
      {
        if (fn.GetModificationTime() > lastmodtime)
        {
          lastmodtime = fn.GetModificationTime();
          *lastfile = fn;
        }
      }
    }

    cont = dir.GetNext(&filename_string);

    wxTheApp->Yield();
  }

  if (!found && (listview != NULL || lastfile != NULL))
  {
    exFrame::StatusText(_("No files found"));
  }

  return found;
}

bool ftForEach(wxAuiNotebook* notebook, int id, const wxFont& font)
{
  for (
    size_t page = 0;
    page < notebook->GetPageCount();
    page++)
  {
    ftListView* lv = (ftListView*)notebook->GetPage(page);

    if (lv == NULL)
    {
      wxLogError(FILE_INFO("Notebook page: %d (%s) is not an ftListView"),
        page,
        notebook->GetPageText(page).c_str());
      return false;
    }

    if (id >= wxID_VIEW_DETAILS &&  id <= wxID_VIEW_LIST)
    {
      long view = 0;
      switch (id)
      {
      case wxID_VIEW_DETAILS: view = wxLC_REPORT; break;
      case wxID_VIEW_LIST: view = wxLC_LIST; break;
      case wxID_VIEW_SMALLICONS: view = wxLC_SMALL_ICON; break;
      default: wxLogError(FILE_INFO("Unhandled"));
      }

      lv->SetSingleStyle(view);
      exApp::GetConfig()->Set("List/Style", view);
    }
    else
    {
    switch (id)
    {
    case ID_LIST_ALL_ITEMS:
      {
        if (font.IsOk())
        {
          lv->SetFont(font);
        }

        lv->ItemsUpdate();
      }
      break;

    case ID_LIST_ALL_CLOSE:
      if (!lv->Continue()) return false;
      if (!notebook->DeletePage(page)) return false;
      break;

    default: wxLogError("Unhandled: %d (ID_TOOL_LOWEST: %d ID_TOOL_SQL: %d ID_LIST_LOWEST: %d",
      id, (int)ID_TOOL_LOWEST, (int)ID_TOOL_SQL, (int)ID_LIST_LOWEST);
    }
    }
  }

  return true;
}

void ftOpenFiles(
  ftFrame* frame,
  const wxArrayString& files,
  long flags)
{
  for (size_t i = 0; i < files.GetCount(); i++)
  {
    wxString file = files[i]; // cannot be const because of file = later on

    if (file.Contains("*") || file.Contains("?"))
    {
      ftDir dir(frame, wxGetCwd(), file, flags);
      dir.FindFiles();
    }
    else
    {
      int line = 0;

      if (file.Contains(":"))
      {
        line = atoi(files[i].AfterFirst(':').c_str());

        if (line != 0) // this indicates an error in the number
        {
          file = file.BeforeFirst(':');
        }
      }

      const exFileName filename(file);
      frame->OpenFile(filename, line, wxEmptyString, flags);
    }
  }
}

ftDir::ftDir(ftListView* listview,
  const wxString& fullpath, const wxString& filespec)
  : exDir(fullpath, filespec)
  , m_Statistics(fullpath)
  , m_Frame(NULL)
  , m_ListView(listview)
  , m_Flags(0)
  , m_RunningTool(false)
  , m_Tool(ID_TOOL_LOWEST)
{
}

ftDir::ftDir(ftFrame* frame,
  const wxString& fullpath, const wxString& filespec, long flags)
  : exDir(fullpath, filespec)
  , m_Statistics(fullpath)
  , m_Frame(frame)
  , m_ListView(NULL)
  , m_Flags(flags)
  , m_RunningTool(false)
  , m_Tool(ID_TOOL_LOWEST)
{
}

bool ftDir::Cancelled()
{
  // TODO: Implement.
  return false;
}

void ftDir::OnFile(const wxString& file)
{
  if (m_RunningTool)
  {
    const exFileName filename(file);

    if (filename.GetStat().IsOk())
    {
      ftTextFile report(filename);
      report.RunTool(m_Tool);
      m_Statistics += report.GetStatistics();
    }
  }
  else
  {
    if (m_Frame != NULL)
    {
      if (wxFileName::DirExists(file)) return;
      m_Frame->OpenFile(file, 0, wxEmptyString, m_Flags);
    }
    else
    {
      if (m_ListView != NULL)
      {
        ftListItem item(m_ListView, file, GetFileSpec());
        item.Insert();

        // Don't move next code into insert, as it itself inserts!
        if (m_ListView->GetType() == ftListView::LIST_VERSION)
        {
          ftListItem item(m_ListView, m_ListView->GetItemCount() - 1);

          ftTextFile report(item.m_Statistics);
          if (report.SetupTool(ID_TOOL_REVISION_RECENT))
          {
            report.RunTool(ID_TOOL_REVISION_RECENT);
            item.UpdateRevisionList(report.GetRCS());
          }
        }
      }
    }
  }
}

size_t ftDir::RunTool(const exTool& tool, int flags)
{
  m_Tool = tool;

  m_RunningTool = true;

  size_t result = FindFiles(flags);

  m_RunningTool = false;

  return result;
}

BEGIN_EVENT_TABLE(ftFind, wxComboBox)
  EVT_CHAR(ftFind::OnKey)
  EVT_MENU(wxID_DELETE, ftFind::OnCommand)
END_EVENT_TABLE()

ftFind::ftFind(
  wxWindow* parent,
  ftFrame* frame,
  wxWindowID id,
  const wxPoint& pos,
  const wxSize& size)
  : wxComboBox(parent, id, wxEmptyString, pos, size)
  , m_Frame(frame)
{
  const int accels = 1;
  wxAcceleratorEntry entries[accels];
  entries[0].Set(wxACCEL_NORMAL, WXK_DELETE, wxID_DELETE);
  wxAcceleratorTable accel(accels, entries);
  SetAcceleratorTable(accel);

  const wxFont font(
    exApp::GetConfig("FindFont", 8),
    wxFONTFAMILY_DEFAULT,
    wxFONTSTYLE_NORMAL,
    wxFONTWEIGHT_NORMAL);

  SetFont(font);

  exComboBoxFromString(this, exApp::GetConfig("FindReplace/FindStrings"));

  // And override the value set by previous, as we want text to be same as in Find.
  SetValue(exApp::GetConfig()->GetFindReplaceData()->GetFindString());
}

void ftFind::OnCommand(wxCommandEvent& event)
{
  // README: The delete key default behaviour does not delete the char right from insertion point.
  // Instead, the event is sent to the editor and a char is deleted from the editor.
  // Therefore implement the delete here.
  if (event.GetId() == wxID_DELETE)
  {
    Remove(GetInsertionPoint(), GetInsertionPoint() + 1);
  }
  else
  {
    event.Skip();
  }
}

void ftFind::OnKey(wxKeyEvent& event)
{
  const int key = event.GetKeyCode();

  if (key == WXK_RETURN)
  {
    ftSTC* stc = m_Frame->GetCurrentSTC();

    if (stc != NULL)
    {
      stc->FindNext(GetValue());
      exApp::GetConfig()->GetFindReplaceData()->SetFindString(GetValue());

      // And keep the changed text in the combo box.
      wxString text;

      if (exComboBoxToString(this, text))
      {
        exApp::GetConfig()->Set("FindReplace/FindStrings", text);
        Clear(); // so exComboBoxFromString can append again
        exComboBoxFromString(this, text);
        SetValue(exApp::GetConfig()->GetFindReplaceData()->GetFindString());
      }
    }
  }
  else
  {
    event.Skip();
  }
}

BEGIN_EVENT_TABLE(ftFindToolBar, wxAuiToolBar)
  EVT_CHECKBOX(ID_MATCH_WHOLE_WORD, ftFindToolBar::OnCommand)
  EVT_CHECKBOX(ID_MATCH_CASE, ftFindToolBar::OnCommand)
  EVT_CHECKBOX(ID_REGULAR_EXPRESSION, ftFindToolBar::OnCommand)
END_EVENT_TABLE()

ftFindToolBar::ftFindToolBar(
  wxWindow* parent,
  ftFrame* frame,
  wxWindowID id)
  : wxAuiToolBar(parent, id)
{
  m_MatchCase = new wxCheckBox(this, ID_MATCH_CASE, _("Match case"));
  m_MatchWholeWord = new wxCheckBox(this, ID_MATCH_WHOLE_WORD, _("Match whole word"));
  m_RegularExpression = new wxCheckBox(this, ID_REGULAR_EXPRESSION, _("Regular expression"));

  m_MatchCase->SetValue(exApp::GetConfig()->GetFindReplaceData()->MatchCase());
  m_MatchWholeWord->SetValue(exApp::GetConfig()->GetFindReplaceData()->MatchWord());
  m_RegularExpression->SetValue(exApp::GetConfig()->GetFindReplaceData()->IsRegExp());

#ifdef __WXMSW__
  const wxSize size(150, 20);
#else
  const wxSize size(150, -1);
#endif
  AddControl(new ftFind(this, frame, ID_FIND_TEXT, wxDefaultPosition, size));
  AddSeparator();
  AddControl(m_MatchWholeWord);
  AddControl(m_MatchCase);
  AddControl(m_RegularExpression);

  Realize();
}

void ftFindToolBar::OnCommand(wxCommandEvent& event)
{
  switch (event.GetId())
  {
  case ID_MATCH_WHOLE_WORD:
  case ID_MATCH_CASE:
  case ID_REGULAR_EXPRESSION:
    exApp::GetConfig()->SetFindReplaceData(
      m_MatchWholeWord->GetValue(),
      m_MatchCase->GetValue(),
      m_RegularExpression->GetValue());
    break;
  }
}
<commit_msg>renamed ftFind in ComboBox<commit_after>/******************************************************************************\
* File:          filetool.cpp
* Purpose:       Implementation of filetool classes
* Author:        Anton van Wezenbeek
* RCS-ID:        $Id$
*
* Copyright (c) 1998-2009 Anton van Wezenbeek
* All rights are reserved. Reproduction in whole or part is prohibited
* without the written consent of the copyright owner.
\******************************************************************************/

#include <wx/extension/configdialog.h>
#include <wx/filetool/filetool.h>

bool ftCompareFile(const wxFileName& file1, const wxFileName& file2)
{
  const wxString comparator = exApp::GetConfig(_("Comparator"));

  if (comparator.empty())
  {
    wxLogMessage(_("Please add a comparator"));
    return false;
  }

  const wxString arguments =
     (file1.GetModificationTime() < file2.GetModificationTime()) ?
       "\"" + file1.GetFullPath() + "\" \"" + file2.GetFullPath() + "\"":
       "\"" + file2.GetFullPath() + "\" \"" + file1.GetFullPath() + "\"";

  if (wxExecute(comparator + " " + arguments) == 0)
  {
    return false;
  }

  const wxString msg = _("Compared") + ": " + arguments;
  exApp::Log(msg);
  exFrame::StatusText(msg);

  return true;
}

void ftFindInFiles(ftFrame* frame, bool replace)
{
  std::vector<exConfigItem> v;
  v.push_back(exConfigItem(_("Find what"), CONFIG_COMBOBOX, wxEmptyString, true));
  if (replace) v.push_back(exConfigItem(_("Replace with"), CONFIG_COMBOBOX));
  v.push_back(exConfigItem(_("In files"), CONFIG_COMBOBOX, wxEmptyString, true));
  v.push_back(exConfigItem(_("In folder"), CONFIG_COMBOBOXDIR, wxEmptyString, true));
  v.push_back(exConfigItem());
  v.push_back(exConfigItem(exApp::GetConfig()->GetFindReplaceData()->GetInfo()));

  if (exConfigDialog(NULL,
    exApp::GetConfig(),
    v,
    (replace ? _("Replace In Files"): _("Find In Files"))).ShowModal() == wxID_CANCEL)
  {
    return;
  }

  ftListView* output =
    frame->Activate(replace ? ftListView::LIST_REPLACE : ftListView::LIST_FIND);
  if (output == NULL) return;

  const exTool tool =
    (replace ?
       ID_TOOL_REPORT_REPLACE:
       ID_TOOL_REPORT_FIND);

  if (!ftTextFile::SetupTool(tool))
  {
    return;
  }

  exApp::Log(exApp::GetConfig()->GetFindReplaceData()->GetText(replace));

  ftDir dir(
    output,
    exApp::GetConfig(_("In folder")),
    exApp::GetConfig(_("In files")));

  dir.RunTool(tool);
  dir.GetStatistics().Log(tool);
}

bool ftFindOtherFileName(
  const wxFileName& filename,
  ftListView* listview,
  wxFileName* lastfile)
{
  /* Add the base version if present. E.g.
  fullpath: F:\CCIS\v990308\com\atis\atis-ctrl\atis-ctrl.cc
  base:  F:\CCIS\
  append:   \com\atis\atis-ctrl\atis-ctrl.cc
  */
  const wxString fullpath = filename.GetFullPath();

  wxRegEx reg("[/|\\][a-z-]*[0-9]+\\.?[0-9]*\\.?[0-9]*\\.?[0-9]*");

  if (!reg.Matches(fullpath.Lower()))
  {
    exFrame::StatusText(_("No version information found"));
    return false;
  }

  size_t start, len;
  if (!reg.GetMatch(&start, &len))
  {
    exFrame::StatusText("No match after all");
    return false;
  }

  wxString base = fullpath.substr(0, start);
  if (!wxEndsWithPathSeparator(base))
  {
    base += wxFileName::GetPathSeparator();
  }

  wxDir dir(base);

  if (!dir.IsOpened())
  {
    exFrame::StatusText("Could not open base dir: " + base);
    return false;
  }

  wxString filename_string;
  bool cont = dir.GetFirst(&filename_string, wxEmptyString, wxDIR_DIRS); // only get dirs

  wxDateTime lastmodtime((time_t)0);
  const wxString append = fullpath.substr(start + len);

  bool found = false;

  // TODO: Use a thread for this.
  while (cont)
  {
    wxFileName fn(base + filename_string + append);

    if (fn.FileExists() &&
        fn.GetPath().CmpNoCase(filename.GetPath()) != 0 &&
        fn.GetModificationTime() != filename.GetModificationTime())
    {
      found = true;

      if (listview == NULL && lastfile == NULL)
      {
        // We are only interested in return value, so speed it up.
        return true;
      }

      if (listview != NULL)
      {
        ftListItem item(listview, fn.GetFullPath());
        item.Insert();
      }

      if (lastfile != NULL)
      {
        if (fn.GetModificationTime() > lastmodtime)
        {
          lastmodtime = fn.GetModificationTime();
          *lastfile = fn;
        }
      }
    }

    cont = dir.GetNext(&filename_string);

    wxTheApp->Yield();
  }

  if (!found && (listview != NULL || lastfile != NULL))
  {
    exFrame::StatusText(_("No files found"));
  }

  return found;
}

bool ftForEach(wxAuiNotebook* notebook, int id, const wxFont& font)
{
  for (
    size_t page = 0;
    page < notebook->GetPageCount();
    page++)
  {
    ftListView* lv = (ftListView*)notebook->GetPage(page);

    if (lv == NULL)
    {
      wxLogError(FILE_INFO("Notebook page: %d (%s) is not an ftListView"),
        page,
        notebook->GetPageText(page).c_str());
      return false;
    }

    if (id >= wxID_VIEW_DETAILS &&  id <= wxID_VIEW_LIST)
    {
      long view = 0;
      switch (id)
      {
      case wxID_VIEW_DETAILS: view = wxLC_REPORT; break;
      case wxID_VIEW_LIST: view = wxLC_LIST; break;
      case wxID_VIEW_SMALLICONS: view = wxLC_SMALL_ICON; break;
      default: wxLogError(FILE_INFO("Unhandled"));
      }

      lv->SetSingleStyle(view);
      exApp::GetConfig()->Set("List/Style", view);
    }
    else
    {
    switch (id)
    {
    case ID_LIST_ALL_ITEMS:
      {
        if (font.IsOk())
        {
          lv->SetFont(font);
        }

        lv->ItemsUpdate();
      }
      break;

    case ID_LIST_ALL_CLOSE:
      if (!lv->Continue()) return false;
      if (!notebook->DeletePage(page)) return false;
      break;

    default: wxLogError("Unhandled: %d (ID_TOOL_LOWEST: %d ID_TOOL_SQL: %d ID_LIST_LOWEST: %d",
      id, (int)ID_TOOL_LOWEST, (int)ID_TOOL_SQL, (int)ID_LIST_LOWEST);
    }
    }
  }

  return true;
}

void ftOpenFiles(
  ftFrame* frame,
  const wxArrayString& files,
  long flags)
{
  for (size_t i = 0; i < files.GetCount(); i++)
  {
    wxString file = files[i]; // cannot be const because of file = later on

    if (file.Contains("*") || file.Contains("?"))
    {
      ftDir dir(frame, wxGetCwd(), file, flags);
      dir.FindFiles();
    }
    else
    {
      int line = 0;

      if (file.Contains(":"))
      {
        line = atoi(files[i].AfterFirst(':').c_str());

        if (line != 0) // this indicates an error in the number
        {
          file = file.BeforeFirst(':');
        }
      }

      const exFileName filename(file);
      frame->OpenFile(filename, line, wxEmptyString, flags);
    }
  }
}

ftDir::ftDir(ftListView* listview,
  const wxString& fullpath, const wxString& filespec)
  : exDir(fullpath, filespec)
  , m_Statistics(fullpath)
  , m_Frame(NULL)
  , m_ListView(listview)
  , m_Flags(0)
  , m_RunningTool(false)
  , m_Tool(ID_TOOL_LOWEST)
{
}

ftDir::ftDir(ftFrame* frame,
  const wxString& fullpath, const wxString& filespec, long flags)
  : exDir(fullpath, filespec)
  , m_Statistics(fullpath)
  , m_Frame(frame)
  , m_ListView(NULL)
  , m_Flags(flags)
  , m_RunningTool(false)
  , m_Tool(ID_TOOL_LOWEST)
{
}

bool ftDir::Cancelled()
{
  // TODO: Implement.
  return false;
}

void ftDir::OnFile(const wxString& file)
{
  if (m_RunningTool)
  {
    const exFileName filename(file);

    if (filename.GetStat().IsOk())
    {
      ftTextFile report(filename);
      report.RunTool(m_Tool);
      m_Statistics += report.GetStatistics();
    }
  }
  else
  {
    if (m_Frame != NULL)
    {
      if (wxFileName::DirExists(file)) return;
      m_Frame->OpenFile(file, 0, wxEmptyString, m_Flags);
    }
    else
    {
      if (m_ListView != NULL)
      {
        ftListItem item(m_ListView, file, GetFileSpec());
        item.Insert();

        // Don't move next code into insert, as it itself inserts!
        if (m_ListView->GetType() == ftListView::LIST_VERSION)
        {
          ftListItem item(m_ListView, m_ListView->GetItemCount() - 1);

          ftTextFile report(item.m_Statistics);
          if (report.SetupTool(ID_TOOL_REVISION_RECENT))
          {
            report.RunTool(ID_TOOL_REVISION_RECENT);
            item.UpdateRevisionList(report.GetRCS());
          }
        }
      }
    }
  }
}

size_t ftDir::RunTool(const exTool& tool, int flags)
{
  m_Tool = tool;

  m_RunningTool = true;

  size_t result = FindFiles(flags);

  m_RunningTool = false;

  return result;
}

/// Offers a find combobox that allows you to find text
/// on a current STC on an ftFrame.
class ComboBox : public wxComboBox
{
public:
  /// Constructor. Fills the combobox box with values from FindReplace from config.
  ComboBox(
    wxWindow* parent,
    ftFrame* frame,
    wxWindowID id = wxID_ANY,
    const wxPoint& pos = wxDefaultPosition,
    const wxSize& size = wxDefaultSize);
private:
  void OnCommand(wxCommandEvent& event);
  void OnKey(wxKeyEvent& event);
  ftFrame* m_Frame;

  DECLARE_EVENT_TABLE()
};

BEGIN_EVENT_TABLE(ComboBox, wxComboBox)
  EVT_CHAR(ComboBox::OnKey)
  EVT_MENU(wxID_DELETE, ComboBox::OnCommand)
END_EVENT_TABLE()

ComboBox::ComboBox(
  wxWindow* parent,
  ftFrame* frame,
  wxWindowID id,
  const wxPoint& pos,
  const wxSize& size)
  : wxComboBox(parent, id, wxEmptyString, pos, size)
  , m_Frame(frame)
{
  const int accels = 1;
  wxAcceleratorEntry entries[accels];
  entries[0].Set(wxACCEL_NORMAL, WXK_DELETE, wxID_DELETE);
  wxAcceleratorTable accel(accels, entries);
  SetAcceleratorTable(accel);

  const wxFont font(
    exApp::GetConfig("FindFont", 8),
    wxFONTFAMILY_DEFAULT,
    wxFONTSTYLE_NORMAL,
    wxFONTWEIGHT_NORMAL);

  SetFont(font);

  exComboBoxFromString(this, exApp::GetConfig("FindReplace/FindStrings"));

  // And override the value set by previous, as we want text to be same as in Find.
  SetValue(exApp::GetConfig()->GetFindReplaceData()->GetFindString());
}

void ComboBox::OnCommand(wxCommandEvent& event)
{
  // README: The delete key default behaviour does not delete the char right from insertion point.
  // Instead, the event is sent to the editor and a char is deleted from the editor.
  // Therefore implement the delete here.
  if (event.GetId() == wxID_DELETE)
  {
    Remove(GetInsertionPoint(), GetInsertionPoint() + 1);
  }
  else
  {
    event.Skip();
  }
}

void ComboBox::OnKey(wxKeyEvent& event)
{
  const int key = event.GetKeyCode();

  if (key == WXK_RETURN)
  {
    ftSTC* stc = m_Frame->GetCurrentSTC();

    if (stc != NULL)
    {
      stc->FindNext(GetValue());
      exApp::GetConfig()->GetFindReplaceData()->SetFindString(GetValue());

      // And keep the changed text in the combo box.
      wxString text;

      if (exComboBoxToString(this, text))
      {
        exApp::GetConfig()->Set("FindReplace/FindStrings", text);
        Clear(); // so exComboBoxFromString can append again
        exComboBoxFromString(this, text);
        SetValue(exApp::GetConfig()->GetFindReplaceData()->GetFindString());
      }
    }
  }
  else
  {
    event.Skip();
  }
}

BEGIN_EVENT_TABLE(ftFindToolBar, wxAuiToolBar)
  EVT_CHECKBOX(ID_MATCH_WHOLE_WORD, ftFindToolBar::OnCommand)
  EVT_CHECKBOX(ID_MATCH_CASE, ftFindToolBar::OnCommand)
  EVT_CHECKBOX(ID_REGULAR_EXPRESSION, ftFindToolBar::OnCommand)
END_EVENT_TABLE()

ftFindToolBar::ftFindToolBar(
  wxWindow* parent,
  ftFrame* frame,
  wxWindowID id)
  : wxAuiToolBar(parent, id)
{
  m_MatchCase = new wxCheckBox(this, ID_MATCH_CASE, _("Match case"));
  m_MatchWholeWord = new wxCheckBox(this, ID_MATCH_WHOLE_WORD, _("Match whole word"));
  m_RegularExpression = new wxCheckBox(this, ID_REGULAR_EXPRESSION, _("Regular expression"));

  m_MatchCase->SetValue(exApp::GetConfig()->GetFindReplaceData()->MatchCase());
  m_MatchWholeWord->SetValue(exApp::GetConfig()->GetFindReplaceData()->MatchWord());
  m_RegularExpression->SetValue(exApp::GetConfig()->GetFindReplaceData()->IsRegExp());

#ifdef __WXMSW__
  const wxSize size(150, 20);
#else
  const wxSize size(150, -1);
#endif
  AddControl(new ComboBox(this, frame, ID_FIND_TEXT, wxDefaultPosition, size));
  AddSeparator();
  AddControl(m_MatchWholeWord);
  AddControl(m_MatchCase);
  AddControl(m_RegularExpression);

  Realize();
}

void ftFindToolBar::OnCommand(wxCommandEvent& event)
{
  switch (event.GetId())
  {
  case ID_MATCH_WHOLE_WORD:
  case ID_MATCH_CASE:
  case ID_REGULAR_EXPRESSION:
    exApp::GetConfig()->SetFindReplaceData(
      m_MatchWholeWord->GetValue(),
      m_MatchCase->GetValue(),
      m_RegularExpression->GetValue());
    break;
  }
}
<|endoftext|>


<commit_before>/**
   @file abstractsensor_a.cpp
   @brief D-Bus adaptor base class for sensors

   Copyright (C) 2009-2010 Nokia Corporation

   @author Semi Malinen <semi.malinen@nokia.com
   @author Joep van Gassel <joep.van.gassel@nokia.com>
   @author Timo Rongas <ext-timo.2.rongas@nokia.com>
   @author Antti Virtanen <antti.i.virtanen@nokia.com>

   This file is part of Sensord.

   Sensord is free software; you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License
   version 2.1 as published by the Free Software Foundation.

   Sensord 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 Sensord.  If not, see <http://www.gnu.org/licenses/>.

 */

#include "abstractsensor_a.h"
#include "sfwerror.h"
#include <sensormanager.h>
#include <sockethandler.h>

AbstractSensorChannelAdaptor::AbstractSensorChannelAdaptor(QObject *parent) :
    QDBusAbstractAdaptor(parent)
{
    setAutoRelaySignals(false); //disabling signals since no public client API supports the use of these
}

bool AbstractSensorChannelAdaptor::isValid() const
{
    return node()->isValid();
}

int AbstractSensorChannelAdaptor::errorCodeInt() const
{
    return node()->errorCodeInt();
}

QString AbstractSensorChannelAdaptor::errorString() const
{
    return node()->errorString();
}

QString AbstractSensorChannelAdaptor::description() const
{
    return node()->description();
}

QString AbstractSensorChannelAdaptor::id() const
{
    return node()->id();
}

unsigned int AbstractSensorChannelAdaptor::interval() const
{
    return node()->getInterval();
}

unsigned int AbstractSensorChannelAdaptor::bufferInterval() const
{
    return node()->bufferInterval();
}

unsigned int AbstractSensorChannelAdaptor::bufferSize() const
{
    return node()->bufferSize();
}

bool AbstractSensorChannelAdaptor::hwBuffering() const
{
    bool hwBuffering = false;
    node()->getAvailableBufferSizes(hwBuffering);
    return hwBuffering;
}

/*
SensorState AbstractSensorChannelAdaptor::state() const
{
    return node()->state();
}
*/

QString AbstractSensorChannelAdaptor::type() const
{
    return node()->type();
}

void AbstractSensorChannelAdaptor::start(int sessionId)
{
    node()->start(sessionId);
}

void AbstractSensorChannelAdaptor::stop(int sessionId)
{
    node()->stop(sessionId);
}

void AbstractSensorChannelAdaptor::setInterval(int sessionId, int value)
{
    node()->setIntervalRequest(sessionId, value);
    SensorManager::instance().socketHandler().setInterval(sessionId, value);
}

bool AbstractSensorChannelAdaptor::standbyOverride() const
{
    return node()->standbyOverride();
}

bool AbstractSensorChannelAdaptor::setStandbyOverride(int sessionId, bool value)
{
    return node()->setStandbyOverrideRequest(sessionId, value);
}

DataRangeList AbstractSensorChannelAdaptor::getAvailableDataRanges()
{
    return node()->getAvailableDataRanges();
}

DataRange AbstractSensorChannelAdaptor::getCurrentDataRange()
{
    return node()->getCurrentDataRange().range;
}

void AbstractSensorChannelAdaptor::requestDataRange(int sessionId, DataRange range)
{
    node()->requestDataRange(sessionId, range);
}

void AbstractSensorChannelAdaptor::removeDataRangeRequest(int sessionId)
{
    node()->removeDataRangeRequest(sessionId);
}

DataRangeList AbstractSensorChannelAdaptor::getAvailableIntervals()
{
    return node()->getAvailableIntervals();
}

bool AbstractSensorChannelAdaptor::setDefaultInterval(int sessionId)
{
    bool ok = node()->requestDefaultInterval(sessionId);
    SensorManager::instance().socketHandler().clearInterval(sessionId);
    return ok;
}

void AbstractSensorChannelAdaptor::setBufferInterval(int sessionId, unsigned int value)
{
    bool hwBuffering = false;
    node()->getAvailableBufferIntervals(hwBuffering);
    if(hwBuffering)
    {
        if(value == 0)
            node()->clearBufferInterval(sessionId);
        else
            node()->setBufferInterval(sessionId, value);
        value = 0;
    }
    if(value == 0)
        SensorManager::instance().socketHandler().clearBufferInterval(sessionId);
    else
        SensorManager::instance().socketHandler().setBufferInterval(sessionId, value);
}

void AbstractSensorChannelAdaptor::setBufferSize(int sessionId, unsigned int value)
{
    bool hwBuffering = false;
    node()->getAvailableBufferSizes(hwBuffering);
    if(hwBuffering)
    {
        if(value == 0)
            node()->clearBufferSize(sessionId);
        else
            node()->setBufferSize(sessionId, value);
    }
    if(value == 0)
        SensorManager::instance().socketHandler().clearBufferSize(sessionId);
    else
        SensorManager::instance().socketHandler().setBufferSize(sessionId, value);
}

IntegerRangeList AbstractSensorChannelAdaptor::getAvailableBufferIntervals() const
{
    bool dummy;
    return node()->getAvailableBufferIntervals(dummy);
}

IntegerRangeList AbstractSensorChannelAdaptor::getAvailableBufferSizes() const
{
    bool dummy;
    return node()->getAvailableBufferSizes(dummy);
}

AbstractSensorChannel* AbstractSensorChannelAdaptor::node() const
{
    return dynamic_cast<AbstractSensorChannel*>(parent());
}

bool AbstractSensorChannelAdaptor::setDataRangeIndex(int sessionId, int rangeIndex)
{
    node()->setDataRangeIndex(sessionId, rangeIndex);
}
<commit_msg>Fixed AbstractSensorChannelAdaptor::setDataRangeIndex(): non-void but didn't return anything.<commit_after>/**
   @file abstractsensor_a.cpp
   @brief D-Bus adaptor base class for sensors

   Copyright (C) 2009-2010 Nokia Corporation

   @author Semi Malinen <semi.malinen@nokia.com
   @author Joep van Gassel <joep.van.gassel@nokia.com>
   @author Timo Rongas <ext-timo.2.rongas@nokia.com>
   @author Antti Virtanen <antti.i.virtanen@nokia.com>

   This file is part of Sensord.

   Sensord is free software; you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License
   version 2.1 as published by the Free Software Foundation.

   Sensord 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 Sensord.  If not, see <http://www.gnu.org/licenses/>.

 */

#include "abstractsensor_a.h"
#include "sfwerror.h"
#include <sensormanager.h>
#include <sockethandler.h>

AbstractSensorChannelAdaptor::AbstractSensorChannelAdaptor(QObject *parent) :
    QDBusAbstractAdaptor(parent)
{
    setAutoRelaySignals(false); //disabling signals since no public client API supports the use of these
}

bool AbstractSensorChannelAdaptor::isValid() const
{
    return node()->isValid();
}

int AbstractSensorChannelAdaptor::errorCodeInt() const
{
    return node()->errorCodeInt();
}

QString AbstractSensorChannelAdaptor::errorString() const
{
    return node()->errorString();
}

QString AbstractSensorChannelAdaptor::description() const
{
    return node()->description();
}

QString AbstractSensorChannelAdaptor::id() const
{
    return node()->id();
}

unsigned int AbstractSensorChannelAdaptor::interval() const
{
    return node()->getInterval();
}

unsigned int AbstractSensorChannelAdaptor::bufferInterval() const
{
    return node()->bufferInterval();
}

unsigned int AbstractSensorChannelAdaptor::bufferSize() const
{
    return node()->bufferSize();
}

bool AbstractSensorChannelAdaptor::hwBuffering() const
{
    bool hwBuffering = false;
    node()->getAvailableBufferSizes(hwBuffering);
    return hwBuffering;
}

/*
SensorState AbstractSensorChannelAdaptor::state() const
{
    return node()->state();
}
*/

QString AbstractSensorChannelAdaptor::type() const
{
    return node()->type();
}

void AbstractSensorChannelAdaptor::start(int sessionId)
{
    node()->start(sessionId);
}

void AbstractSensorChannelAdaptor::stop(int sessionId)
{
    node()->stop(sessionId);
}

void AbstractSensorChannelAdaptor::setInterval(int sessionId, int value)
{
    node()->setIntervalRequest(sessionId, value);
    SensorManager::instance().socketHandler().setInterval(sessionId, value);
}

bool AbstractSensorChannelAdaptor::standbyOverride() const
{
    return node()->standbyOverride();
}

bool AbstractSensorChannelAdaptor::setStandbyOverride(int sessionId, bool value)
{
    return node()->setStandbyOverrideRequest(sessionId, value);
}

DataRangeList AbstractSensorChannelAdaptor::getAvailableDataRanges()
{
    return node()->getAvailableDataRanges();
}

DataRange AbstractSensorChannelAdaptor::getCurrentDataRange()
{
    return node()->getCurrentDataRange().range;
}

void AbstractSensorChannelAdaptor::requestDataRange(int sessionId, DataRange range)
{
    node()->requestDataRange(sessionId, range);
}

void AbstractSensorChannelAdaptor::removeDataRangeRequest(int sessionId)
{
    node()->removeDataRangeRequest(sessionId);
}

DataRangeList AbstractSensorChannelAdaptor::getAvailableIntervals()
{
    return node()->getAvailableIntervals();
}

bool AbstractSensorChannelAdaptor::setDefaultInterval(int sessionId)
{
    bool ok = node()->requestDefaultInterval(sessionId);
    SensorManager::instance().socketHandler().clearInterval(sessionId);
    return ok;
}

void AbstractSensorChannelAdaptor::setBufferInterval(int sessionId, unsigned int value)
{
    bool hwBuffering = false;
    node()->getAvailableBufferIntervals(hwBuffering);
    if(hwBuffering)
    {
        if(value == 0)
            node()->clearBufferInterval(sessionId);
        else
            node()->setBufferInterval(sessionId, value);
        value = 0;
    }
    if(value == 0)
        SensorManager::instance().socketHandler().clearBufferInterval(sessionId);
    else
        SensorManager::instance().socketHandler().setBufferInterval(sessionId, value);
}

void AbstractSensorChannelAdaptor::setBufferSize(int sessionId, unsigned int value)
{
    bool hwBuffering = false;
    node()->getAvailableBufferSizes(hwBuffering);
    if(hwBuffering)
    {
        if(value == 0)
            node()->clearBufferSize(sessionId);
        else
            node()->setBufferSize(sessionId, value);
    }
    if(value == 0)
        SensorManager::instance().socketHandler().clearBufferSize(sessionId);
    else
        SensorManager::instance().socketHandler().setBufferSize(sessionId, value);
}

IntegerRangeList AbstractSensorChannelAdaptor::getAvailableBufferIntervals() const
{
    bool dummy;
    return node()->getAvailableBufferIntervals(dummy);
}

IntegerRangeList AbstractSensorChannelAdaptor::getAvailableBufferSizes() const
{
    bool dummy;
    return node()->getAvailableBufferSizes(dummy);
}

AbstractSensorChannel* AbstractSensorChannelAdaptor::node() const
{
    return dynamic_cast<AbstractSensorChannel*>(parent());
}

bool AbstractSensorChannelAdaptor::setDataRangeIndex(int sessionId, int rangeIndex)
{
    return node()->setDataRangeIndex(sessionId, rangeIndex);
}
<|endoftext|>


<commit_before>// @(#)root/base:$Id$
// Author: Fons Rademakers   04/05/96

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TBuffer                                                              //
//                                                                      //
// Buffer base class used for serializing objects.                      //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TBuffer.h"
#include "TClass.h"
#include "TProcessID.h"

const Int_t  kExtraSpace        = 8;   // extra space at end of buffer (used for free block count)

ClassImp(TBuffer)

//______________________________________________________________________________
static char *R__NoReAllocChar(char *, size_t, size_t)
{
   // The user has provided memory than we don't own, thus we can not extent it
   // either.
   return 0;
}

//______________________________________________________________________________
static inline ULong_t Void_Hash(const void *ptr)
{
   // Return hash value for this object.

   return TString::Hash(&ptr, sizeof(void*));
}

//______________________________________________________________________________
TBuffer::TBuffer(EMode mode)
{
   // Create an I/O buffer object. Mode should be either TBuffer::kRead or
   // TBuffer::kWrite. By default the I/O buffer has a size of
   // TBuffer::kInitialSize (1024) bytes.

   fBufSize      = kInitialSize;
   fMode         = mode;
   fVersion      = 0;
   fParent       = 0;

   SetBit(kIsOwner);

   fBuffer = new char[fBufSize+kExtraSpace];

   fBufCur = fBuffer;
   fBufMax = fBuffer + fBufSize;

   SetReAllocFunc( 0 );
}

//______________________________________________________________________________
TBuffer::TBuffer(EMode mode, Int_t bufsiz)
{
   // Create an I/O buffer object. Mode should be either TBuffer::kRead or
   // TBuffer::kWrite.

   if (bufsiz < kMinimalSize) bufsiz = kMinimalSize;
   fBufSize  = bufsiz;
   fMode     = mode;
   fVersion  = 0;
   fParent   = 0;

   SetBit(kIsOwner);

   fBuffer = new char[fBufSize+kExtraSpace];

   fBufCur = fBuffer;
   fBufMax = fBuffer + fBufSize;

   SetReAllocFunc( 0 );
}

//______________________________________________________________________________
TBuffer::TBuffer(EMode mode, Int_t bufsiz, void *buf, Bool_t adopt, ReAllocCharFun_t reallocfunc)
{
   // Create an I/O buffer object. Mode should be either TBuffer::kRead or
   // TBuffer::kWrite. By default the I/O buffer has a size of
   // TBuffer::kInitialSize (1024) bytes. An external buffer can be passed
   // to TBuffer via the buf argument. By default this buffer will be adopted
   // unless adopt is false.
   // If the new buffer is _not_ adopted and no memory allocation routine
   // is provided, a Fatal error will be issued if the Buffer attempts to
   // expand.

   fBufSize  = bufsiz;
   fMode     = mode;
   fVersion  = 0;
   fParent   = 0;

   SetBit(kIsOwner);

   if (buf) {
      fBuffer = (char *)buf;
      if ( (fMode&kWrite)!=0 ) {
         fBufSize -= kExtraSpace;
      }
      if (!adopt) ResetBit(kIsOwner);
   } else {
      if (fBufSize < kMinimalSize) {
         fBufSize = kMinimalSize;
      }
      fBuffer = new char[fBufSize+kExtraSpace];
   }
   fBufCur = fBuffer;
   fBufMax = fBuffer + fBufSize;

   SetReAllocFunc( reallocfunc );

   if (buf && ( (fMode&kWrite)!=0 ) && fBufSize < 0) {
      Expand( kMinimalSize );
   }
}

//______________________________________________________________________________
TBuffer::~TBuffer()
{
   // Delete an I/O buffer object.

   if (TestBit(kIsOwner)) {
      //printf("Deleting fBuffer=%lx\n", fBuffer);
      delete [] fBuffer;
   }
   fBuffer = 0;
   fParent = 0;
}

//______________________________________________________________________________
void TBuffer::SetBuffer(void *buf, UInt_t newsiz, Bool_t adopt, ReAllocCharFun_t reallocfunc)
{
   // Sets a new buffer in an existing TBuffer object. If newsiz=0 then the
   // new buffer is expected to have the same size as the previous buffer.
   // The current buffer position is reset to the start of the buffer.
   // If the TBuffer owned the previous buffer, it will be deleted prior
   // to accepting the new buffer. By default the new buffer will be
   // adopted unless adopt is false.
   // If the new buffer is _not_ adopted and no memory allocation routine
   // is provided, a Fatal error will be issued if the Buffer attempts to
   // expand.

   if (fBuffer && TestBit(kIsOwner))
      delete [] fBuffer;

   if (adopt)
      SetBit(kIsOwner);
   else
      ResetBit(kIsOwner);

   fBuffer = (char *)buf;
   fBufCur = fBuffer;
   if (newsiz > 0) {
      fBufSize = newsiz - kExtraSpace;
   }
   fBufMax = fBuffer + fBufSize;

   SetReAllocFunc( reallocfunc );

   if (buf && ( (fMode&kWrite)!=0 ) && fBufSize < 0) {
      Expand( kMinimalSize );
   }
}

//______________________________________________________________________________
void TBuffer::Expand(Int_t newsize)
{
   // Expand the I/O buffer to newsize bytes.

   Int_t l  = Length();
   fBuffer  = fReAllocFunc(fBuffer, newsize+kExtraSpace,
                           fBufSize+kExtraSpace);
   if (fBuffer == 0) {
      if (fReAllocFunc == TStorage::ReAllocChar) {
         Fatal("Expand","Failed to expand the data buffer using TStorage::ReAllocChar.");
      } if (fReAllocFunc == R__NoReAllocChar) {
         Fatal("Expand","Failed to expand the data buffer because TBuffer does not own it and no custom memory reallocator was provided.");
      } else {
         Fatal("Expand","Failed to expand the data buffer using custom memory reallocator 0x%lx.", fReAllocFunc);
      }
   }
   fBufSize = newsize;
   fBufCur  = fBuffer + l;
   fBufMax  = fBuffer + fBufSize;
}

//______________________________________________________________________________
TObject *TBuffer::GetParent() const
{
   // Return pointer to parent of this buffer.

   return fParent;
}

//______________________________________________________________________________
void TBuffer::SetParent(TObject *parent)
{
   // Set parent owning this buffer.

   fParent = parent;
}
//______________________________________________________________________________
ReAllocCharFun_t TBuffer::GetReAllocFunc() const
{
   // Return the reallocation method currently used.
   return fReAllocFunc;
}

//______________________________________________________________________________
void  TBuffer::SetReAllocFunc(ReAllocCharFun_t reallocfunc )
{
   // Set which memory reallocation method to use.  If reallocafunc is null,
   // reset it to the defaul value (TStorage::ReAlloc)

   if (reallocfunc) {
      fReAllocFunc = reallocfunc;
   } else {
      if (TestBit(kIsOwner)) {
         fReAllocFunc = TStorage::ReAllocChar;
      } else {
         fReAllocFunc = R__NoReAllocChar;
      }
   }
}

//______________________________________________________________________________
void TBuffer::SetReadMode()
{
   // Set buffer in read mode.

   fMode = kRead;
}

//______________________________________________________________________________
void TBuffer::SetWriteMode()
{
   // Set buffer in write mode.

   fMode = kWrite;
}

//______________________________________________________________________________
TClass *TBuffer::GetClass(const type_info &typeinfo)
{
   // Forward to TROOT::GetClass().

   return TClass::GetClass(typeinfo);
}

//______________________________________________________________________________
TClass *TBuffer::GetClass(const char *className)
{
   // Forward to TROOT::GetClass().

   return TClass::GetClass(className);
}

//______________________________________________________________________________
TProcessID *TBuffer::ReadProcessID(UShort_t pidf)
{
   // Return the current PRocessID.

   if (!pidf) return TProcessID::GetPID(); //may happen when cloning an object
   return 0;
}

//______________________________________________________________________________
UShort_t TBuffer::WriteProcessID(TProcessID *)
{
   // Always return 0 (current processID).

   return 0;
}
<commit_msg>In SetBuffer do not 'tweak' the buffer size in read mode.<commit_after>// @(#)root/base:$Id$
// Author: Fons Rademakers   04/05/96

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TBuffer                                                              //
//                                                                      //
// Buffer base class used for serializing objects.                      //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TBuffer.h"
#include "TClass.h"
#include "TProcessID.h"

const Int_t  kExtraSpace        = 8;   // extra space at end of buffer (used for free block count)

ClassImp(TBuffer)

//______________________________________________________________________________
static char *R__NoReAllocChar(char *, size_t, size_t)
{
   // The user has provided memory than we don't own, thus we can not extent it
   // either.
   return 0;
}

//______________________________________________________________________________
static inline ULong_t Void_Hash(const void *ptr)
{
   // Return hash value for this object.

   return TString::Hash(&ptr, sizeof(void*));
}

//______________________________________________________________________________
TBuffer::TBuffer(EMode mode)
{
   // Create an I/O buffer object. Mode should be either TBuffer::kRead or
   // TBuffer::kWrite. By default the I/O buffer has a size of
   // TBuffer::kInitialSize (1024) bytes.

   fBufSize      = kInitialSize;
   fMode         = mode;
   fVersion      = 0;
   fParent       = 0;

   SetBit(kIsOwner);

   fBuffer = new char[fBufSize+kExtraSpace];

   fBufCur = fBuffer;
   fBufMax = fBuffer + fBufSize;

   SetReAllocFunc( 0 );
}

//______________________________________________________________________________
TBuffer::TBuffer(EMode mode, Int_t bufsiz)
{
   // Create an I/O buffer object. Mode should be either TBuffer::kRead or
   // TBuffer::kWrite.

   if (bufsiz < kMinimalSize) bufsiz = kMinimalSize;
   fBufSize  = bufsiz;
   fMode     = mode;
   fVersion  = 0;
   fParent   = 0;

   SetBit(kIsOwner);

   fBuffer = new char[fBufSize+kExtraSpace];

   fBufCur = fBuffer;
   fBufMax = fBuffer + fBufSize;

   SetReAllocFunc( 0 );
}

//______________________________________________________________________________
TBuffer::TBuffer(EMode mode, Int_t bufsiz, void *buf, Bool_t adopt, ReAllocCharFun_t reallocfunc)
{
   // Create an I/O buffer object. Mode should be either TBuffer::kRead or
   // TBuffer::kWrite. By default the I/O buffer has a size of
   // TBuffer::kInitialSize (1024) bytes. An external buffer can be passed
   // to TBuffer via the buf argument. By default this buffer will be adopted
   // unless adopt is false.
   // If the new buffer is _not_ adopted and no memory allocation routine
   // is provided, a Fatal error will be issued if the Buffer attempts to
   // expand.

   fBufSize  = bufsiz;
   fMode     = mode;
   fVersion  = 0;
   fParent   = 0;

   SetBit(kIsOwner);

   if (buf) {
      fBuffer = (char *)buf;
      if ( (fMode&kWrite)!=0 ) {
         fBufSize -= kExtraSpace;
      }
      if (!adopt) ResetBit(kIsOwner);
   } else {
      if (fBufSize < kMinimalSize) {
         fBufSize = kMinimalSize;
      }
      fBuffer = new char[fBufSize+kExtraSpace];
   }
   fBufCur = fBuffer;
   fBufMax = fBuffer + fBufSize;

   SetReAllocFunc( reallocfunc );

   if (buf && ( (fMode&kWrite)!=0 ) && fBufSize < 0) {
      Expand( kMinimalSize );
   }
}

//______________________________________________________________________________
TBuffer::~TBuffer()
{
   // Delete an I/O buffer object.

   if (TestBit(kIsOwner)) {
      //printf("Deleting fBuffer=%lx\n", fBuffer);
      delete [] fBuffer;
   }
   fBuffer = 0;
   fParent = 0;
}

//______________________________________________________________________________
void TBuffer::SetBuffer(void *buf, UInt_t newsiz, Bool_t adopt, ReAllocCharFun_t reallocfunc)
{
   // Sets a new buffer in an existing TBuffer object. If newsiz=0 then the
   // new buffer is expected to have the same size as the previous buffer.
   // The current buffer position is reset to the start of the buffer.
   // If the TBuffer owned the previous buffer, it will be deleted prior
   // to accepting the new buffer. By default the new buffer will be
   // adopted unless adopt is false.
   // If the new buffer is _not_ adopted and no memory allocation routine
   // is provided, a Fatal error will be issued if the Buffer attempts to
   // expand.

   if (fBuffer && TestBit(kIsOwner))
      delete [] fBuffer;

   if (adopt)
      SetBit(kIsOwner);
   else
      ResetBit(kIsOwner);

   fBuffer = (char *)buf;
   fBufCur = fBuffer;
   if (newsiz > 0) {
      if ( (fMode&kWrite)!=0 ) {
         fBufSize = newsiz - kExtraSpace;
      } else {
         fBufSize = newsiz;
      }
   }
   fBufMax = fBuffer + fBufSize;

   SetReAllocFunc( reallocfunc );

   if (buf && ( (fMode&kWrite)!=0 ) && fBufSize < 0) {
      Expand( kMinimalSize );
   }
}

//______________________________________________________________________________
void TBuffer::Expand(Int_t newsize)
{
   // Expand the I/O buffer to newsize bytes.

   Int_t l  = Length();
   fBuffer  = fReAllocFunc(fBuffer, newsize+kExtraSpace,
                           fBufSize+kExtraSpace);
   if (fBuffer == 0) {
      if (fReAllocFunc == TStorage::ReAllocChar) {
         Fatal("Expand","Failed to expand the data buffer using TStorage::ReAllocChar.");
      } if (fReAllocFunc == R__NoReAllocChar) {
         Fatal("Expand","Failed to expand the data buffer because TBuffer does not own it and no custom memory reallocator was provided.");
      } else {
         Fatal("Expand","Failed to expand the data buffer using custom memory reallocator 0x%lx.", fReAllocFunc);
      }
   }
   fBufSize = newsize;
   fBufCur  = fBuffer + l;
   fBufMax  = fBuffer + fBufSize;
}

//______________________________________________________________________________
TObject *TBuffer::GetParent() const
{
   // Return pointer to parent of this buffer.

   return fParent;
}

//______________________________________________________________________________
void TBuffer::SetParent(TObject *parent)
{
   // Set parent owning this buffer.

   fParent = parent;
}
//______________________________________________________________________________
ReAllocCharFun_t TBuffer::GetReAllocFunc() const
{
   // Return the reallocation method currently used.
   return fReAllocFunc;
}

//______________________________________________________________________________
void  TBuffer::SetReAllocFunc(ReAllocCharFun_t reallocfunc )
{
   // Set which memory reallocation method to use.  If reallocafunc is null,
   // reset it to the defaul value (TStorage::ReAlloc)

   if (reallocfunc) {
      fReAllocFunc = reallocfunc;
   } else {
      if (TestBit(kIsOwner)) {
         fReAllocFunc = TStorage::ReAllocChar;
      } else {
         fReAllocFunc = R__NoReAllocChar;
      }
   }
}

//______________________________________________________________________________
void TBuffer::SetReadMode()
{
   // Set buffer in read mode.

   fMode = kRead;
}

//______________________________________________________________________________
void TBuffer::SetWriteMode()
{
   // Set buffer in write mode.

   fMode = kWrite;
}

//______________________________________________________________________________
TClass *TBuffer::GetClass(const type_info &typeinfo)
{
   // Forward to TROOT::GetClass().

   return TClass::GetClass(typeinfo);
}

//______________________________________________________________________________
TClass *TBuffer::GetClass(const char *className)
{
   // Forward to TROOT::GetClass().

   return TClass::GetClass(className);
}

//______________________________________________________________________________
TProcessID *TBuffer::ReadProcessID(UShort_t pidf)
{
   // Return the current PRocessID.

   if (!pidf) return TProcessID::GetPID(); //may happen when cloning an object
   return 0;
}

//______________________________________________________________________________
UShort_t TBuffer::WriteProcessID(TProcessID *)
{
   // Always return 0 (current processID).

   return 0;
}
<|endoftext|>


<commit_before>#include "command.hh"
#include "globals.hh"
#include "eval.hh"
#include "eval-inline.hh"
#include "names.hh"
#include "get-drvs.hh"
#include "common-args.hh"
#include "json.hh"
#include "json-to-value.hh"
#include "shared.hh"

#include <regex>
#include <fstream>

using namespace nix;

std::string wrap(std::string prefix, std::string s)
{
    return prefix + s + ANSI_NORMAL;
}

std::string hilite(const std::string & s, const std::smatch & m, std::string postfix)
{
    return
        m.empty()
        ? s
        : std::string(m.prefix())
          + ANSI_RED + std::string(m.str()) + postfix
          + std::string(m.suffix());
}

struct CmdSearch : SourceExprCommand, MixJSON
{
    std::vector<std::string> res;

    bool writeCache = true;
    bool useCache = true;
    bool attrPathOnly = false;

    CmdSearch()
    {
        expectArgs("regex", &res);

        mkFlag()
            .longName("update-cache")
            .shortName('u')
            .description("update the package search cache")
            .handler([&]() { writeCache = true; useCache = false; });

        mkFlag()
            .longName("no-cache")
            .description("do not use or update the package search cache")
            .handler([&]() { writeCache = false; useCache = false; });

        mkFlag()
            .longName("attr-path")
            .shortName('A')
            .description("Only search for attribute paths")
            .handler([&]() { attrPathOnly = true; });
    }

    std::string name() override
    {
        return "search";
    }

    std::string description() override
    {
        return "query available packages";
    }

    Examples examples() override
    {
        return {
            Example{
                "To show all available packages:",
                "nix search"
            },
            Example{
                "To show any packages containing 'blender' in its name or description:",
                "nix search blender"
            },
            Example{
                "To search for Firefox or Chromium:",
                "nix search 'firefox|chromium'"
            },
            Example{
                "To search for git and frontend or gui:",
                "nix search git 'frontend|gui'"
            },
            Example{
                "Only search for attribute paths:",
                "nix search -A git"
            }
        };
    }

    void run(ref<Store> store) override
    {
        settings.readOnlyMode = true;

        // Empty search string should match all packages
        // Use "^" here instead of ".*" due to differences in resulting highlighting
        // (see #1893 -- libc++ claims empty search string is not in POSIX grammar)
        if (res.empty()) {
            res.push_back("^");
        }

        std::vector<std::regex> regexes;
        regexes.reserve(res.size());

        for (auto &re : res) {
            regexes.push_back(std::regex(re, std::regex::extended | std::regex::icase));
        }

        auto state = getEvalState();

        auto jsonOut = json ? std::make_unique<JSONObject>(std::cout) : nullptr;

        auto sToplevel = state->symbols.create("_toplevel");
        auto sRecurse = state->symbols.create("recurseForDerivations");

        bool fromCache = false;

        std::map<std::string, std::string> results;

        std::function<void(Value *, std::string, bool, JSONObject *)> doExpr;

        doExpr = [&](Value * v, std::string attrPath, bool toplevel, JSONObject * cache) {
            debug("at attribute '%s'", attrPath);

            try {
                uint found = 0;

                state->forceValue(*v);

                if (v->type == tLambda && toplevel) {
                    Value * v2 = state->allocValue();
                    state->autoCallFunction(*state->allocBindings(1), *v, *v2);
                    v = v2;
                    state->forceValue(*v);
                }

                if (state->isDerivation(*v)) {

                    DrvInfo drv(*state, attrPath, v->attrs);
                    std::string description;
                    std::smatch attrPathMatch;
                    std::smatch descriptionMatch;
                    std::smatch nameMatch;
                    std::string name;

                    DrvName parsed(drv.queryName());

                    for (auto &regex : regexes) {
                        description = drv.queryMetaString("description");
                        std::regex_search(attrPath, attrPathMatch, regex);
                        if (attrPathOnly) {
                            if (!attrPathMatch.empty()) found++;
                            continue;
                        }

                        name = parsed.name;
                        std::regex_search(name, nameMatch, regex);

                        std::replace(description.begin(), description.end(), '\n', ' ');
                        std::regex_search(description, descriptionMatch, regex);

                        if (!attrPathMatch.empty()
                            || !nameMatch.empty()
                            || !descriptionMatch.empty())
                        {
                            found++;
                        }
                    }

                    if (found == res.size()) {
                        if (json) {

                            auto jsonElem = jsonOut->object(attrPath);

                            jsonElem.attr("pkgName", parsed.name);
                            jsonElem.attr("version", parsed.version);
                            jsonElem.attr("description", description);

                        } else {
                            auto display_description =
                                description.empty() ? "\e[3mNo description\e[23m" : description;
                            auto name = hilite(parsed.name, nameMatch, "\e[0;2m")
                                + std::string(parsed.fullName, parsed.name.length());
                            results[attrPath] = fmt(
                                "* %s (%s)\n  %s\n",
                                wrap("\e[0;1m", hilite(attrPath, attrPathMatch, "\e[0;1m")),
                                wrap("\e[0;2m", name),
                                hilite(display_description, descriptionMatch, ANSI_NORMAL));
                        }
                    }

                    if (cache) {
                        cache->attr("type", "derivation");
                        cache->attr("name", drv.queryName());
                        cache->attr("system", drv.querySystem());
                        if (description != "") {
                            auto meta(cache->object("meta"));
                            meta.attr("description", description);
                        }
                    }
                }

                else if (v->type == tAttrs) {

                    if (!toplevel) {
                        auto attrs = v->attrs;
                        Bindings::iterator j = attrs->find(sRecurse);
                        if (j == attrs->end() || !state->forceBool(*j->value, *j->pos)) {
                            debug("skip attribute '%s'", attrPath);
                            return;
                        }
                    }

                    bool toplevel2 = false;
                    if (!fromCache) {
                        Bindings::iterator j = v->attrs->find(sToplevel);
                        toplevel2 = j != v->attrs->end() && state->forceBool(*j->value, *j->pos);
                    }

                    for (auto & i : *v->attrs) {
                        auto cache2 =
                            cache ? std::make_unique<JSONObject>(cache->object(i.name)) : nullptr;
                        doExpr(i.value,
                            attrPath == "" ? (std::string) i.name : attrPath + "." + (std::string) i.name,
                            toplevel2 || fromCache, cache2 ? cache2.get() : nullptr);
                    }
                }

            } catch (AssertionError & e) {
            } catch (Error & e) {
                if (!toplevel) {
                    e.addPrefix(fmt("While evaluating the attribute '%s':\n", attrPath));
                    debug("warning: %s", e.what());
                    // don't throw, try other attrs
                }
            }
        };

        Path jsonCacheFileName = getCacheDir() + "/nix/package-search.json";

        if (useCache && pathExists(jsonCacheFileName)) {

            warn("using cached results; pass '-u' to update the cache");

            Value vRoot;
            parseJSON(*state, readFile(jsonCacheFileName), vRoot);

            fromCache = true;

            doExpr(&vRoot, "", true, nullptr);
        }

        else {
            createDirs(dirOf(jsonCacheFileName));

            Path tmpFile = fmt("%s.tmp.%d", jsonCacheFileName, getpid());

            std::ofstream jsonCacheFile;

            try {
                // iostream considered harmful
                jsonCacheFile.exceptions(std::ofstream::failbit);
                jsonCacheFile.open(tmpFile);

                auto cache = writeCache ? std::make_unique<JSONObject>(jsonCacheFile, false) : nullptr;

                doExpr(getSourceExpr(*state), "", true, cache.get());

            } catch (std::exception &) {
                /* Fun fact: catching std::ios::failure does not work
                   due to C++11 ABI shenanigans.
                   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66145 */
                if (!jsonCacheFile)
                    throw Error("error writing to %s", tmpFile);
                throw;
            }

            if (writeCache && rename(tmpFile.c_str(), jsonCacheFileName.c_str()) == -1)
                throw SysError("cannot rename '%s' to '%s'", tmpFile, jsonCacheFileName);
        }

        if (!json) {
            if (results.size() == 0)
                throw Error("no results for the given search term(s)!");

            RunPager pager;
            for (auto el : results) std::cout << el.second << "\n";
        }

    }
};

static RegisterCommand r1(make_ref<CmdSearch>());
<commit_msg>nix search: optimize search regex, used many times<commit_after>#include "command.hh"
#include "globals.hh"
#include "eval.hh"
#include "eval-inline.hh"
#include "names.hh"
#include "get-drvs.hh"
#include "common-args.hh"
#include "json.hh"
#include "json-to-value.hh"
#include "shared.hh"

#include <regex>
#include <fstream>

using namespace nix;

std::string wrap(std::string prefix, std::string s)
{
    return prefix + s + ANSI_NORMAL;
}

std::string hilite(const std::string & s, const std::smatch & m, std::string postfix)
{
    return
        m.empty()
        ? s
        : std::string(m.prefix())
          + ANSI_RED + std::string(m.str()) + postfix
          + std::string(m.suffix());
}

struct CmdSearch : SourceExprCommand, MixJSON
{
    std::vector<std::string> res;

    bool writeCache = true;
    bool useCache = true;
    bool attrPathOnly = false;

    CmdSearch()
    {
        expectArgs("regex", &res);

        mkFlag()
            .longName("update-cache")
            .shortName('u')
            .description("update the package search cache")
            .handler([&]() { writeCache = true; useCache = false; });

        mkFlag()
            .longName("no-cache")
            .description("do not use or update the package search cache")
            .handler([&]() { writeCache = false; useCache = false; });

        mkFlag()
            .longName("attr-path")
            .shortName('A')
            .description("Only search for attribute paths")
            .handler([&]() { attrPathOnly = true; });
    }

    std::string name() override
    {
        return "search";
    }

    std::string description() override
    {
        return "query available packages";
    }

    Examples examples() override
    {
        return {
            Example{
                "To show all available packages:",
                "nix search"
            },
            Example{
                "To show any packages containing 'blender' in its name or description:",
                "nix search blender"
            },
            Example{
                "To search for Firefox or Chromium:",
                "nix search 'firefox|chromium'"
            },
            Example{
                "To search for git and frontend or gui:",
                "nix search git 'frontend|gui'"
            },
            Example{
                "Only search for attribute paths:",
                "nix search -A git"
            }
        };
    }

    void run(ref<Store> store) override
    {
        settings.readOnlyMode = true;

        // Empty search string should match all packages
        // Use "^" here instead of ".*" due to differences in resulting highlighting
        // (see #1893 -- libc++ claims empty search string is not in POSIX grammar)
        if (res.empty()) {
            res.push_back("^");
        }

        std::vector<std::regex> regexes;
        regexes.reserve(res.size());

        for (auto &re : res) {
            regexes.push_back(std::regex(re, std::regex::extended | std::regex::icase | std::regex::optimize));
        }

        auto state = getEvalState();

        auto jsonOut = json ? std::make_unique<JSONObject>(std::cout) : nullptr;

        auto sToplevel = state->symbols.create("_toplevel");
        auto sRecurse = state->symbols.create("recurseForDerivations");

        bool fromCache = false;

        std::map<std::string, std::string> results;

        std::function<void(Value *, std::string, bool, JSONObject *)> doExpr;

        doExpr = [&](Value * v, std::string attrPath, bool toplevel, JSONObject * cache) {
            debug("at attribute '%s'", attrPath);

            try {
                uint found = 0;

                state->forceValue(*v);

                if (v->type == tLambda && toplevel) {
                    Value * v2 = state->allocValue();
                    state->autoCallFunction(*state->allocBindings(1), *v, *v2);
                    v = v2;
                    state->forceValue(*v);
                }

                if (state->isDerivation(*v)) {

                    DrvInfo drv(*state, attrPath, v->attrs);
                    std::string description;
                    std::smatch attrPathMatch;
                    std::smatch descriptionMatch;
                    std::smatch nameMatch;
                    std::string name;

                    DrvName parsed(drv.queryName());

                    for (auto &regex : regexes) {
                        description = drv.queryMetaString("description");
                        std::regex_search(attrPath, attrPathMatch, regex);
                        if (attrPathOnly) {
                            if (!attrPathMatch.empty()) found++;
                            continue;
                        }

                        name = parsed.name;
                        std::regex_search(name, nameMatch, regex);

                        std::replace(description.begin(), description.end(), '\n', ' ');
                        std::regex_search(description, descriptionMatch, regex);

                        if (!attrPathMatch.empty()
                            || !nameMatch.empty()
                            || !descriptionMatch.empty())
                        {
                            found++;
                        }
                    }

                    if (found == res.size()) {
                        if (json) {

                            auto jsonElem = jsonOut->object(attrPath);

                            jsonElem.attr("pkgName", parsed.name);
                            jsonElem.attr("version", parsed.version);
                            jsonElem.attr("description", description);

                        } else {
                            auto display_description =
                                description.empty() ? "\e[3mNo description\e[23m" : description;
                            auto name = hilite(parsed.name, nameMatch, "\e[0;2m")
                                + std::string(parsed.fullName, parsed.name.length());
                            results[attrPath] = fmt(
                                "* %s (%s)\n  %s\n",
                                wrap("\e[0;1m", hilite(attrPath, attrPathMatch, "\e[0;1m")),
                                wrap("\e[0;2m", name),
                                hilite(display_description, descriptionMatch, ANSI_NORMAL));
                        }
                    }

                    if (cache) {
                        cache->attr("type", "derivation");
                        cache->attr("name", drv.queryName());
                        cache->attr("system", drv.querySystem());
                        if (description != "") {
                            auto meta(cache->object("meta"));
                            meta.attr("description", description);
                        }
                    }
                }

                else if (v->type == tAttrs) {

                    if (!toplevel) {
                        auto attrs = v->attrs;
                        Bindings::iterator j = attrs->find(sRecurse);
                        if (j == attrs->end() || !state->forceBool(*j->value, *j->pos)) {
                            debug("skip attribute '%s'", attrPath);
                            return;
                        }
                    }

                    bool toplevel2 = false;
                    if (!fromCache) {
                        Bindings::iterator j = v->attrs->find(sToplevel);
                        toplevel2 = j != v->attrs->end() && state->forceBool(*j->value, *j->pos);
                    }

                    for (auto & i : *v->attrs) {
                        auto cache2 =
                            cache ? std::make_unique<JSONObject>(cache->object(i.name)) : nullptr;
                        doExpr(i.value,
                            attrPath == "" ? (std::string) i.name : attrPath + "." + (std::string) i.name,
                            toplevel2 || fromCache, cache2 ? cache2.get() : nullptr);
                    }
                }

            } catch (AssertionError & e) {
            } catch (Error & e) {
                if (!toplevel) {
                    e.addPrefix(fmt("While evaluating the attribute '%s':\n", attrPath));
                    debug("warning: %s", e.what());
                    // don't throw, try other attrs
                }
            }
        };

        Path jsonCacheFileName = getCacheDir() + "/nix/package-search.json";

        if (useCache && pathExists(jsonCacheFileName)) {

            warn("using cached results; pass '-u' to update the cache");

            Value vRoot;
            parseJSON(*state, readFile(jsonCacheFileName), vRoot);

            fromCache = true;

            doExpr(&vRoot, "", true, nullptr);
        }

        else {
            createDirs(dirOf(jsonCacheFileName));

            Path tmpFile = fmt("%s.tmp.%d", jsonCacheFileName, getpid());

            std::ofstream jsonCacheFile;

            try {
                // iostream considered harmful
                jsonCacheFile.exceptions(std::ofstream::failbit);
                jsonCacheFile.open(tmpFile);

                auto cache = writeCache ? std::make_unique<JSONObject>(jsonCacheFile, false) : nullptr;

                doExpr(getSourceExpr(*state), "", true, cache.get());

            } catch (std::exception &) {
                /* Fun fact: catching std::ios::failure does not work
                   due to C++11 ABI shenanigans.
                   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66145 */
                if (!jsonCacheFile)
                    throw Error("error writing to %s", tmpFile);
                throw;
            }

            if (writeCache && rename(tmpFile.c_str(), jsonCacheFileName.c_str()) == -1)
                throw SysError("cannot rename '%s' to '%s'", tmpFile, jsonCacheFileName);
        }

        if (!json) {
            if (results.size() == 0)
                throw Error("no results for the given search term(s)!");

            RunPager pager;
            for (auto el : results) std::cout << el.second << "\n";
        }

    }
};

static RegisterCommand r1(make_ref<CmdSearch>());
<|endoftext|>