<commit_before>/*
 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include <string.h>

#include <algorithm>
#include <initializer_list>
#include <memory>
#include <utility>

#include "webrtc/modules/desktop_capture/screen_capturer.h"

#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/constructormagic.h"
#include "webrtc/base/logging.h"
#include "webrtc/modules/desktop_capture/rgba_color.h"
#include "webrtc/modules/desktop_capture/desktop_capture_options.h"
#include "webrtc/modules/desktop_capture/desktop_frame.h"
#include "webrtc/modules/desktop_capture/desktop_region.h"
#include "webrtc/modules/desktop_capture/screen_capturer_mock_objects.h"
#include "webrtc/modules/desktop_capture/screen_drawer.h"
#include "webrtc/system_wrappers/include/sleep.h"

#if defined(WEBRTC_WIN)
#include "webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h"
#endif  // defined(WEBRTC_WIN)

using ::testing::_;
using ::testing::AnyNumber;
using ::testing::Return;

const int kTestSharedMemoryId = 123;

namespace webrtc {

namespace {

ACTION_P(SaveUniquePtrArg, dest) {
  *dest = std::move(*arg1);
}

// Returns true if color in |rect| of |frame| is |color|.
bool ArePixelsColoredBy(const DesktopFrame& frame,
                        DesktopRect rect,
                        RgbaColor color) {
  // updated_region() should cover the painted area.
  DesktopRegion updated_region(frame.updated_region());
  updated_region.IntersectWith(rect);
  if (!updated_region.Equals(DesktopRegion(rect))) {
    return false;
  }

  // Color in the |rect| should be |color|.
  uint8_t* row = frame.GetFrameDataAtPos(rect.top_left());
  for (int i = 0; i < rect.height(); i++) {
    uint8_t* column = row;
    for (int j = 0; j < rect.width(); j++) {
      if (color != RgbaColor(column)) {
        return false;
      }
      column += DesktopFrame::kBytesPerPixel;
    }
    row += frame.stride();
  }
  return true;
}

}  // namespace

class ScreenCapturerTest : public testing::Test {
 public:
  void SetUp() override {
    capturer_.reset(
        ScreenCapturer::Create(DesktopCaptureOptions::CreateDefault()));
  }

 protected:
  void TestCaptureUpdatedRegion(
      std::initializer_list<ScreenCapturer*> capturers) {
    RTC_DCHECK(capturers.size() > 0);
    // A large enough area for the tests, which should be able to fulfill by
    // most of systems.
    const int kTestArea = 512;
    const int kRectSize = 32;
    std::unique_ptr<ScreenDrawer> drawer = ScreenDrawer::Create();
    if (!drawer || drawer->DrawableRegion().is_empty()) {
      LOG(LS_WARNING) << "No ScreenDrawer implementation for current platform.";
      return;
    }
    if (drawer->DrawableRegion().width() < kTestArea ||
        drawer->DrawableRegion().height() < kTestArea) {
      LOG(LS_WARNING) << "ScreenDrawer::DrawableRegion() is too small for the "
                         "CaptureUpdatedRegion tests.";
      return;
    }

    for (ScreenCapturer* capturer : capturers) {
      capturer->Start(&callback_);
    }

    // Draw a set of |kRectSize| by |kRectSize| rectangles at (|i|, |i|). One of
    // (controlled by |c|) its primary colors is |i|, and the other two are
    // 0xff. So we won't draw a white rectangle.
    for (int c = 0; c < 3; c++) {
      for (int i = 0; i < kTestArea - kRectSize; i += 16) {
        DesktopRect rect = DesktopRect::MakeXYWH(i, i, kRectSize, kRectSize);
        rect.Translate(drawer->DrawableRegion().top_left());
        RgbaColor color((c == 0 ? (i & 0xff) : 0x7f),
                        (c == 1 ? (i & 0xff) : 0x7f),
                        (c == 2 ? (i & 0xff) : 0x7f));
        drawer->Clear();
        drawer->DrawRectangle(rect, color);
        TestCaptureOneFrame(capturers, drawer.get(), rect, color);
      }
    }
  }

  void TestCaptureUpdatedRegion() {
    TestCaptureUpdatedRegion({capturer_.get()});
  }

#if defined(WEBRTC_WIN)
  bool CreateDirectxCapturer() {
    if (!ScreenCapturerWinDirectx::IsSupported()) {
      LOG(LS_WARNING) << "Directx capturer is not supported";
      return false;
    }

    DesktopCaptureOptions options(DesktopCaptureOptions::CreateDefault());
    options.set_allow_directx_capturer(true);
    capturer_.reset(ScreenCapturer::Create(options));
    return true;
  }

  void CreateMagnifierCapturer() {
    DesktopCaptureOptions options(DesktopCaptureOptions::CreateDefault());
    options.set_allow_use_magnification_api(true);
    capturer_.reset(ScreenCapturer::Create(options));
  }
#endif  // defined(WEBRTC_WIN)

  std::unique_ptr<ScreenCapturer> capturer_;
  MockScreenCapturerCallback callback_;

 private:
  // Repeats capturing the frame by using |capturers| one-by-one for 600 times,
  // typically 30 seconds, until they succeeded captured a |color| rectangle at
  // |rect|. This function uses |drawer|->WaitForPendingDraws() between two
  // attempts to wait for the screen to update.
  void TestCaptureOneFrame(std::vector<ScreenCapturer*> capturers,
                           ScreenDrawer* drawer,
                           DesktopRect rect,
                           RgbaColor color) {
    size_t succeeded_capturers = 0;
    const int wait_capture_round = 600;
    for (int i = 0; i < wait_capture_round; i++) {
      drawer->WaitForPendingDraws();
      for (size_t j = 0; j < capturers.size(); j++) {
        if (capturers[j] == nullptr) {
          // ScreenCapturer should return an empty updated_region() if no
          // update detected. So we won't test it again if it has captured
          // the rectangle we drew.
          continue;
        }
        std::unique_ptr<DesktopFrame> frame = CaptureFrame(capturers[j]);
        if (!frame) {
          // CaptureFrame() has triggered an assertion failure already, we
          // only need to return here.
          return;
        }

        if (ArePixelsColoredBy(*frame, rect, color)) {
          capturers[j] = nullptr;
          succeeded_capturers++;
        }
      }

      if (succeeded_capturers == capturers.size()) {
        break;
      }
    }

    ASSERT_EQ(succeeded_capturers, capturers.size());
  }

  // Expects |capturer| to successfully capture a frame, and returns it.
  std::unique_ptr<DesktopFrame> CaptureFrame(ScreenCapturer* capturer) {
    std::unique_ptr<DesktopFrame> frame;
    EXPECT_CALL(callback_,
                OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _))
        .WillOnce(SaveUniquePtrArg(&frame));
    capturer->Capture(DesktopRegion());
    EXPECT_TRUE(frame);
    return frame;
  }
};

class FakeSharedMemory : public SharedMemory {
 public:
  FakeSharedMemory(char* buffer, size_t size)
    : SharedMemory(buffer, size, 0, kTestSharedMemoryId),
      buffer_(buffer) {
  }
  virtual ~FakeSharedMemory() {
    delete[] buffer_;
  }
 private:
  char* buffer_;
  RTC_DISALLOW_COPY_AND_ASSIGN(FakeSharedMemory);
};

class FakeSharedMemoryFactory : public SharedMemoryFactory {
 public:
  FakeSharedMemoryFactory() {}
  ~FakeSharedMemoryFactory() override {}

  std::unique_ptr<SharedMemory> CreateSharedMemory(size_t size) override {
    return std::unique_ptr<SharedMemory>(
        new FakeSharedMemory(new char[size], size));
  }

 private:
  RTC_DISALLOW_COPY_AND_ASSIGN(FakeSharedMemoryFactory);
};

TEST_F(ScreenCapturerTest, GetScreenListAndSelectScreen) {
  webrtc::ScreenCapturer::ScreenList screens;
  EXPECT_TRUE(capturer_->GetScreenList(&screens));
  for (webrtc::ScreenCapturer::ScreenList::iterator it = screens.begin();
       it != screens.end(); ++it) {
    EXPECT_TRUE(capturer_->SelectScreen(it->id));
  }
}

TEST_F(ScreenCapturerTest, StartCapturer) {
  capturer_->Start(&callback_);
}

TEST_F(ScreenCapturerTest, Capture) {
  // Assume that Start() treats the screen as invalid initially.
  std::unique_ptr<DesktopFrame> frame;
  EXPECT_CALL(callback_,
              OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _))
      .WillOnce(SaveUniquePtrArg(&frame));

  capturer_->Start(&callback_);
  capturer_->Capture(DesktopRegion());

  ASSERT_TRUE(frame);
  EXPECT_GT(frame->size().width(), 0);
  EXPECT_GT(frame->size().height(), 0);
  EXPECT_GE(frame->stride(),
            frame->size().width() * DesktopFrame::kBytesPerPixel);
  EXPECT_TRUE(frame->shared_memory() == NULL);

  // Verify that the region contains whole screen.
  EXPECT_FALSE(frame->updated_region().is_empty());
  DesktopRegion::Iterator it(frame->updated_region());
  ASSERT_TRUE(!it.IsAtEnd());
  EXPECT_TRUE(it.rect().equals(DesktopRect::MakeSize(frame->size())));
  it.Advance();
  EXPECT_TRUE(it.IsAtEnd());
}

TEST_F(ScreenCapturerTest, CaptureUpdatedRegion) {
  TestCaptureUpdatedRegion();
}

// TODO(zijiehe): Find out the reason of failure of this test on trybot.
TEST_F(ScreenCapturerTest, DISABLED_TwoCapturers) {
  std::unique_ptr<ScreenCapturer> capturer2 = std::move(capturer_);
  SetUp();
  TestCaptureUpdatedRegion({capturer_.get(), capturer2.get()});
}

#if defined(WEBRTC_WIN)

TEST_F(ScreenCapturerTest, UseSharedBuffers) {
  std::unique_ptr<DesktopFrame> frame;
  EXPECT_CALL(callback_,
              OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _))
      .WillOnce(SaveUniquePtrArg(&frame));

  capturer_->Start(&callback_);
  capturer_->SetSharedMemoryFactory(
      std::unique_ptr<SharedMemoryFactory>(new FakeSharedMemoryFactory()));
  capturer_->Capture(DesktopRegion());

  ASSERT_TRUE(frame);
  ASSERT_TRUE(frame->shared_memory());
  EXPECT_EQ(frame->shared_memory()->id(), kTestSharedMemoryId);
}

TEST_F(ScreenCapturerTest, UseMagnifier) {
  CreateMagnifierCapturer();

  std::unique_ptr<DesktopFrame> frame;
  EXPECT_CALL(callback_,
              OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _))
      .WillOnce(SaveUniquePtrArg(&frame));

  capturer_->Start(&callback_);
  capturer_->Capture(DesktopRegion());
  ASSERT_TRUE(frame);
}

TEST_F(ScreenCapturerTest, UseDirectxCapturer) {
  if (!CreateDirectxCapturer()) {
    return;
  }

  std::unique_ptr<DesktopFrame> frame;
  EXPECT_CALL(callback_,
              OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _))
      .WillOnce(SaveUniquePtrArg(&frame));

  capturer_->Start(&callback_);
  capturer_->Capture(DesktopRegion());
  ASSERT_TRUE(frame);
}

TEST_F(ScreenCapturerTest, UseDirectxCapturerWithSharedBuffers) {
  if (!CreateDirectxCapturer()) {
    return;
  }

  std::unique_ptr<DesktopFrame> frame;
  EXPECT_CALL(callback_,
              OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _))
      .WillOnce(SaveUniquePtrArg(&frame));

  capturer_->Start(&callback_);
  capturer_->SetSharedMemoryFactory(
      std::unique_ptr<SharedMemoryFactory>(new FakeSharedMemoryFactory()));
  capturer_->Capture(DesktopRegion());
  ASSERT_TRUE(frame);
  ASSERT_TRUE(frame->shared_memory());
  EXPECT_EQ(frame->shared_memory()->id(), kTestSharedMemoryId);
}

TEST_F(ScreenCapturerTest, CaptureUpdatedRegionWithDirectxCapturer) {
  if (!CreateDirectxCapturer()) {
    return;
  }

  TestCaptureUpdatedRegion();
}

TEST_F(ScreenCapturerTest, TwoDirectxCapturers) {
  if (!CreateDirectxCapturer()) {
    return;
  }

  std::unique_ptr<ScreenCapturer> capturer2 = std::move(capturer_);
  RTC_CHECK(CreateDirectxCapturer());
  TestCaptureUpdatedRegion({capturer_.get(), capturer2.get()});
}

TEST_F(ScreenCapturerTest, TwoMagnifierCapturers) {
  CreateMagnifierCapturer();
  std::unique_ptr<ScreenCapturer> capturer2 = std::move(capturer_);
  CreateMagnifierCapturer();
  TestCaptureUpdatedRegion({capturer_.get(), capturer2.get()});
}

#endif  // defined(WEBRTC_WIN)

}  // namespace webrtc
<commit_msg>Disable all screen-capturer tests<commit_after>/*
 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include <string.h>

#include <algorithm>
#include <initializer_list>
#include <memory>
#include <utility>

#include "webrtc/modules/desktop_capture/screen_capturer.h"

#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/constructormagic.h"
#include "webrtc/base/logging.h"
#include "webrtc/modules/desktop_capture/rgba_color.h"
#include "webrtc/modules/desktop_capture/desktop_capture_options.h"
#include "webrtc/modules/desktop_capture/desktop_frame.h"
#include "webrtc/modules/desktop_capture/desktop_region.h"
#include "webrtc/modules/desktop_capture/screen_capturer_mock_objects.h"
#include "webrtc/modules/desktop_capture/screen_drawer.h"
#include "webrtc/system_wrappers/include/sleep.h"

#if defined(WEBRTC_WIN)
#include "webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h"
#endif  // defined(WEBRTC_WIN)

using ::testing::_;
using ::testing::AnyNumber;
using ::testing::Return;

const int kTestSharedMemoryId = 123;

namespace webrtc {

namespace {

ACTION_P(SaveUniquePtrArg, dest) {
  *dest = std::move(*arg1);
}

// Returns true if color in |rect| of |frame| is |color|.
bool ArePixelsColoredBy(const DesktopFrame& frame,
                        DesktopRect rect,
                        RgbaColor color) {
  // updated_region() should cover the painted area.
  DesktopRegion updated_region(frame.updated_region());
  updated_region.IntersectWith(rect);
  if (!updated_region.Equals(DesktopRegion(rect))) {
    return false;
  }

  // Color in the |rect| should be |color|.
  uint8_t* row = frame.GetFrameDataAtPos(rect.top_left());
  for (int i = 0; i < rect.height(); i++) {
    uint8_t* column = row;
    for (int j = 0; j < rect.width(); j++) {
      if (color != RgbaColor(column)) {
        return false;
      }
      column += DesktopFrame::kBytesPerPixel;
    }
    row += frame.stride();
  }
  return true;
}

}  // namespace

class ScreenCapturerTest : public testing::Test {
 public:
  void SetUp() override {
    capturer_.reset(
        ScreenCapturer::Create(DesktopCaptureOptions::CreateDefault()));
  }

 protected:
  void TestCaptureUpdatedRegion(
      std::initializer_list<ScreenCapturer*> capturers) {
    RTC_DCHECK(capturers.size() > 0);
    // A large enough area for the tests, which should be able to fulfill by
    // most of systems.
    const int kTestArea = 512;
    const int kRectSize = 32;
    std::unique_ptr<ScreenDrawer> drawer = ScreenDrawer::Create();
    if (!drawer || drawer->DrawableRegion().is_empty()) {
      LOG(LS_WARNING) << "No ScreenDrawer implementation for current platform.";
      return;
    }
    if (drawer->DrawableRegion().width() < kTestArea ||
        drawer->DrawableRegion().height() < kTestArea) {
      LOG(LS_WARNING) << "ScreenDrawer::DrawableRegion() is too small for the "
                         "CaptureUpdatedRegion tests.";
      return;
    }

    for (ScreenCapturer* capturer : capturers) {
      capturer->Start(&callback_);
    }

    // Draw a set of |kRectSize| by |kRectSize| rectangles at (|i|, |i|). One of
    // (controlled by |c|) its primary colors is |i|, and the other two are
    // 0xff. So we won't draw a white rectangle.
    for (int c = 0; c < 3; c++) {
      for (int i = 0; i < kTestArea - kRectSize; i += 16) {
        DesktopRect rect = DesktopRect::MakeXYWH(i, i, kRectSize, kRectSize);
        rect.Translate(drawer->DrawableRegion().top_left());
        RgbaColor color((c == 0 ? (i & 0xff) : 0x7f),
                        (c == 1 ? (i & 0xff) : 0x7f),
                        (c == 2 ? (i & 0xff) : 0x7f));
        drawer->Clear();
        drawer->DrawRectangle(rect, color);
        TestCaptureOneFrame(capturers, drawer.get(), rect, color);
      }
    }
  }

  void TestCaptureUpdatedRegion() {
    TestCaptureUpdatedRegion({capturer_.get()});
  }

#if defined(WEBRTC_WIN)
  bool CreateDirectxCapturer() {
    if (!ScreenCapturerWinDirectx::IsSupported()) {
      LOG(LS_WARNING) << "Directx capturer is not supported";
      return false;
    }

    DesktopCaptureOptions options(DesktopCaptureOptions::CreateDefault());
    options.set_allow_directx_capturer(true);
    capturer_.reset(ScreenCapturer::Create(options));
    return true;
  }

  void CreateMagnifierCapturer() {
    DesktopCaptureOptions options(DesktopCaptureOptions::CreateDefault());
    options.set_allow_use_magnification_api(true);
    capturer_.reset(ScreenCapturer::Create(options));
  }
#endif  // defined(WEBRTC_WIN)

  std::unique_ptr<ScreenCapturer> capturer_;
  MockScreenCapturerCallback callback_;

 private:
  // Repeats capturing the frame by using |capturers| one-by-one for 600 times,
  // typically 30 seconds, until they succeeded captured a |color| rectangle at
  // |rect|. This function uses |drawer|->WaitForPendingDraws() between two
  // attempts to wait for the screen to update.
  void TestCaptureOneFrame(std::vector<ScreenCapturer*> capturers,
                           ScreenDrawer* drawer,
                           DesktopRect rect,
                           RgbaColor color) {
    size_t succeeded_capturers = 0;
    const int wait_capture_round = 600;
    for (int i = 0; i < wait_capture_round; i++) {
      drawer->WaitForPendingDraws();
      for (size_t j = 0; j < capturers.size(); j++) {
        if (capturers[j] == nullptr) {
          // ScreenCapturer should return an empty updated_region() if no
          // update detected. So we won't test it again if it has captured
          // the rectangle we drew.
          continue;
        }
        std::unique_ptr<DesktopFrame> frame = CaptureFrame(capturers[j]);
        if (!frame) {
          // CaptureFrame() has triggered an assertion failure already, we
          // only need to return here.
          return;
        }

        if (ArePixelsColoredBy(*frame, rect, color)) {
          capturers[j] = nullptr;
          succeeded_capturers++;
        }
      }

      if (succeeded_capturers == capturers.size()) {
        break;
      }
    }

    ASSERT_EQ(succeeded_capturers, capturers.size());
  }

  // Expects |capturer| to successfully capture a frame, and returns it.
  std::unique_ptr<DesktopFrame> CaptureFrame(ScreenCapturer* capturer) {
    std::unique_ptr<DesktopFrame> frame;
    EXPECT_CALL(callback_,
                OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _))
        .WillOnce(SaveUniquePtrArg(&frame));
    capturer->Capture(DesktopRegion());
    EXPECT_TRUE(frame);
    return frame;
  }
};

class FakeSharedMemory : public SharedMemory {
 public:
  FakeSharedMemory(char* buffer, size_t size)
    : SharedMemory(buffer, size, 0, kTestSharedMemoryId),
      buffer_(buffer) {
  }
  virtual ~FakeSharedMemory() {
    delete[] buffer_;
  }
 private:
  char* buffer_;
  RTC_DISALLOW_COPY_AND_ASSIGN(FakeSharedMemory);
};

class FakeSharedMemoryFactory : public SharedMemoryFactory {
 public:
  FakeSharedMemoryFactory() {}
  ~FakeSharedMemoryFactory() override {}

  std::unique_ptr<SharedMemory> CreateSharedMemory(size_t size) override {
    return std::unique_ptr<SharedMemory>(
        new FakeSharedMemory(new char[size], size));
  }

 private:
  RTC_DISALLOW_COPY_AND_ASSIGN(FakeSharedMemoryFactory);
};

TEST_F(ScreenCapturerTest, GetScreenListAndSelectScreen) {
  webrtc::ScreenCapturer::ScreenList screens;
  EXPECT_TRUE(capturer_->GetScreenList(&screens));
  for (webrtc::ScreenCapturer::ScreenList::iterator it = screens.begin();
       it != screens.end(); ++it) {
    EXPECT_TRUE(capturer_->SelectScreen(it->id));
  }
}

TEST_F(ScreenCapturerTest, StartCapturer) {
  capturer_->Start(&callback_);
}

TEST_F(ScreenCapturerTest, Capture) {
  // Assume that Start() treats the screen as invalid initially.
  std::unique_ptr<DesktopFrame> frame;
  EXPECT_CALL(callback_,
              OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _))
      .WillOnce(SaveUniquePtrArg(&frame));

  capturer_->Start(&callback_);
  capturer_->Capture(DesktopRegion());

  ASSERT_TRUE(frame);
  EXPECT_GT(frame->size().width(), 0);
  EXPECT_GT(frame->size().height(), 0);
  EXPECT_GE(frame->stride(),
            frame->size().width() * DesktopFrame::kBytesPerPixel);
  EXPECT_TRUE(frame->shared_memory() == NULL);

  // Verify that the region contains whole screen.
  EXPECT_FALSE(frame->updated_region().is_empty());
  DesktopRegion::Iterator it(frame->updated_region());
  ASSERT_TRUE(!it.IsAtEnd());
  EXPECT_TRUE(it.rect().equals(DesktopRect::MakeSize(frame->size())));
  it.Advance();
  EXPECT_TRUE(it.IsAtEnd());
}

// Disabled due to being flaky due to the fact that it useds rendering / UI,
// see webrtc/6366.
TEST_F(ScreenCapturerTest, DISABLED_CaptureUpdatedRegion) {
  TestCaptureUpdatedRegion();
}

// Disabled due to being flaky due to the fact that it useds rendering / UI,
// see webrtc/6366.
// TODO(zijiehe): Find out the reason of failure of this test on trybot.
TEST_F(ScreenCapturerTest, DISABLED_TwoCapturers) {
  std::unique_ptr<ScreenCapturer> capturer2 = std::move(capturer_);
  SetUp();
  TestCaptureUpdatedRegion({capturer_.get(), capturer2.get()});
}

#if defined(WEBRTC_WIN)

TEST_F(ScreenCapturerTest, UseSharedBuffers) {
  std::unique_ptr<DesktopFrame> frame;
  EXPECT_CALL(callback_,
              OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _))
      .WillOnce(SaveUniquePtrArg(&frame));

  capturer_->Start(&callback_);
  capturer_->SetSharedMemoryFactory(
      std::unique_ptr<SharedMemoryFactory>(new FakeSharedMemoryFactory()));
  capturer_->Capture(DesktopRegion());

  ASSERT_TRUE(frame);
  ASSERT_TRUE(frame->shared_memory());
  EXPECT_EQ(frame->shared_memory()->id(), kTestSharedMemoryId);
}

TEST_F(ScreenCapturerTest, UseMagnifier) {
  CreateMagnifierCapturer();

  std::unique_ptr<DesktopFrame> frame;
  EXPECT_CALL(callback_,
              OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _))
      .WillOnce(SaveUniquePtrArg(&frame));

  capturer_->Start(&callback_);
  capturer_->Capture(DesktopRegion());
  ASSERT_TRUE(frame);
}

TEST_F(ScreenCapturerTest, UseDirectxCapturer) {
  if (!CreateDirectxCapturer()) {
    return;
  }

  std::unique_ptr<DesktopFrame> frame;
  EXPECT_CALL(callback_,
              OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _))
      .WillOnce(SaveUniquePtrArg(&frame));

  capturer_->Start(&callback_);
  capturer_->Capture(DesktopRegion());
  ASSERT_TRUE(frame);
}

TEST_F(ScreenCapturerTest, UseDirectxCapturerWithSharedBuffers) {
  if (!CreateDirectxCapturer()) {
    return;
  }

  std::unique_ptr<DesktopFrame> frame;
  EXPECT_CALL(callback_,
              OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _))
      .WillOnce(SaveUniquePtrArg(&frame));

  capturer_->Start(&callback_);
  capturer_->SetSharedMemoryFactory(
      std::unique_ptr<SharedMemoryFactory>(new FakeSharedMemoryFactory()));
  capturer_->Capture(DesktopRegion());
  ASSERT_TRUE(frame);
  ASSERT_TRUE(frame->shared_memory());
  EXPECT_EQ(frame->shared_memory()->id(), kTestSharedMemoryId);
}

// Disabled due to being flaky due to the fact that it useds rendering / UI,
// see webrtc/6366.
TEST_F(ScreenCapturerTest, DISABLED_CaptureUpdatedRegionWithDirectxCapturer) {
  if (!CreateDirectxCapturer()) {
    return;
  }

  TestCaptureUpdatedRegion();
}

// Disabled due to being flaky due to the fact that it useds rendering / UI,
// see webrtc/6366.
TEST_F(ScreenCapturerTest, DISABLED_TwoDirectxCapturers) {
  if (!CreateDirectxCapturer()) {
    return;
  }

  std::unique_ptr<ScreenCapturer> capturer2 = std::move(capturer_);
  RTC_CHECK(CreateDirectxCapturer());
  TestCaptureUpdatedRegion({capturer_.get(), capturer2.get()});
}

// Disabled due to being flaky due to the fact that it useds rendering / UI,
// see webrtc/6366.
TEST_F(ScreenCapturerTest, DISABLED_TwoMagnifierCapturers) {
  CreateMagnifierCapturer();
  std::unique_ptr<ScreenCapturer> capturer2 = std::move(capturer_);
  CreateMagnifierCapturer();
  TestCaptureUpdatedRegion({capturer_.get(), capturer2.get()});
}

#endif  // defined(WEBRTC_WIN)

}  // namespace webrtc
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <fstream>
#include <cstdint>

using namespace std;

template <typename T>
struct Node {
	Node *left;
	Node *right;
	T data;
};

template <typename T>
class BinaryTree
{
private:
	Node<T>* root;
	int CountElements = 0;

public:
	BinaryTree();
	~BinaryTree();
	BinaryTree(const std::initializer_list<T>&);
	unsigned int count() const;
	void insert_node(const T&x);
	Node<T> *find_node(const T&, Node<T>*)const;
	Node<T>*root_();
	void deleteNode(Node<T>* temp);
	void writing(const std::string& filename)const;
	void output(std::ostream& ost, const Node<T>* temp);
	friend std::ostream& operator<< <> (std::ostream&, const BinaryTree<T>&);

};

template <typename T>
BinaryTree<T>::BinaryTree()
{
	root = nullptr;
}

template<typename T>
Node<T>* BinaryTree<T>::root_()
{
	return root;
}

template <typename T>
BinaryTree<T>::~BinaryTree()
{
	deleteNode(root);
}

template<typename T>
void BinaryTree<T>::insert_node(const T&x)
{
	if (find_node(x, root_())) return;
	Node<T>* MyTree = new Node<T>;
	MyTree->data = x;
	MyTree->left = MyTree->right = 0;
	Node<T>* buff = root;
	Node<T>* temp = root;
	while (temp)
	{
		buff = temp;
		if (x < temp->data)
			temp = temp->left;
		else
			temp = temp->right;
	}
	if (!buff)
		root = MyTree;
	else
	{
		if (x < buff->data)
			buff->left = MyTree;
		else
			buff->right = MyTree;
	}
	++CountElements;
}

template<typename T>
Node<T>* BinaryTree<T>::find_node(const T& value, Node<T>* temp) const
{
	if (temp == 0 || value == temp->data)
		return temp;
	if (value > temp->data)
		return find_node(value, temp->right);
	else
		return find_node(value, temp->left);
}

template<typename T>
void BinaryTree<T>::deleteNode(Node<T>* temp)
{
	if (!temp)
	{
		throw "error";
	}
	if (temp->left)
	{
		deleteNode(temp->left);
		temp->left = nullptr;
	}

	if (temp->right)
	{
		deleteNode(temp->right);
		temp->right = nullptr;
	}
	delete temp;
}

template<typename T>
void BinaryTree<T>::output(std::ostream& ost, const Node<T>* temp)
{
	if (temp == nullptr)
	{
		throw "error";
		return;
	}
	else
	{
		ost << temp->data << "	";
		output(ost, temp->left);
		output(ost, temp->right);
	}
}

template<typename T>
void BinaryTree<T>::writing(const std::string& filename)const
{
	ofstream file_1(filename);
	file_1 << CountElements << "\t";
	output(file_1, root);
	file_1.close();
}

template <typename T>
std::ostream& show(std::ostream& ost, const Node<T>* node, unsigned int level)
{
	if (!node)
		return ost;
	show(ost, node->right, level + 1);
	for (unsigned int i = 0; i < level; i++)
		ost << "\t";
	ost << node->data << std::endl;
	show(ost, node->left, level + 1);
	return ost;
}

template <typename T>
std::ostream& operator<<(std::ostream& ost, const BinaryTree<T>& bst)
{
	if (!bst.root)
		throw "error";
	show(ost, bst.root, 0);
	return ost;
}
<commit_msg>Update BinaryTree.hpp<commit_after>#include <iostream>
#include <string>
#include <fstream>
#include <cstdint>

using namespace std;

+template<typename T>
 +class BinaryTree;
 +
 +template<typename T>
 +std::ostream& operator<<(ostream& ost, BinaryTree<T>& temp);

template <typename T>
struct Node {
	Node *left;
	Node *right;
	T data;
};

template <typename T>
class BinaryTree
{
private:
	Node<T>* root;
	int CountElements = 0;

public:
	BinaryTree();
	~BinaryTree();
	BinaryTree(const std::initializer_list<T>&);
	unsigned int count() const;
	void insert_node(const T&x);
	Node<T> *find_node(const T&, Node<T>*)const;
	Node<T>*root_();
	void deleteNode(Node<T>* temp);
	void writing(const std::string& filename)const;
	void output(std::ostream& ost, const Node<T>* temp);
	friend std::ostream& operator<< <> (std::ostream&, const BinaryTree<T>&);

};

template <typename T>
BinaryTree<T>::BinaryTree()
{
	root = nullptr;
}

template<typename T>
Node<T>* BinaryTree<T>::root_()
{
	return root;
}

template <typename T>
BinaryTree<T>::~BinaryTree()
{
	deleteNode(root);
}

template<typename T>
void BinaryTree<T>::insert_node(const T&x)
{
	if (find_node(x, root_())) return;
	Node<T>* MyTree = new Node<T>;
	MyTree->data = x;
	MyTree->left = MyTree->right = 0;
	Node<T>* buff = root;
	Node<T>* temp = root;
	while (temp)
	{
		buff = temp;
		if (x < temp->data)
			temp = temp->left;
		else
			temp = temp->right;
	}
	if (!buff)
		root = MyTree;
	else
	{
		if (x < buff->data)
			buff->left = MyTree;
		else
			buff->right = MyTree;
	}
	++CountElements;
}

template<typename T>
Node<T>* BinaryTree<T>::find_node(const T& value, Node<T>* temp) const
{
	if (temp == 0 || value == temp->data)
		return temp;
	if (value > temp->data)
		return find_node(value, temp->right);
	else
		return find_node(value, temp->left);
}

template<typename T>
void BinaryTree<T>::deleteNode(Node<T>* temp)
{
	if (!temp)
	{
		throw "error";
	}
	if (temp->left)
	{
		deleteNode(temp->left);
		temp->left = nullptr;
	}

	if (temp->right)
	{
		deleteNode(temp->right);
		temp->right = nullptr;
	}
	delete temp;
}

template<typename T>
void BinaryTree<T>::output(std::ostream& ost, const Node<T>* temp)
{
	if (temp == nullptr)
	{
		throw "error";
		return;
	}
	else
	{
		ost << temp->data << "	";
		output(ost, temp->left);
		output(ost, temp->right);
	}
}

template<typename T>
void BinaryTree<T>::writing(const std::string& filename)const
{
	ofstream file_1(filename);
	file_1 << CountElements << "\t";
	output(file_1, root);
	file_1.close();
}

template <typename T>
std::ostream& show(std::ostream& ost, const Node<T>* node, unsigned int level)
{
	if (!node)
		return ost;
	show(ost, node->right, level + 1);
	for (unsigned int i = 0; i < level; i++)
		ost << "\t";
	ost << node->data << std::endl;
	show(ost, node->left, level + 1);
	return ost;
}

template <typename T>
std::ostream& operator<<(std::ostream& ost, const BinaryTree<T>& bst)
{
	if (!bst.root)
		throw "error";
	show(ost, bst.root, 0);
	return ost;
}
<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2014 Tavendo GmbH
//
//  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.
//
///////////////////////////////////////////////////////////////////////////////

#ifndef AUTOBAHN_TCP_CLIENT_H
#define AUTOBAHN_TCP_CLIENT_H

#include <autobahn/autobahn.hpp>
#include <boost/asio.hpp>
#include <boost/version.hpp>
#include <iostream>
#include <memory>
#include <string>
#include <tuple>
namespace autobahn {
/**
 * @brief a class that wraps intialization of a raw tcp socket and WAMP client session utilizing it
 */
    class wamp_tcp_client {
        typedef autobahn::wamp_session<boost::asio::ip::tcp::socket, boost::asio::ip::tcp::socket> wamp_tcp_session_t;
    public:
        wamp_tcp_client(std::shared_ptr<boost::asio::io_service> pIo,
                        const boost::asio::ip::tcp::endpoint &Endpoint,
                        const std::string &Realm,
                        bool Debug = false) :
                m_realm(Realm),
                m_rawsocket_endpoint(Endpoint),
                m_pIo(pIo),
                m_debug(Debug) {
            init();
        }

        wamp_tcp_client(std::shared_ptr<boost::asio::io_service> pIo,
                        const std::string &IpAddress,
                        uint16_t Port,
                        const std::string &Realm,
                        bool Debug = false) :
                m_realm(Realm),
                m_rawsocket_endpoint(boost::asio::ip::address::from_string(IpAddress), Port),
                m_pIo(pIo),
                m_debug(Debug) {
            init();
        }

        /**
     * @brief initialize members, creating shared pointers for the socket, and session
     */
        void init() {
            m_pSession.reset();
            m_pSocket.reset();
            m_connected = boost::promise<bool>();
            m_pSocket = std::make_shared<boost::asio::ip::tcp::socket>(*m_pIo);
            m_pSession = std::make_shared<wamp_tcp_session_t>(*m_pIo, *m_pSocket, *m_pSocket, m_debug);
        }

        /**
     * @brief launches the session asyncronously, returns a future containing an error code (0 means success)
     */
        boost::future<bool> launch() {
            m_pSocket->async_connect(m_rawsocket_endpoint, [&](boost::system::error_code ec) {
                if (!ec) {
                    std::cerr << "connected to server" << std::endl;
                    m_startFuture = m_pSession->start().then([&](boost::future<bool> started) {
                        std::cerr << "session started" << std::endl;
                        m_joinFuture = m_pSession->join(m_realm).then([&](boost::future<uint64_t> connected) {
                            std::cerr << "connected to realm" << connected.get() << std::endl;
                            m_connected.set_value(true);
                        });
                    });
                } else {
                    std::cerr << "connect failed: " << ec.message() << std::endl;
                    m_connected.set_value(false);
                }
            });
            return m_connected.get_future();
        }

        ~wamp_tcp_client() {
        }

        /**
     * This operator is used to pass through calls to the WAMP session. i.e *(pClient)->call(...)
     */
        std::shared_ptr<wamp_tcp_session_t> &operator->() {
            return m_pSession;
        }

    private:
        boost::future<void> m_stopFuture;
        boost::future<void> m_startFuture;
        boost::future<void> m_joinFuture;
        boost::promise<bool> m_connected;
        std::shared_ptr<wamp_tcp_session_t> m_pSession; //<need to be sure this is destructed before m_pSocket
        std::shared_ptr<boost::asio::ip::tcp::socket> m_pSocket;
        std::string m_realm;
        boost::asio::ip::tcp::endpoint m_rawsocket_endpoint;
        std::shared_ptr<boost::asio::io_service> m_pIo; ///<hold a reference so that we can clean up when the last user goes out of scope
        bool m_debug;
    };
} //namespace autobahn
#endif //AUTOBAHN_TCP_CLIENT_H
<commit_msg>typo cleanup<commit_after>///////////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2014 Tavendo GmbH
//
//  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.
//
///////////////////////////////////////////////////////////////////////////////

