<commit_before>/*******************************
Copyright (C) 2013-2015 gregoire ANGERAND

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 3 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
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, see <http://www.gnu.org/licenses/>.
**********************************/

#include <iostream>
#include <n/io/File.h>
#include "MeshLoader.h"
#include "MaterialLoader.h"
#include <n/core/Timer.h>

namespace n {
namespace graphics {

MeshLoader *MeshLoader::loader = 0;

class ObjDecoder : public MeshLoader::MeshDecoder<ObjDecoder, core::String>
{
	public:
		ObjDecoder() : MeshLoader::MeshDecoder<ObjDecoder, core::String>() {
		}

		internal::MeshInstance<> *operator()(core::String name) override {
			if(!name.endsWith(".obj")) {
				return 0;
			}
			io::File file(name);
			return load(file);
		}

	private:
		internal::MeshInstance<> *load(io::File &file) {
			if(!file.open(io::IODevice::Read)) {
				std::cerr<<file.getName()<<" not found"<<std::endl;
				return 0;
			}
			//core::Timer timer;
			uint fs = file.size();
			char *data = new char[fs + 1];
			data[file.readBytes(data)] = 0;
			core::Array<core::String> lines = core::String(data).split("\n");
			delete[] data;
			file.close();

			core::Array<math::Vec3> positions;
			positions.append(math::Vec3());
			core::Array<math::Vec3> normals;
			normals.append(math::Vec3());
			core::Array<math::Vec2> coords;
			coords.append(math::Vec2());

			for(const core::String &l : lines) {
				if(l.size() < 4) {
					continue;
				}
				if(l.beginsWith("v ")) {
					/*core::Array<float> fl = l.subString(2).split(" ");//.mapped([](const core::String &s) { return s.to<float>(); });
					if(fl.size() != 3) {
						std::cerr<<"Invalid position"<<std::endl;
						return 0;
					}*/
					float fl[3] = {0};
					sscanf(l.toChar(), "v %f %f %f", &fl[0], &fl[1], &fl[2]);
					positions.append(math::Vec3(fl[0], fl[1], fl[2]));
				} else if(l.beginsWith("vn ")) {
					/*core::Array<float> fl = l.subString(3).split(" ");//.mapped([](const core::String &s) { return s.to<float>(); });
					if(fl.size() != 3) {
						std::cerr<<"Invalid normal"<<std::endl;
						return 0;
					}*/
					float fl[3] = {0};
					sscanf(l.toChar(), "vn %f %f %f", &fl[0], &fl[1], &fl[2]);
					normals.append(math::Vec3(fl[0], fl[1], fl[2]));
				} else if(l.beginsWith("vt ")) {
					/*core::Array<float> fl = l.subString(3).split(" ");//.mapped([](const core::String &s) { return s.to<float>(); });
					if(fl.size() != 2) {
						std::cerr<<"Invalid texture coord"<<std::endl;
						return 0;
					}*/
					float fl[2] = {0};
					sscanf(l.toChar(), "vt %f %f", &fl[0], &fl[1]);
					coords.append(math::Vec2(fl[0], fl[1]));
				}
			}
			//std::cout<<positions.size()<<" "<<normals.size()<<" "<<coords.size()<<std::endl;
			core::String mtllib;
			core::Map<math::Vec3ui, uint> vmap;
			bool smooth = false;
			TriangleBuffer<> tr;
			Material<> mat;
			core::Array<MeshInstanceBase<> *> bases;
			for(const core::String &l : lines) {
				if(l.beginsWith("f ")) {
					core::Array<core::String> fl = l.subString(2).split(" ");
					uint face[] = {0, 0, 0};
					if(fl.size() != 3) {
						std::cerr<<"Invalid (non triangle) face. \""<<l<<"\""<<std::endl;
						return 0;
					}
					for(uint i = 0; i != 3; i++) {
						core::Array<uint> uis = fl[i].split("/", true).mapped([](const core::String &str) { return str.isEmpty() ? 0 : uint(str); });
						for(; uis.size() < 3;) {
							uis += 0;
						}
						math::Vec3ui v(uis[0], uis[1], smooth ? 0 : uis[2]);
						core::Map<math::Vec3ui, uint>::const_iterator it = vmap.find(v);
						if(it == vmap.end()) {
							if(v.x() >= positions.size() || v.z() >= normals.size() || v.y() >= coords.size()) {
								std::cerr<<"Index out of bound : "<<core::String(v)<<std::endl;
								return 0;
							}
							face[i] = vmap[v] = tr.append(Vertex<>(positions[v.x()], normals[v.z()], coords[v.y()]));
						} else {
							face[i] = (*it)._2;
						}
					}
					tr.append(face[0], face[1], face[2]);
				} else if(l.beginsWith("s ")) {
					core::String sm = l.subString(2).toLower().filtered([](char c) { return !isspace(c); });
					smooth = !(sm == "off" || sm == "0");
				} else if(l.beginsWith("usemtl ")) {
					mat = MaterialLoader::load<core::String, core::String>(mtllib, l.subString(7));
					if(!tr.getTriangles().isEmpty()) {
						bases.append(new MeshInstanceBase<>(std::move(tr.freezed()), mat));
					}
				} else if(l.beginsWith("mtllib ")) {
					mtllib = l.subString(7);
				}
			}
			if(!tr.getTriangles().isEmpty()) {
				bases.append(new MeshInstanceBase<>(std::move(tr.freezed()), mat));
			}
			//std::cout<<file.getName()<<" loaded in "<<timer.elapsed() * 1000<<"ms ["<<bases.first()->getTriangleBuffer().indexes.size() / 3<<"]"<<std::endl;
			return new internal::MeshInstance<>(bases);
		}
};

}
}

<commit_msg>Fixed ObjDecoder duplicating objects.<commit_after>/*******************************
Copyright (C) 2013-2015 gregoire ANGERAND

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 3 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
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, see <http://www.gnu.org/licenses/>.
**********************************/

#include <iostream>
#include <n/io/File.h>
#include "MeshLoader.h"
#include "MaterialLoader.h"
#include <n/core/Timer.h>

namespace n {
namespace graphics {

MeshLoader *MeshLoader::loader = 0;

class ObjDecoder : public MeshLoader::MeshDecoder<ObjDecoder, core::String>
{
	public:
		ObjDecoder() : MeshLoader::MeshDecoder<ObjDecoder, core::String>() {
		}

		internal::MeshInstance<> *operator()(core::String name) override {
			if(!name.endsWith(".obj")) {
				return 0;
			}
			io::File file(name);
			return load(file);
		}

	private:
		internal::MeshInstance<> *load(io::File &file) {
			if(!file.open(io::IODevice::Read)) {
				std::cerr<<file.getName()<<" not found"<<std::endl;
				return 0;
			}
			//core::Timer timer;
			uint fs = file.size();
			char *data = new char[fs + 1];
			data[file.readBytes(data)] = 0;
			core::Array<core::String> lines = core::String(data).split("\n");
			delete[] data;
			file.close();

			core::Array<math::Vec3> positions;
			positions.append(math::Vec3());
			core::Array<math::Vec3> normals;
			normals.append(math::Vec3());
			core::Array<math::Vec2> coords;
			coords.append(math::Vec2());

			for(const core::String &l : lines) {
				if(l.size() < 4) {
					continue;
				}
				if(l.beginsWith("v ")) {
					/*core::Array<float> fl = l.subString(2).split(" ");//.mapped([](const core::String &s) { return s.to<float>(); });
					if(fl.size() != 3) {
						std::cerr<<"Invalid position"<<std::endl;
						return 0;
					}*/
					float fl[3] = {0};
					sscanf(l.toChar(), "v %f %f %f", &fl[0], &fl[1], &fl[2]);
					positions.append(math::Vec3(fl[0], fl[1], fl[2]));
				} else if(l.beginsWith("vn ")) {
					/*core::Array<float> fl = l.subString(3).split(" ");//.mapped([](const core::String &s) { return s.to<float>(); });
					if(fl.size() != 3) {
						std::cerr<<"Invalid normal"<<std::endl;
						return 0;
					}*/
					float fl[3] = {0};
					sscanf(l.toChar(), "vn %f %f %f", &fl[0], &fl[1], &fl[2]);
					normals.append(math::Vec3(fl[0], fl[1], fl[2]));
				} else if(l.beginsWith("vt ")) {
					/*core::Array<float> fl = l.subString(3).split(" ");//.mapped([](const core::String &s) { return s.to<float>(); });
					if(fl.size() != 2) {
						std::cerr<<"Invalid texture coord"<<std::endl;
						return 0;
					}*/
					float fl[2] = {0};
					sscanf(l.toChar(), "vt %f %f", &fl[0], &fl[1]);
					coords.append(math::Vec2(fl[0], fl[1]));
				}
			}
			//std::cout<<positions.size()<<" "<<normals.size()<<" "<<coords.size()<<std::endl;
			core::String mtllib;
			core::Map<math::Vec3ui, uint> vmap;
			bool smooth = false;
			TriangleBuffer<> tr;
			Material<> mat;
			core::Array<MeshInstanceBase<> *> bases;
			for(const core::String &l : lines) {
				if(l.beginsWith("f ")) {
					core::Array<core::String> fl = l.subString(2).split(" ");
					uint face[] = {0, 0, 0};
					if(fl.size() != 3) {
						std::cerr<<"Invalid (non triangle) face. \""<<l<<"\""<<std::endl;
						return 0;
					}
					for(uint i = 0; i != 3; i++) {
						core::Array<uint> uis = fl[i].split("/", true).mapped([](const core::String &str) { return str.isEmpty() ? 0 : uint(str); });
						for(; uis.size() < 3;) {
							uis += 0;
						}
						math::Vec3ui v(uis[0], uis[1], smooth ? 0 : uis[2]);
						core::Map<math::Vec3ui, uint>::const_iterator it = vmap.find(v);
						if(it == vmap.end()) {
							if(v.x() >= positions.size() || v.z() >= normals.size() || v.y() >= coords.size()) {
								std::cerr<<"Index out of bound : "<<core::String(v)<<std::endl;
								return 0;
							}
							face[i] = vmap[v] = tr.append(Vertex<>(positions[v.x()], normals[v.z()], coords[v.y()]));
						} else {
							face[i] = (*it)._2;
						}
					}
					tr.append(face[0], face[1], face[2]);
				} else if(l.beginsWith("s ")) {
					core::String sm = l.subString(2).toLower().filtered([](char c) { return !isspace(c); });
					smooth = !(sm == "off" || sm == "0");
				} else if(l.beginsWith("usemtl ")) {
					mat = MaterialLoader::load<core::String, core::String>(mtllib, l.subString(7));
					if(!tr.getTriangles().isEmpty()) {
						bases.append(new MeshInstanceBase<>(std::move(tr.freezed()), mat));
					}
					tr = TriangleBuffer<>();
				} else if(l.beginsWith("mtllib ")) {
					mtllib = l.subString(7);
				}
			}
			if(!tr.getTriangles().isEmpty()) {
				bases.append(new MeshInstanceBase<>(std::move(tr.freezed()), mat));
			}
			//std::cout<<file.getName()<<" loaded in "<<timer.elapsed() * 1000<<"ms ["<<bases.first()->getTriangleBuffer().indexes.size() / 3<<"]"<<std::endl;
			return new internal::MeshInstance<>(bases);
		}
};

}
}

<|endoftext|>


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

#include <string>

#include "base/message_loop/message_loop.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/accessibility/accessibility_extension_api.h"
#include "chrome/browser/ui/views/accessibility/accessibility_event_router_views.h"
#include "chrome/test/base/testing_profile.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/accessibility/accessible_view_state.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/grid_layout.h"
#include "ui/views/test/test_views_delegate.h"
#include "ui/views/widget/native_widget.h"
#include "ui/views/widget/root_view.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"

#if defined(OS_WIN)
#include "ui/base/win/scoped_ole_initializer.h"
#endif

