<commit_before>// Copyright (c) 2010 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 "chrome/browser/notifications/desktop_notification_service.h"

#include "base/task.h"
#include "base/waitable_event.h"
#include "chrome/browser/notifications/notifications_prefs_cache.h"
#include "chrome/browser/renderer_host/test/test_render_view_host.h"
#include "chrome/test/testing_profile.h"
#include "grit/generated_resources.h"
#include "testing/gtest/include/gtest/gtest.h"

class DesktopNotificationServiceTest : public RenderViewHostTestHarness {
 public:
  DesktopNotificationServiceTest()
      : event_(false, false),
        ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
  }

  void LetIOThreadWait() {
    event_.Wait();
  }

  base::WaitableEvent event_;
  ScopedRunnableMethodFactory<DesktopNotificationServiceTest> method_factory_;
};

TEST_F(DesktopNotificationServiceTest, DefaultContentSettingSentToCache) {
  // The current message loop was already initalized by the superclass.
  ChromeThread ui_thread(ChromeThread::UI, MessageLoop::current());

  // Create IO thread, start its message loop.
  ChromeThread io_thread(ChromeThread::IO);
  io_thread.Start();
  ChromeThread::PostTask(ChromeThread::UI, FROM_HERE,
      method_factory_.NewRunnableMethod(
          &DesktopNotificationServiceTest::LetIOThreadWait));

  // Creates the service, calls InitPrefs() on it which loads data from the
  // profile into the cache and then puts the cache in io thread mode.
  DesktopNotificationService* service =
      profile()->GetDesktopNotificationService();
  NotificationsPrefsCache* cache = service->prefs_cache();

  // The default pref registered in DesktopNotificationService is "ask",
  // and that's what sent to the cache.
  EXPECT_EQ(CONTENT_SETTING_ASK, cache->CachedDefaultContentSetting());

  // Change the default content setting. This will post a task on the IO thread
  // to update the cache.
  service->SetDefaultContentSetting(CONTENT_SETTING_BLOCK);

  // The updated pref shouldn't be sent to the cache immediately.
  EXPECT_EQ(CONTENT_SETTING_ASK, cache->CachedDefaultContentSetting());

  // Run IO thread tasks.
  event_.Signal();
  io_thread.Stop();

  // Now that IO thread events have been processed, it should be there.
  EXPECT_EQ(CONTENT_SETTING_BLOCK, cache->CachedDefaultContentSetting());
}

<commit_msg>Attempted build fix: Run IO blocking task actually on IO thread.<commit_after>// Copyright (c) 2010 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 "chrome/browser/notifications/desktop_notification_service.h"

#include "base/task.h"
#include "base/waitable_event.h"
#include "chrome/browser/notifications/notifications_prefs_cache.h"
#include "chrome/browser/renderer_host/test/test_render_view_host.h"
#include "chrome/test/testing_profile.h"
#include "grit/generated_resources.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

class WaitTask : public Task {
 public:
  WaitTask(base::WaitableEvent* event)
      : event_(event) {
  }
  virtual void Run() {
    event_->Wait();
  }

 private:
  base::WaitableEvent* event_;
};

class DesktopNotificationServiceTest : public RenderViewHostTestHarness {
 public:
  DesktopNotificationServiceTest()
      : event_(false, false) {
  }
  base::WaitableEvent event_;
};

TEST_F(DesktopNotificationServiceTest, DefaultContentSettingSentToCache) {
  // The current message loop was already initalized by the superclass.
  ChromeThread ui_thread(ChromeThread::UI, MessageLoop::current());

  // Create IO thread, start its message loop.
  ChromeThread io_thread(ChromeThread::IO);
  io_thread.Start();
  ChromeThread::PostTask(ChromeThread::IO, FROM_HERE, new WaitTask(&event_));

  // Creates the service, calls InitPrefs() on it which loads data from the
  // profile into the cache and then puts the cache in io thread mode.
  DesktopNotificationService* service =
      profile()->GetDesktopNotificationService();
  NotificationsPrefsCache* cache = service->prefs_cache();

  // The default pref registered in DesktopNotificationService is "ask",
  // and that's what sent to the cache.
  EXPECT_EQ(CONTENT_SETTING_ASK, cache->CachedDefaultContentSetting());

  // Change the default content setting. This will post a task on the IO thread
  // to update the cache.
  service->SetDefaultContentSetting(CONTENT_SETTING_BLOCK);

  // The updated pref shouldn't be sent to the cache immediately.
  EXPECT_EQ(CONTENT_SETTING_ASK, cache->CachedDefaultContentSetting());

  // Run IO thread tasks.
  event_.Signal();
  io_thread.Stop();

  // Now that IO thread events have been processed, it should be there.
  EXPECT_EQ(CONTENT_SETTING_BLOCK, cache->CachedDefaultContentSetting());
}

}  // namespace
<|endoftext|>


<commit_before>// ========================================================================== //
// This file is part of Sara, a basic set of libraries in C++ for computer
// vision.
//
// Copyright (C) 2019 David Ok <david.ok8@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License v. 2.0. If a copy of the MPL was not distributed with this file,
// you can obtain one at http://mozilla.org/MPL/2.0/.
// ========================================================================== //

//! @example

#include <algorithm>
#include <cmath>

#include <omp.h>

#include <DO/Sara/Core.hpp>
#include <DO/Sara/Graphics.hpp>
#include <DO/Sara/ImageIO.hpp>
#include <DO/Sara/VideoIO.hpp>

#include <drafts/Halide/Draw.hpp>
#include <drafts/Halide/SIFTPipeline.hpp>

#include "shakti_halide_rgb_to_gray.h"

namespace sara = DO::Sara;
namespace halide = DO::Shakti::HalideBackend;

auto test_on_image()
{
  const auto image_filepath =
#ifdef __APPLE__
      "/Users/david/GitLab/DO-CV/sara/data/sunflowerField.jpg";
#else
      "/home/david/GitLab/DO-CV/sara/data/sunflowerField.jpg";
#endif
  auto image = sara::imread<float>(image_filepath);
  auto image_tensor = tensor_view(image).reshape(
      Eigen::Vector4i{1, 1, image.height(), image.width()});
  auto buffer_4d = halide::as_runtime_buffer(image_tensor);

  auto sift_pipeline = halide::v2::SiftPyramidPipeline{};
  sift_pipeline.initialize(-1, image.width(), image.height());

  auto timer = sara::Timer{};

  timer.restart();
  {
    buffer_4d.set_host_dirty();
    sift_pipeline.feed(buffer_4d);
  }
  const auto elapsed_ms = timer.elapsed_ms();
  SARA_DEBUG << "SIFT pipeline: " << elapsed_ms << " ms" << std::endl;

#ifdef CHECK_INPUT_UPSCALED
  if (sift_pipeline.start_octave_index < 0)
  {
    auto input_upscaled = sift_pipeline.input_upscaled_view();
    sara::create_window(input_upscaled.sizes());
    sara::display(input_upscaled);
    sara::get_key();
    sara::resize_window(image.sizes());
  }
#endif

  if (!sara::active_window())
    sara::create_window(image.sizes());

// #define CHECK_PYRAMIDS
#ifdef CHECK_PYRAMIDS
  for (auto& octave : sift_pipeline.octaves)
    for (auto s = 0; s < octave.params.num_scales + 3; ++s)
      sara::display(octave.gaussian_view(s));
  sara::get_key();

  for (auto& octave : sift_pipeline.octaves)
    for (auto s = 0; s < octave.params.num_scales + 2; ++s)
    {
      sara::display(sara::color_rescale(octave.dog_view(s)));
      sara::get_key();
    }
  sara::get_key();
#endif

  sara::set_antialiasing();
  sara::display(image);
  for (auto o = 0u; o < sift_pipeline.octaves.size(); ++o)
  {
    auto& octave = sift_pipeline.octaves[o];
    for (auto s = 0u; s < octave.extrema_oriented.size(); ++s)
    {
      SARA_DEBUG << sara::format("[o = %d, s = %d] Num extrema = %d",
                                 sift_pipeline.start_octave_index + o, s,
                                 octave.extrema_oriented[s].size())
                 << std::endl;
      draw_oriented_extrema(octave.extrema_oriented[s],
                            sift_pipeline.octave_scaling_factor(
                                sift_pipeline.start_octave_index + o));
    }
  }

  while (sara::get_key() != sara::KEY_ESCAPE)
    ;
}

auto test_on_video(int argc, char **argv)
{
  using namespace std::string_literals;

#ifdef _WIN32
  const auto video_filepath = "C:/Users/David/Desktop/GOPR0542.MP4"s;
#elif __APPLE__
  const auto
      video_filepath =  //"/Users/david/Desktop/Datasets/sfm/Family.mp4"s;
      "/Users/david/Desktop/Datasets/videos/sample10.mp4"s;
#else
  const auto video_filepath =
      argc < 2 ? "/home/david/Desktop/Datasets/sfm/Family.mp4"s
               : std::string{argv[1]};
#endif

  // ===========================================================================
  // SARA PIPELINE
  //
  // Input and output from Sara.
  sara::VideoStream video_stream(video_filepath);
  auto frame = video_stream.frame();
  auto frame_gray = sara::Image<float>{frame.sizes()};
  auto frame_gray_tensor =
      tensor_view(frame_gray)
          .reshape(
              Eigen::Vector4i{1, 1, frame_gray.height(), frame_gray.width()});

  // ===========================================================================
  // HALIDE PIPELINE.
  //
  // RGB-grayscale conversion.
  auto buffer_rgb = halide::as_interleaved_runtime_buffer(frame);
  auto buffer_gray = halide::as_runtime_buffer(frame_gray);
  auto buffer_gray_4d = halide::as_runtime_buffer(frame_gray_tensor);

  auto sift_pipeline = halide::v2::SiftPyramidPipeline{};

  const auto start_octave_index = 0;
  sift_pipeline.initialize(start_octave_index, frame.width(), frame.height());

  // Show the local extrema.
  sara::create_window(frame.sizes());
  sara::set_antialiasing();

  auto frames_read = 0;

  auto timer = sara::Timer{};
  auto elapsed_ms = double{};

  while (true)
  {
    sara::tic();
    if (!video_stream.read())
    {
      std::cout << "Reached the end of the video!" << std::endl;
      break;
    }
    sara::toc("Video Decoding");

    ++frames_read;
    SARA_CHECK(frames_read);

    // if(frames_read % 3 != 0)
    //   continue;

    timer.restart();
    {
      sara::tic();
      shakti_halide_rgb_to_gray(buffer_rgb, buffer_gray);
      sara::toc("CPU RGB to grayscale");

      buffer_gray_4d.set_host_dirty();
      sift_pipeline.feed(buffer_gray_4d);
    }
    elapsed_ms = timer.elapsed_ms();
    SARA_DEBUG << "[Frame: " << frames_read << "] "
               << "total computation time = " << elapsed_ms << " ms"
               << std::endl;

    sara::tic();
    for (auto o = 0u; o < sift_pipeline.octaves.size(); ++o)
    {
      auto& octave = sift_pipeline.octaves[o];
      for (auto s = 0u; s < octave.extrema_oriented.size(); ++s)
        draw_oriented_extrema(frame, octave.extrema_oriented[s],
                              sift_pipeline.octave_scaling_factor(
                                  sift_pipeline.start_octave_index + o));
    }
    sara::display(frame);
    sara::toc("Display");
  }
}

int __main(int argc, char** argv)
{
  // Optimization.
  omp_set_num_threads(omp_get_max_threads());
  std::ios_base::sync_with_stdio(false);

  // test_on_image();
  test_on_video(argc, argv);
  return 0;
}

int main(int argc, char** argv)
{
  DO::Sara::GraphicsApplication app(argc, argv);
  app.register_user_main(__main);
  return app.exec();
}
<commit_msg>MAINT: fix compiler warning.<commit_after>// ========================================================================== //
// This file is part of Sara, a basic set of libraries in C++ for computer
// vision.
//
// Copyright (C) 2019 David Ok <david.ok8@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License v. 2.0. If a copy of the MPL was not distributed with this file,
// you can obtain one at http://mozilla.org/MPL/2.0/.
// ========================================================================== //

//! @example

#include <algorithm>
#include <cmath>

#include <omp.h>

#include <DO/Sara/Core.hpp>
#include <DO/Sara/Graphics.hpp>
#include <DO/Sara/ImageIO.hpp>
#include <DO/Sara/VideoIO.hpp>

#include <drafts/Halide/Draw.hpp>
#include <drafts/Halide/SIFTPipeline.hpp>