#ifndef AUTOBAHN_TCP_CLIENT_H
#define AUTOBAHN_TCP_CLIENT_H

#include <autobahn/autobahn.hpp>
#include <boost/asio.hpp>
#include <boost/version.hpp>
#include <iostream>
#include <memory>
#include <string>
#include <tuple>
namespace autobahn {
/**
 * @brief a class that wraps initialization of a raw tcp socket and WAMP client session utilizing it
 */
    class wamp_tcp_client {
        typedef autobahn::wamp_session<boost::asio::ip::tcp::socket, boost::asio::ip::tcp::socket> wamp_tcp_session_t;
    public:
        wamp_tcp_client(std::shared_ptr<boost::asio::io_service> pIo,
                        const boost::asio::ip::tcp::endpoint &Endpoint,
                        const std::string &Realm,
                        bool Debug = false) :
                m_realm(Realm),
                m_rawsocket_endpoint(Endpoint),
                m_pIo(pIo),
                m_debug(Debug) {
            init();
        }

        wamp_tcp_client(std::shared_ptr<boost::asio::io_service> pIo,
                        const std::string &IpAddress,
                        uint16_t Port,
                        const std::string &Realm,
                        bool Debug = false) :
                m_realm(Realm),
                m_rawsocket_endpoint(boost::asio::ip::address::from_string(IpAddress), Port),
                m_pIo(pIo),
                m_debug(Debug) {
            init();
        }