#if defined(USE_AURA)
#include "ui/aura/root_window.h"
#include "ui/aura/test/aura_test_helper.h"
#endif

namespace {

// The expected initial focus count.
#if defined(OS_WIN) && !defined(USE_AURA)
// On windows (non-aura) this code triggers activating the window. Activating
// the window triggers clearing the focus then resetting it. This results in an
// additional focus change.
const int kInitialFocusCount = 2;
#else
const int kInitialFocusCount = 1;
#endif

}  // namespace

class AccessibilityViewsDelegate : public views::TestViewsDelegate {
 public:
  AccessibilityViewsDelegate() {}
  virtual ~AccessibilityViewsDelegate() {}

  // Overridden from views::TestViewsDelegate:
  virtual void NotifyAccessibilityEvent(
      views::View* view, ui::AccessibilityTypes::Event event_type) OVERRIDE {
    AccessibilityEventRouterViews::GetInstance()->HandleAccessibilityEvent(
        view, event_type);
  }

  DISALLOW_COPY_AND_ASSIGN(AccessibilityViewsDelegate);
};

class AccessibilityWindowDelegate : public views::WidgetDelegate {
 public:
  explicit AccessibilityWindowDelegate(views::View* contents)
      : contents_(contents) { }

  // Overridden from views::WidgetDelegate:
  virtual void DeleteDelegate() OVERRIDE { delete this; }
  virtual views::View* GetContentsView() OVERRIDE { return contents_; }
  virtual const views::Widget* GetWidget() const OVERRIDE {
    return contents_->GetWidget();
  }
  virtual views::Widget* GetWidget() OVERRIDE { return contents_->GetWidget(); }

 private:
  views::View* contents_;

  DISALLOW_COPY_AND_ASSIGN(AccessibilityWindowDelegate);
};

class ViewWithNameAndRole : public views::View {
 public:
  explicit ViewWithNameAndRole(const string16& name,
                               ui::AccessibilityTypes::Role role)
      : name_(name),
        role_(role) {
  }

  virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE {
    views::View::GetAccessibleState(state);
    state->name = name_;
    state->role = role_;
  }

  void set_name(const string16& name) { name_ = name; }

 private:
  string16 name_;
  ui::AccessibilityTypes::Role role_;
  DISALLOW_COPY_AND_ASSIGN(ViewWithNameAndRole);
};

class AccessibilityEventRouterViewsTest
    : public testing::Test {
 public:
  AccessibilityEventRouterViewsTest() {
  }

  virtual void SetUp() {
#if defined(OS_WIN)
    ole_initializer_.reset(new ui::ScopedOleInitializer());
#endif
    views::ViewsDelegate::views_delegate = new AccessibilityViewsDelegate();
#if defined(USE_AURA)
    aura_test_helper_.reset(new aura::test::AuraTestHelper(&message_loop_));
    aura_test_helper_->SetUp();
#endif  // USE_AURA
    EnableAccessibilityAndListenToFocusNotifications();
  }

  virtual void TearDown() {
    ClearCallback();
#if defined(USE_AURA)
    aura_test_helper_->TearDown();
#endif
    delete views::ViewsDelegate::views_delegate;
    views::ViewsDelegate::views_delegate = NULL;

    // The Widget's FocusManager is deleted using DeleteSoon - this
    // forces it to be deleted now, so we don't have any memory leaks
    // when this method exits.
    base::MessageLoop::current()->RunUntilIdle();

#if defined(OS_WIN)
    ole_initializer_.reset();
#endif
  }

  views::Widget* CreateWindowWithContents(views::View* contents) {
    gfx::NativeView context = NULL;
#if defined(USE_AURA)
    context = aura_test_helper_->root_window();
#endif
    views::Widget* widget = views::Widget::CreateWindowWithContextAndBounds(
        new AccessibilityWindowDelegate(contents),
        context,
        gfx::Rect(0, 0, 500, 500));

    // Create a profile and associate it with this window.
    widget->SetNativeWindowProperty(Profile::kProfileKey, &profile_);

    return widget;
  }

  void EnableAccessibilityAndListenToFocusNotifications() {
    // Switch on accessibility event notifications.
    ExtensionAccessibilityEventRouter* accessibility_event_router =
        ExtensionAccessibilityEventRouter::GetInstance();
    accessibility_event_router->SetAccessibilityEnabled(true);
    accessibility_event_router->SetControlEventCallbackForTesting(base::Bind(
        &AccessibilityEventRouterViewsTest::OnFocusEvent,
        base::Unretained(this)));
  }

  void ClearCallback() {
    ExtensionAccessibilityEventRouter* accessibility_event_router =
        ExtensionAccessibilityEventRouter::GetInstance();
    accessibility_event_router->ClearControlEventCallback();
  }

 protected:
  // Handle Focus event.
  virtual void OnFocusEvent(ui::AccessibilityTypes::Event event,
                            const AccessibilityControlInfo* info) {
    focus_event_count_++;
    last_control_name_ = info->name();
    last_control_context_ = info->context();
  }

  base::MessageLoopForUI message_loop_;
  int focus_event_count_;
  std::string last_control_name_;
  std::string last_control_context_;
  TestingProfile profile_;
#if defined(OS_WIN)
  scoped_ptr<ui::ScopedOleInitializer> ole_initializer_;
#endif
#if defined(USE_AURA)
  scoped_ptr<aura::test::AuraTestHelper> aura_test_helper_;
#endif
};

TEST_F(AccessibilityEventRouterViewsTest, TestFocusNotification) {
  const char kButton1ASCII[] = "Button1";
  const char kButton2ASCII[] = "Button2";
  const char kButton3ASCII[] = "Button3";
  const char kButton3NewASCII[] = "Button3New";

  // Create a contents view with 3 buttons.
  views::View* contents = new views::View();
  views::LabelButton* button1 = new views::LabelButton(
      NULL, ASCIIToUTF16(kButton1ASCII));
  button1->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
  contents->AddChildView(button1);
  views::LabelButton* button2 = new views::LabelButton(
      NULL, ASCIIToUTF16(kButton2ASCII));
  button2->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
  contents->AddChildView(button2);
  views::LabelButton* button3 = new views::LabelButton(
      NULL, ASCIIToUTF16(kButton3ASCII));
  button3->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
  contents->AddChildView(button3);

  // Put the view in a window.
  views::Widget* window = CreateWindowWithContents(contents);
  window->Show();
  window->Activate();

  // Set focus to the first button initially and run message loop to execute
  // callback.
  button1->RequestFocus();
  base::MessageLoop::current()->RunUntilIdle();

  // Change the accessible name of button3.
  button3->SetAccessibleName(ASCIIToUTF16(kButton3NewASCII));

  // Advance focus to the next button and test that we got the
  // expected notification with the name of button 2.
  views::FocusManager* focus_manager = contents->GetWidget()->GetFocusManager();
  focus_event_count_ = 0;
  focus_manager->AdvanceFocus(false);
  base::MessageLoop::current()->RunUntilIdle();
  EXPECT_EQ(1, focus_event_count_);
  EXPECT_EQ(kButton2ASCII, last_control_name_);

  // Advance to button 3. Expect the new accessible name we assigned.
  focus_manager->AdvanceFocus(false);
  base::MessageLoop::current()->RunUntilIdle();
  EXPECT_EQ(2, focus_event_count_);
  EXPECT_EQ(kButton3NewASCII, last_control_name_);

  // Advance to button 1 and check the notification.
  focus_manager->AdvanceFocus(false);
  base::MessageLoop::current()->RunUntilIdle();
  EXPECT_EQ(3, focus_event_count_);
  EXPECT_EQ(kButton1ASCII, last_control_name_);

  window->CloseNow();
}

TEST_F(AccessibilityEventRouterViewsTest, TestToolbarContext) {
  const char kToolbarNameASCII[] = "MyToolbar";
  const char kButtonNameASCII[] = "MyButton";

  // Create a toolbar with a button.
  views::View* contents = new ViewWithNameAndRole(
      ASCIIToUTF16(kToolbarNameASCII),
      ui::AccessibilityTypes::ROLE_TOOLBAR);
  views::LabelButton* button = new views::LabelButton(
      NULL, ASCIIToUTF16(kButtonNameASCII));
  button->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
  contents->AddChildView(button);

  // Put the view in a window.
  views::Widget* window = CreateWindowWithContents(contents);

  // Set focus to the button.
  focus_event_count_ = 0;
  button->RequestFocus();

  base::MessageLoop::current()->RunUntilIdle();

  // Test that we got the event with the expected name and context.
  EXPECT_EQ(kInitialFocusCount, focus_event_count_);
  EXPECT_EQ(kButtonNameASCII, last_control_name_);
  EXPECT_EQ(kToolbarNameASCII, last_control_context_);

  window->CloseNow();
}

TEST_F(AccessibilityEventRouterViewsTest, TestAlertContext) {
  const char kAlertTextASCII[] = "MyAlertText";
  const char kButtonNameASCII[] = "MyButton";

  // Create an alert with static text and a button, similar to an infobar.
  views::View* contents = new ViewWithNameAndRole(
      string16(),
      ui::AccessibilityTypes::ROLE_ALERT);
  views::Label* label = new views::Label(ASCIIToUTF16(kAlertTextASCII));
  contents->AddChildView(label);
  views::LabelButton* button = new views::LabelButton(
      NULL, ASCIIToUTF16(kButtonNameASCII));
  button->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
  contents->AddChildView(button);

  // Put the view in a window.
  views::Widget* window = CreateWindowWithContents(contents);

  // Set focus to the button.
  focus_event_count_ = 0;
  button->RequestFocus();

  base::MessageLoop::current()->RunUntilIdle();

  // Test that we got the event with the expected name and context.
  EXPECT_EQ(kInitialFocusCount, focus_event_count_);
  EXPECT_EQ(kButtonNameASCII, last_control_name_);
  EXPECT_EQ(kAlertTextASCII, last_control_context_);

  window->CloseNow();
}

TEST_F(AccessibilityEventRouterViewsTest, StateChangeAfterNotification) {
  const char kContentsNameASCII[] = "Contents";
  const char kOldNameASCII[] = "OldName";
  const char kNewNameASCII[] = "NewName";

  // Create a toolbar with a button.
  views::View* contents = new ViewWithNameAndRole(
      ASCIIToUTF16(kContentsNameASCII),
      ui::AccessibilityTypes::ROLE_CLIENT);
  ViewWithNameAndRole* child = new ViewWithNameAndRole(
      ASCIIToUTF16(kOldNameASCII),
      ui::AccessibilityTypes::ROLE_PUSHBUTTON);
  child->set_focusable(true);
  contents->AddChildView(child);

  // Put the view in a window.
  views::Widget* window = CreateWindowWithContents(contents);

  // Set focus to the child view.
  focus_event_count_ = 0;
  child->RequestFocus();

  // Change the child's name after the focus notification.
  child->set_name(ASCIIToUTF16(kNewNameASCII));

  // We shouldn't get the notification right away.
  EXPECT_EQ(0, focus_event_count_);

  // Process anything in the event loop. Now we should get the notification,
  // and it should give us the new control name, not the old one.
  base::MessageLoop::current()->RunUntilIdle();
  EXPECT_EQ(kInitialFocusCount, focus_event_count_);
  EXPECT_EQ(kNewNameASCII, last_control_name_);

  window->CloseNow();
}