#include "shakti_halide_rgb_to_gray.h"

namespace sara = DO::Sara;
namespace halide = DO::Shakti::HalideBackend;

auto test_on_image()
{
  const auto image_filepath =
#ifdef __APPLE__
      "/Users/david/GitLab/DO-CV/sara/data/sunflowerField.jpg";
#else
      "/home/david/GitLab/DO-CV/sara/data/sunflowerField.jpg";
#endif
  auto image = sara::imread<float>(image_filepath);
  auto image_tensor = tensor_view(image).reshape(
      Eigen::Vector4i{1, 1, image.height(), image.width()});
  auto buffer_4d = halide::as_runtime_buffer(image_tensor);

  auto sift_pipeline = halide::v2::SiftPyramidPipeline{};
  sift_pipeline.initialize(-1, image.width(), image.height());

  auto timer = sara::Timer{};

  timer.restart();
  {
    buffer_4d.set_host_dirty();
    sift_pipeline.feed(buffer_4d);
  }
  const auto elapsed_ms = timer.elapsed_ms();
  SARA_DEBUG << "SIFT pipeline: " << elapsed_ms << " ms" << std::endl;

#ifdef CHECK_INPUT_UPSCALED
  if (sift_pipeline.start_octave_index < 0)
  {
    auto input_upscaled = sift_pipeline.input_upscaled_view();
    sara::create_window(input_upscaled.sizes());
    sara::display(input_upscaled);
    sara::get_key();
    sara::resize_window(image.sizes());
  }
#endif

  if (!sara::active_window())
    sara::create_window(image.sizes());

// #define CHECK_PYRAMIDS
#ifdef CHECK_PYRAMIDS
  for (auto& octave : sift_pipeline.octaves)
    for (auto s = 0; s < octave.params.num_scales + 3; ++s)
      sara::display(octave.gaussian_view(s));
  sara::get_key();

  for (auto& octave : sift_pipeline.octaves)
    for (auto s = 0; s < octave.params.num_scales + 2; ++s)
    {
      sara::display(sara::color_rescale(octave.dog_view(s)));
      sara::get_key();
    }
  sara::get_key();
#endif

  sara::set_antialiasing();
  sara::display(image);
  for (auto o = 0u; o < sift_pipeline.octaves.size(); ++o)
  {
    auto& octave = sift_pipeline.octaves[o];
    for (auto s = 0u; s < octave.extrema_oriented.size(); ++s)
    {
      SARA_DEBUG << sara::format("[o = %d, s = %d] Num extrema = %d",
                                 sift_pipeline.start_octave_index + o, s,
                                 octave.extrema_oriented[s].size())
                 << std::endl;
      draw_oriented_extrema(octave.extrema_oriented[s],
                            sift_pipeline.octave_scaling_factor(
                                sift_pipeline.start_octave_index + o));
    }
  }

  while (sara::get_key() != sara::KEY_ESCAPE)
    ;
}

auto test_on_video(int argc, char **argv)
{
  using namespace std::string_literals;

#ifdef _WIN32
  const auto video_filepath =
    argc < 2 ? "C:/Users/David/Desktop/GOPR0542.MP4"s
             : std::string{argv[1]};
#elif __APPLE__
  const auto video_filepath =
    argc < 2 ? "/Users/david/Desktop/Datasets/videos/sample10.mp4"s
             : std::string{argv[1]};
#else
  const auto video_filepath =
      argc < 2 ? "/home/david/Desktop/Datasets/sfm/Family.mp4"s
               : std::string{argv[1]};
#endif

  // ===========================================================================
  // SARA PIPELINE
  //
  // Input and output from Sara.
  sara::VideoStream video_stream(video_filepath);
  auto frame = video_stream.frame();
  auto frame_gray = sara::Image<float>{frame.sizes()};
  auto frame_gray_tensor =
      tensor_view(frame_gray)
          .reshape(
              Eigen::Vector4i{1, 1, frame_gray.height(), frame_gray.width()});

  // ===========================================================================
  // HALIDE PIPELINE.
  //
  // RGB-grayscale conversion.
  auto buffer_rgb = halide::as_interleaved_runtime_buffer(frame);
  auto buffer_gray = halide::as_runtime_buffer(frame_gray);
  auto buffer_gray_4d = halide::as_runtime_buffer(frame_gray_tensor);

  auto sift_pipeline = halide::v2::SiftPyramidPipeline{};

  const auto start_octave_index = 0;
  sift_pipeline.initialize(start_octave_index, frame.width(), frame.height());

  // Show the local extrema.
  sara::create_window(frame.sizes());
  sara::set_antialiasing();

  auto frames_read = 0;

  auto timer = sara::Timer{};
  auto elapsed_ms = double{};

  while (true)
  {
    sara::tic();
    if (!video_stream.read())
    {
      std::cout << "Reached the end of the video!" << std::endl;
      break;
    }
    sara::toc("Video Decoding");

    ++frames_read;
    SARA_CHECK(frames_read);

    // if(frames_read % 3 != 0)
    //   continue;

    timer.restart();
    {
      sara::tic();
      shakti_halide_rgb_to_gray(buffer_rgb, buffer_gray);
      sara::toc("CPU RGB to grayscale");

      buffer_gray_4d.set_host_dirty();
      sift_pipeline.feed(buffer_gray_4d);
    }
    elapsed_ms = timer.elapsed_ms();
    SARA_DEBUG << "[Frame: " << frames_read << "] "
               << "total computation time = " << elapsed_ms << " ms"
               << std::endl;

    sara::tic();
    for (auto o = 0u; o < sift_pipeline.octaves.size(); ++o)
    {
      auto& octave = sift_pipeline.octaves[o];
      for (auto s = 0u; s < octave.extrema_oriented.size(); ++s)
        draw_oriented_extrema(frame, octave.extrema_oriented[s],
                              sift_pipeline.octave_scaling_factor(
                                  sift_pipeline.start_octave_index + o));
    }
    sara::display(frame);
    sara::toc("Display");
  }
}

int __main(int argc, char** argv)
{
  // Optimization.
  omp_set_num_threads(omp_get_max_threads());
  std::ios_base::sync_with_stdio(false);

  // test_on_image();
  test_on_video(argc, argv);
  return 0;
}

int main(int argc, char** argv)
{
  DO::Sara::GraphicsApplication app(argc, argv);
  app.register_user_main(__main);
  return app.exec();
}
<|endoftext|>


<commit_before>void sink(const char *);
void sink(int);

struct S {
    void(*f)(const char*);

    void apply(char* p) {
        f(p);
    }

    void (*get())(const char*) {
        return f;
    }
};

void calls_sink_with_argv(const char* a) {
    sink(a);
}

extern int i;

class BaseWithPureVirtual {
public:
    virtual void f(const char*) = 0;
};

class DerivedCallsSink : public BaseWithPureVirtual {
public:
    void f(const char* p) override {
        sink(p);
    }
};

class DerivedDoesNotCallSink : public BaseWithPureVirtual {
public:
    void f(const char* p) override {}
};

class DerivedCallsSinkDiamond1 : virtual public BaseWithPureVirtual {
public:
    void f(const char* p) override {
        sink(p);
    }
};

class DerivedDoesNotCallSinkDiamond2 : virtual public BaseWithPureVirtual {
public:
    void f(const char* p) override {}
};

class DerivesMultiple : public DerivedCallsSinkDiamond1, public DerivedDoesNotCallSinkDiamond2 {
    void f(const char* p) override {
        DerivedCallsSinkDiamond1::f(p);
    }
};

template<typename T>
class CRTP {
public:
    void f(const char* p) {
        static_cast<T*>(this)->g(p);
    }
};

class CRTPCallsSink : public CRTP<CRTPCallsSink> {
    public:
    void g(const char* p) {
        sink(p);
    }
};

class Derived1 : public BaseWithPureVirtual {};

class Derived2 : public Derived1 {
    public:
    void f(const char* p) override {}
};

class Derived3 : public Derived2 {
    public:
    void f(const char* p) override {
        sink(p);
    }
};

class CRTPDoesNotCallSink : public CRTP<CRTPDoesNotCallSink> {
    public:
    void g(const char* p) {}
};

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

    sink(reinterpret_cast<int>(argv));

    calls_sink_with_argv(argv[1]);

    char*** p = &argv;

    sink(*p[0]);

    calls_sink_with_argv(*p[i]);

    sink(*(argv + 1)); // flow [NOT DECTED by AST]

    BaseWithPureVirtual* b = new DerivedCallsSink;

    b->f(argv[1]); // flow [NOT DETECTED by IR]

    b = new DerivedDoesNotCallSink;
    b->f(argv[0]); // no flow [FALSE POSITIVE by AST]

    BaseWithPureVirtual* b2 = new DerivesMultiple;

    b2->f(argv[i]); // flow [NOT DETECTED]

    CRTP<CRTPDoesNotCallSink> crtp_not_call_sink;
    crtp_not_call_sink.f(argv[0]);

    CRTP<CRTPCallsSink> crtp_calls_sink;
    crtp_calls_sink.f(argv[0]); // flow [NOT DETECTED]

    Derived1* calls_sink = new Derived3;
    calls_sink->f(argv[1]); // flow [NOT DETECTED by AST]

    static_cast<Derived2*>(calls_sink)->f(argv[1]); // flow [NOT DETECTED]

    dynamic_cast<Derived2*>(calls_sink)->f(argv[1]); // flow [NOT DETECTED by IR]
}<commit_msg>C++: Fix annotations in testcase file<commit_after>void sink(const char *);
void sink(int);

struct S {
    void(*f)(const char*);

    void apply(char* p) {
        f(p);
    }

    void (*get())(const char*) {
        return f;
    }
};

void calls_sink_with_argv(const char* a) {
    sink(a);
}

extern int i;

class BaseWithPureVirtual {
public:
    virtual void f(const char*) = 0;
};

class DerivedCallsSink : public BaseWithPureVirtual {
public:
    void f(const char* p) override {
        sink(p);
    }
};

class DerivedDoesNotCallSink : public BaseWithPureVirtual {
public:
    void f(const char* p) override {}
};

class DerivedCallsSinkDiamond1 : virtual public BaseWithPureVirtual {
public:
    void f(const char* p) override {
        sink(p);
    }
};

class DerivedDoesNotCallSinkDiamond2 : virtual public BaseWithPureVirtual {
public:
    void f(const char* p) override {}
};

class DerivesMultiple : public DerivedCallsSinkDiamond1, public DerivedDoesNotCallSinkDiamond2 {
    void f(const char* p) override {
        DerivedCallsSinkDiamond1::f(p);
    }
};

template<typename T>
class CRTP {
public:
    void f(const char* p) {
        static_cast<T*>(this)->g(p);
    }
};

class CRTPCallsSink : public CRTP<CRTPCallsSink> {
    public:
    void g(const char* p) {
        sink(p);
    }
};

class Derived1 : public BaseWithPureVirtual {};

class Derived2 : public Derived1 {
    public:
    void f(const char* p) override {}
};

class Derived3 : public Derived2 {
    public:
    void f(const char* p) override {
        sink(p);
    }
};

class CRTPDoesNotCallSink : public CRTP<CRTPDoesNotCallSink> {
    public:
    void g(const char* p) {}
};

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

    sink(reinterpret_cast<int>(argv));

    calls_sink_with_argv(argv[1]);

    char*** p = &argv;

    sink(*p[0]);

    calls_sink_with_argv(*p[i]);

    sink(*(argv + 1));

    BaseWithPureVirtual* b = new DerivedCallsSink;

    b->f(argv[1]);

    b = new DerivedDoesNotCallSink;
    b->f(argv[0]); // no flow [FALSE POSITIVE by AST]

    BaseWithPureVirtual* b2 = new DerivesMultiple;

    b2->f(argv[i]);

    CRTP<CRTPDoesNotCallSink> crtp_not_call_sink;
    crtp_not_call_sink.f(argv[0]);

    CRTP<CRTPCallsSink> crtp_calls_sink;
    crtp_calls_sink.f(argv[0]);

    Derived1* calls_sink = new Derived3;
    calls_sink->f(argv[1]);

    static_cast<Derived2*>(calls_sink)->f(argv[1]);

    dynamic_cast<Derived2*>(calls_sink)->f(argv[1]); // flow [NOT DETECTED by IR]
}<|endoftext|>


<commit_before>/* Copyright (C) 1995-2002 MySQL AB

   This program 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 2 of the License, or
   (at your option) any later version.

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

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA */

/**********************************************************************
This file contains the implementation of error and warnings related

  - Whenever an error or warning occurred, it pushes it to a warning list
    that the user can retrieve with SHOW WARNINGS or SHOW ERRORS.

  - For each statement, we return the number of warnings generated from this
    command.  Note that this can be different from @@warning_count as
    we reset the warning list only for questions that uses a table.
    This is done to allow on to do:
    INSERT ...;
    SELECT @@warning_count;
    SHOW WARNINGS;
    (If we would reset after each command, we could not retrieve the number
     of warnings)

  - When client requests the information using SHOW command, then
    server processes from this list and returns back in the form of
    resultset.

    Supported syntaxes:

    SHOW [COUNT(*)] ERRORS [LIMIT [offset,] rows]
    SHOW [COUNT(*)] WARNINGS [LIMIT [offset,] rows]
    SELECT @@warning_count, @@error_count;

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

#include "mysql_priv.h"
#include "sp_rcontext.h"

/*
  Store a new message in an error object

  This is used to in group_concat() to register how many warnings we actually
  got after the query has been executed.
*/

void MYSQL_ERROR::set_msg(THD *thd, const char *msg_arg)
{
  msg= strdup_root(&thd->warn_root, msg_arg);
}

/*
  Reset all warnings for the thread

  SYNOPSIS
    mysql_reset_errors()
    thd			Thread handle
    force               Reset warnings even if it has been done before

  IMPLEMENTATION
    Don't reset warnings if this has already been called for this query.
    This may happen if one gets a warning during the parsing stage,
    in which case push_warnings() has already called this function.
*/

void mysql_reset_errors(THD *thd, bool force)
{
  DBUG_ENTER("mysql_reset_errors");
  if (thd->query_id != thd->warn_id || force)
  {
    thd->warn_id= thd->query_id;
    free_root(&thd->warn_root,MYF(0));
    bzero((char*) thd->warn_count, sizeof(thd->warn_count));
    if (force)
      thd->total_warn_count= 0;
    thd->warn_list.empty();
    thd->row_count= 1; // by default point to row 1
  }
  DBUG_VOID_RETURN;
}

/*
  Push the warning/error to error list if there is still room in the list

  SYNOPSIS
    push_warning()
    thd			Thread handle
    level		Severity of warning (note, warning, error ...)
    code		Error number
    msg			Clear error message

  RETURN
    pointer on MYSQL_ERROR object
*/

MYSQL_ERROR *push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level,
                          uint code, const char *msg)
{
  MYSQL_ERROR *err= 0;
  DBUG_ENTER("push_warning");

  if (level == MYSQL_ERROR::WARN_LEVEL_NOTE &&
      !(thd->options & OPTION_SQL_NOTES))
    DBUG_RETURN(0);

  if (thd->query_id != thd->warn_id && !thd->spcont)
    mysql_reset_errors(thd, 0);
  thd->got_warning= 1;

  /* Abort if we are using strict mode and we are not using IGNORE */
  if ((int) level >= (int) MYSQL_ERROR::WARN_LEVEL_WARN &&
      thd->really_abort_on_warning())
  {
    /* Avoid my_message() calling push_warning */
    bool no_warnings_for_error= thd->no_warnings_for_error;
    sp_rcontext *spcont= thd->spcont;

    thd->no_warnings_for_error= 1;
    thd->spcont= 0;

    thd->killed= THD::KILL_BAD_DATA;
    my_message(code, msg, MYF(0));

    thd->spcont= spcont;
    thd->no_warnings_for_error= no_warnings_for_error;
    /* Store error in error list (as my_message() didn't do it) */
    level= MYSQL_ERROR::WARN_LEVEL_ERROR;
  }

  if (thd->spcont &&
      thd->spcont->find_handler(code,
                                ((int) level >=
                                 (int) MYSQL_ERROR::WARN_LEVEL_WARN &&
                                 thd->really_abort_on_warning()) ?
                                MYSQL_ERROR::WARN_LEVEL_ERROR : level))
  {
    if (! thd->spcont->found_handler_here())
      thd->net.report_error= 1; /* Make "select" abort correctly */
    DBUG_RETURN(NULL);
  }
  query_cache_abort(&thd->net);

  if (thd->warn_list.elements < thd->variables.max_error_count)
  {
    /*
      The following code is here to change the allocation to not
      use the thd->mem_root, which is freed after each query
    */
    MEM_ROOT *old_root= thd->mem_root;
    thd->mem_root= &thd->warn_root;
    if ((err= new MYSQL_ERROR(thd, code, level, msg)))
      thd->warn_list.push_back(err);
    thd->mem_root= old_root;
  }
  thd->warn_count[(uint) level]++;
  thd->total_warn_count++;
  DBUG_RETURN(err);
}

/*
  Push the warning/error to error list if there is still room in the list

  SYNOPSIS
    push_warning_printf()
    thd			Thread handle
    level		Severity of warning (note, warning, error ...)
    code		Error number
    msg			Clear error message
*/

void push_warning_printf(THD *thd, MYSQL_ERROR::enum_warning_level level,
			 uint code, const char *format, ...)
{
  va_list args;
  char    warning[ERRMSGSIZE+20];
  DBUG_ENTER("push_warning_printf");
  DBUG_PRINT("enter",("warning: %u", code));

  va_start(args,format);
  my_vsnprintf(warning, sizeof(warning), format, args);
  va_end(args);
  push_warning(thd, level, code, warning);
  DBUG_VOID_RETURN;
}

/*
  Send all notes, errors or warnings to the client in a result set

  SYNOPSIS
    mysqld_show_warnings()
    thd			Thread handler
    levels_to_show	Bitmap for which levels to show

  DESCRIPTION
    Takes into account the current LIMIT

  RETURN VALUES
    FALSE ok
    TRUE  Error sending data to client
*/

static const char *warning_level_names[]= {"Note", "Warning", "Error", "?"};
static int warning_level_length[]= { 4, 7, 5, 1 };

bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
{
  List<Item> field_list;
  DBUG_ENTER("mysqld_show_warnings");

  field_list.push_back(new Item_empty_string("Level", 7));
  field_list.push_back(new Item_return_int("Code",4, MYSQL_TYPE_LONG));
  field_list.push_back(new Item_empty_string("Message",MYSQL_ERRMSG_SIZE));

  if (thd->protocol->send_fields(&field_list,
                                 Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
    DBUG_RETURN(TRUE);

  MYSQL_ERROR *err;
  SELECT_LEX *sel= &thd->lex->select_lex;
  SELECT_LEX_UNIT *unit= &thd->lex->unit;
  ha_rows idx= 0;
  Protocol *protocol=thd->protocol;

  unit->set_limit(sel);

  List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
  while ((err= it++))
  {
    /* Skip levels that the user is not interested in */
    if (!(levels_to_show & ((ulong) 1 << err->level)))
      continue;
    if (++idx <= unit->offset_limit_cnt)
      continue;
    if (idx > unit->select_limit_cnt)
      break;
    protocol->prepare_for_resend();
    protocol->store(warning_level_names[err->level],
		    warning_level_length[err->level], system_charset_info);
    protocol->store((uint32) err->code);
    protocol->store(err->msg, strlen(err->msg), system_charset_info);
    if (protocol->write())
      DBUG_RETURN(TRUE);
  }
  send_eof(thd);
  DBUG_RETURN(FALSE);
}
<commit_msg>Add extre DBUG_PRINT in push_warning<commit_after>/* Copyright (C) 1995-2002 MySQL AB

   This program 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 2 of the License, or
   (at your option) any later version.

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

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA */

/**********************************************************************
This file contains the implementation of error and warnings related

  - Whenever an error or warning occurred, it pushes it to a warning list
    that the user can retrieve with SHOW WARNINGS or SHOW ERRORS.

  - For each statement, we return the number of warnings generated from this
    command.  Note that this can be different from @@warning_count as
    we reset the warning list only for questions that uses a table.
    This is done to allow on to do:
    INSERT ...;
    SELECT @@warning_count;
    SHOW WARNINGS;
    (If we would reset after each command, we could not retrieve the number
     of warnings)

  - When client requests the information using SHOW command, then
    server processes from this list and returns back in the form of
    resultset.

    Supported syntaxes:

    SHOW [COUNT(*)] ERRORS [LIMIT [offset,] rows]
    SHOW [COUNT(*)] WARNINGS [LIMIT [offset,] rows]
    SELECT @@warning_count, @@error_count;

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

#include "mysql_priv.h"
#include "sp_rcontext.h"

/*
  Store a new message in an error object

  This is used to in group_concat() to register how many warnings we actually
  got after the query has been executed.
*/

void MYSQL_ERROR::set_msg(THD *thd, const char *msg_arg)
{
  msg= strdup_root(&thd->warn_root, msg_arg);
}

/*
  Reset all warnings for the thread

  SYNOPSIS
    mysql_reset_errors()
    thd			Thread handle
    force               Reset warnings even if it has been done before

  IMPLEMENTATION
    Don't reset warnings if this has already been called for this query.
    This may happen if one gets a warning during the parsing stage,
    in which case push_warnings() has already called this function.
*/

void mysql_reset_errors(THD *thd, bool force)
{
  DBUG_ENTER("mysql_reset_errors");
  if (thd->query_id != thd->warn_id || force)
  {
    thd->warn_id= thd->query_id;
    free_root(&thd->warn_root,MYF(0));
    bzero((char*) thd->warn_count, sizeof(thd->warn_count));
    if (force)
      thd->total_warn_count= 0;
    thd->warn_list.empty();
    thd->row_count= 1; // by default point to row 1
  }
  DBUG_VOID_RETURN;
}

/*
  Push the warning/error to error list if there is still room in the list

  SYNOPSIS
    push_warning()
    thd			Thread handle
    level		Severity of warning (note, warning, error ...)
    code		Error number
    msg			Clear error message

  RETURN
    pointer on MYSQL_ERROR object
*/

MYSQL_ERROR *push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level,
                          uint code, const char *msg)
{
  MYSQL_ERROR *err= 0;
  DBUG_ENTER("push_warning");
  DBUG_PRINT("enter", ("code: %d, msg: %s", code, msg));

  if (level == MYSQL_ERROR::WARN_LEVEL_NOTE &&
      !(thd->options & OPTION_SQL_NOTES))
    DBUG_RETURN(0);

  if (thd->query_id != thd->warn_id && !thd->spcont)
    mysql_reset_errors(thd, 0);
  thd->got_warning= 1;

  /* Abort if we are using strict mode and we are not using IGNORE */
  if ((int) level >= (int) MYSQL_ERROR::WARN_LEVEL_WARN &&
      thd->really_abort_on_warning())
  {
    /* Avoid my_message() calling push_warning */
    bool no_warnings_for_error= thd->no_warnings_for_error;
    sp_rcontext *spcont= thd->spcont;

    thd->no_warnings_for_error= 1;
    thd->spcont= 0;

    thd->killed= THD::KILL_BAD_DATA;
    my_message(code, msg, MYF(0));

    thd->spcont= spcont;
    thd->no_warnings_for_error= no_warnings_for_error;
    /* Store error in error list (as my_message() didn't do it) */
    level= MYSQL_ERROR::WARN_LEVEL_ERROR;
  }

  if (thd->spcont &&
      thd->spcont->find_handler(code,
                                ((int) level >=
                                 (int) MYSQL_ERROR::WARN_LEVEL_WARN &&
                                 thd->really_abort_on_warning()) ?
                                MYSQL_ERROR::WARN_LEVEL_ERROR : level))
  {
    if (! thd->spcont->found_handler_here())
      thd->net.report_error= 1; /* Make "select" abort correctly */
    DBUG_RETURN(NULL);
  }
  query_cache_abort(&thd->net);

  if (thd->warn_list.elements < thd->variables.max_error_count)
  {
    /*
      The following code is here to change the allocation to not
      use the thd->mem_root, which is freed after each query
    */
    MEM_ROOT *old_root= thd->mem_root;
    thd->mem_root= &thd->warn_root;
    if ((err= new MYSQL_ERROR(thd, code, level, msg)))
      thd->warn_list.push_back(err);
    thd->mem_root= old_root;
  }
  thd->warn_count[(uint) level]++;
  thd->total_warn_count++;
  DBUG_RETURN(err);
}

/*
  Push the warning/error to error list if there is still room in the list

  SYNOPSIS
    push_warning_printf()
    thd			Thread handle
    level		Severity of warning (note, warning, error ...)
    code		Error number
    msg			Clear error message
*/

void push_warning_printf(THD *thd, MYSQL_ERROR::enum_warning_level level,
			 uint code, const char *format, ...)
{
  va_list args;
  char    warning[ERRMSGSIZE+20];
  DBUG_ENTER("push_warning_printf");
  DBUG_PRINT("enter",("warning: %u", code));

  va_start(args,format);
  my_vsnprintf(warning, sizeof(warning), format, args);
  va_end(args);
  push_warning(thd, level, code, warning);
  DBUG_VOID_RETURN;
}

/*
  Send all notes, errors or warnings to the client in a result set

  SYNOPSIS
    mysqld_show_warnings()
    thd			Thread handler
    levels_to_show	Bitmap for which levels to show

  DESCRIPTION
    Takes into account the current LIMIT

  RETURN VALUES
    FALSE ok
    TRUE  Error sending data to client
*/

static const char *warning_level_names[]= {"Note", "Warning", "Error", "?"};
static int warning_level_length[]= { 4, 7, 5, 1 };

bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
{
  List<Item> field_list;
  DBUG_ENTER("mysqld_show_warnings");

  field_list.push_back(new Item_empty_string("Level", 7));
  field_list.push_back(new Item_return_int("Code",4, MYSQL_TYPE_LONG));
  field_list.push_back(new Item_empty_string("Message",MYSQL_ERRMSG_SIZE));

  if (thd->protocol->send_fields(&field_list,
                                 Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
    DBUG_RETURN(TRUE);

  MYSQL_ERROR *err;
  SELECT_LEX *sel= &thd->lex->select_lex;
  SELECT_LEX_UNIT *unit= &thd->lex->unit;
  ha_rows idx= 0;
  Protocol *protocol=thd->protocol;

  unit->set_limit(sel);

  List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
  while ((err= it++))
  {
    /* Skip levels that the user is not interested in */
    if (!(levels_to_show & ((ulong) 1 << err->level)))
      continue;
    if (++idx <= unit->offset_limit_cnt)
      continue;
    if (idx > unit->select_limit_cnt)
      break;
    protocol->prepare_for_resend();
    protocol->store(warning_level_names[err->level],
		    warning_level_length[err->level], system_charset_info);
    protocol->store((uint32) err->code);
    protocol->store(err->msg, strlen(err->msg), system_charset_info);
    if (protocol->write())
      DBUG_RETURN(TRUE);
  }
  send_eof(thd);
  DBUG_RETURN(FALSE);
}
<|endoftext|>


<commit_before>#include "cvolumeenumerator.h"
#include "volumeinfohelper.hpp"

DISABLE_COMPILER_WARNINGS
#include <QDir>
RESTORE_COMPILER_WARNINGS

const std::vector<VolumeInfo> CVolumeEnumerator::enumerateVolumesImpl()
{
	std::vector<VolumeInfo> volumes;

	for (const QString& volumeName: QDir("/Volumes/").entryList(QDir::NoDotAndDotDot | QDir::Dirs | QDir::Hidden | QDir::System))
	{
		VolumeInfo info;
		info.rootObjectInfo = "/Volumes/" + volumeName;
		info.volumeLabel = volumeName;
		info.isReady = true;

		const auto sys_info = volumeInfoForPath(info.rootObjectInfo.fullAbsolutePath());
		info.volumeSize = sys_info.f_bsize * sys_info.f_blocks;
		info.freeSize = sys_info.f_bsize * sys_info.f_bavail;
		info.fileSystemName = QString(sys_info.f_fstypename).toUpper();

		volumes.emplace_back(std::move(info));
	}

	return volumes;
}
<commit_msg>CVolumeEnumerator::enumerateVolumesImpl() improved on Mac<commit_after>#include "cvolumeenumerator.h"
#include "volumeinfohelper.hpp"

DISABLE_COMPILER_WARNINGS
#include <QDir>
RESTORE_COMPILER_WARNINGS

const std::vector<VolumeInfo> CVolumeEnumerator::enumerateVolumesImpl()
{
	std::vector<VolumeInfo> volumes;

	for (const QString& volumeName: QDir("/Volumes/").entryList(QDir::NoDotAndDotDot | QDir::Dirs | QDir::Hidden | QDir::System))
	{
		VolumeInfo info;
		info.volumeLabel = volumeName;
		info.isReady = true;

		const auto sys_info = volumeInfoForPath("/Volumes/" + volumeName);
		info.rootObjectInfo = sys_info.f_mntonname;
		info.volumeSize = sys_info.f_bsize * sys_info.f_blocks;
		info.freeSize = sys_info.f_bsize * sys_info.f_bavail;
		info.fileSystemName = QString(sys_info.f_fstypename).toUpper();

		volumes.emplace_back(std::move(info));
	}

	return volumes;
}
<|endoftext|>


<commit_before>// Copyright 2021 Google LLC

#include <chrono>  // NOLINT(build/c++11)
#include <thread>  // NOLINT(build/c++11)

#include "Firestore/core/src/auth/empty_credentials_provider.h"
#include "absl/memory/memory.h"
#include "app_framework.h"
#include "firebase/app.h"
#include "firebase/firestore.h"
#include "firestore/src/common/hard_assert_common.h"
#include "firestore/src/main/firestore_main.h"

namespace firebase {
namespace firestore {

using auth::EmptyCredentialsProvider;

struct TestFriend {
  static FirestoreInternal* CreateTestFirestoreInternal(App* app) {
#if !defined(__ANDROID__)
    return new FirestoreInternal(app,
                                 absl::make_unique<EmptyCredentialsProvider>());
#else
    return new FirestoreInternal(app);
#endif  // !defined(__ANDROID__)
  }
};

App* GetApp(const char* name) {
  // TODO(varconst): try to avoid using a real project ID when possible. iOS
  // unit tests achieve this by using fake options:
  // https://github.com/firebase/firebase-ios-sdk/blob/9a5afbffc17bb63b7bb7f51b9ea9a6a9e1c88a94/Firestore/core/test/firebase/firestore/testutil/app_testing.mm#L29

  if (name == nullptr || std::string{name} == kDefaultAppName) {
#if defined(__ANDROID__)
    return App::Create(app_framework::GetJniEnv(),
                       app_framework::GetActivity());
#else
    return App::Create();
#endif  // defined(__ANDROID__)
  } else {
    App* default_app = App::GetInstance();
    SIMPLE_HARD_ASSERT(default_app,
                       "Cannot create a named app before the default app");
#if defined(__ANDROID__)
    return App::Create(default_app->options(), name, app_framework::GetJniEnv(),
                       app_framework::GetActivity());
#else
    return App::Create(default_app->options(), name);
#endif  // defined(__ANDROID__)
  }
}

App* GetApp() { return GetApp(nullptr); }

FirestoreInternal* CreateTestFirestoreInternal(App* app) {
  return TestFriend::CreateTestFirestoreInternal(app);
}

void InitializeFirestore(Firestore* instance) {
  Firestore::set_log_level(LogLevel::kLogLevelDebug);
}

}  // namespace firestore
}  // namespace firebase
<commit_msg>Fix ODR violation of FirestoreInternal in integration_test_util.cc (#559)<commit_after>// Copyright 2021 Google LLC

#include <chrono>  // NOLINT(build/c++11)
#include <thread>  // NOLINT(build/c++11)

#include "Firestore/core/src/auth/empty_credentials_provider.h"
#include "absl/memory/memory.h"
#include "app_framework.h"
#include "firebase/app.h"
#include "firebase/firestore.h"
#include "firestore/src/common/hard_assert_common.h"

#if !defined(__ANDROID__)
#include "firestore/src/main/firestore_main.h"
#else
#include "firestore/src/android/firestore_android.h"
#endif  // !defined(__ANDROID__)

namespace firebase {
namespace firestore {

using auth::EmptyCredentialsProvider;

struct TestFriend {
  static FirestoreInternal* CreateTestFirestoreInternal(App* app) {
#if !defined(__ANDROID__)
    return new FirestoreInternal(app,
                                 absl::make_unique<EmptyCredentialsProvider>());
#else
    return new FirestoreInternal(app);
#endif  // !defined(__ANDROID__)
  }
};

App* GetApp(const char* name) {
  // TODO(varconst): try to avoid using a real project ID when possible. iOS
  // unit tests achieve this by using fake options:
  // https://github.com/firebase/firebase-ios-sdk/blob/9a5afbffc17bb63b7bb7f51b9ea9a6a9e1c88a94/Firestore/core/test/firebase/firestore/testutil/app_testing.mm#L29

  if (name == nullptr || std::string{name} == kDefaultAppName) {
#if defined(__ANDROID__)
    return App::Create(app_framework::GetJniEnv(),
                       app_framework::GetActivity());
#else
    return App::Create();
#endif  // defined(__ANDROID__)
  } else {
    App* default_app = App::GetInstance();
    SIMPLE_HARD_ASSERT(default_app,
                       "Cannot create a named app before the default app");
#if defined(__ANDROID__)
    return App::Create(default_app->options(), name, app_framework::GetJniEnv(),
                       app_framework::GetActivity());
#else
    return App::Create(default_app->options(), name);
#endif  // defined(__ANDROID__)
  }
}

App* GetApp() { return GetApp(nullptr); }

FirestoreInternal* CreateTestFirestoreInternal(App* app) {
  return TestFriend::CreateTestFirestoreInternal(app);
}

void InitializeFirestore(Firestore* instance) {
  Firestore::set_log_level(LogLevel::kLogLevelDebug);
}

}  // namespace firestore
}  // namespace firebase
<|endoftext|>


<commit_before>/***************************************************************************
 *   Copyright (c) Juergen Riegel          (juergen.riegel@web.de) 2014    *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 of the License, or (at your option) any later version.      *
 *                                                                         *
 *   This library  is distributed in the hope that it will be useful,      *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/

#include "PreCompiled.h"

#ifndef _PreComp_
#endif

#include <App/Document.h>
#include <App/Plane.h>

#include "Part.h"
#include "PartPy.h"

using namespace App;

PROPERTY_SOURCE(App::Part, App::GeoFeatureGroup)

//===========================================================================
// Feature
//===========================================================================

const char* Part::BaseplaneTypes[3] = {"XY-Plane", "XZ-Plane", "YZ-Plane"};

Part::Part(void)
{
    ADD_PROPERTY(Type,(""));
    ADD_PROPERTY_TYPE(Material, (), 0, App::Prop_None, "Map with material properties");
    ADD_PROPERTY_TYPE(Meta, (), 0, App::Prop_None, "Map with additional meta information");

    // create the uuid for the document
    Base::Uuid id;
    ADD_PROPERTY_TYPE(Id, (""), 0, App::Prop_None, "ID (Part-Number) of the Item");
    ADD_PROPERTY_TYPE(Uid, (id), 0, App::Prop_None, "UUID of the Item");

    // license stuff
    ADD_PROPERTY_TYPE(License, ("CC BY 3.0"), 0, App::Prop_None, "License string of the Item");
    ADD_PROPERTY_TYPE(LicenseURL, ("http://creativecommons.org/licenses/by/3.0/"), 0, App::Prop_None, "URL to the license text/contract");
    // color and apperance
    ADD_PROPERTY(Color, (1.0, 1.0, 1.0, 1.0)); // set transparent -> not used

}

Part::~Part(void)
{
}

PyObject *Part::getPyObject()
{
    if (PythonObject.is(Py::_None())){
        // ref counter is set to 1
        PythonObject = Py::Object(new PartPy(this),true);
    }
    return Py::new_reference_to(PythonObject);
}

// Python feature ---------------------------------------------------------

// Not quit sure yet makeing Part derivable in Python is good Idea!
// JR 2014

//namespace App {
///// @cond DOXERR
//PROPERTY_SOURCE_TEMPLATE(App::PartPython, App::Part)
//template<> const char* App::PartPython::getViewProviderName(void) const {
//    return "Gui::ViewProviderPartPython";
//}
//template<> PyObject* App::PartPython::getPyObject(void) {
//    if (PythonObject.is(Py::_None())) {
//        // ref counter is set to 1
//        PythonObject = Py::Object(new FeaturePythonPyT<App::PartPy>(this),true);
//    }
//    return Py::new_reference_to(PythonObject);
//}
///// @endcond
//
//// explicit template instantiation
//template class AppExport FeaturePythonT<App::Part>;
//}
<commit_msg>App: Part: rename base planes.<commit_after>/***************************************************************************
 *   Copyright (c) Juergen Riegel          (juergen.riegel@web.de) 2014    *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 of the License, or (at your option) any later version.      *
 *                                                                         *
 *   This library  is distributed in the hope that it will be useful,      *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/

#include "PreCompiled.h"

#ifndef _PreComp_
#endif

#include <App/Document.h>
#include <App/Plane.h>

#include "Part.h"
#include "PartPy.h"

using namespace App;

PROPERTY_SOURCE(App::Part, App::GeoFeatureGroup)

//===========================================================================
// Feature
//===========================================================================

const char* Part::BaseplaneTypes[3] = {"XY_Plane", "XZ_Plane", "YZ_Plane"};

Part::Part(void)
{
    ADD_PROPERTY(Type,(""));
    ADD_PROPERTY_TYPE(Material, (), 0, App::Prop_None, "Map with material properties");
    ADD_PROPERTY_TYPE(Meta, (), 0, App::Prop_None, "Map with additional meta information");

    // create the uuid for the document
    Base::Uuid id;
    ADD_PROPERTY_TYPE(Id, (""), 0, App::Prop_None, "ID (Part-Number) of the Item");
    ADD_PROPERTY_TYPE(Uid, (id), 0, App::Prop_None, "UUID of the Item");

    // license stuff
    ADD_PROPERTY_TYPE(License, ("CC BY 3.0"), 0, App::Prop_None, "License string of the Item");
    ADD_PROPERTY_TYPE(LicenseURL, ("http://creativecommons.org/licenses/by/3.0/"), 0, App::Prop_None, "URL to the license text/contract");
    // color and apperance
    ADD_PROPERTY(Color, (1.0, 1.0, 1.0, 1.0)); // set transparent -> not used

}

Part::~Part(void)
{
}

PyObject *Part::getPyObject()
{
    if (PythonObject.is(Py::_None())){
        // ref counter is set to 1
        PythonObject = Py::Object(new PartPy(this),true);
    }
    return Py::new_reference_to(PythonObject);
}

// Python feature ---------------------------------------------------------

// Not quit sure yet makeing Part derivable in Python is good Idea!
// JR 2014

//namespace App {
///// @cond DOXERR
//PROPERTY_SOURCE_TEMPLATE(App::PartPython, App::Part)
//template<> const char* App::PartPython::getViewProviderName(void) const {
//    return "Gui::ViewProviderPartPython";
//}
//template<> PyObject* App::PartPython::getPyObject(void) {
//    if (PythonObject.is(Py::_None())) {
//        // ref counter is set to 1
//        PythonObject = Py::Object(new FeaturePythonPyT<App::PartPy>(this),true);
//    }
//    return Py::new_reference_to(PythonObject);
//}
///// @endcond
//
//// explicit template instantiation
//template class AppExport FeaturePythonT<App::Part>;
//}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <iostream>
#include <cstdio>

#include "Compiler.hpp"

#include "Timer.hpp"
#include "DebugTimer.hpp"
#include "Options.hpp"

#include "StringPool.hpp"
#include "FunctionTable.hpp"

#include "ast/Program.hpp"

//Annotators
#include "DefaultValues.hpp"
#include "ContextAnnotator.hpp"
#include "FunctionsAnnotator.hpp"
#include "VariablesAnnotator.hpp"

//Checkers
#include "StringChecker.hpp"
#include "TypeChecker.hpp"

//Visitors
#include "OptimizationEngine.hpp"
#include "TransformerEngine.hpp"
#include "IntermediateCompiler.hpp"
#include "WarningsEngine.hpp"

//Three Address Code
#include "tac/TacCompiler.hpp"
#include "tac/Printer.hpp"
#include "tac/Program.hpp"
#include "tac/BasicBlockExtractor.hpp"
#include "tac/IntelX86CodeGenerator.hpp"

#include "SemanticalException.hpp"

#include "parser/SpiritParser.hpp"

#include "AssemblyFileWriter.hpp"

#ifdef DEBUG
static const bool debug = true;
#else
static const bool debug = false;
#endif

#define TIMER_START(name) Timer name_timer;
#define TIMER_END(name) if(debug){std::cout << #name << " took " << name_timer.elapsed() << "s" << std::endl;}

using namespace eddic;

int Compiler::compile(const std::string& file) {
    std::cout << "Compile " << file << std::endl;

    Timer timer;

    std::string output = options["output"].as<std::string>();

    int code = 0;
    try {
        TIMER_START(parsing)

        SpiritParser parser;

        //The program to build
        ast::Program program;

        //Parse the file into the program
        bool parsing = parser.parse(file, program);

        TIMER_END(parsing)

        if(parsing){
            //Symbol tables
            FunctionTable functionTable;
            StringPool pool;

            //Annotate the AST with more informations
            defineDefaultValues(program);
            defineContexts(program);
            defineVariables(program);
            defineFunctions(program, functionTable);

            //Transform the AST
            transform(program);

            //Static analysis
            checkStrings(program, pool);
            checkTypes(program);

            //Check for warnings
            checkForWarnings(program, functionTable);

            //Optimize the AST
            optimize(program, functionTable, pool);

            tac::Program tacProgram;

            //Generate Three-Address-Code language
            tac::TacCompiler compiler;
            compiler.compile(program, pool, tacProgram);

            //Separate into basic blocks
            tac::BasicBlockExtractor extractor;
            extractor.extract(tacProgram);

            //Generate assembly from TAC
            AssemblyFileWriter writer("output.asm");
            tac::IntelX86CodeGenerator generator(writer);
            generator.generate(tacProgram, pool);
            writer.write();

            //If it's necessary, assemble and link the assembly
            if(!options.count("assembly")){
                execCommand("as --32 -o output.o output.asm");
                execCommand("ld -m elf_i386 output.o -o " + output);

                //Remove temporary files
                remove("output.asm");
                remove("output.o");
            }
        }
    } catch (const SemanticalException& e) {
        std::cout << e.what() << std::endl;
        code = 1;
    }

    std::cout << "Compilation took " << timer.elapsed() << "s" << std::endl;

    return code;
}

void eddic::defineDefaultValues(ast::Program& program){
    DebugTimer<debug> timer("Annotate with default values");
    DefaultValues values;
    values.fill(program);
}

void eddic::defineContexts(ast::Program& program){
    DebugTimer<debug> timer("Annotate contexts");
    ContextAnnotator annotator;
    annotator.annotate(program);
}

void eddic::defineVariables(ast::Program& program){
    DebugTimer<debug> timer("Annotate variables");
    VariablesAnnotator annotator;
    annotator.annotate(program);
}

void eddic::defineFunctions(ast::Program& program, FunctionTable& functionTable){
    DebugTimer<debug> timer("Annotate functions");
    FunctionsAnnotator annotator;
    annotator.annotate(program, functionTable);
}

void eddic::checkStrings(ast::Program& program, StringPool& pool){
    DebugTimer<debug> timer("Strings checking");
    StringChecker checker;
    checker.check(program, pool);
}

void eddic::checkTypes(ast::Program& program){
    DebugTimer<debug> timer("Types checking");
    TypeChecker checker;
    checker.check(program);
}

void eddic::checkForWarnings(ast::Program& program, FunctionTable& table){
    DebugTimer<debug> timer("Check for warnings");
    WarningsEngine engine;
    engine.check(program, table);
}

void eddic::transform(ast::Program& program){
    DebugTimer<debug> timer("Transformation");
    TransformerEngine engine;
    engine.transform(program);
}

void eddic::optimize(ast::Program& program, FunctionTable& functionTable, StringPool& pool){
    DebugTimer<debug> timer("Optimization");
    OptimizationEngine engine;
    engine.optimize(program, functionTable, pool);
}

void eddic::execCommand(const std::string& command) {
    DebugTimer<debug> timer("Exec " + command);

    if(debug){
        std::cout << "eddic : exec command : " << command << std::endl;
    }

    char buffer[1024];

    FILE* stream = popen(command.c_str(), "r");

    while (fgets(buffer, 1024, stream) != NULL) {
        std::cout << buffer;
    }

    pclose(stream);
}

void eddic::warn(const std::string& warning){
    std::cout << "warning: " << warning << std::endl;
}
<commit_msg>Cleanup imports<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <iostream>
#include <cstdio>

#include "Compiler.hpp"

#include "Timer.hpp"
#include "DebugTimer.hpp"
#include "Options.hpp"

#include "StringPool.hpp"
#include "FunctionTable.hpp"
#include "SemanticalException.hpp"
#include "AssemblyFileWriter.hpp"

#include "ast/Program.hpp"

//Annotators
#include "DefaultValues.hpp"
#include "ContextAnnotator.hpp"
#include "FunctionsAnnotator.hpp"
#include "VariablesAnnotator.hpp"

//Checkers
#include "StringChecker.hpp"
#include "TypeChecker.hpp"

//Visitors
#include "OptimizationEngine.hpp"
#include "TransformerEngine.hpp"
#include "IntermediateCompiler.hpp"
#include "WarningsEngine.hpp"

//Three Address Code
#include "tac/TacCompiler.hpp"
#include "tac/Printer.hpp"
#include "tac/Program.hpp"
#include "tac/BasicBlockExtractor.hpp"
#include "tac/IntelX86CodeGenerator.hpp"

#include "parser/SpiritParser.hpp"

#ifdef DEBUG
static const bool debug = true;
#else
static const bool debug = false;
#endif

#define TIMER_START(name) Timer name_timer;
#define TIMER_END(name) if(debug){std::cout << #name << " took " << name_timer.elapsed() << "s" << std::endl;}

using namespace eddic;

int Compiler::compile(const std::string& file) {
    std::cout << "Compile " << file << std::endl;

    Timer timer;

    std::string output = options["output"].as<std::string>();

    int code = 0;
    try {
        TIMER_START(parsing)

        SpiritParser parser;

        //The program to build
        ast::Program program;

        //Parse the file into the program
        bool parsing = parser.parse(file, program);

        TIMER_END(parsing)

        if(parsing){
            //Symbol tables
            FunctionTable functionTable;
            StringPool pool;

            //Annotate the AST with more informations
            defineDefaultValues(program);
            defineContexts(program);
            defineVariables(program);
            defineFunctions(program, functionTable);

            //Transform the AST
            transform(program);

            //Static analysis
            checkStrings(program, pool);
            checkTypes(program);

            //Check for warnings
            checkForWarnings(program, functionTable);

            //Optimize the AST
            optimize(program, functionTable, pool);

            tac::Program tacProgram;

            //Generate Three-Address-Code language
            tac::TacCompiler compiler;
            compiler.compile(program, pool, tacProgram);

            //Separate into basic blocks
            tac::BasicBlockExtractor extractor;
            extractor.extract(tacProgram);

            //Generate assembly from TAC
            AssemblyFileWriter writer("output.asm");
            tac::IntelX86CodeGenerator generator(writer);
            generator.generate(tacProgram, pool);
            writer.write();

            //If it's necessary, assemble and link the assembly
            if(!options.count("assembly")){
                execCommand("as --32 -o output.o output.asm");
                execCommand("ld -m elf_i386 output.o -o " + output);

                //Remove temporary files
                remove("output.asm");
                remove("output.o");
            }
        }
    } catch (const SemanticalException& e) {
        std::cout << e.what() << std::endl;
        code = 1;
    }

    std::cout << "Compilation took " << timer.elapsed() << "s" << std::endl;

    return code;
}

void eddic::defineDefaultValues(ast::Program& program){
    DebugTimer<debug> timer("Annotate with default values");
    DefaultValues values;
    values.fill(program);
}

void eddic::defineContexts(ast::Program& program){
    DebugTimer<debug> timer("Annotate contexts");
    ContextAnnotator annotator;
    annotator.annotate(program);
}

void eddic::defineVariables(ast::Program& program){
    DebugTimer<debug> timer("Annotate variables");
    VariablesAnnotator annotator;
    annotator.annotate(program);
}

void eddic::defineFunctions(ast::Program& program, FunctionTable& functionTable){
    DebugTimer<debug> timer("Annotate functions");
    FunctionsAnnotator annotator;
    annotator.annotate(program, functionTable);
}

void eddic::checkStrings(ast::Program& program, StringPool& pool){
    DebugTimer<debug> timer("Strings checking");
    StringChecker checker;
    checker.check(program, pool);
}

void eddic::checkTypes(ast::Program& program){
    DebugTimer<debug> timer("Types checking");
    TypeChecker checker;
    checker.check(program);
}

void eddic::checkForWarnings(ast::Program& program, FunctionTable& table){
    DebugTimer<debug> timer("Check for warnings");
    WarningsEngine engine;
    engine.check(program, table);
}

void eddic::transform(ast::Program& program){
    DebugTimer<debug> timer("Transformation");
    TransformerEngine engine;
    engine.transform(program);
}

void eddic::optimize(ast::Program& program, FunctionTable& functionTable, StringPool& pool){
    DebugTimer<debug> timer("Optimization");
    OptimizationEngine engine;
    engine.optimize(program, functionTable, pool);
}

void eddic::execCommand(const std::string& command) {
    DebugTimer<debug> timer("Exec " + command);

    if(debug){
        std::cout << "eddic : exec command : " << command << std::endl;
    }

    char buffer[1024];

    FILE* stream = popen(command.c_str(), "r");

    while (fgets(buffer, 1024, stream) != NULL) {
        std::cout << buffer;
    }

    pclose(stream);
}

void eddic::warn(const std::string& warning){
    std::cout << "warning: " << warning << std::endl;
}
<|endoftext|>


<commit_before>/*---------------------------------------------------------------------\
|                                                                      |
|                     _     _   _   _     __     _                     |
|                    | |   | | | \_/ |   /  \   | |                    |
|                    | |   | | | |_| |  / /\ \  | |                    |
|                    | |__ | | | | | | / ____ \ | |__                  |
|                    |____||_| |_| |_|/ /    \ \|____|                 |
|                                                                      |
|                             ca-mgm library                           |
|                                                                      |
|                                         (C) SUSE Linux Products GmbH |
\----------------------------------------------------------------------/

  File:       DNObject.cpp

  Author:     <Michael Calmer>     <mc@suse.de>
  Maintainer: <Michael Calmer>     <mc@suse.de>

  Purpose:

/-*/

#include  <limal/ca-mgm/DNObject.hpp>
#include  <limal/ca-mgm/CAConfig.hpp>
#include  <limal/ValueRegExCheck.hpp>
#include  <limal/Exception.hpp>
#include  <blocxx/Format.hpp>

#include  "DNObject_Priv.hpp"
#include  "Utils.hpp"

using namespace limal;
using namespace limal::ca_mgm;
using namespace blocxx;

RDNObject::RDNObject(const RDNObject& rdn)
    : type(rdn.type), value(rdn.value)
{}

RDNObject::~RDNObject()
{}

RDNObject&
RDNObject::operator=(const RDNObject& rdn)
{
    if(this == &rdn) return *this;

    type  = rdn.type;
    value = rdn.value;

    return *this;
}

void
RDNObject::setRDNValue(const String& value)
{
    this->value = value;
}

blocxx::String
RDNObject::getType() const
{
    return type;
}

blocxx::String
RDNObject::getValue() const
{
    return value;
}

bool
RDNObject::valid() const
{
    if(type.empty()) {
        LOGIT_DEBUG("type is empty");
        return false;
    }
    /*
      if(value.empty()) {
      LOGIT_DEBUG("value is empty");
      return false;
      }
    */
    // FIXME: define and check pre defined types ?

    return true;
}

blocxx::StringArray
RDNObject::verify() const
{
    StringArray result;

    if(type.empty()) {
        result.append("type is empty");
    }
    /*
      if(value.empty()) {
      result.append("value is empty");
      }
    */
    // FIXME: define and check pre defined types ?

    LOGIT_DEBUG_STRINGARRAY("RDNObject::verify()", result);

    return result;
}

blocxx::StringArray
RDNObject::dump() const
{
    StringArray result;
    result.append("RDNObject::dump()");

    result.append(type + "=" + value);

    return result;
}

// protected

RDNObject::RDNObject()
    : type(String()), value(String())
{
}

// ######################################################################

DNObject::DNObject()
    : dn(blocxx::List<RDNObject>())
{
    dn.push_back(RDNObject_Priv("countryName", ""));
    dn.push_back(RDNObject_Priv("stateOrProvinceName", ""));
    dn.push_back(RDNObject_Priv("localityName", ""));
    dn.push_back(RDNObject_Priv("organizationName", ""));
    dn.push_back(RDNObject_Priv("organizationalUnitName", ""));
    dn.push_back(RDNObject_Priv("commonName", ""));
    dn.push_back(RDNObject_Priv("emailAddress", ""));
}

DNObject::DNObject(CAConfig* caConfig, Type type)
    : dn(blocxx::List<RDNObject>())
{
    // FIXME: get these values from the configfile
    dn.push_back(RDNObject_Priv("countryName", ""));
    dn.push_back(RDNObject_Priv("stateOrProvinceName", ""));
    dn.push_back(RDNObject_Priv("localityName", ""));
    dn.push_back(RDNObject_Priv("organizationName", ""));
    dn.push_back(RDNObject_Priv("organizationalUnitName", ""));
    dn.push_back(RDNObject_Priv("commonName", ""));
    dn.push_back(RDNObject_Priv("emailAddress", ""));
}

DNObject::DNObject(const blocxx::List<RDNObject> &dn)
    : dn(dn)
{
    StringArray r = this->verify();
    if(!r.empty()) {
        BLOCXX_THROW(limal::ValueException, r[0].c_str());
    }
}

DNObject::DNObject(const DNObject& dn)
    : dn(dn.dn)
{}

DNObject::~DNObject()
{}

DNObject&
DNObject::operator=(const DNObject& dn)
{
    if(this == &dn) return *this;

    this->dn = dn.dn;

    return *this;
}

void
DNObject::setDN(const blocxx::List<RDNObject> &dn)
{
    StringArray r = checkRDNList(dn);
    if(!r.empty()) {
        LOGIT_ERROR(r[0]);
        BLOCXX_THROW(limal::ValueException, r[0].c_str());
    }
    this->dn = dn;
}

blocxx::List<RDNObject>
DNObject::getDN() const
{
    return dn;
}

bool
DNObject::valid() const
{
    if(dn.empty()) {
        LOGIT_DEBUG("empty DN");
        return false;
    }
    StringArray r = checkRDNList(dn);
    if(!r.empty()) {
        LOGIT_DEBUG(r[0]);
        return false;
    }
    return true;
}

blocxx::StringArray
DNObject::verify() const
{
    StringArray result;

    if(dn.empty()) {
        result.append("empty DN");
    }
    result.appendArray(checkRDNList(dn));

    LOGIT_DEBUG_STRINGARRAY("DNObject::verify()", result);

    return result;
}

blocxx::StringArray
DNObject::checkRDNList(const blocxx::List<RDNObject>& list) const
{
    StringArray result;

    blocxx::List<RDNObject>::const_iterator it = list.begin();
    for(; it != list.end(); ++it) {
        result.appendArray((*it).verify());
    }
    return result;
}

blocxx::StringArray
DNObject::dump() const
{
    StringArray result;
    result.append("DNObject::dump()");

    blocxx::List< RDNObject >::const_iterator it = dn.begin();
    for(; it != dn.end(); ++it) {
        result.appendArray((*it).dump());
    }

    return result;
}
<commit_msg>try to implement reading DN keys and order from openssl.cnf; does not work currently<commit_after>/*---------------------------------------------------------------------\
|                                                                      |
|                     _     _   _   _     __     _                     |
|                    | |   | | | \_/ |   /  \   | |                    |
|                    | |   | | | |_| |  / /\ \  | |                    |
|                    | |__ | | | | | | / ____ \ | |__                  |
|                    |____||_| |_| |_|/ /    \ \|____|                 |
|                                                                      |
|                             ca-mgm library                           |
|                                                                      |
|                                         (C) SUSE Linux Products GmbH |
\----------------------------------------------------------------------/

  File:       DNObject.cpp

  Author:     <Michael Calmer>     <mc@suse.de>
  Maintainer: <Michael Calmer>     <mc@suse.de>

  Purpose:

/-*/

#include  <limal/ca-mgm/DNObject.hpp>
#include  <limal/ca-mgm/CAConfig.hpp>
#include  <limal/ValueRegExCheck.hpp>
#include  <limal/Exception.hpp>
#include  <blocxx/Format.hpp>

#include  "DNObject_Priv.hpp"
#include  "Utils.hpp"

using namespace limal;
using namespace limal::ca_mgm;
using namespace blocxx;

RDNObject::RDNObject(const RDNObject& rdn)
    : type(rdn.type), value(rdn.value)
{}

RDNObject::~RDNObject()
{}

RDNObject&
RDNObject::operator=(const RDNObject& rdn)
{
    if(this == &rdn) return *this;

    type  = rdn.type;
    value = rdn.value;

    return *this;
}

void
RDNObject::setRDNValue(const String& value)
{
    this->value = value;
}

blocxx::String
RDNObject::getType() const
{
    return type;
}

blocxx::String
RDNObject::getValue() const
{
    return value;
}

bool
RDNObject::valid() const
{
    if(type.empty()) {
        LOGIT_DEBUG("type is empty");
        return false;
    }
    /*
      if(value.empty()) {
      LOGIT_DEBUG("value is empty");
      return false;
      }
    */
    // FIXME: define and check pre defined types ?

    return true;
}

blocxx::StringArray
RDNObject::verify() const
{
    StringArray result;

    if(type.empty()) {
        result.append("type is empty");
    }
    /*
      if(value.empty()) {
      result.append("value is empty");
      }
    */
    // FIXME: define and check pre defined types ?

    LOGIT_DEBUG_STRINGARRAY("RDNObject::verify()", result);

    return result;
}

blocxx::StringArray
RDNObject::dump() const
{
    StringArray result;
    result.append("RDNObject::dump()");

    result.append(type + "=" + value);

    return result;
}

// protected

RDNObject::RDNObject()
    : type(String()), value(String())
{
}

// ######################################################################

DNObject::DNObject()
    : dn(blocxx::List<RDNObject>())
{
    dn.push_back(RDNObject_Priv("countryName", ""));
    dn.push_back(RDNObject_Priv("stateOrProvinceName", ""));
    dn.push_back(RDNObject_Priv("localityName", ""));
    dn.push_back(RDNObject_Priv("organizationName", ""));
    dn.push_back(RDNObject_Priv("organizationalUnitName", ""));
    dn.push_back(RDNObject_Priv("commonName", ""));
    dn.push_back(RDNObject_Priv("emailAddress", ""));
}

DNObject::DNObject(CAConfig* caConfig, Type type)
    : dn(blocxx::List<RDNObject>())
{
    if(type == Client_Cert || type == Server_Cert ||
       type == CA_Cert     || type == CRL           ) {
        LOGIT_ERROR("wrong type" << type);
        BLOCXX_THROW(limal::ValueException, Format("wrong type: %1", type).c_str());
    }

#if 0

    // FIXME: does not work till we get the exact order of the keys
    //        like it is in the configfiles

    bool p = caConfig->exists(type2Section(type, false), "distinguished_name");
    if(!p) {
        LOGIT_ERROR("missing section 'distinguished_name' in config file");
        BLOCXX_THROW(limal::SyntaxException,
                     "missing section 'distinguished_name' in config file");
    }
    String dnSect = caConfig->getValue(type2Section(type, false),
                                       "distinguished_name");

    StringList dnKeys = caConfig->getKeylist(dnSect);

    if(dnKeys.empty()) {
        LOGIT_ERROR("Can not parse Section " << dnSect);
        BLOCXX_THROW(limal::SyntaxException,
                     Format("Can not parse Section %1", dnSect).c_str());
    }
    StringList::const_iterator it = dnKeys.begin();

    String fieldName;
    String prompt;
    String defaultValue;
    String min;
    String max;

    Array<Map<String, String> > configDN;

    for(; it != dnKeys.end(); ++it) {

        if((*it).endsWith("_default", String::E_CASE_INSENSITIVE)) {

            if((*it).startsWith(fieldName, String::E_CASE_INSENSITIVE)) {

                defaultValue = caConfig->getValue(dnSect, *it);

            } else {
                LOGIT_INFO("Wrong order of section '" << dnSect <<
                           "'. FieldName is '" << fieldName <<
                           "' but parsed Key is '" << *it <<
                           "'. Ignoring value.");
                continue;
            }

        } else if((*it).endsWith("_min", String::E_CASE_INSENSITIVE)) {

            if((*it).startsWith(fieldName, String::E_CASE_INSENSITIVE)) {

                min = caConfig->getValue(dnSect, *it);

            } else {
                LOGIT_INFO("Wrong order of section '" << dnSect <<
                           "'. FieldName is '" << fieldName <<
                           "' but parsed Key is '" << *it <<
                           "'. Ignoring value.");
                continue;
            }

        } else if((*it).endsWith("_max", String::E_CASE_INSENSITIVE)) {

            if((*it).startsWith(fieldName, String::E_CASE_INSENSITIVE)) {

                max = caConfig->getValue(dnSect, *it);

            } else {
                LOGIT_INFO("Wrong order of section '" << dnSect <<
                           "'. FieldName is '" << fieldName <<
                           "' but parsed Key is '" << *it <<
                           "'. Ignoring value.");
                continue;
            }

        } else {
            // A new fieldName

            // commit values
            if(!fieldName.empty()) {

                dn.push_back(RDNObject_Priv(fieldName, defaultValue));
                //FIXME: do something with the other values too

            }

            // reset
            prompt       = String();
            defaultValue = String();
            min          = String();
            max          = String();

            fieldName    = *it;
            prompt       = caConfig->getValue(dnSect, *it);

        }

    }
    // commit the last values
    if(!fieldName.empty()) {

        dn.push_back(RDNObject_Priv(fieldName, defaultValue));
        //FIXME: do something with the other values too

    }
#endif

    dn.push_back(RDNObject_Priv("countryName", ""));
    dn.push_back(RDNObject_Priv("stateOrProvinceName", ""));
    dn.push_back(RDNObject_Priv("localityName", ""));
    dn.push_back(RDNObject_Priv("organizationName", ""));
    dn.push_back(RDNObject_Priv("organizationalUnitName", ""));
    dn.push_back(RDNObject_Priv("commonName", ""));
    dn.push_back(RDNObject_Priv("emailAddress", ""));

}

DNObject::DNObject(const blocxx::List<RDNObject> &dn)
    : dn(dn)
{
    StringArray r = this->verify();
    if(!r.empty()) {
        BLOCXX_THROW(limal::ValueException, r[0].c_str());
    }
}

DNObject::DNObject(const DNObject& dn)
    : dn(dn.dn)
{}

DNObject::~DNObject()
{}

DNObject&
DNObject::operator=(const DNObject& dn)
{
    if(this == &dn) return *this;

    this->dn = dn.dn;

    return *this;
}

void
DNObject::setDN(const blocxx::List<RDNObject> &dn)
{
    StringArray r = checkRDNList(dn);
    if(!r.empty()) {
        LOGIT_ERROR(r[0]);
        BLOCXX_THROW(limal::ValueException, r[0].c_str());
    }
    this->dn = dn;
}

blocxx::List<RDNObject>
DNObject::getDN() const
{
    return dn;
}

bool
DNObject::valid() const
{
    if(dn.empty()) {
        LOGIT_DEBUG("empty DN");
        return false;
    }
    StringArray r = checkRDNList(dn);
    if(!r.empty()) {
        LOGIT_DEBUG(r[0]);
        return false;
    }
    return true;
}

blocxx::StringArray
DNObject::verify() const
{
    StringArray result;

    if(dn.empty()) {
        result.append("empty DN");
    }
    result.appendArray(checkRDNList(dn));

    LOGIT_DEBUG_STRINGARRAY("DNObject::verify()", result);

    return result;
}

blocxx::StringArray
DNObject::checkRDNList(const blocxx::List<RDNObject>& list) const
{
    StringArray result;

    blocxx::List<RDNObject>::const_iterator it = list.begin();
    for(; it != list.end(); ++it) {
        result.appendArray((*it).verify());
    }
    return result;
}

blocxx::StringArray
DNObject::dump() const
{
    StringArray result;
    result.append("DNObject::dump()");

    blocxx::List< RDNObject >::const_iterator it = dn.begin();
    for(; it != dn.end(); ++it) {
        result.appendArray((*it).dump());
    }

    return result;
}
<|endoftext|>


<commit_before>#include <Refal2.h>

namespace Refal2 {

//-----------------------------------------------------------------------------

class CRulePrintHelper : public CPrintHelper {
public:
	CRulePrintHelper( const CPrintHelper& _printHelper,
			const CVariables& _variables ) :
		printHelper( _printHelper ),
		variables( _variables )
	{
	}

	virtual void Variable( std::ostream& outputStream,
		const TVariableIndex variable ) const
	{
		outputStream << variables.GetVariable( variable ).GetType();
		variables.GetVariable( variable ).GetQualifier().Print( outputStream,
			printHelper );
	}

	virtual void Label( std::ostream& outputStream,
		const TLabel label ) const
	{
		printHelper.Label( outputStream, label );
	}

private:
	const CPrintHelper& printHelper;
	const CVariables& variables;
};

void CRule::Print( std::ostream& outputStream,
	const CPrintHelper& printHelper ) const
{
	CRulePrintHelper rulePrintHelper( printHelper, Variables );
	outputStream << "\t" << ( RightMatching ? "R" : "" ) << " ";
	Left.Print( outputStream, rulePrintHelper );
	outputStream << "= ";
	Right.Print( outputStream, printHelper );
}

void CRule::Compile( CFunctionCompiler& compiler ) const
{
	compiler.CompileRule( const_cast<CRule&>( *this ) );
}

//-----------------------------------------------------------------------------

CPreparatoryFunction::CPreparatoryFunction( const CToken& _nameToken ):
	type( PFT_Declared ),
	entry( false ),
	name( _nameToken.word ),
	nameToken( _nameToken ),
	firstOperation( nullptr )
{
	assert( !name.empty() );
	MakeLower( name );
}

const std::string& CPreparatoryFunction::ExternalName() const
{
	assert( IsEntry() || IsExternal() );
	return externalName;
}

const CToken& CPreparatoryFunction::ExternalNameToken() const
{
	assert( IsEntry() || IsExternal() );
	return externalNameToken;
}

const CRule* CPreparatoryFunction::FirstRule() const
{
	assert( IsOrdinary() );
	return firstRule.get();
}

TOperationAddress CPreparatoryFunction::FirstOperation() const
{
	assert( IsCompiled() );
	return firstOperation;
}

void CPreparatoryFunction::SetDefined( const CToken& _nameToken )
{
	assert( _nameToken.type == TT_Word );
	assert( CompareNoCase( nameToken.word, _nameToken.word ) );
	assert( type == PFT_Declared );
	type = PFT_Defined;
	nameToken = _nameToken;
}

void CPreparatoryFunction::SetOrdinary( CRulePtr& _firstRule )
{
	assert( type == PFT_Defined );
	assert( static_cast<bool>( _firstRule ) );
	type = PFT_Ordinary;
	firstRule.reset( _firstRule.release() );
}

void CPreparatoryFunction::SetEmpty()
{
	assert( type == PFT_Defined );
	type = PFT_Empty;
}

void CPreparatoryFunction::SetEntry( const CToken& _externalNameToken )
{
	assert( type != PFT_External );
	entry = true;
	setExternalName( _externalNameToken );
}

void CPreparatoryFunction::SetExternal( const CToken& _externalNameToken )
{
	assert( !entry );
	assert( type == PFT_Defined );
	type = PFT_External;
	setExternalName( _externalNameToken );
}

void CPreparatoryFunction::Compile( CFunctionCompiler& compiler )
{
	assert( IsOrdinary() );
	const CRule* rule = FirstRule();
	while( rule != nullptr ) {
		rule->Compile( compiler );
		rule = rule->NextRule.get();
	}
	type = PFT_Compiled;
	firstOperation = compiler.GetFirstOperation();
	assert( firstOperation != nullptr );
}

void CPreparatoryFunction::Print( std::ostream& outputStream,
	const CPrintHelper& printHelper ) const
{
	assert( IsOrdinary() );
	const CRule* rule = FirstRule();
	while( rule != nullptr ) {
		rule->Print( outputStream, printHelper );
		outputStream << std::endl;
		rule = rule->NextRule.get();
	}
}

void CPreparatoryFunction::setExternalName( const CToken& _externalNameToken )
{
	assert( ( entry && !IsExternal() ) || ( !entry && IsExternal() ) );
	externalNameToken = _externalNameToken;
	externalName = externalNameToken.word;
	assert( !externalName.empty() );
	MakeLower( externalName );
}

//-----------------------------------------------------------------------------

CFunctionBuilder::CFunctionBuilder( IErrorHandler* errorHandler ):
	CVariablesBuilder( errorHandler ),
	isProcessRightPart( false ),
	isRightDirection( false ),
	lastRule( nullptr )
{
}

CFunctionBuilder::~CFunctionBuilder()
{
	Reset();
}

void CFunctionBuilder::Reset()
{
	CVariablesBuilder::Reset();
	isProcessRightPart = false;
	isRightDirection = false;
	acc.Empty();
	leftPart.Empty();
	emptyRules();
	emptyStack();
}

void CFunctionBuilder::Export( CRulePtr& _firstRule )
{
	// todo: check rule
	if( !HasErrors() && static_cast<bool>( firstRule ) ) {
		_firstRule.reset( firstRule.release() );
	}
	Reset();
}

void CFunctionBuilder::SetRightDirection()
{
	isRightDirection = true;
}

void CFunctionBuilder::AddEndOfLeft()
{
	if( isProcessRightPart ) {
		error( EC_ThereAreMultiplePartsSeparatorInRules );
	} else {
		while( !balanceStack.empty() ) {
			balanceStack.pop();
			error( EC_UnclosedLeftParenInLeftPart );
		}
		if( HasErrors() ) {
			acc.Empty();
		} else {
			acc.Move( leftPart );
		}
		isProcessRightPart = true;
	}
}

void CFunctionBuilder::AddEndOfRight()
{
	while( !balanceStack.empty() ) {
		CUnitNode* unit = balanceStack.top();
		balanceStack.pop();
		error( unit->IsLeftParen() ? EC_UnclosedLeftParenInRightPart :
			EC_UnclosedLeftBracketInRightPart );
	}
	if( !isProcessRightPart ) {
		error( EC_ThereAreNoPartsSeparatorInRules );
	}
	if( HasErrors() ) {
		acc.Empty();
		CVariablesBuilder::Reset();
	} else {
		addRule();
	}
	isProcessRightPart = false;
}

void CFunctionBuilder::AddChar( TChar c )
{
	if( !HasErrors() ) {
		acc.AppendChar( c );
	}
}

void CFunctionBuilder::AddLabel( TLabel label )
{
	if( !HasErrors() ) {
		acc.AppendLabel( label );
	}
}

void CFunctionBuilder::AddNumber( TNumber number )
{
	if( !HasErrors() ) {
		acc.AppendNumber( number );
	}
}

void CFunctionBuilder::AddVariable( TVariableTypeTag type, TVariableName name,
	CQualifier* qualifier )
{
	TVariableIndex index = InvalidVariableIndex;
	if( isProcessRightPart ) {
		index = CVariablesBuilder::AddRight( name, type );
	} else {
		index = CVariablesBuilder::AddLeft( name, type );
	}
	if( !HasErrors() ) {
		if( index == InvalidVariableIndex ) {
			//SetErrors();
		} else {
			if( qualifier != nullptr ) {
				CVariablesBuilder::AddQualifier( index, *qualifier );
			}
			acc.AppendVariable( index );
		}
	}
}

void CFunctionBuilder::AddLeftParen()
{
	balanceStack.push( acc.AppendLeftParen() );
}

void CFunctionBuilder::AddRightParen()
{
	CUnitNode* leftParen = nullptr;
	if( !balanceStack.empty() ) {
		leftParen = balanceStack.top();
	}
	if( leftParen != nullptr && leftParen->IsLeftParen() ) {
		leftParen->PairedParen() = acc.AppendRightParen(leftParen);
		balanceStack.pop();
	} else {
		error( EC_RightParenDoesNotMatchLeftParen );
	}
}

void CFunctionBuilder::AddLeftBracket()
{
	if( isProcessRightPart ) {
		balanceStack.push( acc.AppendLeftBracket() );
	} else {
		error( EC_IllegalLeftBracketInLeftPart );
	}
}

void CFunctionBuilder::AddRightBracket()
{
	if( isProcessRightPart ) {
		CUnitNode* leftBracket = nullptr;
		if( !balanceStack.empty() ) {
			leftBracket = balanceStack.top();
		}
		if( leftBracket != nullptr && leftBracket->IsLeftBracket() ) {
			leftBracket->PairedParen() = acc.AppendRightBracket(leftBracket);
			balanceStack.pop();
		} else {
			error( EC_RightBracketDoesNotMatchLeftBracket );
		}
	} else {
		error( EC_IllegalRightBracketInLeftPart );
	}
}

const char* CFunctionBuilder::getErrorMessage( TErrorCode errorCode )
{
	switch( errorCode ) {
		case EC_IllegalLeftBracketInLeftPart:
			return "illegal left bracket in left part of rule";
		case EC_IllegalRightBracketInLeftPart:
			return "illegal right bracket in left part of rule";
		case EC_RightParenDoesNotMatchLeftParen:
			return "right paren does not match left paren";
		case EC_RightBracketDoesNotMatchLeftBracket:
			return "right bracket does not match left bracket";
		case EC_UnclosedLeftParenInLeftPart:
			return "unclosed left paren in left part of rule";
		case EC_UnclosedLeftParenInRightPart:
			return "unclosed left paren in right part of rule";
		case EC_UnclosedLeftBracketInRightPart:
			return "unclosed left bracket in right part of rule";
		case EC_ThereAreMultiplePartsSeparatorInRules:
			return "there are multiple parts separator in rule";
		case EC_ThereAreNoPartsSeparatorInRules:
			return "there are no parts separator in rule";
	}
	assert( false );
	return nullptr;
}

void CFunctionBuilder::error( TErrorCode errorCode )
{
	CErrorsHelper::RaiseError( ES_Error, getErrorMessage( errorCode ) );
}

void CFunctionBuilder::emptyStack()
{
	std::stack<CUnitNode*> emptyStack;
	std::swap( balanceStack, emptyStack );
}

void CFunctionBuilder::emptyRules()
{
	firstRule.reset();
	lastRule = nullptr;
}

void CFunctionBuilder::addRule()
{
	if( static_cast<bool>( firstRule ) ) {
		lastRule->NextRule.reset( new CRule );
		lastRule = lastRule->NextRule.get();
	} else {
		firstRule.reset( new CRule );
		lastRule = firstRule.get();
	}

	lastRule->RightMatching = isRightDirection;
	leftPart.Move( lastRule->Left );
	acc.Move( lastRule->Right );
	CVariablesBuilder::Export( lastRule->Variables );
}

//-----------------------------------------------------------------------------

} // end of namespace refal2
<commit_msg>refactoring<commit_after>#include <Refal2.h>

namespace Refal2 {

//-----------------------------------------------------------------------------

class CRulePrintHelper : public CPrintHelper {
public:
	CRulePrintHelper( const CPrintHelper& _printHelper,
			const CVariables& _variables ) :
		printHelper( _printHelper ),
		variables( _variables )
	{
	}

	virtual void Variable( std::ostream& outputStream,
		const TVariableIndex variable ) const
	{
		outputStream << variables.GetVariable( variable ).GetType();
		variables.GetVariable( variable ).GetQualifier().Print( outputStream,
			printHelper );
	}

	virtual void Label( std::ostream& outputStream,
		const TLabel label ) const
	{
		printHelper.Label( outputStream, label );
	}

private:
	const CPrintHelper& printHelper;
	const CVariables& variables;
};

void CRule::Print( std::ostream& outputStream,
	const CPrintHelper& printHelper ) const
{
	CRulePrintHelper rulePrintHelper( printHelper, Variables );
	outputStream << "\t" << ( RightMatching ? "R" : "" ) << " ";
	Left.Print( outputStream, rulePrintHelper );
	outputStream << "= ";
	Right.Print( outputStream, printHelper );
}

void CRule::Compile( CFunctionCompiler& compiler ) const
{
	compiler.CompileRule( const_cast<CRule&>( *this ) );
}

//-----------------------------------------------------------------------------

CPreparatoryFunction::CPreparatoryFunction( const CToken& _nameToken ):
	type( PFT_Declared ),
	entry( false ),
	name( _nameToken.word ),
	nameToken( _nameToken ),
	firstOperation( nullptr )
{
	assert( !name.empty() );
	MakeLower( name );
}

const std::string& CPreparatoryFunction::ExternalName() const
{
	assert( IsEntry() || IsExternal() );
	return externalName;
}

const CToken& CPreparatoryFunction::ExternalNameToken() const
{
	assert( IsEntry() || IsExternal() );
	return externalNameToken;
}

const CRule* CPreparatoryFunction::FirstRule() const
{
	assert( IsOrdinary() );
	return firstRule.get();
}

TOperationAddress CPreparatoryFunction::FirstOperation() const
{
	assert( IsCompiled() );
	return firstOperation;
}

void CPreparatoryFunction::SetDefined( const CToken& _nameToken )
{
	assert( _nameToken.type == TT_Word );
	assert( CompareNoCase( nameToken.word, _nameToken.word ) );
	assert( type == PFT_Declared );
	type = PFT_Defined;
	nameToken = _nameToken;
}

void CPreparatoryFunction::SetOrdinary( CRulePtr& _firstRule )
{
	assert( type == PFT_Defined );
	assert( static_cast<bool>( _firstRule ) );
	type = PFT_Ordinary;
	firstRule.reset( _firstRule.release() );
}

void CPreparatoryFunction::SetEmpty()
{
	assert( type == PFT_Defined );
	type = PFT_Empty;
}

void CPreparatoryFunction::SetEntry( const CToken& _externalNameToken )
{
	assert( type != PFT_External );
	entry = true;
	setExternalName( _externalNameToken );
}

void CPreparatoryFunction::SetExternal( const CToken& _externalNameToken )
{
	assert( !entry );
	assert( type == PFT_Defined );
	type = PFT_External;
	setExternalName( _externalNameToken );
}

void CPreparatoryFunction::Compile( CFunctionCompiler& compiler )
{
	assert( IsOrdinary() );
	const CRule* rule = FirstRule();
	while( rule != nullptr ) {
		rule->Compile( compiler );
		rule = rule->NextRule.get();
	}
	type = PFT_Compiled;
	firstOperation = compiler.GetFirstOperation();
	assert( firstOperation != nullptr );
}

void CPreparatoryFunction::Print( std::ostream& outputStream,
	const CPrintHelper& printHelper ) const
{
	assert( IsOrdinary() );
	const CRule* rule = FirstRule();
	while( rule != nullptr ) {
		rule->Print( outputStream, printHelper );
		outputStream << std::endl;
		rule = rule->NextRule.get();
	}
}

void CPreparatoryFunction::setExternalName( const CToken& _externalNameToken )
{
	assert( ( entry && !IsExternal() ) || ( !entry && IsExternal() ) );
	externalNameToken = _externalNameToken;
	externalName = externalNameToken.word;
	assert( !externalName.empty() );
	MakeLower( externalName );
}

//-----------------------------------------------------------------------------

CFunctionBuilder::CFunctionBuilder( IErrorHandler* errorHandler ):
	CVariablesBuilder( errorHandler ),
	isProcessRightPart( false ),
	isRightDirection( false ),
	lastRule( nullptr )
{
}

CFunctionBuilder::~CFunctionBuilder()
{
	Reset();
}

void CFunctionBuilder::Reset()
{
	CVariablesBuilder::Reset();
	isProcessRightPart = false;
	isRightDirection = false;
	acc.Empty();
	leftPart.Empty();
	emptyRules();
	emptyStack();
}

void CFunctionBuilder::Export( CRulePtr& _firstRule )
{
	// todo: check rule
	if( !HasErrors() && static_cast<bool>( firstRule ) ) {
		_firstRule.reset( firstRule.release() );
	}
	Reset();
}

void CFunctionBuilder::SetRightDirection()
{
	isRightDirection = true;
}

void CFunctionBuilder::AddEndOfLeft()
{
	if( isProcessRightPart ) {
		error( EC_ThereAreMultiplePartsSeparatorInRules );
	} else {
		while( !balanceStack.empty() ) {
			balanceStack.pop();
			error( EC_UnclosedLeftParenInLeftPart );
		}
		if( HasErrors() ) {
			acc.Empty();
		} else {
			acc.Move( leftPart );
		}
		isProcessRightPart = true;
	}
}

void CFunctionBuilder::AddEndOfRight()
{
	while( !balanceStack.empty() ) {
		CUnitNode* unit = balanceStack.top();
		balanceStack.pop();
		error( unit->IsLeftParen() ? EC_UnclosedLeftParenInRightPart :
			EC_UnclosedLeftBracketInRightPart );
	}
	if( !isProcessRightPart ) {
		error( EC_ThereAreNoPartsSeparatorInRules );
	}
	if( HasErrors() ) {
		acc.Empty();
		CVariablesBuilder::Reset();
	} else {
		addRule();
	}
	isProcessRightPart = false;
}

void CFunctionBuilder::AddChar( TChar c )
{
	if( !HasErrors() ) {
		acc.AppendChar( c );
	}
}

void CFunctionBuilder::AddLabel( TLabel label )
{
	if( !HasErrors() ) {
		acc.AppendLabel( label );
	}
}

void CFunctionBuilder::AddNumber( TNumber number )
{
	if( !HasErrors() ) {
		acc.AppendNumber( number );
	}
}

void CFunctionBuilder::AddVariable( TVariableTypeTag type, TVariableName name,
	CQualifier* qualifier )
{
	const TVariableIndex index = isProcessRightPart ?
		CVariablesBuilder::AddRight( name, type ) :
		CVariablesBuilder::AddLeft( name, type );
	if( !HasErrors() ) {
		assert( index != InvalidVariableIndex );
		if( qualifier != nullptr ) {
			CVariablesBuilder::AddQualifier( index, *qualifier );
		}
		acc.AppendVariable( index );
	}
}

void CFunctionBuilder::AddLeftParen()
{
	balanceStack.push( acc.AppendLeftParen() );
}

void CFunctionBuilder::AddRightParen()
{
	CUnitNode* leftParen = nullptr;
	if( !balanceStack.empty() ) {
		leftParen = balanceStack.top();
	}
	if( leftParen != nullptr && leftParen->IsLeftParen() ) {
		leftParen->PairedParen() = acc.AppendRightParen(leftParen);
		balanceStack.pop();
	} else {
		error( EC_RightParenDoesNotMatchLeftParen );
	}
}

void CFunctionBuilder::AddLeftBracket()
{
	if( isProcessRightPart ) {
		balanceStack.push( acc.AppendLeftBracket() );
	} else {
		error( EC_IllegalLeftBracketInLeftPart );
	}
}

void CFunctionBuilder::AddRightBracket()
{
	if( isProcessRightPart ) {
		CUnitNode* leftBracket = nullptr;
		if( !balanceStack.empty() ) {
			leftBracket = balanceStack.top();
		}
		if( leftBracket != nullptr && leftBracket->IsLeftBracket() ) {
			leftBracket->PairedParen() = acc.AppendRightBracket(leftBracket);
			balanceStack.pop();
		} else {
			error( EC_RightBracketDoesNotMatchLeftBracket );
		}
	} else {
		error( EC_IllegalRightBracketInLeftPart );
	}
}

const char* CFunctionBuilder::getErrorMessage( TErrorCode errorCode )
{
	switch( errorCode ) {
		case EC_IllegalLeftBracketInLeftPart:
			return "illegal left bracket in left part of rule";
		case EC_IllegalRightBracketInLeftPart:
			return "illegal right bracket in left part of rule";
		case EC_RightParenDoesNotMatchLeftParen:
			return "right paren does not match left paren";
		case EC_RightBracketDoesNotMatchLeftBracket:
			return "right bracket does not match left bracket";
		case EC_UnclosedLeftParenInLeftPart:
			return "unclosed left paren in left part of rule";
		case EC_UnclosedLeftParenInRightPart:
			return "unclosed left paren in right part of rule";
		case EC_UnclosedLeftBracketInRightPart:
			return "unclosed left bracket in right part of rule";
		case EC_ThereAreMultiplePartsSeparatorInRules:
			return "there are multiple parts separator in rule";
		case EC_ThereAreNoPartsSeparatorInRules:
			return "there are no parts separator in rule";
	}
	assert( false );
	return nullptr;
}

void CFunctionBuilder::error( TErrorCode errorCode )
{
	CErrorsHelper::RaiseError( ES_Error, getErrorMessage( errorCode ) );
}

void CFunctionBuilder::emptyStack()
{
	std::stack<CUnitNode*> emptyStack;
	std::swap( balanceStack, emptyStack );
}

void CFunctionBuilder::emptyRules()
{
	firstRule.reset();
	lastRule = nullptr;
}

void CFunctionBuilder::addRule()
{
	if( static_cast<bool>( firstRule ) ) {
		lastRule->NextRule.reset( new CRule );
		lastRule = lastRule->NextRule.get();
	} else {
		firstRule.reset( new CRule );
		lastRule = firstRule.get();
	}

	lastRule->RightMatching = isRightDirection;
	leftPart.Move( lastRule->Left );
	acc.Move( lastRule->Right );
	CVariablesBuilder::Export( lastRule->Variables );
}

//-----------------------------------------------------------------------------

} // end of namespace refal2
<|endoftext|>