        /**
     * @brief initialize members, creating shared pointers for the socket, and session
     */
        void init() {
            m_pSession.reset();
            m_pSocket.reset();
            m_connected = boost::promise<bool>();
            m_pSocket = std::make_shared<boost::asio::ip::tcp::socket>(*m_pIo);
            m_pSession = std::make_shared<wamp_tcp_session_t>(*m_pIo, *m_pSocket, *m_pSocket, m_debug);
        }

        /**
     * @brief launches the session asynchronously, returns a future containing an error code (0 means success)
     */
        boost::future<bool> launch() {
            m_pSocket->async_connect(m_rawsocket_endpoint, [&](boost::system::error_code ec) {
                if (!ec) {
                    m_startFuture = m_pSession->start().then([&](boost::future<bool> started) {
                        m_joinFuture = m_pSession->join(m_realm).then([&](boost::future<uint64_t> connected) {
                            m_connected.set_value(true);
                        });
                    });
                } else {
                    std::cerr << "connect failed: " << ec.message() << std::endl;
                    m_connected.set_value(false);
                }
            });
            return m_connected.get_future();
        }

        ~wamp_tcp_client() {
        }

        /**
     * This operator is used to pass through calls to the WAMP session. i.e *(pClient)->call(...)
     */
        std::shared_ptr<wamp_tcp_session_t> &operator->() {
            return m_pSession;
        }