TEST_F(AccessibilityEventRouterViewsTest, NotificationOnDeletedObject) {
  const char kContentsNameASCII[] = "Contents";
  const char kNameASCII[] = "OldName";

  // Create a toolbar with a button.
  views::View* contents = new ViewWithNameAndRole(
      ASCIIToUTF16(kContentsNameASCII),
      ui::AccessibilityTypes::ROLE_CLIENT);
  ViewWithNameAndRole* child = new ViewWithNameAndRole(
      ASCIIToUTF16(kNameASCII),
      ui::AccessibilityTypes::ROLE_PUSHBUTTON);
  child->set_focusable(true);
  contents->AddChildView(child);

  // Put the view in a window.
  views::Widget* window = CreateWindowWithContents(contents);

  // Set focus to the child view.
  focus_event_count_ = 0;
  child->RequestFocus();

  // Delete the child!
  delete child;

  // We shouldn't get the notification right away.
  EXPECT_EQ(0, focus_event_count_);

  // Process anything in the event loop. We shouldn't get a notification
  // because the view is no longer valid, and this shouldn't crash.
  base::MessageLoop::current()->RunUntilIdle();
  EXPECT_EQ(0, focus_event_count_);

  window->CloseNow();
}
<commit_msg>Fix uninitialized field in constructor.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <string>

#include "base/message_loop/message_loop.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/accessibility/accessibility_extension_api.h"
#include "chrome/browser/ui/views/accessibility/accessibility_event_router_views.h"
#include "chrome/test/base/testing_profile.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/accessibility/accessible_view_state.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/grid_layout.h"
#include "ui/views/test/test_views_delegate.h"
#include "ui/views/widget/native_widget.h"
#include "ui/views/widget/root_view.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"

#if defined(OS_WIN)
#include "ui/base/win/scoped_ole_initializer.h"
#endif

#if defined(USE_AURA)
#include "ui/aura/root_window.h"
#include "ui/aura/test/aura_test_helper.h"
#endif

namespace {

// The expected initial focus count.
#if defined(OS_WIN) && !defined(USE_AURA)
// On windows (non-aura) this code triggers activating the window. Activating
// the window triggers clearing the focus then resetting it. This results in an
// additional focus change.
const int kInitialFocusCount = 2;
#else
const int kInitialFocusCount = 1;
#endif

}  // namespace

class AccessibilityViewsDelegate : public views::TestViewsDelegate {
 public:
  AccessibilityViewsDelegate() {}
  virtual ~AccessibilityViewsDelegate() {}

  // Overridden from views::TestViewsDelegate:
  virtual void NotifyAccessibilityEvent(
      views::View* view, ui::AccessibilityTypes::Event event_type) OVERRIDE {
    AccessibilityEventRouterViews::GetInstance()->HandleAccessibilityEvent(
        view, event_type);
  }

  DISALLOW_COPY_AND_ASSIGN(AccessibilityViewsDelegate);
};

class AccessibilityWindowDelegate : public views::WidgetDelegate {
 public:
  explicit AccessibilityWindowDelegate(views::View* contents)
      : contents_(contents) { }

  // Overridden from views::WidgetDelegate:
  virtual void DeleteDelegate() OVERRIDE { delete this; }
  virtual views::View* GetContentsView() OVERRIDE { return contents_; }
  virtual const views::Widget* GetWidget() const OVERRIDE {
    return contents_->GetWidget();
  }
  virtual views::Widget* GetWidget() OVERRIDE { return contents_->GetWidget(); }

 private:
  views::View* contents_;

  DISALLOW_COPY_AND_ASSIGN(AccessibilityWindowDelegate);
};

class ViewWithNameAndRole : public views::View {
 public:
  explicit ViewWithNameAndRole(const string16& name,
                               ui::AccessibilityTypes::Role role)
      : name_(name),
        role_(role) {
  }

  virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE {
    views::View::GetAccessibleState(state);
    state->name = name_;
    state->role = role_;
  }

  void set_name(const string16& name) { name_ = name; }

 private:
  string16 name_;
  ui::AccessibilityTypes::Role role_;
  DISALLOW_COPY_AND_ASSIGN(ViewWithNameAndRole);
};

class AccessibilityEventRouterViewsTest
    : public testing::Test {
 public:
  AccessibilityEventRouterViewsTest() : focus_event_count_(0) {
  }

  virtual void SetUp() {
#if defined(OS_WIN)
    ole_initializer_.reset(new ui::ScopedOleInitializer());
#endif
    views::ViewsDelegate::views_delegate = new AccessibilityViewsDelegate();
#if defined(USE_AURA)
    aura_test_helper_.reset(new aura::test::AuraTestHelper(&message_loop_));
    aura_test_helper_->SetUp();
#endif  // USE_AURA
    EnableAccessibilityAndListenToFocusNotifications();
  }

  virtual void TearDown() {
    ClearCallback();
#if defined(USE_AURA)
    aura_test_helper_->TearDown();
#endif
    delete views::ViewsDelegate::views_delegate;
    views::ViewsDelegate::views_delegate = NULL;

    // The Widget's FocusManager is deleted using DeleteSoon - this
    // forces it to be deleted now, so we don't have any memory leaks
    // when this method exits.
    base::MessageLoop::current()->RunUntilIdle();

#if defined(OS_WIN)
    ole_initializer_.reset();
#endif
  }

  views::Widget* CreateWindowWithContents(views::View* contents) {
    gfx::NativeView context = NULL;
#if defined(USE_AURA)
    context = aura_test_helper_->root_window();
#endif
    views::Widget* widget = views::Widget::CreateWindowWithContextAndBounds(
        new AccessibilityWindowDelegate(contents),
        context,
        gfx::Rect(0, 0, 500, 500));

    // Create a profile and associate it with this window.
    widget->SetNativeWindowProperty(Profile::kProfileKey, &profile_);

    return widget;
  }

  void EnableAccessibilityAndListenToFocusNotifications() {
    // Switch on accessibility event notifications.
    ExtensionAccessibilityEventRouter* accessibility_event_router =
        ExtensionAccessibilityEventRouter::GetInstance();
    accessibility_event_router->SetAccessibilityEnabled(true);
    accessibility_event_router->SetControlEventCallbackForTesting(base::Bind(
        &AccessibilityEventRouterViewsTest::OnFocusEvent,
        base::Unretained(this)));
  }

  void ClearCallback() {
    ExtensionAccessibilityEventRouter* accessibility_event_router =
        ExtensionAccessibilityEventRouter::GetInstance();
    accessibility_event_router->ClearControlEventCallback();
  }

 protected:
  // Handle Focus event.
  virtual void OnFocusEvent(ui::AccessibilityTypes::Event event,
                            const AccessibilityControlInfo* info) {
    focus_event_count_++;
    last_control_name_ = info->name();
    last_control_context_ = info->context();
  }

  base::MessageLoopForUI message_loop_;
  int focus_event_count_;
  std::string last_control_name_;
  std::string last_control_context_;
  TestingProfile profile_;
#if defined(OS_WIN)
  scoped_ptr<ui::ScopedOleInitializer> ole_initializer_;
#endif
#if defined(USE_AURA)
  scoped_ptr<aura::test::AuraTestHelper> aura_test_helper_;
#endif
};

TEST_F(AccessibilityEventRouterViewsTest, TestFocusNotification) {
  const char kButton1ASCII[] = "Button1";
  const char kButton2ASCII[] = "Button2";
  const char kButton3ASCII[] = "Button3";
  const char kButton3NewASCII[] = "Button3New";

  // Create a contents view with 3 buttons.
  views::View* contents = new views::View();
  views::LabelButton* button1 = new views::LabelButton(
      NULL, ASCIIToUTF16(kButton1ASCII));
  button1->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
  contents->AddChildView(button1);
  views::LabelButton* button2 = new views::LabelButton(
      NULL, ASCIIToUTF16(kButton2ASCII));
  button2->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
  contents->AddChildView(button2);
  views::LabelButton* button3 = new views::LabelButton(
      NULL, ASCIIToUTF16(kButton3ASCII));
  button3->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
  contents->AddChildView(button3);

  // Put the view in a window.
  views::Widget* window = CreateWindowWithContents(contents);
  window->Show();
  window->Activate();

  // Set focus to the first button initially and run message loop to execute
  // callback.
  button1->RequestFocus();
  base::MessageLoop::current()->RunUntilIdle();

  // Change the accessible name of button3.
  button3->SetAccessibleName(ASCIIToUTF16(kButton3NewASCII));

  // Advance focus to the next button and test that we got the
  // expected notification with the name of button 2.
  views::FocusManager* focus_manager = contents->GetWidget()->GetFocusManager();
  focus_event_count_ = 0;
  focus_manager->AdvanceFocus(false);
  base::MessageLoop::current()->RunUntilIdle();
  EXPECT_EQ(1, focus_event_count_);
  EXPECT_EQ(kButton2ASCII, last_control_name_);

  // Advance to button 3. Expect the new accessible name we assigned.
  focus_manager->AdvanceFocus(false);
  base::MessageLoop::current()->RunUntilIdle();
  EXPECT_EQ(2, focus_event_count_);
  EXPECT_EQ(kButton3NewASCII, last_control_name_);

  // Advance to button 1 and check the notification.
  focus_manager->AdvanceFocus(false);
  base::MessageLoop::current()->RunUntilIdle();
  EXPECT_EQ(3, focus_event_count_);
  EXPECT_EQ(kButton1ASCII, last_control_name_);

  window->CloseNow();
}

TEST_F(AccessibilityEventRouterViewsTest, TestToolbarContext) {
  const char kToolbarNameASCII[] = "MyToolbar";
  const char kButtonNameASCII[] = "MyButton";

  // Create a toolbar with a button.
  views::View* contents = new ViewWithNameAndRole(
      ASCIIToUTF16(kToolbarNameASCII),
      ui::AccessibilityTypes::ROLE_TOOLBAR);
  views::LabelButton* button = new views::LabelButton(
      NULL, ASCIIToUTF16(kButtonNameASCII));
  button->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
  contents->AddChildView(button);

  // Put the view in a window.
  views::Widget* window = CreateWindowWithContents(contents);

  // Set focus to the button.
  focus_event_count_ = 0;
  button->RequestFocus();

  base::MessageLoop::current()->RunUntilIdle();

  // Test that we got the event with the expected name and context.
  EXPECT_EQ(kInitialFocusCount, focus_event_count_);
  EXPECT_EQ(kButtonNameASCII, last_control_name_);
  EXPECT_EQ(kToolbarNameASCII, last_control_context_);

  window->CloseNow();
}

TEST_F(AccessibilityEventRouterViewsTest, TestAlertContext) {
  const char kAlertTextASCII[] = "MyAlertText";
  const char kButtonNameASCII[] = "MyButton";

  // Create an alert with static text and a button, similar to an infobar.
  views::View* contents = new ViewWithNameAndRole(
      string16(),
      ui::AccessibilityTypes::ROLE_ALERT);
  views::Label* label = new views::Label(ASCIIToUTF16(kAlertTextASCII));
  contents->AddChildView(label);
  views::LabelButton* button = new views::LabelButton(
      NULL, ASCIIToUTF16(kButtonNameASCII));
  button->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
  contents->AddChildView(button);

  // Put the view in a window.
  views::Widget* window = CreateWindowWithContents(contents);

  // Set focus to the button.
  focus_event_count_ = 0;
  button->RequestFocus();

  base::MessageLoop::current()->RunUntilIdle();

  // Test that we got the event with the expected name and context.
  EXPECT_EQ(kInitialFocusCount, focus_event_count_);
  EXPECT_EQ(kButtonNameASCII, last_control_name_);
  EXPECT_EQ(kAlertTextASCII, last_control_context_);

  window->CloseNow();
}