    private:
        boost::future<void> m_startFuture; ///<holds the future of the start() operation
        boost::future<void> m_joinFuture; ///<holds the future of the join() operation
        boost::promise<bool> m_connected; ///<holds the future state of the success of launch
        std::shared_ptr<wamp_tcp_session_t> m_pSession; //<need to be sure this is destructed before m_pSocket
        std::shared_ptr<boost::asio::ip::tcp::socket> m_pSocket;
        std::string m_realm;
        boost::asio::ip::tcp::endpoint m_rawsocket_endpoint;
        std::shared_ptr<boost::asio::io_service> m_pIo; ///<hold a reference so that we can clean up when the last user goes out of scope
        bool m_debug;
    };
} //namespace autobahn
#endif //AUTOBAHN_TCP_CLIENT_H
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <fstream>
#include <cstdint>

using namespace std;

template <typename T>
struct Node {
	Node *left;
	Node *right;
	T data;
};

template <typename T>
class BinaryTree
{
private:
	Node<T>*root();
	int CountElements = 0;

public:
	BinaryTree();
	~BinaryTree();
	BinaryTree(const std::initializer_list<T>&);
	void _deleteElements(Node<T>*);
	Node<T>* root_;
	unsigned int count() const;
	void insert_node(const T&x);
	Node<T> *find_node(const T&, Node<T>*)const;
	void deleteNode(Node<T>* temp);
	void writing(const std::string& filename)const;
	friend std::ostream& output(std::ostream& ost, const Node<T>* temp);
	friend std::ostream& operator<<<>(std::ostream&, const BinaryTree<T>&);

};

template <typename T>
BinaryTree<T>::BinaryTree()
{
	root = nullptr;
}

template<typename T>
Node<T>* BinaryTree<T>::root_()
{
	return root;
}

template <typename T>
BinaryTree<T>::~BinaryTree()
{
	deleteNode(root);
}

template<typename T>
void BinaryTree<T>::insert_node(const T&x)
{
	if (find_node(x, root_())) return;
	Node<T>* MyTree = new Node<T>;
	MyTree->data = x;
	MyTree->left = MyTree->right = 0;
	Node<T>* buff = root;
	Node<T>* temp = root;
	while (temp)
	{
		buff = temp;
		if (x < temp->data)
			temp = temp->left;
		else
			temp = temp->right;
	}
	if (!buff)
		root = MyTree;
	else
	{
		if (x < buff->data)
			buff->left = MyTree;
		else
			buff->right = MyTree;
	}
	++CountElements;
}

template<typename T>
Node<T>* BinaryTree<T>::find_node(const T& value, Node<T>* temp) const
{
	if (temp == 0 || value == temp->data)
		return temp;
	if (value > temp->data)
		return find_node(value, temp->right);
	else
		return find_node(value, temp->left);
}

template<typename T>
void BinaryTree<T>::deleteNode(Node<T>* temp)
{
	if (!temp)
	{
		throw "error";
	}
	if (temp->left)
	{
		deleteNode(temp->left);
		temp->left = nullptr;
	}

	if (temp->right)
	{
		deleteNode(temp->right);
		temp->right = nullptr;
	}
	delete temp;
}

template<typename T>
std::ostream& show(std::ostream& ost, const Node<T>* temp)
{
	if (temp == nullptr)
	{
		throw "error";
	}
	else
	{
		ost << temp->data << "	";
		output(ost, temp->left);
		output(ost, temp->right);
	}
}

template<typename T>
void BinaryTree<T>::writing(const std::string& filename)const
{
	ofstream file_1(filename);
	file_1 << CountElements << "\t";
	output(file_1, root);
	file_1.close();
}

template <typename T>
std::ostream& show(std::ostream& ost, const Node<T>* node, unsigned int level)
{
	if (!node)
		return ost;
	show(ost, node->right, level + 1);
	for (unsigned int i = 0; i < level; i++)
		ost << "\t";
	ost << node->data << std::endl;
	show(ost, node->left, level + 1);
	return ost;
}

template <typename T>
std::ostream& operator<<(std::ostream& ost, const BinaryTree<T>& temp)
{
	if (!temp.root)
		throw "error";
	show(ost, temp.root, 0);
	return ost;
}
<commit_msg>Update BinaryTree.hpp<commit_after>#include <iostream>
#include <string>
#include <fstream>
#include <cstdint>

using namespace std;

template <typename T>
struct Node {
	Node *left;
	Node *right;
	T data;
};

template <typename T>
class BinaryTree
{
private:
	Node<T>*root;
	int CountElements = 0;

public:
	BinaryTree();
	~BinaryTree();
	BinaryTree(const std::initializer_list<T>&);
	void _deleteElements(Node<T>*);
	Node<T>* root_;
	unsigned int count() const;
	void insert_node(const T&x);
	Node<T> *find_node(const T&, Node<T>*)const;
	void deleteNode(Node<T>* temp);
	void writing(const std::string& filename)const;
	friend std::ostream& output(std::ostream& ost, const Node<T>* temp);
	friend std::ostream& operator<<<>(std::ostream&, const BinaryTree<T>&);

};

template <typename T>
BinaryTree<T>::BinaryTree()
{
	root = nullptr;
}

template<typename T>
Node<T>* BinaryTree<T>::root_()
{
	return root;
}

template <typename T>
BinaryTree<T>::~BinaryTree()
{
	deleteNode(root);
}

template<typename T>
void BinaryTree<T>::insert_node(const T&x)
{
	if (find_node(x, root_())) return;
	Node<T>* MyTree = new Node<T>;
	MyTree->data = x;
	MyTree->left = MyTree->right = 0;
	Node<T>* buff = root;
	Node<T>* temp = root;
	while (temp)
	{
		buff = temp;
		if (x < temp->data)
			temp = temp->left;
		else
			temp = temp->right;
	}
	if (!buff)
		root = MyTree;
	else
	{
		if (x < buff->data)
			buff->left = MyTree;
		else
			buff->right = MyTree;
	}
	++CountElements;
}

template<typename T>
Node<T>* BinaryTree<T>::find_node(const T& value, Node<T>* temp) const
{
	if (temp == 0 || value == temp->data)
		return temp;
	if (value > temp->data)
		return find_node(value, temp->right);
	else
		return find_node(value, temp->left);
}

template<typename T>
void BinaryTree<T>::deleteNode(Node<T>* temp)
{
	if (!temp)
	{
		throw "error";
	}
	if (temp->left)
	{
		deleteNode(temp->left);
		temp->left = nullptr;
	}

	if (temp->right)
	{
		deleteNode(temp->right);
		temp->right = nullptr;
	}
	delete temp;
}

template<typename T>
std::ostream& show(std::ostream& ost, const Node<T>* temp)
{
	if (temp == nullptr)
	{
		throw "error";
	}
	else
	{
		ost << temp->data << "	";
		output(ost, temp->left);
		output(ost, temp->right);
	}
}

template<typename T>
void BinaryTree<T>::writing(const std::string& filename)const
{
	ofstream file_1(filename);
	file_1 << CountElements << "\t";
	output(file_1, root);
	file_1.close();
}

template <typename T>
std::ostream& show(std::ostream& ost, const Node<T>* node, unsigned int level)
{
	if (!node)
		return ost;
	show(ost, node->right, level + 1);
	for (unsigned int i = 0; i < level; i++)
		ost << "\t";
	ost << node->data << std::endl;
	show(ost, node->left, level + 1);
	return ost;
}

template <typename T>
std::ostream& operator<<(std::ostream& ost, const BinaryTree<T>& temp)
{
	if (!temp.root)
		throw "error";
	show(ost, temp.root, 0);
	return ost;
}
<|endoftext|>


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

#include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
#include "base/run_loop.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/extensions/extension_prefs.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/updater/extension_updater.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/global_error/global_error.h"
#include "chrome/browser/ui/global_error/global_error_service.h"
#include "chrome/browser/ui/global_error/global_error_service_factory.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension.h"
#include "content/test/net/url_request_prepackaged_interceptor.h"
#include "net/url_request/url_fetcher.h"

using extensions::Extension;

class ExtensionDisabledGlobalErrorTest : public ExtensionBrowserTest {
 protected:
  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
    ExtensionBrowserTest::SetUpCommandLine(command_line);
    command_line->AppendSwitchASCII(switches::kAppsGalleryUpdateURL,
                                    "http://localhost/autoupdate/updates.xml");
  }

  virtual void SetUpOnMainThread() OVERRIDE {
    EXPECT_TRUE(scoped_temp_dir_.CreateUniqueTempDir());
    service_ = browser()->profile()->GetExtensionService();
    base::FilePath pem_path = test_data_dir_.
        AppendASCII("permissions_increase").AppendASCII("permissions.pem");
    path_v1_ = PackExtensionWithOptions(
        test_data_dir_.AppendASCII("permissions_increase").AppendASCII("v1"),
        scoped_temp_dir_.path().AppendASCII("permissions1.crx"),
        pem_path,
        base::FilePath());
    path_v2_ = PackExtensionWithOptions(
        test_data_dir_.AppendASCII("permissions_increase").AppendASCII("v2"),
        scoped_temp_dir_.path().AppendASCII("permissions2.crx"),
        pem_path,
        base::FilePath());
    path_v3_ = PackExtensionWithOptions(
        test_data_dir_.AppendASCII("permissions_increase").AppendASCII("v3"),
        scoped_temp_dir_.path().AppendASCII("permissions3.crx"),
        pem_path,
        base::FilePath());
  }

  // Returns the ExtensionDisabledGlobalError, if present.
  // Caution: currently only supports one error at a time.
  GlobalError* GetExtensionDisabledGlobalError() {
    return GlobalErrorServiceFactory::GetForProfile(browser()->profile())->
        GetGlobalErrorByMenuItemCommandID(IDC_EXTENSION_DISABLED_FIRST);
  }

  // Install the initial version, which should happen just fine.
  const Extension* InstallIncreasingPermissionExtensionV1() {
    size_t size_before = service_->extensions()->size();
    const Extension* extension = InstallExtension(path_v1_, 1);
    if (!extension)
      return NULL;
    if (service_->extensions()->size() != size_before + 1)
      return NULL;
    return extension;
  }

  // Upgrade to a version that wants more permissions. We should disable the
  // extension and prompt the user to reenable.
  const Extension* UpdateIncreasingPermissionExtension(
      const Extension* extension,
      const base::FilePath& crx_path,
      int expected_change) {
    size_t size_before = service_->extensions()->size();
    if (UpdateExtension(extension->id(), crx_path, expected_change))
      return NULL;
    base::RunLoop().RunUntilIdle();
    EXPECT_EQ(size_before + expected_change, service_->extensions()->size());
    if (service_->disabled_extensions()->size() != 1u)
      return NULL;

    return *service_->disabled_extensions()->begin();
  }

  // Helper function to install an extension and upgrade it to a version
  // requiring additional permissions. Returns the new disabled Extension.
  const Extension* InstallAndUpdateIncreasingPermissionsExtension() {
    const Extension* extension = InstallIncreasingPermissionExtensionV1();
    extension = UpdateIncreasingPermissionExtension(extension, path_v2_, -1);
    return extension;
  }

  ExtensionService* service_;
  base::ScopedTempDir scoped_temp_dir_;
  base::FilePath path_v1_;
  base::FilePath path_v2_;
  base::FilePath path_v3_;
};

// Tests the process of updating an extension to one that requires higher
// permissions, and accepting the permissions.
IN_PROC_BROWSER_TEST_F(ExtensionDisabledGlobalErrorTest, AcceptPermissions) {
  const Extension* extension = InstallAndUpdateIncreasingPermissionsExtension();
  ASSERT_TRUE(extension);
  ASSERT_TRUE(GetExtensionDisabledGlobalError());
  const size_t size_before = service_->extensions()->size();

  service_->GrantPermissionsAndEnableExtension(extension);
  EXPECT_EQ(size_before + 1, service_->extensions()->size());
  EXPECT_EQ(0u, service_->disabled_extensions()->size());
  ASSERT_FALSE(GetExtensionDisabledGlobalError());
}

// Tests uninstalling an extension that was disabled due to higher permissions.
IN_PROC_BROWSER_TEST_F(ExtensionDisabledGlobalErrorTest, Uninstall) {
  const Extension* extension = InstallAndUpdateIncreasingPermissionsExtension();
  ASSERT_TRUE(extension);
  ASSERT_TRUE(GetExtensionDisabledGlobalError());
  const size_t size_before = service_->extensions()->size();

  UninstallExtension(extension->id());
  EXPECT_EQ(size_before, service_->extensions()->size());
  EXPECT_EQ(0u, service_->disabled_extensions()->size());
  ASSERT_FALSE(GetExtensionDisabledGlobalError());
}

// Tests that no error appears if the user disabled the extension.
IN_PROC_BROWSER_TEST_F(ExtensionDisabledGlobalErrorTest, UserDisabled) {
  const Extension* extension = InstallIncreasingPermissionExtensionV1();
  DisableExtension(extension->id());
  extension = UpdateIncreasingPermissionExtension(extension, path_v2_, 0);
  ASSERT_FALSE(GetExtensionDisabledGlobalError());
}

// Test that no error appears if the disable reason is unknown
// (but probably was by the user).
IN_PROC_BROWSER_TEST_F(ExtensionDisabledGlobalErrorTest,
                       UnknownReasonSamePermissions) {
  const Extension* extension = InstallIncreasingPermissionExtensionV1();
  DisableExtension(extension->id());
  // Clear disable reason to simulate legacy disables.
  service_->extension_prefs()->ClearDisableReasons(extension->id());
  // Upgrade to version 2. Infer from version 1 having the same permissions
  // granted by the user that it was disabled by the user.
  extension = UpdateIncreasingPermissionExtension(extension, path_v2_, 0);
  ASSERT_TRUE(extension);
  ASSERT_FALSE(GetExtensionDisabledGlobalError());
}

// Test that an error appears if the disable reason is unknown
// (but probably was for increased permissions).
// Disabled due to http://crbug.com/246431
IN_PROC_BROWSER_TEST_F(ExtensionDisabledGlobalErrorTest,
                       DISABLED_UnknownReasonHigherPermissions) {
  const Extension* extension = InstallAndUpdateIncreasingPermissionsExtension();
  // Clear disable reason to simulate legacy disables.
  service_->extension_prefs()->ClearDisableReasons(extension->id());
  // We now have version 2 but only accepted permissions for version 1.
  GlobalError* error = GetExtensionDisabledGlobalError();
  ASSERT_TRUE(error);
  // Also, remove the upgrade error for version 2.
  GlobalErrorServiceFactory::GetForProfile(browser()->profile())->
      RemoveGlobalError(error);
  delete error;
  // Upgrade to version 3, with even higher permissions. Infer from
  // version 2 having higher-than-granted permissions that it was disabled
  // for permissions increase.
  extension = UpdateIncreasingPermissionExtension(extension, path_v3_, 0);
  ASSERT_TRUE(extension);
  ASSERT_TRUE(GetExtensionDisabledGlobalError());
}

// Test that an error appears if the extension gets disabled because a
// version with higher permissions was installed by sync.
IN_PROC_BROWSER_TEST_F(ExtensionDisabledGlobalErrorTest,
                       HigherPermissionsFromSync) {
  // Get data for extension v2 (disabled) into sync.
  const Extension* extension = InstallAndUpdateIncreasingPermissionsExtension();
  std::string extension_id = extension->id();
  // service_->GrantPermissionsAndEnableExtension(extension, false);
  extensions::ExtensionSyncData sync_data =
      service_->GetExtensionSyncData(*extension);
  UninstallExtension(extension_id);
  extension = NULL;

  // Install extension v1.
  InstallIncreasingPermissionExtensionV1();

  // Note: This interceptor gets requests on the IO thread.
  content::URLLocalHostRequestPrepackagedInterceptor interceptor;
  net::URLFetcher::SetEnableInterceptionForTests(true);
  interceptor.SetResponseIgnoreQuery(
      GURL("http://localhost/autoupdate/updates.xml"),
      test_data_dir_.AppendASCII("permissions_increase")
                    .AppendASCII("updates.xml"));
  interceptor.SetResponseIgnoreQuery(
      GURL("http://localhost/autoupdate/v2.crx"),
      scoped_temp_dir_.path().AppendASCII("permissions2.crx"));

  extensions::ExtensionUpdater::CheckParams params;
  params.check_blacklist = false;
  service_->updater()->set_default_check_params(params);

  // Sync is replacing an older version, so it pends.
  EXPECT_FALSE(service_->ProcessExtensionSyncData(sync_data));

  WaitForExtensionInstall();
  base::RunLoop().RunUntilIdle();

  extension = service_->GetExtensionById(extension_id, true);
  ASSERT_TRUE(extension);
  EXPECT_EQ("2", extension->VersionString());
  EXPECT_EQ(1u, service_->disabled_extensions()->size());
  EXPECT_EQ(Extension::DISABLE_PERMISSIONS_INCREASE,
            service_->extension_prefs()->GetDisableReasons(extension_id));
  EXPECT_TRUE(GetExtensionDisabledGlobalError());
}
<commit_msg>Another speculative fix for ExtensionDisabledGlobalErrorTests. Flush blocking tasks.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
#include "base/threading/sequenced_worker_pool.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/extensions/extension_prefs.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/updater/extension_updater.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/global_error/global_error.h"
#include "chrome/browser/ui/global_error/global_error_service.h"
#include "chrome/browser/ui/global_error/global_error_service_factory.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension.h"
#include "content/test/net/url_request_prepackaged_interceptor.h"
#include "net/url_request/url_fetcher.h"

using extensions::Extension;

class ExtensionDisabledGlobalErrorTest : public ExtensionBrowserTest {
 protected:
  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
    ExtensionBrowserTest::SetUpCommandLine(command_line);
    command_line->AppendSwitchASCII(switches::kAppsGalleryUpdateURL,
                                    "http://localhost/autoupdate/updates.xml");
  }

  virtual void SetUpOnMainThread() OVERRIDE {
    EXPECT_TRUE(scoped_temp_dir_.CreateUniqueTempDir());
    service_ = browser()->profile()->GetExtensionService();
    base::FilePath pem_path = test_data_dir_.
        AppendASCII("permissions_increase").AppendASCII("permissions.pem");
    path_v1_ = PackExtensionWithOptions(
        test_data_dir_.AppendASCII("permissions_increase").AppendASCII("v1"),
        scoped_temp_dir_.path().AppendASCII("permissions1.crx"),
        pem_path,
        base::FilePath());
    path_v2_ = PackExtensionWithOptions(
        test_data_dir_.AppendASCII("permissions_increase").AppendASCII("v2"),
        scoped_temp_dir_.path().AppendASCII("permissions2.crx"),
        pem_path,
        base::FilePath());
    path_v3_ = PackExtensionWithOptions(
        test_data_dir_.AppendASCII("permissions_increase").AppendASCII("v3"),
        scoped_temp_dir_.path().AppendASCII("permissions3.crx"),
        pem_path,
        base::FilePath());
  }

  // Returns the ExtensionDisabledGlobalError, if present.
  // Caution: currently only supports one error at a time.
  GlobalError* GetExtensionDisabledGlobalError() {
    return GlobalErrorServiceFactory::GetForProfile(browser()->profile())->
        GetGlobalErrorByMenuItemCommandID(IDC_EXTENSION_DISABLED_FIRST);
  }

  // Install the initial version, which should happen just fine.
  const Extension* InstallIncreasingPermissionExtensionV1() {
    size_t size_before = service_->extensions()->size();
    const Extension* extension = InstallExtension(path_v1_, 1);
    if (!extension)
      return NULL;
    if (service_->extensions()->size() != size_before + 1)
      return NULL;
    return extension;
  }

  // Upgrade to a version that wants more permissions. We should disable the
  // extension and prompt the user to reenable.
  const Extension* UpdateIncreasingPermissionExtension(
      const Extension* extension,
      const base::FilePath& crx_path,
      int expected_change) {
    size_t size_before = service_->extensions()->size();
    if (UpdateExtension(extension->id(), crx_path, expected_change))
      return NULL;
    BrowserThread::GetBlockingPool()->FlushForTesting();
    EXPECT_EQ(size_before + expected_change, service_->extensions()->size());
    if (service_->disabled_extensions()->size() != 1u)
      return NULL;

    return *service_->disabled_extensions()->begin();
  }

  // Helper function to install an extension and upgrade it to a version
  // requiring additional permissions. Returns the new disabled Extension.
  const Extension* InstallAndUpdateIncreasingPermissionsExtension() {
    const Extension* extension = InstallIncreasingPermissionExtensionV1();
    extension = UpdateIncreasingPermissionExtension(extension, path_v2_, -1);
    return extension;
  }

  ExtensionService* service_;
  base::ScopedTempDir scoped_temp_dir_;
  base::FilePath path_v1_;
  base::FilePath path_v2_;
  base::FilePath path_v3_;
};

// Tests the process of updating an extension to one that requires higher
// permissions, and accepting the permissions.
IN_PROC_BROWSER_TEST_F(ExtensionDisabledGlobalErrorTest, AcceptPermissions) {
  const Extension* extension = InstallAndUpdateIncreasingPermissionsExtension();
  ASSERT_TRUE(extension);
  ASSERT_TRUE(GetExtensionDisabledGlobalError());
  const size_t size_before = service_->extensions()->size();

  service_->GrantPermissionsAndEnableExtension(extension);
  EXPECT_EQ(size_before + 1, service_->extensions()->size());
  EXPECT_EQ(0u, service_->disabled_extensions()->size());
  ASSERT_FALSE(GetExtensionDisabledGlobalError());
}

// Tests uninstalling an extension that was disabled due to higher permissions.
IN_PROC_BROWSER_TEST_F(ExtensionDisabledGlobalErrorTest, Uninstall) {
  const Extension* extension = InstallAndUpdateIncreasingPermissionsExtension();
  ASSERT_TRUE(extension);
  ASSERT_TRUE(GetExtensionDisabledGlobalError());
  const size_t size_before = service_->extensions()->size();

  UninstallExtension(extension->id());
  EXPECT_EQ(size_before, service_->extensions()->size());
  EXPECT_EQ(0u, service_->disabled_extensions()->size());
  ASSERT_FALSE(GetExtensionDisabledGlobalError());
}

// Tests that no error appears if the user disabled the extension.
IN_PROC_BROWSER_TEST_F(ExtensionDisabledGlobalErrorTest, UserDisabled) {
  const Extension* extension = InstallIncreasingPermissionExtensionV1();
  DisableExtension(extension->id());
  extension = UpdateIncreasingPermissionExtension(extension, path_v2_, 0);
  ASSERT_FALSE(GetExtensionDisabledGlobalError());
}

// Test that no error appears if the disable reason is unknown
// (but probably was by the user).
IN_PROC_BROWSER_TEST_F(ExtensionDisabledGlobalErrorTest,
                       UnknownReasonSamePermissions) {
  const Extension* extension = InstallIncreasingPermissionExtensionV1();
  DisableExtension(extension->id());
  // Clear disable reason to simulate legacy disables.
  service_->extension_prefs()->ClearDisableReasons(extension->id());
  // Upgrade to version 2. Infer from version 1 having the same permissions
  // granted by the user that it was disabled by the user.
  extension = UpdateIncreasingPermissionExtension(extension, path_v2_, 0);
  ASSERT_TRUE(extension);
  ASSERT_FALSE(GetExtensionDisabledGlobalError());
}

// Test that an error appears if the disable reason is unknown
// (but probably was for increased permissions).
// Disabled due to http://crbug.com/246431
IN_PROC_BROWSER_TEST_F(ExtensionDisabledGlobalErrorTest,
                       DISABLED_UnknownReasonHigherPermissions) {
  const Extension* extension = InstallAndUpdateIncreasingPermissionsExtension();
  // Clear disable reason to simulate legacy disables.
  service_->extension_prefs()->ClearDisableReasons(extension->id());
  // We now have version 2 but only accepted permissions for version 1.
  GlobalError* error = GetExtensionDisabledGlobalError();
  ASSERT_TRUE(error);
  // Also, remove the upgrade error for version 2.
  GlobalErrorServiceFactory::GetForProfile(browser()->profile())->
      RemoveGlobalError(error);
  delete error;
  // Upgrade to version 3, with even higher permissions. Infer from
  // version 2 having higher-than-granted permissions that it was disabled
  // for permissions increase.
  extension = UpdateIncreasingPermissionExtension(extension, path_v3_, 0);
  ASSERT_TRUE(extension);
  ASSERT_TRUE(GetExtensionDisabledGlobalError());
}