TEST_F(AccessibilityEventRouterViewsTest, StateChangeAfterNotification) {
  const char kContentsNameASCII[] = "Contents";
  const char kOldNameASCII[] = "OldName";
  const char kNewNameASCII[] = "NewName";

  // Create a toolbar with a button.
  views::View* contents = new ViewWithNameAndRole(
      ASCIIToUTF16(kContentsNameASCII),
      ui::AccessibilityTypes::ROLE_CLIENT);
  ViewWithNameAndRole* child = new ViewWithNameAndRole(
      ASCIIToUTF16(kOldNameASCII),
      ui::AccessibilityTypes::ROLE_PUSHBUTTON);
  child->set_focusable(true);
  contents->AddChildView(child);

  // Put the view in a window.
  views::Widget* window = CreateWindowWithContents(contents);

  // Set focus to the child view.
  focus_event_count_ = 0;
  child->RequestFocus();

  // Change the child's name after the focus notification.
  child->set_name(ASCIIToUTF16(kNewNameASCII));

  // We shouldn't get the notification right away.
  EXPECT_EQ(0, focus_event_count_);

  // Process anything in the event loop. Now we should get the notification,
  // and it should give us the new control name, not the old one.
  base::MessageLoop::current()->RunUntilIdle();
  EXPECT_EQ(kInitialFocusCount, focus_event_count_);
  EXPECT_EQ(kNewNameASCII, last_control_name_);

  window->CloseNow();
}