// Test that an error appears if the extension gets disabled because a
// version with higher permissions was installed by sync.
IN_PROC_BROWSER_TEST_F(ExtensionDisabledGlobalErrorTest,
                       HigherPermissionsFromSync) {
  // Get data for extension v2 (disabled) into sync.
  const Extension* extension = InstallAndUpdateIncreasingPermissionsExtension();
  std::string extension_id = extension->id();
  // service_->GrantPermissionsAndEnableExtension(extension, false);
  extensions::ExtensionSyncData sync_data =
      service_->GetExtensionSyncData(*extension);
  UninstallExtension(extension_id);
  extension = NULL;

  // Install extension v1.
  InstallIncreasingPermissionExtensionV1();

  // Note: This interceptor gets requests on the IO thread.
  content::URLLocalHostRequestPrepackagedInterceptor interceptor;
  net::URLFetcher::SetEnableInterceptionForTests(true);
  interceptor.SetResponseIgnoreQuery(
      GURL("http://localhost/autoupdate/updates.xml"),
      test_data_dir_.AppendASCII("permissions_increase")
                    .AppendASCII("updates.xml"));
  interceptor.SetResponseIgnoreQuery(
      GURL("http://localhost/autoupdate/v2.crx"),
      scoped_temp_dir_.path().AppendASCII("permissions2.crx"));

  extensions::ExtensionUpdater::CheckParams params;
  params.check_blacklist = false;
  service_->updater()->set_default_check_params(params);

  // Sync is replacing an older version, so it pends.
  EXPECT_FALSE(service_->ProcessExtensionSyncData(sync_data));

  WaitForExtensionInstall();
  BrowserThread::GetBlockingPool()->FlushForTesting();

  extension = service_->GetExtensionById(extension_id, true);
  ASSERT_TRUE(extension);
  EXPECT_EQ("2", extension->VersionString());
  EXPECT_EQ(1u, service_->disabled_extensions()->size());
  EXPECT_EQ(Extension::DISABLE_PERMISSIONS_INCREASE,
            service_->extension_prefs()->GetDisableReasons(extension_id));
  EXPECT_TRUE(GetExtensionDisabledGlobalError());
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <fstream>
using namespace std;

template<typename T>
struct Node
{
	T x;
	Node<T> * left;
	Node<T> * right;
};

template<typename T>
class Tree
{
private:
	Node<T> * root;
public:
	Tree()
	{
		root->x = 0;
		root->left = root->right = nullptr;
	}

	~Tree()
	{
		deleteNode(root);
	}

	void deleteNode(Node<T> * node)
	{
		if (node == NULL) return;
		deleteNode(node->left);
		deleteNode(node->right);
		delete node;
	}

	T x_() const
	{
		return root->x;
	}

	Node<T> * left_() const
	{
		return root->left;
	}

	Node<T> * right_() const
	{
		return root->right;
	}

	void add(const T newEl)
	{
		if (root == nullptr)
			root->x = newEl;
		else
		{
			Node<T> * El = new Node<T>;
			Node<T> * curEl = new Node<T>;
			curEl = root;
			while (curEl != nullptr)
			{
				El = curEl;
				if (newEl > curEl->x)
					curEl = curEl->right;
				else
				if (newEl < curEl->x)
					curEl = curEl->left;
				else return;
			}
			if (newEl > El->x)
			{
				El->right = new Node<T>;
				El->right->x = newEl;
				El->right->left = El->right->right = nullptr;
			}
			else
			{
				El->left = new Node<T>;
				El->left->x = newEl;
				El->left->left = El->left->right = nullptr;
			}
		}
	}

	Node<T> * search(const T x)
	{
		Node<T> * curEl = root;
		while (curEl != nullptr)
		{
			if (curEl->x == x)
				return curEl;
			else
			{
				if (x > curEl->x)
					curEl = curEl->right;
				else curEl = curEl->left;
			}
		}
		return nullptr;
	}

	void fIn(string filename)
	{
		ifstream fin;
		fin.open(filename);
		if (!fin.is_open())
			cout << "The file isn't find" << endl;
		else
		{
			deleteNode(root);
			root = new Node<T>;
			root->x = 0;
			root->left = root->right = nullptr;
			if (fin.eof()) return;
			else
			{
<commit_msg>Update BinaryTree.hpp<commit_after>#include <iostream>
#include <string>
#include <fstream>
using namespace std;

template<typename T>
struct Node
{
	T x;
	Node<T> * left;
	Node<T> * right;
	Node(T const& value) : x{value}, left{nullptr}, right{nullptr} {}
};

template<typename T>
class Tree
{
private:
	Node<T> * root;
public:
	Tree()
	{
		root = nullptr;
	}

	~Tree()
	{
		deleteNode(root);
	}

	void deleteNode(Node<T> * node)
	{
		if (node == NULL) return;
		deleteNode(node->left);
		deleteNode(node->right);
		delete node;
	}

	T x_() const
	{
		return root->x;
	}

	Node<T> * left_() const
	{
		return root->left;
	}

	Node<T> * right_() const
	{
		return root->right;
	}

	void add(const T newEl)
	{
		if (root == nullptr)
			root = new Node(newEl);
		else
		{
			Node<T> * El = new Node<T>;
			Node<T> *& curEl = new Node<T>;
			curEl = root;
			while (curEl != nullptr)
			{
				El = curEl;
				if (newEl > curEl->x)
					curEl = curEl->right;
				else
				if (newEl < curEl->x)
					curEl = curEl->left;
				else return;
			}
			if (newEl > El->x)
			{
				El->right = new Node<T>;
				El->right->x = newEl;
				El->right->left = El->right->right = nullptr;
			}
			else
			{
				El->left = new Node<T>;
				El->left->x = newEl;
				El->left->left = El->left->right = nullptr;
			}
		}
	}

	Node<T> * search(const T& x)
	{
		Node<T> * curEl = root;
		while (curEl != nullptr)
		{
			if (curEl->x == x)
				break;
			else
			{
				if (x > curEl->x)
					curEl = curEl->right;
				else curEl = curEl->left;
			}
		}
		return curEl;
	}

	void fIn(string filename)
	{
		ifstream fin;
		fin.open(filename);
		if (!fin.is_open())
			cout << "The file isn't find" << endl;
		else
		{
			deleteNode(root);
			root = new Node<T>;
			root->x = 0;
			root->left = root->right = nullptr;
			if (fin.eof()) return;
			else
			{
<|endoftext|>


<commit_before>/* -*- coding: utf-8; mode: c++; tab-width: 3; indent-tabs-mode: nil -*-

Copyright 2010, 2011, 2012, 2013, 2014
Raffaello D. Di Napoli

This file is part of Application-Building Components (henceforth referred to as ABC).

ABC is free software: you can redistribute it and/or modify it under the terms of the GNU General
Public License as published by the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.

ABC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.

You should have received a copy of the GNU General Public License along with ABC. If not, see
<http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------------------------------*/

#ifndef _ABC_MEMORY_HXX
#define _ABC_MEMORY_HXX

#include <abc/core.hxx>
#ifdef ABC_CXX_PRAGMA_ONCE
   #pragma once
#endif

#include <abc/exception.hxx>

#if ABC_HOST_API_POSIX

   #include <stdlib.h> // free() malloc() realloc()
   #include <memory.h> // memcpy() memmove() memset()

#elif ABC_HOST_API_WIN32 //if ABC_HOST_API_POSIX

   // Clean up pollution caused by previous headers.
   extern "C" {

   // Rtl*Memory*

   #undef RtlZeroMemory
   WINBASEAPI void WINAPI RtlZeroMemory(void UNALIGNED * pDst, size_t cb);

   #undef RtlFillMemory
   WINBASEAPI void WINAPI RtlFillMemory(void UNALIGNED * pDst, size_t cb, UCHAR iValue);

   #undef RtlFillMemoryUlong
   WINBASEAPI void WINAPI RtlFillMemoryUlong(void * pDst, size_t cb, ULONG iValue);

   #undef RtlFillMemoryUlonglong
   WINBASEAPI void WINAPI RtlFillMemoryUlonglong(void * pDst, size_t cb, ULONGLONG iValue);

   #undef RtlCopyMemory
   WINBASEAPI void WINAPI RtlCopyMemory(
      void UNALIGNED * pDst, void UNALIGNED const * pSrc, size_t cb
   );

   #undef RtlMoveMemory
   WINBASEAPI void WINAPI RtlMoveMemory(
      void UNALIGNED * pDst, void UNALIGNED const * pSrc, size_t cb
   );

   } //extern "C"

#endif //if ABC_HOST_API_POSIX … elif ABC_HOST_API_WIN32

/** TODO: comment or remove.
*/
#if ABC_HOST_GCC
   #define _abc_alloca(cb) \
      __builtin_alloca((cb))
#elif ABC_HOST_MSC
   extern "C" void * ABC_STL_CALLCONV _alloca(size_t cb);
   #define _abc_alloca(cb) \
      _alloca(cb)
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////
// :: globals - standard new/delete operators

#if ABC_HOST_MSC
   #pragma warning(push)
   // “'operator': exception specification does not match previous declaration”
   #pragma warning(disable: 4986)
#endif

void * ABC_STL_CALLCONV operator new(size_t cb) ABC_STL_NOEXCEPT_FALSE((std::bad_alloc));
void * ABC_STL_CALLCONV operator new[](size_t cb) ABC_STL_NOEXCEPT_FALSE((std::bad_alloc));
void * ABC_STL_CALLCONV operator new(size_t cb, std::nothrow_t const &) ABC_STL_NOEXCEPT_TRUE();
void * ABC_STL_CALLCONV operator new[](size_t cb, std::nothrow_t const &) ABC_STL_NOEXCEPT_TRUE();

void ABC_STL_CALLCONV operator delete(void * p) ABC_STL_NOEXCEPT_TRUE();
void ABC_STL_CALLCONV operator delete[](void * p) ABC_STL_NOEXCEPT_TRUE();
void ABC_STL_CALLCONV operator delete(void * p, std::nothrow_t const &) ABC_STL_NOEXCEPT_TRUE();
void ABC_STL_CALLCONV operator delete[](void * p, std::nothrow_t const &) ABC_STL_NOEXCEPT_TRUE();

#if ABC_HOST_MSC
   #pragma warning(pop)
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::memory::freeing_deleter

namespace abc {

namespace memory {

// Forward declaration.
template <typename T>
void free(T const * pt);

/** Deleter that deallocates memory using memory::free().
*/
template <typename T>
struct freeing_deleter {

   /** Deallocates the specified memory block.

   pt
      Pointer to the object to delete.
   */
   void operator()(T * pt) const {
      free(pt);
   }
};

// Specialization for arrays.
template <typename T>
struct freeing_deleter<T[]> :
   public freeing_deleter<T> {

   /** Deallocates the specified array. See also freeing_deleter<T>::operator()().

   pt
      Pointer to the array to deallocate.
   */
   template <typename T2>
   void operator()(T2 * pt) const {
      freeing_deleter<T>::operator()(pt);
   }
};

} //namespace memory

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::memory::conditional_deleter

namespace abc {

namespace memory {

/** Wrapper that invokes a deleter if and only if a set condition is true.
*/
template <typename T, typename TDeleter = std::default_delete<T>>
class conditional_deleter :
   public TDeleter {
public:

   /** Constructor.

   bEnabled
      If true, the deleter will delete objects when invoked; if false, it will do nothing.
   cd
      Source deleter.
   */
   conditional_deleter(bool bEnabled) :
      TDeleter(),
      m_bEnabled(bEnabled) {
   }
   template <typename T2, typename TDeleter2>
   conditional_deleter(conditional_deleter<T2, TDeleter2> const & cd) :
      TDeleter(static_cast<TDeleter2 const &>(cd)),
      m_bEnabled(cd.enabled()) {
   }

   /** Deletes the specified object if the condition set in the constructor was true.

   pt
      Pointer to the object to delete.
   */
   void operator()(T * pt) const {
      if (m_bEnabled) {
         TDeleter::operator()(pt);
      }
   }

   /** Returns true if the deleter is enabled.

   return
      true if the deleter is enable, or false otherwise.
   */
   bool enabled() const {
      return m_bEnabled;
   }

protected:

   bool m_bEnabled;
};

// Specialization for arrays.
template <typename T, typename TDeleter>
class conditional_deleter<T[], TDeleter> :
   public conditional_deleter<T, TDeleter> {
public:

   /** See conditional_deleter<T>::conditional_deleter().
   */
   conditional_deleter(bool bEnabled) :
      conditional_deleter<T, TDeleter>(bEnabled) {
   }
   template <typename T2, typename TDeleter2>
   conditional_deleter(conditional_deleter<T2, TDeleter2> const & cd) :
      conditional_deleter<T, TDeleter>(cd) {
   }

   /** Deletes the specified array if the condition set in the constructor was true. See also
   conditional_deleter<T, TDeleter>::operator()().

   pt
      Pointer to the array to delete.
   */
   template <typename T2>
   void operator()(T2 * pt) const {
      if (this->m_bEnabled) {
         TDeleter::operator()(pt);
      }
   }
};

} //namespace memory

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::memory globals - management

namespace abc {

namespace memory {

/** Requests the dynamic allocation of a memory block of the specified number of bytes.

TODO: comment signature.
*/
inline void * _raw_alloc(size_t cb) {
   void * p(::malloc(cb));
   if (!p) {
      ABC_THROW(memory_allocation_error, ());
   }
   return p;
}

/** Resizes a dynamically allocated memory block.

TODO: comment signature.
*/
inline void * _raw_realloc(void * p, size_t cb) {
   p = ::realloc(p, cb);
   if (!p) {
      ABC_THROW(memory_allocation_error, ());
   }
   return p;
}

/** Requests the dynamic allocation of a memory block large enough to contain c objects of type T,
plus an additional cbExtra bytes. With specialization that ignores types (void) and allocates the
specified number of bytes.

TODO: comment signature.
*/
template <typename T>
inline std::unique_ptr<T, freeing_deleter<T>> alloc(size_t c = 1, size_t cbExtra = 0) {
   return std::unique_ptr<T, freeing_deleter<T>>(
      static_cast<T *>(_raw_alloc(sizeof(T) * c + cbExtra))
   );
}
template <>
inline std::unique_ptr<void, freeing_deleter<void>> alloc(
   size_t cb /*= 1*/, size_t cbExtra /*= 0*/
) {
   return std::unique_ptr<void, freeing_deleter<void>>(_raw_alloc(cb + cbExtra));
}

/** Releases a block of dynamically allocated memory.

pt
   Pointer to the memory block to be released.
*/
template <typename T>
inline void free(T const * pt) {
   ::free(const_cast<T *>(pt));
}

/** Changes the size of a block of dynamically allocated memory. Both overloads have a
specialization that ignores pointer types (void), and allocates the specified number of bytes.

TODO: comment signature.
*/
template <typename T>
inline T * realloc(T * pt, size_t c, size_t cbExtra = 0) {
   return static_cast<T *>(_raw_realloc(pt, sizeof(T) * c + cbExtra));
}
template <>
inline void * realloc(void * p, size_t cb, size_t cbExtra /*= 0*/) {
   return _raw_realloc(p, cb + cbExtra);
}
template <typename T>
inline void realloc(std::unique_ptr<T, freeing_deleter<T>> * ppt, size_t c, size_t cbExtra = 0) {
   typedef typename std::unique_ptr<T, freeing_deleter<T>>::element_type TElt;
   TElt * pt(static_cast<TElt *>(_raw_realloc(ppt->get(), sizeof(TElt) * c + cbExtra)));
   ppt->release();
   ppt->reset(pt);
}
template <>
inline void realloc(
   std::unique_ptr<void, freeing_deleter<void>> * pp, size_t cb, size_t cbExtra /*= 0*/
) {
   void * p(_raw_realloc(pp->get(), cb + cbExtra));
   pp->release();
   pp->reset(p);
}

} //namespace memory

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::memory globals - manipulation

namespace abc {

namespace memory {

/** Sets to the value 0 every item in an array.

TODO: comment signature.
*/
template <typename T>
inline T * clear(T * ptDst, size_t c = 1) {
   return static_cast<T *>(clear<void>(ptDst, sizeof(T) * c));
}
template <>
inline void * clear(void * pDst, size_t cb /*= 1*/) {
#if ABC_HOST_API_POSIX
   ::memset(pDst, 0, cb);
#elif ABC_HOST_API_WIN32
   ::RtlZeroMemory(pDst, cb);
#else
   #error TODO-PORT: HOST_API
#endif
   return pDst;
}

/** Copies memory, by number of items. With specialization that ignores pointer types (void), and
copies the specified number of bytes.

TODO: comment signature.
*/
template <typename T>
inline T * copy(T * ptDst, T const * ptSrc) {
   // Optimization: if the copy can be made by mem-reg-mem transfers, avoid calling a function, so
   // that the compiler can inline the copy.
   switch (sizeof(T)) {
      case sizeof(int8_t):
         *reinterpret_cast<int8_t *>(ptDst) = *reinterpret_cast<int8_t const *>(ptSrc);
         break;
      case sizeof(int16_t):
         *reinterpret_cast<int16_t *>(ptDst) = *reinterpret_cast<int16_t const *>(ptSrc);
         break;
      case sizeof(int32_t):
         *reinterpret_cast<int32_t *>(ptDst) = *reinterpret_cast<int32_t const *>(ptSrc);
         break;
      case sizeof(int64_t):
         *reinterpret_cast<int64_t *>(ptDst) = *reinterpret_cast<int64_t const *>(ptSrc);
         break;
      default:
         copy<void>(ptDst, ptSrc, sizeof(T));
         break;
   }
   return static_cast<T *>(ptDst);
}
// Nobody should want to use this, but it’s here for consistency.
template <>
inline void * copy(void * pDst, void const * pSrc) {
   *reinterpret_cast<int8_t *>(pDst) = *reinterpret_cast<int8_t const *>(pSrc);
   return pDst;
}
template <typename T>
inline T * copy(T * ptDst, T const * ptSrc, size_t c) {
   return static_cast<T *>(copy<void>(ptDst, ptSrc, sizeof(T) * c));
}
template <>
inline void * copy(void * pDst, void const * pSrc, size_t cb) {
#if ABC_HOST_API_POSIX
   ::memcpy(pDst, pSrc, cb);
#elif ABC_HOST_API_WIN32
   ::RtlMoveMemory(pDst, pSrc, cb);
#else
   #error TODO-PORT: HOST_API
#endif
   return pDst;
}

/** Copies possibly overlapping memory, by number of items. With specialization that ignores pointer
types (void), and copies the specified number of bytes.

TODO: comment signature.
*/
template <typename T>
inline T * move(T * ptDst, T const * ptSrc, size_t c) {
   return static_cast<T *>(move<void>(ptDst, ptSrc, sizeof(T) * c));
}
template <>
inline void * move(void * pDst, void const * pSrc, size_t cb) {
#if ABC_HOST_API_POSIX
   ::memmove(pDst, pSrc, cb);
#elif ABC_HOST_API_WIN32
   ::RtlMoveMemory(pDst, pSrc, cb);
#else
   #error TODO-PORT: HOST_API
#endif
   return pDst;
}

/** Copies a value over each item of a static array.

TODO: comment signature.
*/
template <typename T>
inline T * set(T * ptDst, T const & tValue, size_t c) {
   switch (sizeof(T)) {
#if ABC_HOST_API_POSIX
      case sizeof(int8_t):
         ::memset(ptDst, tValue, c);
         break;
#elif ABC_HOST_API_WIN32
      case sizeof(UCHAR):
         ::RtlFillMemory(ptDst, c, tValue);
         break;
#endif
      default:
         for (T const * ptDstMax(ptDst + c); ptDst < ptDstMax; ++ptDst) {
            copy(ptDst, &tValue);
         }
         break;
   }
   return ptDst;
}

} //namespace memory

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////

#endif //ifdef _ABC_MEMORY_HXX

<commit_msg>Refactor abc::memory::alloc() to support std::unique_ptr<T[]><commit_after>/* -*- coding: utf-8; mode: c++; tab-width: 3; indent-tabs-mode: nil -*-

Copyright 2010, 2011, 2012, 2013, 2014
Raffaello D. Di Napoli

This file is part of Application-Building Components (henceforth referred to as ABC).

ABC is free software: you can redistribute it and/or modify it under the terms of the GNU General
Public License as published by the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.

ABC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.

You should have received a copy of the GNU General Public License along with ABC. If not, see
<http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------------------------------*/

#ifndef _ABC_MEMORY_HXX
#define _ABC_MEMORY_HXX

#include <abc/core.hxx>
#ifdef ABC_CXX_PRAGMA_ONCE
   #pragma once
#endif

#include <abc/exception.hxx>

#if ABC_HOST_API_POSIX

   #include <stdlib.h> // free() malloc() realloc()
   #include <memory.h> // memcpy() memmove() memset()

#elif ABC_HOST_API_WIN32 //if ABC_HOST_API_POSIX

   // Clean up pollution caused by previous headers.
   extern "C" {

   // Rtl*Memory*

   #undef RtlZeroMemory
   WINBASEAPI void WINAPI RtlZeroMemory(void UNALIGNED * pDst, size_t cb);

   #undef RtlFillMemory
   WINBASEAPI void WINAPI RtlFillMemory(void UNALIGNED * pDst, size_t cb, UCHAR iValue);

   #undef RtlFillMemoryUlong
   WINBASEAPI void WINAPI RtlFillMemoryUlong(void * pDst, size_t cb, ULONG iValue);

   #undef RtlFillMemoryUlonglong
   WINBASEAPI void WINAPI RtlFillMemoryUlonglong(void * pDst, size_t cb, ULONGLONG iValue);

   #undef RtlCopyMemory
   WINBASEAPI void WINAPI RtlCopyMemory(
      void UNALIGNED * pDst, void UNALIGNED const * pSrc, size_t cb
   );

   #undef RtlMoveMemory
   WINBASEAPI void WINAPI RtlMoveMemory(
      void UNALIGNED * pDst, void UNALIGNED const * pSrc, size_t cb
   );

   } //extern "C"

#endif //if ABC_HOST_API_POSIX … elif ABC_HOST_API_WIN32

/** TODO: comment or remove.
*/
#if ABC_HOST_GCC
   #define _abc_alloca(cb) \
      __builtin_alloca((cb))
#elif ABC_HOST_MSC
   extern "C" void * ABC_STL_CALLCONV _alloca(size_t cb);
   #define _abc_alloca(cb) \
      _alloca(cb)
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////
// :: globals - standard new/delete operators

#if ABC_HOST_MSC
   #pragma warning(push)
   // “'operator': exception specification does not match previous declaration”
   #pragma warning(disable: 4986)
#endif

void * ABC_STL_CALLCONV operator new(size_t cb) ABC_STL_NOEXCEPT_FALSE((std::bad_alloc));
void * ABC_STL_CALLCONV operator new[](size_t cb) ABC_STL_NOEXCEPT_FALSE((std::bad_alloc));
void * ABC_STL_CALLCONV operator new(size_t cb, std::nothrow_t const &) ABC_STL_NOEXCEPT_TRUE();
void * ABC_STL_CALLCONV operator new[](size_t cb, std::nothrow_t const &) ABC_STL_NOEXCEPT_TRUE();

void ABC_STL_CALLCONV operator delete(void * p) ABC_STL_NOEXCEPT_TRUE();
void ABC_STL_CALLCONV operator delete[](void * p) ABC_STL_NOEXCEPT_TRUE();
void ABC_STL_CALLCONV operator delete(void * p, std::nothrow_t const &) ABC_STL_NOEXCEPT_TRUE();
void ABC_STL_CALLCONV operator delete[](void * p, std::nothrow_t const &) ABC_STL_NOEXCEPT_TRUE();

#if ABC_HOST_MSC
   #pragma warning(pop)
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::memory::freeing_deleter

namespace abc {

namespace memory {

// Forward declaration.
template <typename T>
void free(T const * pt);

/** Deleter that deallocates memory using memory::free().
*/
template <typename T>
struct freeing_deleter {

   /** Deallocates the specified memory block.

   pt
      Pointer to the object to delete.
   */
   void operator()(T * pt) const {
      free(pt);
   }
};

// Specialization for arrays.
template <typename T>
struct freeing_deleter<T[]> :
   public freeing_deleter<T> {

   /** Deallocates the specified array. See also freeing_deleter<T>::operator()().

   pt
      Pointer to the array to deallocate.
   */
   template <typename T2>
   void operator()(T2 * pt) const {
      freeing_deleter<T>::operator()(pt);
   }
};

} //namespace memory

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::memory::conditional_deleter

namespace abc {

namespace memory {

/** Wrapper that invokes a deleter if and only if a set condition is true.
*/
template <typename T, typename TDeleter = std::default_delete<T>>
class conditional_deleter :
   public TDeleter {
public:

   /** Constructor.

   bEnabled
      If true, the deleter will delete objects when invoked; if false, it will do nothing.
   cd
      Source deleter.
   */
   conditional_deleter(bool bEnabled) :
      TDeleter(),
      m_bEnabled(bEnabled) {
   }
   template <typename T2, typename TDeleter2>
   conditional_deleter(conditional_deleter<T2, TDeleter2> const & cd) :
      TDeleter(static_cast<TDeleter2 const &>(cd)),
      m_bEnabled(cd.enabled()) {
   }

   /** Deletes the specified object if the condition set in the constructor was true.

   pt
      Pointer to the object to delete.
   */
   void operator()(T * pt) const {
      if (m_bEnabled) {
         TDeleter::operator()(pt);
      }
   }

   /** Returns true if the deleter is enabled.

   return
      true if the deleter is enable, or false otherwise.
   */
   bool enabled() const {
      return m_bEnabled;
   }

protected:

   bool m_bEnabled;
};

// Specialization for arrays.
template <typename T, typename TDeleter>
class conditional_deleter<T[], TDeleter> :
   public conditional_deleter<T, TDeleter> {
public:

   /** See conditional_deleter<T>::conditional_deleter().
   */
   conditional_deleter(bool bEnabled) :
      conditional_deleter<T, TDeleter>(bEnabled) {
   }
   template <typename T2, typename TDeleter2>
   conditional_deleter(conditional_deleter<T2, TDeleter2> const & cd) :
      conditional_deleter<T, TDeleter>(cd) {
   }

   /** Deletes the specified array if the condition set in the constructor was true. See also
   conditional_deleter<T, TDeleter>::operator()().

   pt
      Pointer to the array to delete.
   */
   template <typename T2>
   void operator()(T2 * pt) const {
      if (this->m_bEnabled) {
         TDeleter::operator()(pt);
      }
   }
};

} //namespace memory

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::memory globals - management

namespace abc {

namespace memory {

/** Requests the dynamic allocation of a memory block of the specified number of bytes.

TODO: comment signature.
*/
inline void * _raw_alloc(size_t cb) {
   void * p(::malloc(cb));
   if (!p) {
      ABC_THROW(memory_allocation_error, ());
   }
   return p;
}

/** Resizes a dynamically allocated memory block.

TODO: comment signature.
*/
inline void * _raw_realloc(void * p, size_t cb) {
   p = ::realloc(p, cb);
   if (!p) {
      ABC_THROW(memory_allocation_error, ());
   }
   return p;
}

/** Requests the dynamic allocation of a memory block large enough to contain c objects of type T,
plus an additional cbExtra bytes. With specialization that ignores types (void) and allocates the
specified number of bytes.

TODO: comment signature.
*/
template <typename T>
inline std::unique_ptr<T, freeing_deleter<T>> alloc(size_t c = 1, size_t cbExtra = 0) {
   typedef typename std::unique_ptr<T, freeing_deleter<T>>::element_type TElt;
   return std::unique_ptr<T, freeing_deleter<T>>(
      static_cast<TElt *>(_raw_alloc(sizeof(TElt) * c + cbExtra))
   );
}
template <>
inline std::unique_ptr<void, freeing_deleter<void>> alloc(
   size_t cb /*= 1*/, size_t cbExtra /*= 0*/
) {
   return std::unique_ptr<void, freeing_deleter<void>>(_raw_alloc(cb + cbExtra));
}

/** Releases a block of dynamically allocated memory.

pt
   Pointer to the memory block to be released.
*/
template <typename T>
inline void free(T const * pt) {
   ::free(const_cast<T *>(pt));
}

/** Changes the size of a block of dynamically allocated memory. Both overloads have a
specialization that ignores pointer types (void), and allocates the specified number of bytes.

TODO: comment signature.
*/
template <typename T>
inline T * realloc(T * pt, size_t c, size_t cbExtra = 0) {
   return static_cast<T *>(_raw_realloc(pt, sizeof(T) * c + cbExtra));
}
template <>
inline void * realloc(void * p, size_t cb, size_t cbExtra /*= 0*/) {
   return _raw_realloc(p, cb + cbExtra);
}
template <typename T>
inline void realloc(std::unique_ptr<T, freeing_deleter<T>> * ppt, size_t c, size_t cbExtra = 0) {
   typedef typename std::unique_ptr<T, freeing_deleter<T>>::element_type TElt;
   TElt * pt(static_cast<TElt *>(_raw_realloc(ppt->get(), sizeof(TElt) * c + cbExtra)));
   ppt->release();
   ppt->reset(pt);
}
template <>
inline void realloc(
   std::unique_ptr<void, freeing_deleter<void>> * pp, size_t cb, size_t cbExtra /*= 0*/
) {
   void * p(_raw_realloc(pp->get(), cb + cbExtra));
   pp->release();
   pp->reset(p);
}

} //namespace memory

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::memory globals - manipulation

namespace abc {

namespace memory {

/** Sets to the value 0 every item in an array.

TODO: comment signature.
*/
template <typename T>
inline T * clear(T * ptDst, size_t c = 1) {
   return static_cast<T *>(clear<void>(ptDst, sizeof(T) * c));
}
template <>
inline void * clear(void * pDst, size_t cb /*= 1*/) {
#if ABC_HOST_API_POSIX
   ::memset(pDst, 0, cb);
#elif ABC_HOST_API_WIN32
   ::RtlZeroMemory(pDst, cb);
#else
   #error TODO-PORT: HOST_API
#endif
   return pDst;
}

/** Copies memory, by number of items. With specialization that ignores pointer types (void), and
copies the specified number of bytes.

TODO: comment signature.
*/
template <typename T>
inline T * copy(T * ptDst, T const * ptSrc) {
   // Optimization: if the copy can be made by mem-reg-mem transfers, avoid calling a function, so
   // that the compiler can inline the copy.
   switch (sizeof(T)) {
      case sizeof(int8_t):
         *reinterpret_cast<int8_t *>(ptDst) = *reinterpret_cast<int8_t const *>(ptSrc);
         break;
      case sizeof(int16_t):
         *reinterpret_cast<int16_t *>(ptDst) = *reinterpret_cast<int16_t const *>(ptSrc);
         break;
      case sizeof(int32_t):
         *reinterpret_cast<int32_t *>(ptDst) = *reinterpret_cast<int32_t const *>(ptSrc);
         break;
      case sizeof(int64_t):
         *reinterpret_cast<int64_t *>(ptDst) = *reinterpret_cast<int64_t const *>(ptSrc);
         break;
      default:
         copy<void>(ptDst, ptSrc, sizeof(T));
         break;
   }
   return static_cast<T *>(ptDst);
}
// Nobody should want to use this, but it’s here for consistency.
template <>
inline void * copy(void * pDst, void const * pSrc) {
   *reinterpret_cast<int8_t *>(pDst) = *reinterpret_cast<int8_t const *>(pSrc);
   return pDst;
}
template <typename T>
inline T * copy(T * ptDst, T const * ptSrc, size_t c) {
   return static_cast<T *>(copy<void>(ptDst, ptSrc, sizeof(T) * c));
}
template <>
inline void * copy(void * pDst, void const * pSrc, size_t cb) {
#if ABC_HOST_API_POSIX
   ::memcpy(pDst, pSrc, cb);
#elif ABC_HOST_API_WIN32
   ::RtlMoveMemory(pDst, pSrc, cb);
#else
   #error TODO-PORT: HOST_API
#endif
   return pDst;
}

/** Copies possibly overlapping memory, by number of items. With specialization that ignores pointer
types (void), and copies the specified number of bytes.

TODO: comment signature.
*/
template <typename T>
inline T * move(T * ptDst, T const * ptSrc, size_t c) {
   return static_cast<T *>(move<void>(ptDst, ptSrc, sizeof(T) * c));
}
template <>
inline void * move(void * pDst, void const * pSrc, size_t cb) {
#if ABC_HOST_API_POSIX
   ::memmove(pDst, pSrc, cb);
#elif ABC_HOST_API_WIN32
   ::RtlMoveMemory(pDst, pSrc, cb);
#else
   #error TODO-PORT: HOST_API
#endif
   return pDst;
}

/** Copies a value over each item of a static array.

TODO: comment signature.
*/
template <typename T>
inline T * set(T * ptDst, T const & tValue, size_t c) {
   switch (sizeof(T)) {
#if ABC_HOST_API_POSIX
      case sizeof(int8_t):
         ::memset(ptDst, tValue, c);
         break;
#elif ABC_HOST_API_WIN32
      case sizeof(UCHAR):
         ::RtlFillMemory(ptDst, c, tValue);
         break;
#endif
      default:
         for (T const * ptDstMax(ptDst + c); ptDst < ptDstMax; ++ptDst) {
            copy(ptDst, &tValue);
         }
         break;
   }
   return ptDst;
}

} //namespace memory

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////

#endif //ifdef _ABC_MEMORY_HXX

<|endoftext|>


<commit_before>#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

struct option
{
  option (
    string optionShortName,
    string optionLongName,
    string optionDescription)
    : fOptionShortName (optionShortName),
      fOptionLongName (optionLongName),
      fOptionDescription (optionDescription)
    {}

  string operator() () const
    { return fOptionDescription; }

  void print (ostream& os) const
    {
      os <<
        "fOptionShortName:" << fOptionShortName << endl <<
        "fOptionLongName:" << fOptionLongName << endl <<
        "fOptionDescription:" << fOptionDescription << endl;
    }

  private:
    string fOptionShortName;
    string fOptionLongName;
    string fOptionDescription;
};

ostream& operator<< (ostream& os, const option& elt)
{
  elt.print (os);
  return os;
}

int main()
{
  vector<option> vec {
    option ("1short", "1long", "descr1"),
    option ("2short", "1long", "descr2")
  };

  int counter = 0;
  cout <<
    "The contents of 'vec' is:" << endl << endl;
  for (option i : vec)
  {
    cout <<
      "Element " << counter << ":" << endl <<
      i << endl;
    counter++;
  }

  cout << "Which element should be printed? ";

  int n;
  cin >> n;

  cout << endl;

  if (n < vec.size ())
    cout <<
      "Element " << n << " constains:" << endl <<
      endl <<
      vec [n] << endl;
  else
    cout <<
      "Sorry, only elements from 0 to " << vec.size () - 1 << " exist" << endl;
}
<commit_msg>c++ functors tests 2<commit_after>#include <iostream>
#include <vector>
#include <algorithm>
#include <iomanip>      // setw, set::precision, ...

#include <getopt.h>

using namespace std;

struct myOption
{
  myOption (
    string optionShortName,
    string optionLongName,
    string optionDescription)
    : fOptionShortName (optionShortName),
      fOptionLongName (optionLongName),
      fOptionDescription (optionDescription)
    {
      fOptionSelected = 0;
    }

  string operator() () const
    { return fOptionDescription; }

  void print (ostream& os) const
    {
      const int fieldWidth = 19;

      os <<
        setw(fieldWidth) <<
        "fOptionShortName" << " : " << fOptionShortName <<
        endl <<
        setw(fieldWidth) <<
        "fOptionLongName" << " : " << fOptionLongName <<
        endl <<
        setw(fieldWidth) <<
        "fOptionDescription" << " : " << fOptionDescription <<
        endl <<
        setw(fieldWidth) <<
        "fOptionSelected" << " : " << fOptionSelected <<
        endl;
    }

  private:
    string fOptionShortName;
    string fOptionLongName;
    string fOptionDescription;

    int    fOptionSelected;
};

ostream& operator<< (ostream& os, const myOption& elt)
{
  elt.print (os);
  return os;
}

//_______________________________________________________________________________
void analyzeOptions (
  int            argc,
  char*          argv[])
{
}

int main (int argc, char *argv[])
{
  vector<myOption> vec {
    myOption ("1short", "1long", "descr1"),
    myOption ("2short", "1long", "descr2")
  };

  int counter = 0;
  cout <<
    "The contents of 'vec' is:" <<
    endl << endl;
  for (myOption i : vec)
  {
    cout <<
      "Element " << counter << ":" <<
      endl <<
      i <<
      endl;
    counter++;
  }

/*
struct option
{
  const char *name;
  // has_arg can't be an enum because some compilers complain about
  // type mismatches in all the code that assumes it is an int.
  int has_arg;
  int *flag;
  int val;
};
*/

  vector<struct option> myLongOptions {
    option ("1short", no_argument, &vec [0].fOptionSelected, 1),
    option ("1long", no_argument, &vec [0].fOptionSelected, 1),

    option ("2short", required_argument, &vec [1].fOptionSelected, 1),
    option ("2long", required_argument, &vec [1].fOptionSelected, 1),

    option (0, 0, 0, 0) // option trailer
  };

/*
  cout << "Which element should be printed? ";

  int n;
  cin >> n;

  cout << endl;

  if (n < vec.size ())
    cout <<
      "Element " << n << " constains:" <<
      endl <<
      endl <<
      vec [n] <<
      endl;
  else
    cout <<
      "Sorry, only elements from 0 to " << vec.size () - 1 << " exist" <<
      endl;
*/

  analyzeOptions (
    argc, argv);

}
<|endoftext|>