TEST_F(AccessibilityEventRouterViewsTest, NotificationOnDeletedObject) {
  const char kContentsNameASCII[] = "Contents";
  const char kNameASCII[] = "OldName";

  // Create a toolbar with a button.
  views::View* contents = new ViewWithNameAndRole(
      ASCIIToUTF16(kContentsNameASCII),
      ui::AccessibilityTypes::ROLE_CLIENT);
  ViewWithNameAndRole* child = new ViewWithNameAndRole(
      ASCIIToUTF16(kNameASCII),
      ui::AccessibilityTypes::ROLE_PUSHBUTTON);
  child->set_focusable(true);
  contents->AddChildView(child);

  // Put the view in a window.
  views::Widget* window = CreateWindowWithContents(contents);

  // Set focus to the child view.
  focus_event_count_ = 0;
  child->RequestFocus();

  // Delete the child!
  delete child;

  // We shouldn't get the notification right away.
  EXPECT_EQ(0, focus_event_count_);

  // Process anything in the event loop. We shouldn't get a notification
  // because the view is no longer valid, and this shouldn't crash.
  base::MessageLoop::current()->RunUntilIdle();
  EXPECT_EQ(0, focus_event_count_);

  window->CloseNow();
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2001 Stephen Williams (steve@icarus.com)
 *
 *    This source code is free software; you can redistribute it
 *    and/or modify it in source code form 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
 */
#ifdef HAVE_CVS_IDENT
#ident "$Id: load_module.cc,v 1.11 2002/08/12 01:34:59 steve Exp $"
#endif

# include  "config.h"
# include  "util.h"
# include  "parse_api.h"
# include  "compiler.h"
# include  <iostream>
# include  <map>
# include  <string>
# include  <sys/types.h>
# include  <dirent.h>
# include  <ctype.h>

/*
 * The module library items are maps of key names to file name within
 * the directory.
 */
struct module_library {
      char*dir;
      bool key_case_sensitive;
      map<string,const char*>name_map;
      struct module_library*next;
};

static struct module_library*library_list = 0;
static struct module_library*library_last = 0;

const char dir_character = '/';
extern FILE *depend_file;

/*
 * Use the type name as a key, and search the module library for a
 * file name that has that key.
 */
bool load_module(const char*type)
{
      char path[4096];
      char*ltype = strdup(type);

      for (char*tmp = ltype ; *tmp ;  tmp += 1)
	    *tmp = tolower(*tmp);

      for (struct module_library*lcur = library_list
		 ; lcur != 0 ;  lcur = lcur->next) {

	    const char*key = lcur->key_case_sensitive? type : ltype;
	    map<string,const char*>::const_iterator cur;
	    cur = lcur->name_map.find(key);
	    if (cur == lcur->name_map.end())
		  continue;

	    sprintf(path, "%s%c%s", lcur->dir, dir_character, (*cur).second);

	    if(depend_file) {
		  fprintf(depend_file, "%s\n", path);
	    }

	    if (ivlpp_string) {
		  char*cmdline = (char*)malloc(strlen(ivlpp_string) +
					       strlen(path) + 2);
		  strcpy(cmdline, ivlpp_string);
		  strcat(cmdline, " ");
		  strcat(cmdline, path);
		  FILE*file = popen(cmdline, "r");

		  if (verbose_flag)
			cerr << "Executing: " << cmdline << endl;

		  pform_parse(path, file);
		  fclose(file);
		  free(cmdline);

	    } else {
		  if (verbose_flag)
			cerr << "Loading library file "
			     << path << "." << endl;

		  FILE*file = fopen(path, "r");
		  assert(file);
		  pform_parse(path, file);
		  fclose(file);
	    }

	    return true;
      }

      return false;
}

/*
 * This function takes the name of a library directory that the caller
 * passed, and builds a name index for it.
 */
int build_library_index(const char*path, bool key_case_sensitive)
{
      DIR*dir = opendir(path);
      if (dir == 0)
	    return -1;

      if (verbose_flag) {
	    cerr << "Indexing library: " << path << endl;
      }

      struct module_library*mlp = new struct module_library;
      mlp->dir = strdup(path);
      mlp->key_case_sensitive = key_case_sensitive;

	/* Scan the director for files. check each file name to see if
	   it has one of the configured suffixes. If it does, then use
	   the root of the name as the key and index the file name. */
      while (struct dirent*de = readdir(dir)) {
	    unsigned namsiz = strlen(de->d_name);
	    char*key = 0;

	    for (list<const char*>::iterator suf = library_suff.begin()
		       ; suf != library_suff.end()
		       ; suf ++ ) {
		  const char*sufptr = *suf;
		  unsigned sufsiz = strlen(sufptr);

		  if (sufsiz >= namsiz)
			continue;

		    /* If the directory is case insensitive, then so
		       is the suffix. */
		  if (key_case_sensitive) {
			if (strcmp(de->d_name + (namsiz-sufsiz),
				   sufptr) != 0)
			      continue;
		  } else {
			if (strcasecmp(de->d_name + (namsiz-sufsiz),
				       sufptr) != 0)
			      continue;
		  }

		  key = new char[namsiz-sufsiz+1];
		  strncpy(key, de->d_name, namsiz-sufsiz);
		  key[namsiz-sufsiz] = 0;

		  break;
	    }

	    if (key == 0)
		  continue;

	      /* If the key is not to be case sensitive, then change
		 it to lowercase. */
	    if (! key_case_sensitive)
		  for (char*tmp = key ;  *tmp ;  tmp += 1)
			*tmp = tolower(*tmp);

	    mlp->name_map[key] = strdup(de->d_name);
	    delete[]key;
      }

      closedir(dir);

      if (library_last) {
	    assert(library_list);
	    library_last->next = mlp;
	    mlp->next = 0;
	    library_last = mlp;
      } else {
	    library_list = mlp;
	    library_last = mlp;
	    mlp->next = 0;
      }

      return 0;
}

/*
 * $Log: load_module.cc,v $
 * Revision 1.11  2002/08/12 01:34:59  steve
 *  conditional ident string using autoconfig.
 *
 * Revision 1.10  2002/08/03 22:30:00  steve
 *  Fix suffix parsing of library index.
 *
 * Revision 1.9  2002/07/10 04:34:18  steve
 *  Library dir case insensitivity includes the suffix.
 *
 * Revision 1.8  2002/06/06 18:57:18  steve
 *  Use standard name for iostream.
 *
 * Revision 1.7  2002/05/28 20:40:37  steve
 *  ivl indexes the search path for libraries, and
 *  supports case insensitive module-to-file lookup.
 *
 * Revision 1.6  2002/05/28 00:50:39  steve
 *  Add the ivl -C flag for bulk configuration
 *  from the driver, and use that to run library
 *  modules through the preprocessor.
 *
 * Revision 1.5  2002/04/04 05:26:13  steve
 *  Add dependency generation.
 *
 * Revision 1.4  2001/11/20 23:36:34  steve
 *  Close library files after parsing.
 *
 * Revision 1.3  2001/11/16 05:07:19  steve
 *  Add support for +libext+ in command files.
 *
 * Revision 1.2  2001/10/22 02:05:21  steve
 *  Handle activating tasks in another root.
 *
 * Revision 1.1  2001/10/20 23:02:40  steve
 *  Add automatic module libraries.
 *
 */

<commit_msg> INclude missing assert.h in load_module.<commit_after>/*
 * Copyright (c) 2001 Stephen Williams (steve@icarus.com)
 *
 *    This source code is free software; you can redistribute it
 *    and/or modify it in source code form 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
 */
#ifdef HAVE_CVS_IDENT
#ident "$Id: load_module.cc,v 1.12 2003/06/05 04:31:09 steve Exp $"
#endif

# include  "config.h"
# include  "util.h"
# include  "parse_api.h"
# include  "compiler.h"
# include  <iostream>
# include  <map>
# include  <string>
# include  <sys/types.h>
# include  <dirent.h>
# include  <ctype.h>
# include  <assert.h>

/*
 * The module library items are maps of key names to file name within
 * the directory.
 */
struct module_library {
      char*dir;
      bool key_case_sensitive;
      map<string,const char*>name_map;
      struct module_library*next;
};

static struct module_library*library_list = 0;
static struct module_library*library_last = 0;

const char dir_character = '/';
extern FILE *depend_file;

/*
 * Use the type name as a key, and search the module library for a
 * file name that has that key.
 */
bool load_module(const char*type)
{
      char path[4096];
      char*ltype = strdup(type);

      for (char*tmp = ltype ; *tmp ;  tmp += 1)
	    *tmp = tolower(*tmp);

      for (struct module_library*lcur = library_list
		 ; lcur != 0 ;  lcur = lcur->next) {

	    const char*key = lcur->key_case_sensitive? type : ltype;
	    map<string,const char*>::const_iterator cur;
	    cur = lcur->name_map.find(key);
	    if (cur == lcur->name_map.end())
		  continue;

	    sprintf(path, "%s%c%s", lcur->dir, dir_character, (*cur).second);

	    if(depend_file) {
		  fprintf(depend_file, "%s\n", path);
	    }

	    if (ivlpp_string) {
		  char*cmdline = (char*)malloc(strlen(ivlpp_string) +
					       strlen(path) + 2);
		  strcpy(cmdline, ivlpp_string);
		  strcat(cmdline, " ");
		  strcat(cmdline, path);
		  FILE*file = popen(cmdline, "r");

		  if (verbose_flag)
			cerr << "Executing: " << cmdline << endl;

		  pform_parse(path, file);
		  fclose(file);
		  free(cmdline);

	    } else {
		  if (verbose_flag)
			cerr << "Loading library file "
			     << path << "." << endl;

		  FILE*file = fopen(path, "r");
		  assert(file);
		  pform_parse(path, file);
		  fclose(file);
	    }

	    return true;
      }

      return false;
}

/*
 * This function takes the name of a library directory that the caller
 * passed, and builds a name index for it.
 */
int build_library_index(const char*path, bool key_case_sensitive)
{
      DIR*dir = opendir(path);
      if (dir == 0)
	    return -1;

      if (verbose_flag) {
	    cerr << "Indexing library: " << path << endl;
      }

      struct module_library*mlp = new struct module_library;
      mlp->dir = strdup(path);
      mlp->key_case_sensitive = key_case_sensitive;

	/* Scan the director for files. check each file name to see if
	   it has one of the configured suffixes. If it does, then use
	   the root of the name as the key and index the file name. */
      while (struct dirent*de = readdir(dir)) {
	    unsigned namsiz = strlen(de->d_name);
	    char*key = 0;

	    for (list<const char*>::iterator suf = library_suff.begin()
		       ; suf != library_suff.end()
		       ; suf ++ ) {
		  const char*sufptr = *suf;
		  unsigned sufsiz = strlen(sufptr);

		  if (sufsiz >= namsiz)
			continue;

		    /* If the directory is case insensitive, then so
		       is the suffix. */
		  if (key_case_sensitive) {
			if (strcmp(de->d_name + (namsiz-sufsiz),
				   sufptr) != 0)
			      continue;
		  } else {
			if (strcasecmp(de->d_name + (namsiz-sufsiz),
				       sufptr) != 0)
			      continue;
		  }

		  key = new char[namsiz-sufsiz+1];
		  strncpy(key, de->d_name, namsiz-sufsiz);
		  key[namsiz-sufsiz] = 0;

		  break;
	    }

	    if (key == 0)
		  continue;

	      /* If the key is not to be case sensitive, then change
		 it to lowercase. */
	    if (! key_case_sensitive)
		  for (char*tmp = key ;  *tmp ;  tmp += 1)
			*tmp = tolower(*tmp);

	    mlp->name_map[key] = strdup(de->d_name);
	    delete[]key;
      }

      closedir(dir);

      if (library_last) {
	    assert(library_list);
	    library_last->next = mlp;
	    mlp->next = 0;
	    library_last = mlp;
      } else {
	    library_list = mlp;
	    library_last = mlp;
	    mlp->next = 0;
      }

      return 0;
}

/*
 * $Log: load_module.cc,v $
 * Revision 1.12  2003/06/05 04:31:09  steve
 *  INclude missing assert.h in load_module.
 *
 * Revision 1.11  2002/08/12 01:34:59  steve
 *  conditional ident string using autoconfig.
 *
 * Revision 1.10  2002/08/03 22:30:00  steve
 *  Fix suffix parsing of library index.
 *
 * Revision 1.9  2002/07/10 04:34:18  steve
 *  Library dir case insensitivity includes the suffix.
 *
 * Revision 1.8  2002/06/06 18:57:18  steve
 *  Use standard name for iostream.
 *
 * Revision 1.7  2002/05/28 20:40:37  steve
 *  ivl indexes the search path for libraries, and
 *  supports case insensitive module-to-file lookup.
 *
 * Revision 1.6  2002/05/28 00:50:39  steve
 *  Add the ivl -C flag for bulk configuration
 *  from the driver, and use that to run library
 *  modules through the preprocessor.
 *
 * Revision 1.5  2002/04/04 05:26:13  steve
 *  Add dependency generation.
 *
 * Revision 1.4  2001/11/20 23:36:34  steve
 *  Close library files after parsing.
 *
 * Revision 1.3  2001/11/16 05:07:19  steve
 *  Add support for +libext+ in command files.
 *
 * Revision 1.2  2001/10/22 02:05:21  steve
 *  Handle activating tasks in another root.
 *
 * Revision 1.1  2001/10/20 23:02:40  steve
 *  Add automatic module libraries.
 *
 */

<|endoftext|>


<commit_before>//
//
//  screen_shot.cpp
//
//  Created by Leopold O'Donnell on 3/18/13.
//  MIT-LIcense Copyright (c) 2013 Leo O'Donnell.
//

#include <ApplicationServices/ApplicationServices.h>
#include "screen_shot.h"

Screenshot::Screenshot(CGContextRef bitmap_context) : _bitmap_context(bitmap_context) {}

Screenshot::~Screenshot() {
  CGContextRelease(_bitmap_context);
}

void* Screenshot::get_bitmap() {
  return CGBitmapContextGetData(_bitmap_context);
}

size_t Screenshot::get_width() {
  return CGBitmapContextGetWidth(_bitmap_context);
}

size_t Screenshot::get_height() {
  return CGBitmapContextGetHeight(_bitmap_context);
}

size_t Screenshot::get_bits_per_pixel() {
  return CGBitmapContextGetBitsPerPixel(_bitmap_context);
}

bool Screenshot::write_png(const char* filepath) {
  CFURLRef url = CFURLCreateWithFileSystemPath(
    NULL,
    CFStringCreateWithCString(NULL, filepath, kCFStringEncodingUTF8),
    kCFURLPOSIXPathStyle,
    false);
  CGImageDestinationRef destination = CGImageDestinationCreateWithURL(url, kUTTypePNG, 1, NULL);

  store_image(destination);

  CFRelease(destination);

  return true;
}

CFMutableDataRef Screenshot::create_png_data(size_t &length) {

  length = get_width() * get_height() * (get_bits_per_pixel()/8);

  CFMutableDataRef png_data         = CFDataCreateMutable(NULL, 0);
  CGImageDestinationRef destination = CGImageDestinationCreateWithData(png_data, kUTTypePNG, 1, NULL);

  if (!store_image(destination)) {
    length = 0;
  }

  CFRelease(destination);

  return png_data;
}

bool Screenshot::store_image(CGImageDestinationRef destination) {
  CGImageRef image = CGBitmapContextCreateImage(_bitmap_context);

  CGImageDestinationAddImage(destination, image, nil);

  if (!CGImageDestinationFinalize(destination)) {
      fprintf(stderr, "Failed to write image to destination\n");
      return false;
  }

  CFRelease(image);

  return true;
}<commit_msg>Specify the length to avoid issues with pointer out of bounds problems should the png generated take less space than expected.<commit_after>//
//
//  screen_shot.cpp
//
//  Created by Leopold O'Donnell on 3/18/13.
//  MIT-LIcense Copyright (c) 2013 Leo O'Donnell.
//

#include <ApplicationServices/ApplicationServices.h>
#include "screen_shot.h"

Screenshot::Screenshot(CGContextRef bitmap_context) : _bitmap_context(bitmap_context) {}

Screenshot::~Screenshot() {
  CGContextRelease(_bitmap_context);
}

void* Screenshot::get_bitmap() {
  return CGBitmapContextGetData(_bitmap_context);
}

size_t Screenshot::get_width() {
  return CGBitmapContextGetWidth(_bitmap_context);
}

size_t Screenshot::get_height() {
  return CGBitmapContextGetHeight(_bitmap_context);
}

size_t Screenshot::get_bits_per_pixel() {
  return CGBitmapContextGetBitsPerPixel(_bitmap_context);
}

bool Screenshot::write_png(const char* filepath) {
  CFURLRef url = CFURLCreateWithFileSystemPath(
    NULL,
    CFStringCreateWithCString(NULL, filepath, kCFStringEncodingUTF8),
    kCFURLPOSIXPathStyle,
    false);
  CGImageDestinationRef destination = CGImageDestinationCreateWithURL(url, kUTTypePNG, 1, NULL);

  store_image(destination);

  CFRelease(destination);

  return true;
}

CFMutableDataRef Screenshot::create_png_data(size_t &length) {

  length = get_width() * get_height() * (get_bits_per_pixel()/8);

  CFMutableDataRef png_data         = CFDataCreateMutable(NULL, length);
  CGImageDestinationRef destination = CGImageDestinationCreateWithData(png_data, kUTTypePNG, 1, NULL);

  if (!store_image(destination)) {
    length = 0;
  }

  CFRelease(destination);

  return png_data;
}

bool Screenshot::store_image(CGImageDestinationRef destination) {
  CGImageRef image = CGBitmapContextCreateImage(_bitmap_context);

  CGImageDestinationAddImage(destination, image, nil);

  if (!CGImageDestinationFinalize(destination)) {
      fprintf(stderr, "Failed to write image to destination\n");
      return false;
  }

  CFRelease(image);

  return true;
}<|endoftext|>


<commit_before>void sim(Int_t nev=50) {
  if (!strcmp(gSystem->GetBuildArch(),"win32gcc")) {
    gSystem->Load("libProof");
    gSystem->Load("libGui");
    gROOT->Macro("loadlibssim.C");
    new AliRun("gAlice","The ALICE Off-line Simulation Framework");
  }

  AliLog::SetClassDebugLevel("AliGeomManager",3);
  AliSimulation simulator;
  simulator.SetMakeSDigits("TRD TOF PHOS HMPID EMCAL MUON FMD ZDC PMD T0 VZERO");
  simulator.SetMakeDigitsFromHits("ITS TPC");
  if (strcmp(gSystem->GetBuildArch(),"win32gcc")) {
    simulator.SetWriteRawData("ALL","raw.root",kTRUE);
  }
  simulator.SetRunHLT("");
  simulator.SetRunQA("");

  TStopwatch timer;
  timer.Start();
  simulator.Run(nev);
  timer.Stop();
  timer.Print();
}
<commit_msg>No debug output from AliGeomManager. Corrected call to SetRunQA<commit_after>void sim(Int_t nev=50) {
  if (!strcmp(gSystem->GetBuildArch(),"win32gcc")) {
    gSystem->Load("libProof");
    gSystem->Load("libGui");
    gROOT->Macro("loadlibssim.C");
    new AliRun("gAlice","The ALICE Off-line Simulation Framework");
  }

  AliSimulation simulator;
  simulator.SetMakeSDigits("TRD TOF PHOS HMPID EMCAL MUON FMD ZDC PMD T0 VZERO");
  simulator.SetMakeDigitsFromHits("ITS TPC");
  if (strcmp(gSystem->GetBuildArch(),"win32gcc")) {
    simulator.SetWriteRawData("ALL","raw.root",kTRUE);
  }
  simulator.SetRunHLT("");
  simulator.SetRunQA(":");

  TStopwatch timer;
  timer.Start();
  simulator.Run(nev);
  timer.Stop();
  timer.Print();
}
<|endoftext|>


<commit_before>// -*- Mode:C++ -*-

/**************************************************************************************************/
/*                                                                                */
/* Copyright (C) 2014 University of Hull                                                          */
/*                                                                                */
/**************************************************************************************************/
/*                                                                                */
/*  module     :  support/test/refcounted.cpp                                                     */
/*  project    :                                                                                */
/*  description:                                                                                */
/*                                                                                */
/**************************************************************************************************/

// includes, system

#include <boost/intrusive_ptr.hpp> // boost::intrusive_ptr<>

// includes, project

#include <support/refcounted.hpp>

// internal unnamed namespace

namespace {

  // types, internal (class, enum, struct, union, typedef)

  class refcounted_test : public support::refcounted { /* ... */ };

  class refcount_user {

  public:

    explicit refcount_user(refcounted_test* a)
      : rt_(a)
    {
      rt_->add_ref();
    }

    ~refcount_user()
    {
      rt_->sub_ref();
    }

  private:

    refcounted_test* rt_;

  };

  // variables, internal

  // functions, internal

} // namespace {

// functions, exported

#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>

BOOST_AUTO_TEST_CASE(test_support_refcounted_add_ref)
{
  refcounted_test a;

  a.add_ref();

  BOOST_CHECK(1 == a.get_ref());
}

BOOST_AUTO_TEST_CASE(test_support_refcounted_sub_ref)
{
  refcounted_test a;

  a.add_ref();
  a.add_ref();
  a.sub_ref();

  BOOST_CHECK(1 == a.get_ref());
}

BOOST_AUTO_TEST_CASE(test_support_refcounted_user)
{
  refcounted_test* a(new refcounted_test);
  refcount_user    b(a);

  {
    refcount_user bb(a);

    BOOST_CHECK(2 == a->get_ref());
  }

  BOOST_CHECK(1 == a->get_ref());
}

BOOST_AUTO_TEST_CASE(test_support_refcounted_guard)
{
  refcounted_test* a(new refcounted_test);

  a->add_ref();

  {
    support::refcounted::guard const rcg(a);

    BOOST_CHECK(2 == a->get_ref());
  }

  BOOST_CHECK(1 == a->get_ref());
}

//BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(test_support_refcounted_intrusive_ptr_0, 1);

BOOST_AUTO_TEST_CASE(test_support_refcounted_intrusive_ptr_0)
{
  refcounted_test* rct(new refcounted_test);

  BOOST_CHECK(0 == rct->get_ref());
  {
    boost::intrusive_ptr<refcounted_test> irct(rct);

    BOOST_CHECK(1 == irct->get_ref());
  }
  BOOST_CHECK(0 == rct->get_ref());
}

BOOST_AUTO_TEST_CASE(test_support_refcounted_intrusive_ptr_1)
{
  refcounted_test* rct(new refcounted_test);

  rct->add_ref();

  BOOST_CHECK(1 == rct->get_ref());
  {
    boost::intrusive_ptr<refcounted_test> irct(rct);

    BOOST_CHECK(2 == irct->get_ref());
  }
  BOOST_CHECK(1 == rct->get_ref());

  rct->sub_ref();
}

//BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(test_support_refcounted_intrusive_ptr_2, 1);

BOOST_AUTO_TEST_CASE(test_support_refcounted_intrusive_ptr_2)
{
  refcounted_test* rct(new refcounted_test);

  BOOST_CHECK(0 == rct->get_ref());
  {
    boost::intrusive_ptr<refcounted_test> irct(rct);

    BOOST_CHECK(rct == irct.get());
    BOOST_CHECK(  1 == irct->get_ref());

    irct = new refcounted_test;

    BOOST_CHECK(rct != irct.get());
    BOOST_CHECK(  1 == irct->get_ref());
  }
  BOOST_CHECK(0 == rct->get_ref());
}
<commit_msg>update: platform-specific expected test-case fail<commit_after>// -*- Mode:C++ -*-

/**************************************************************************************************/
/*                                                                                */
/* Copyright (C) 2014-2015 University of Hull                                                     */
/*                                                                                */
/**************************************************************************************************/
/*                                                                                */
/*  module     :  support/test/refcounted.cpp                                                     */
/*  project    :                                                                                */
/*  description:                                                                                */
/*                                                                                */
/**************************************************************************************************/

// includes, system

#include <boost/intrusive_ptr.hpp> // boost::intrusive_ptr<>

// includes, project

#include <support/refcounted.hpp>

// internal unnamed namespace

namespace {

  // types, internal (class, enum, struct, union, typedef)

  class refcounted_test : public support::refcounted { /* ... */ };

  class refcount_user {

  public:

    explicit refcount_user(refcounted_test* a)
      : rt_(a)
    {
      rt_->add_ref();
    }

    ~refcount_user()
    {
      rt_->sub_ref();
    }

  private:

    refcounted_test* rt_;

  };

  // variables, internal

  // functions, internal

} // namespace {

// functions, exported

#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>

BOOST_AUTO_TEST_CASE(test_support_refcounted_add_ref)
{
  refcounted_test a;

  a.add_ref();

  BOOST_CHECK(1 == a.get_ref());
}

BOOST_AUTO_TEST_CASE(test_support_refcounted_sub_ref)
{
  refcounted_test a;

  a.add_ref();
  a.add_ref();
  a.sub_ref();

  BOOST_CHECK(1 == a.get_ref());
}

BOOST_AUTO_TEST_CASE(test_support_refcounted_user)
{
  refcounted_test* a(new refcounted_test);
  refcount_user    b(a);

  {
    refcount_user bb(a);

    BOOST_CHECK(2 == a->get_ref());
  }

  BOOST_CHECK(1 == a->get_ref());
}

BOOST_AUTO_TEST_CASE(test_support_refcounted_guard)
{
  refcounted_test* a(new refcounted_test);

  a->add_ref();

  {
    support::refcounted::guard const rcg(a);

    BOOST_CHECK(2 == a->get_ref());
  }

  BOOST_CHECK(1 == a->get_ref());
}

#if defined(_MSC_VER) && (_MSC_VER < 1900)
BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(test_support_refcounted_intrusive_ptr_0, 1);
#endif

BOOST_AUTO_TEST_CASE(test_support_refcounted_intrusive_ptr_0)
{
  refcounted_test* rct(new refcounted_test);

  BOOST_CHECK(0 == rct->get_ref());
  {
    boost::intrusive_ptr<refcounted_test> irct(rct);

    BOOST_CHECK(1 == irct->get_ref());
  }
  BOOST_CHECK(0 == rct->get_ref());
}

BOOST_AUTO_TEST_CASE(test_support_refcounted_intrusive_ptr_1)
{
  refcounted_test* rct(new refcounted_test);

  rct->add_ref();

  BOOST_CHECK(1 == rct->get_ref());
  {
    boost::intrusive_ptr<refcounted_test> irct(rct);

    BOOST_CHECK(2 == irct->get_ref());
  }
  BOOST_CHECK(1 == rct->get_ref());

  rct->sub_ref();
}

#if defined(_MSC_VER) && (_MSC_VER < 1900)
BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(test_support_refcounted_intrusive_ptr_2, 1);
#endif

BOOST_AUTO_TEST_CASE(test_support_refcounted_intrusive_ptr_2)
{
  refcounted_test* rct(new refcounted_test);

  BOOST_CHECK(0 == rct->get_ref());
  {
    boost::intrusive_ptr<refcounted_test> irct(rct);

    BOOST_CHECK(rct == irct.get());
    BOOST_CHECK(  1 == irct->get_ref());

    irct = new refcounted_test;

    BOOST_CHECK(rct != irct.get());
    BOOST_CHECK(  1 == irct->get_ref());
  }
  BOOST_CHECK(0 == rct->get_ref());
}
<|endoftext|>


<commit_before>/**
	This software was developed by the University of Tennessee as part of the
	Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
	project funded by the US National Science Foundation.

	If you use DANSE applications to do scientific research that leads to
	publication, we ask that you acknowledge the use of the software with the
	following sentence:

	"This work benefited from DANSE software developed under NSF award DMR-0520547."

	copyright 2008, University of Tennessee
 */

/**
 * Scattering model classes
 * The classes use the IGOR library found in
 *   sansmodels/src/libigor
 *
 *	TODO: refactor so that we pull in the old sansmodels.c_extensions
 */

#include <math.h>
#include "models.hh"
#include "parameters.hh"
#include <stdio.h>
using namespace std;

extern "C" {
	#include "libStructureFactor.h"
	#include "HayterMSA.h"
}

HayterMSAStructure :: HayterMSAStructure() {
	effect_radius      = Parameter(20.75, true);
	effect_radius.set_min(0.0);
	charge      = Parameter(19.0, true);
	volfraction = Parameter(0.0192, true);
	volfraction.set_min(0.0);
	temperature = Parameter(318.16, true);
	temperature.set_min(0.0);
	saltconc   = Parameter(0.0);
	dielectconst  = Parameter(71.08);
}

/**
 * Function to evaluate 1D scattering function
 * The NIST IGOR library is used for the actual calculation.
 * @param q: q-value
 * @return: function value
 */
double HayterMSAStructure :: operator()(double q) {
	double dp[6];

	// Fill parameter array for IGOR library
	// Add the background after averaging
	dp[0] = 2.0*effect_radius();
	dp[1] = fabs(charge());
	dp[2] = volfraction();
	dp[3] = temperature();
	dp[4] = saltconc();
	dp[5] = dielectconst();

	// Get the dispersion points for the radius
	vector<WeightPoint> weights_rad;
	effect_radius.get_weights(weights_rad);

	// Perform the computation, with all weight points
	double sum = 0.0;
	double norm = 0.0;

	// Loop over radius weight points
	for(int i=0; i<weights_rad.size(); i++) {
		dp[0] = 2.0*weights_rad[i].value;

		sum += weights_rad[i].weight
				* HayterPenfoldMSA(dp, q);
		norm += weights_rad[i].weight;
	}
	return sum/norm ;
}

/**
 * Function to evaluate 2D scattering function
 * @param q_x: value of Q along x
 * @param q_y: value of Q along y
 * @return: function value
 */
double HayterMSAStructure :: operator()(double qx, double qy) {
	double q = sqrt(qx*qx + qy*qy);
	return (*this).operator()(q);
}

/**
 * Function to evaluate 2D scattering function
 * @param pars: parameters of the cylinder
 * @param q: q-value
 * @param phi: angle phi
 * @return: function value
 */
double HayterMSAStructure :: evaluate_rphi(double q, double phi) {
	double qx = q*cos(phi);
	double qy = q*sin(phi);
	return (*this).operator()(qx, qy);
}
/**
 * Function to calculate effective radius
 * @return: effective radius value
 */
double HayterMSAStructure :: calculate_ER() {
//NOT implemented yet!!!
  return 0.0;
}

// Testing code
/*
int main(void)
{
	SquareWellModel c = SquareWellModel();

	printf("I(Qx=%g,Qy=%g) = %g\n", 0.001, 0.001, c(0.001, 0.001));
	printf("I(Q=%g) = %g\n", 0.001, c(0.001));
	c.radius.dispersion = new GaussianDispersion();
	c.radius.dispersion->npts = 100;
	c.radius.dispersion->width = 5;

	//c.length.dispersion = GaussianDispersion();
	//c.length.dispersion.npts = 20;
	//c.length.dispersion.width = 65;

	printf("I(Q=%g) = %g\n", 0.001, c(0.001));
	printf("I(Q=%g) = %g\n", 0.001, c(0.001));
	printf("I(Qx=%g, Qy=%g) = %g\n", 0.001, 0.001, c(0.001, 0.001));
	printf("I(Q=%g,  Phi=%g) = %g\n", 0.00447, .7854, c.evaluate_rphi(sqrt(0.00002), .7854));

	double i_avg = c(0.01, 0.01);
	double i_1d = c(sqrt(0.0002));

	printf("\nI(Qx=%g, Qy=%g) = %g\n", 0.01, 0.01, i_avg);
	printf("I(Q=%g)         = %g\n", sqrt(0.0002), i_1d);
	printf("ratio %g %g\n", i_avg/i_1d, i_1d/i_avg);

	return 0;
}
*/
<commit_msg>Fix warning<commit_after>/**
	This software was developed by the University of Tennessee as part of the
	Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
	project funded by the US National Science Foundation.

	If you use DANSE applications to do scientific research that leads to
	publication, we ask that you acknowledge the use of the software with the
	following sentence:

	"This work benefited from DANSE software developed under NSF award DMR-0520547."

	copyright 2008, University of Tennessee
 */

/**
 * Scattering model classes
 * The classes use the IGOR library found in
 *   sansmodels/src/libigor
 *
 *	TODO: refactor so that we pull in the old sansmodels.c_extensions
 */

#include <math.h>
#include "models.hh"
#include "parameters.hh"
#include <stdio.h>
using namespace std;

extern "C" {
	#include "libStructureFactor.h"
	#include "HayterMSA.h"
}

HayterMSAStructure :: HayterMSAStructure() {
	effect_radius      = Parameter(20.75, true);
	effect_radius.set_min(0.0);
	charge      = Parameter(19.0, true);
	volfraction = Parameter(0.0192, true);
	volfraction.set_min(0.0);
	temperature = Parameter(318.16, true);
	temperature.set_min(0.0);
	saltconc   = Parameter(0.0);
	dielectconst  = Parameter(71.08);
}

/**
 * Function to evaluate 1D scattering function
 * The NIST IGOR library is used for the actual calculation.
 * @param q: q-value
 * @return: function value
 */
double HayterMSAStructure :: operator()(double q) {
	double dp[6];

	// Fill parameter array for IGOR library
	// Add the background after averaging
	dp[0] = 2.0*effect_radius();
	dp[1] = fabs(charge());
	dp[2] = volfraction();
	dp[3] = temperature();
	dp[4] = saltconc();
	dp[5] = dielectconst();

	// Get the dispersion points for the radius
	vector<WeightPoint> weights_rad;
	effect_radius.get_weights(weights_rad);

	// Perform the computation, with all weight points
	double sum = 0.0;
	double norm = 0.0;

	// Loop over radius weight points
	for(size_t i=0; i<weights_rad.size(); i++) {
		dp[0] = 2.0*weights_rad[i].value;

		sum += weights_rad[i].weight
				* HayterPenfoldMSA(dp, q);
		norm += weights_rad[i].weight;
	}
	return sum/norm ;
}

/**
 * Function to evaluate 2D scattering function
 * @param q_x: value of Q along x
 * @param q_y: value of Q along y
 * @return: function value
 */
double HayterMSAStructure :: operator()(double qx, double qy) {
	double q = sqrt(qx*qx + qy*qy);
	return (*this).operator()(q);
}

/**
 * Function to evaluate 2D scattering function
 * @param pars: parameters of the cylinder
 * @param q: q-value
 * @param phi: angle phi
 * @return: function value
 */
double HayterMSAStructure :: evaluate_rphi(double q, double phi) {
	double qx = q*cos(phi);
	double qy = q*sin(phi);
	return (*this).operator()(qx, qy);
}
/**
 * Function to calculate effective radius
 * @return: effective radius value
 */
double HayterMSAStructure :: calculate_ER() {
//NOT implemented yet!!!
  return 0.0;
}

// Testing code
/*
int main(void)
{
	SquareWellModel c = SquareWellModel();

	printf("I(Qx=%g,Qy=%g) = %g\n", 0.001, 0.001, c(0.001, 0.001));
	printf("I(Q=%g) = %g\n", 0.001, c(0.001));
	c.radius.dispersion = new GaussianDispersion();
	c.radius.dispersion->npts = 100;
	c.radius.dispersion->width = 5;

	//c.length.dispersion = GaussianDispersion();
	//c.length.dispersion.npts = 20;
	//c.length.dispersion.width = 65;

	printf("I(Q=%g) = %g\n", 0.001, c(0.001));
	printf("I(Q=%g) = %g\n", 0.001, c(0.001));
	printf("I(Qx=%g, Qy=%g) = %g\n", 0.001, 0.001, c(0.001, 0.001));
	printf("I(Q=%g,  Phi=%g) = %g\n", 0.00447, .7854, c.evaluate_rphi(sqrt(0.00002), .7854));

	double i_avg = c(0.01, 0.01);
	double i_1d = c(sqrt(0.0002));

	printf("\nI(Qx=%g, Qy=%g) = %g\n", 0.01, 0.01, i_avg);
	printf("I(Q=%g)         = %g\n", sqrt(0.0002), i_1d);
	printf("ratio %g %g\n", i_avg/i_1d, i_1d/i_avg);

	return 0;
}
*/
<|endoftext|>


<commit_before>
//
// This source file is part of appleseed.
// Visit https://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2019 Francois Beaune, The appleseedhq Organization
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "backendapi.h"

// appleseed.bench headers.
#include "utility/encryptionkey.h"

// appleseed.foundation headers.
#include "foundation/platform/compiler.h"

// appleseed.qtcommon headers.
#include "utility/encryption.h"

// Qt headers.
#include <QByteArray>
#include <QFile>
#include <QIODevice>
#include <QJsonObject>
#include <QJsonValue>
#include <QNetworkRequest>
#include <QTextStream>
#include <QUrl>
#include <QVariant>

// Standard headers.
#include <cassert>
#include <cstdint>
#include <stdexcept>

using namespace foundation;

namespace appleseed {
namespace bench {

//
// Setup:
//
//   1. Retrieve the API key (in the form of a Base64 string) from the backend API's configuration page.
//
//   2. Generate a new encryption key:
//        a. Go to https://www.random.org/cgi-bin/randbyte?nbytes=16&format=h
//        b. Copy the hexadecimal key
//        c. Go to https://base64.guru/converter/encode/hex
//        d. Convert the hexadecimal key to a Base64 one and copy it
//
//   3. Encode the API URL in Base64:
//        a. Go to https://base64.guru/converter/encode/text
//        b. Convert the API URL to Base64 and copy it
//
//   4. Run CMake a first time:
//        cmake
//            -DAPPLESEED_BENCH_BACKEND_API_URL=<unencrypted API URL in Base64>
//            -DAPPLESEED_BENCH_BACKEND_API_KEY=<unencrypted API key in Base64>
//            -DAPPLESEED_BENCH_ENCRYPTION_KEY=<encryption key in Base64>
//            ..
//
//   5. Encrypt the API URL and API key:
//        a. In appleseed.bench's main.cpp, uncomment the lines
//             const QString encrypted_api_url = get_encrypted_api_url();
//             const QString encrypted_api_key = get_encrypted_api_key();
//        b. Set a breakpoint on the next line
//        c. Build appleseed.bench in Debug mode and run it
//        d. Capture and copy the values of the `encrypted_api_url` and `encrypted_api_key` variables
//        e. Comment again the two lines uncommented on step a and remove the breakpoint
//
//   6. Run CMake a second time to replace the API URL and API key by their encrypted counterparts:
//        cmake
//            -DAPPLESEED_BENCH_BACKEND_API_URL=<encrypted API URL in Base64>
//            -DAPPLESEED_BENCH_BACKEND_API_KEY=<encrypted API key in Base64>
//            ..
//
//   7. Convert the encryption key to C++ code:
//        a. In appleseed.bench's main.cpp, uncomment the line
//             generate_encryption_key_cpp_file();
//        b. Build appleseed.bench and run it
//        c. Make sure the file utility/encryptionkey.cpp has been generated or overwritten
//        d. Comment again the line uncommented on step a
//        e. Build appleseed.bench and run it
//        f. Check that you can view rankings
//

#ifndef APPLESEED_SHIP

void generate_encryption_key_cpp_file()
{
    // Assume that the working directory is sandbox/.
    QFile file("../src/appleseed.bench/utility/encryptionkey.cpp");

    if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
        throw std::runtime_error("Failed to open encryption_key.h for writing");

    const QByteArray encryption_key = QByteArray::fromBase64(APPLESEED_TO_STRING_EVAL(APPLESEED_BENCH_ENCRYPTION_KEY));

    QTextStream stream(&file);

    stream << "// This file is auto-generated. Do not modify it.\n";
    stream << "\n";
    stream << "// Interface header.\n";
    stream << "#include \"encryptionkey.h\"\n";
    stream << "\n";
    stream << "// Qt headers.\n";
    stream << "#include <QByteArray>\n";
    stream << "\n";
    stream << "namespace appleseed {\n";
    stream << "namespace bench {\n";
    stream << "\n";
    stream << "QByteArray get_encryption_key()\n";
    stream << "{\n";
    stream << "    QByteArray key;\n";
    stream << QString("    key.resize(%1);\n").arg(encryption_key.size());

    for (int i = 0, e = encryption_key.size(); i < e; ++i)
        stream << QString("    key[%1] = %2;\n").arg(i).arg(static_cast<int>(encryption_key[i]));

    stream << "    return key;\n";
    stream << "}\n";
    stream << "\n";
    stream << "}   // namespace bench\n";
    stream << "}   // namespace appleseed\n";
}

QByteArray encrypt(const QByteArray& input)
{
    const QByteArray encryption_key = QByteArray::fromBase64(APPLESEED_TO_STRING_EVAL(APPLESEED_BENCH_ENCRYPTION_KEY));

    // Abort (don't just assert) if the key is too short.
    if (encryption_key.size() < 16)
        throw std::runtime_error("Encryption key must be 16-byte long (24-character long in Base64)");

    return qtcommon::encrypt(input, encryption_key);
}

QString get_encrypted_api_url()
{
    const QByteArray api_url = QByteArray::fromBase64(APPLESEED_TO_STRING_EVAL(APPLESEED_BENCH_BACKEND_API_URL));
    return encrypt(api_url).toBase64();
}

QString get_encrypted_api_key()
{
    const QByteArray api_key = QByteArray::fromBase64(APPLESEED_TO_STRING_EVAL(APPLESEED_BENCH_BACKEND_API_KEY));
    return encrypt(api_key).toBase64();
}

#endif

QByteArray decrypt(const QByteArray& input)
{
    const QByteArray encryption_key = get_encryption_key();
    assert(encryption_key.size() == 16);

    return qtcommon::decrypt(input, encryption_key);
}

QString get_decrypted_api_url()
{
    const QByteArray encrypted_api_url = QByteArray::fromBase64(APPLESEED_TO_STRING_EVAL(APPLESEED_BENCH_BACKEND_API_URL));
    return decrypt(encrypted_api_url);
}

QString get_decrypted_api_key()
{
    const QByteArray encrypted_api_key = QByteArray::fromBase64(APPLESEED_TO_STRING_EVAL(APPLESEED_BENCH_BACKEND_API_KEY));
    return decrypt(encrypted_api_key).toBase64();
}

QNetworkRequest make_api_request(const QString& route)
{
    assert(!route.isEmpty() && route[0] == '/');

    const QUrl url(
        get_decrypted_api_url()
            .arg(route)
            .arg(QString(QUrl::toPercentEncoding(get_decrypted_api_key()))));

    return QNetworkRequest(url);
}

QString filter_api_key(const QString& s)
{
    QString result = s;
    result.replace(get_decrypted_api_key(), QString(3, 'X'));
    return result;
}

namespace
{
    QString get_string(const QJsonObject& json_obj, const QString& key)
    {
        const QJsonValue json_value = json_obj[key];
        if (!json_value.isString())
            throw ExceptionJsonValue();
        return json_value.toString();
    }

    int get_int(const QJsonObject& json_obj, const QString& key)
    {
        const QJsonValue json_value = json_obj[key];
        bool ok = false;
        const int value = json_value.toVariant().toInt(&ok);
        if (!ok)
            throw ExceptionJsonValue();
        return value;
    }
}

BenchmarkResult BenchmarkResult::from_json_object(const QJsonObject& json_obj)
{
    BenchmarkResult result;
    result.m_id = get_string(json_obj, "_id");
    result.m_submission_datetime_utc = QDateTime::fromString(get_string(json_obj, "submissionDateTimeUtc"));
    result.m_benchmark_version = get_int(json_obj, "benchmarkVersion");
    result.m_benchmark_scene_id = get_string(json_obj, "benchmarkSceneId");
    result.m_cpu_model = get_string(json_obj, "cpuModel");
    result.m_enabled_cpu_core_count = get_int(json_obj, "cpuCoreCount");
    result.m_cpu_thread_count = get_int(json_obj, "cpuThreadCount");
    result.m_render_thread_count = get_int(json_obj, "renderThreadCount");
    result.m_render_time = get_int(json_obj, "renderTime");
    return result;
}

QJsonObject BenchmarkResult::to_json_object() const
{
    QJsonObject json_obj;
    // _id is ignored, it will be set automatically by MongoDB.
    json_obj["submissionDateTimeUtc"] = m_submission_datetime_utc.toString(Qt::ISODate);
    json_obj["benchmarkVersion"] = m_benchmark_version;
    json_obj["benchmarkSceneId"] = m_benchmark_scene_id;
    json_obj["cpuModel"] = m_cpu_model;
    json_obj["cpuCoreCount"] = m_enabled_cpu_core_count;
    json_obj["cpuThreadCount"] = m_cpu_thread_count;
    json_obj["renderThreadCount"] = m_render_thread_count;
    json_obj["renderTime"] = m_render_time;
    return json_obj;
}

}   // namespace bench
}   // namespace appleseed
<commit_msg>Improve appleseed.bench setup instructions<commit_after>
//
// This source file is part of appleseed.
// Visit https://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2019 Francois Beaune, The appleseedhq Organization
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "backendapi.h"

// appleseed.bench headers.
#include "utility/encryptionkey.h"

// appleseed.foundation headers.
#include "foundation/platform/compiler.h"

// appleseed.qtcommon headers.
#include "utility/encryption.h"

// Qt headers.
#include <QByteArray>
#include <QFile>
#include <QIODevice>
#include <QJsonObject>
#include <QJsonValue>
#include <QNetworkRequest>
#include <QTextStream>
#include <QUrl>
#include <QVariant>

// Standard headers.
#include <cassert>
#include <cstdint>
#include <stdexcept>

using namespace foundation;

namespace appleseed {
namespace bench {

//
// Setup:
//
//   1. Retrieve from the backend API's configuration page:
//        - the API URL (append %1?apiKey=%2 to it)
//        - the API key (in the form of a Base64 string)
//
//   2. Generate a new encryption key:
//        a. Go to https://www.random.org/cgi-bin/randbyte?nbytes=16&format=h
//        b. Copy the hexadecimal key
//        c. Go to https://base64.guru/converter/encode/hex
//        d. Convert the hexadecimal key to a Base64 one and copy it
//
//   3. Encode the API URL in Base64:
//        a. Go to https://base64.guru/converter/encode/text
//        b. Convert the API URL to Base64 and copy it
//
//   4. Run CMake a first time:
//        cmake
//            -DAPPLESEED_BENCH_BACKEND_API_URL=<unencrypted API URL in Base64>
//            -DAPPLESEED_BENCH_BACKEND_API_KEY=<unencrypted API key in Base64>
//            -DAPPLESEED_BENCH_ENCRYPTION_KEY=<encryption key in Base64>
//            ..
//
//   5. Encrypt the API URL and API key:
//        a. In appleseed.bench's main.cpp, uncomment the lines
//             const QString encrypted_api_url = get_encrypted_api_url();
//             const QString encrypted_api_key = get_encrypted_api_key();
//        b. Set a breakpoint on the next line
//        c. Build appleseed.bench in Debug mode and run it (make sure you have Qt Visual Studio Tools installed)
//        d. Capture and copy the values of the `encrypted_api_url` and `encrypted_api_key` variables
//        e. Comment again the two lines uncommented on step a and remove the breakpoint
//
//   6. Run CMake a second time to replace the API URL and API key by their encrypted versions:
//        cmake
//            -DAPPLESEED_BENCH_BACKEND_API_URL=<encrypted API URL in Base64>
//            -DAPPLESEED_BENCH_BACKEND_API_KEY=<encrypted API key in Base64>
//            ..
//
//   7. Convert the encryption key to C++ code:
//        a. In appleseed.bench's main.cpp, uncomment the line
//             generate_encryption_key_cpp_file();
//        b. Build appleseed.bench and run it
//        c. Make sure the file utility/encryptionkey.cpp has been generated or overwritten
//        d. Comment again the line uncommented on step a
//        e. Build appleseed.bench and run it
//        f. Check that you can view rankings
//

#ifndef APPLESEED_SHIP

void generate_encryption_key_cpp_file()
{
    // Assume that the working directory is sandbox/.
    QFile file("../src/appleseed.bench/utility/encryptionkey.cpp");

    if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
        throw std::runtime_error("Failed to open encryption_key.h for writing");

    const QByteArray encryption_key = QByteArray::fromBase64(APPLESEED_TO_STRING_EVAL(APPLESEED_BENCH_ENCRYPTION_KEY));

    QTextStream stream(&file);

    stream << "// This file is auto-generated. Do not modify it.\n";
    stream << "\n";
    stream << "// Interface header.\n";
    stream << "#include \"encryptionkey.h\"\n";
    stream << "\n";
    stream << "// Qt headers.\n";
    stream << "#include <QByteArray>\n";
    stream << "\n";
    stream << "namespace appleseed {\n";
    stream << "namespace bench {\n";
    stream << "\n";
    stream << "QByteArray get_encryption_key()\n";
    stream << "{\n";
    stream << "    QByteArray key;\n";
    stream << QString("    key.resize(%1);\n").arg(encryption_key.size());

    for (int i = 0, e = encryption_key.size(); i < e; ++i)
        stream << QString("    key[%1] = %2;\n").arg(i).arg(static_cast<int>(encryption_key[i]));

    stream << "    return key;\n";
    stream << "}\n";
    stream << "\n";
    stream << "}   // namespace bench\n";
    stream << "}   // namespace appleseed\n";
}

QByteArray encrypt(const QByteArray& input)
{
    const QByteArray encryption_key = QByteArray::fromBase64(APPLESEED_TO_STRING_EVAL(APPLESEED_BENCH_ENCRYPTION_KEY));

    // Abort (don't just assert) if the key is too short.
    if (encryption_key.size() < 16)
        throw std::runtime_error("Encryption key must be 16-byte long (24-character long in Base64)");

    return qtcommon::encrypt(input, encryption_key);
}

QString get_encrypted_api_url()
{
    const QByteArray api_url = QByteArray::fromBase64(APPLESEED_TO_STRING_EVAL(APPLESEED_BENCH_BACKEND_API_URL));
    return encrypt(api_url).toBase64();
}

QString get_encrypted_api_key()
{
    const QByteArray api_key = QByteArray::fromBase64(APPLESEED_TO_STRING_EVAL(APPLESEED_BENCH_BACKEND_API_KEY));
    return encrypt(api_key).toBase64();
}

#endif

QByteArray decrypt(const QByteArray& input)
{
    const QByteArray encryption_key = get_encryption_key();
    assert(encryption_key.size() == 16);

    return qtcommon::decrypt(input, encryption_key);
}

QString get_decrypted_api_url()
{
    const QByteArray encrypted_api_url = QByteArray::fromBase64(APPLESEED_TO_STRING_EVAL(APPLESEED_BENCH_BACKEND_API_URL));
    return decrypt(encrypted_api_url);
}

QString get_decrypted_api_key()
{
    const QByteArray encrypted_api_key = QByteArray::fromBase64(APPLESEED_TO_STRING_EVAL(APPLESEED_BENCH_BACKEND_API_KEY));
    return decrypt(encrypted_api_key).toBase64();
}

QNetworkRequest make_api_request(const QString& route)
{
    assert(!route.isEmpty() && route[0] == '/');

    const QUrl url(
        get_decrypted_api_url()
            .arg(route)
            .arg(QString(QUrl::toPercentEncoding(get_decrypted_api_key()))));

    return QNetworkRequest(url);
}

QString filter_api_key(const QString& s)
{
    QString result = s;
    result.replace(get_decrypted_api_key(), QString(3, 'X'));
    return result;
}

namespace
{
    QString get_string(const QJsonObject& json_obj, const QString& key)
    {
        const QJsonValue json_value = json_obj[key];
        if (!json_value.isString())
            throw ExceptionJsonValue();
        return json_value.toString();
    }

    int get_int(const QJsonObject& json_obj, const QString& key)
    {
        const QJsonValue json_value = json_obj[key];
        bool ok = false;
        const int value = json_value.toVariant().toInt(&ok);
        if (!ok)
            throw ExceptionJsonValue();
        return value;
    }
}

BenchmarkResult BenchmarkResult::from_json_object(const QJsonObject& json_obj)
{
    BenchmarkResult result;
    result.m_id = get_string(json_obj, "_id");
    result.m_submission_datetime_utc = QDateTime::fromString(get_string(json_obj, "submissionDateTimeUtc"));
    result.m_benchmark_version = get_int(json_obj, "benchmarkVersion");
    result.m_benchmark_scene_id = get_string(json_obj, "benchmarkSceneId");
    result.m_cpu_model = get_string(json_obj, "cpuModel");
    result.m_enabled_cpu_core_count = get_int(json_obj, "cpuCoreCount");
    result.m_cpu_thread_count = get_int(json_obj, "cpuThreadCount");
    result.m_render_thread_count = get_int(json_obj, "renderThreadCount");
    result.m_render_time = get_int(json_obj, "renderTime");
    return result;
}

QJsonObject BenchmarkResult::to_json_object() const
{
    QJsonObject json_obj;
    // _id is ignored, it will be set automatically by MongoDB.
    json_obj["submissionDateTimeUtc"] = m_submission_datetime_utc.toString(Qt::ISODate);
    json_obj["benchmarkVersion"] = m_benchmark_version;
    json_obj["benchmarkSceneId"] = m_benchmark_scene_id;
    json_obj["cpuModel"] = m_cpu_model;
    json_obj["cpuCoreCount"] = m_enabled_cpu_core_count;
    json_obj["cpuThreadCount"] = m_cpu_thread_count;
    json_obj["renderThreadCount"] = m_render_thread_count;
    json_obj["renderTime"] = m_render_time;
    return json_obj;
}

}   // namespace bench
}   // namespace appleseed
<|endoftext|>


<commit_before>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2012 Francois Beaune, Jupiter Jazz Limited
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "path.h"

// appleseed.foundation headers.
#ifdef __APPLE__
#include "foundation/platform/types.h"
#endif

// boost headers.
#include "boost/filesystem/operations.hpp"

// Platform headers.
#if defined __APPLE__
#include <mach-o/dyld.h>
#elif defined __linux__
#include <unistd.h>
#endif

// Standard headers.
#include <cassert>
#include <cstddef>
#include <cstring>
#include <cstdio>

using namespace boost;
using namespace std;

namespace foundation
{

//
// Path class implementation.
//

const char* Path::get_executable_path()
{
    static char path[FOUNDATION_MAX_PATH_LENGTH + 1];
    static bool path_initialized = false;

    if (!path_initialized)
    {
// Windows.
#if defined _WIN32

	    const DWORD result =
            GetModuleFileName(
		        GetModuleHandle(NULL),
		        path,
		        sizeof(path));
        assert(result);

// Mac OS X.
#elif defined __APPLE__

        uint32 path_len = MAXPATHLEN;
        const int result = _NSGetExecutablePath(path, &path_len);
        assert(result == 0);

// Linux.
#elif defined __linux__

		static char linkname[FOUNDATION_MAX_PATH_LENGTH + 1];
		pid_t pid = getpid();

		if (snprintf(linkname, sizeof(linkname), "/proc/%i/exe", pid) < 0)
			assert(false);

		int result = readlink(linkname, path, sizeof(path));

		if (result == -1)
			assert(false);

		if (result >= sizeof(path))
			assert( false);

        assert(result > 0);
        path[result] = '\0';

#endif

        path_initialized = true;
    }

    return path;
}

const char* Path::get_executable_directory()
{
    static char path[FOUNDATION_MAX_PATH_LENGTH + 1];
    static bool path_initialized = false;

    if (!path_initialized)
    {
        filesystem::path executable_path(get_executable_path());

        assert(executable_path.has_filename());
        executable_path.remove_filename();

        assert(executable_path.string().size() <= FOUNDATION_MAX_PATH_LENGTH);
        strcpy(path, executable_path.string().c_str());

        path_initialized = true;
    }

    return path;
}

}   // namespace foundation
<commit_msg>Undo previous commit.<commit_after>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2012 Francois Beaune, Jupiter Jazz Limited
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "path.h"

// appleseed.foundation headers.
#ifdef __APPLE__
#include "foundation/platform/types.h"
#endif

// boost headers.
#include "boost/filesystem/operations.hpp"

// Platform headers.
#if defined __APPLE__
#include <mach-o/dyld.h>
#elif defined __linux__
#include <unistd.h>
#endif

// Standard headers.
#include <cassert>
#include <cstddef>
#include <cstring>

using namespace boost;
using namespace std;

namespace foundation
{

//
// Path class implementation.
//

const char* Path::get_executable_path()
{
    static char path[FOUNDATION_MAX_PATH_LENGTH + 1];
    static bool path_initialized = false;

    if (!path_initialized)
    {
// Windows.
#if defined _WIN32

	    const DWORD result =
            GetModuleFileName(
		        GetModuleHandle(NULL),
		        path,
		        sizeof(path));
        assert(result);

// Mac OS X.
#elif defined __APPLE__

        uint32 path_len = MAXPATHLEN;
        const int result = _NSGetExecutablePath(path, &path_len);
        assert(result == 0);

// Linux.
#elif defined __linux__

        ssize_t result = readlink("/proc/self/exe", path, sizeof(path));
        assert(result > 0);
        path[result] = '\0';

#endif

        path_initialized = true;
    }

    return path;
}

const char* Path::get_executable_directory()
{
    static char path[FOUNDATION_MAX_PATH_LENGTH + 1];
    static bool path_initialized = false;

    if (!path_initialized)
    {
        filesystem::path executable_path(get_executable_path());

        assert(executable_path.has_filename());
        executable_path.remove_filename();

        assert(executable_path.string().size() <= FOUNDATION_MAX_PATH_LENGTH);
        strcpy(path, executable_path.string().c_str());

        path_initialized = true;
    }

    return path;
}

}   // namespace foundation
<|endoftext|>