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

#include <vector>
#include <memory>

#include "LIEF/types.hpp"
#include "LIEF/visibility.h"
#include "LIEF/Object.hpp"
#include "LIEF/iterators.hpp"

#include "LIEF/Abstract/Header.hpp"
#include "LIEF/Abstract/Function.hpp"

//! LIEF namespace
namespace LIEF {
class Section;
class Relocation;
class Symbol;

//! Abstract binary that exposes an uniform API for the
//! different executable file formats
class LIEF_API Binary : public Object {

  public:

  //! Type of a virtual address
  enum class VA_TYPES {
    AUTO = 0, ///< Try to guess if it's relative or not
    RVA  = 1, ///< Relative
    VA   = 2, ///< Absolute
  };

  using functions_t = std::vector<Function>;

  //! Internal container
  using sections_t = std::vector<Section*>;

  //! Iterator that outputs LIEF::Section&
  using it_sections = ref_iterator<sections_t>;

  //! Iterator that outputs const LIEF::Section&
  using it_const_sections = const_ref_iterator<sections_t>;

  //! Internal container
  using symbols_t = std::vector<Symbol*>;

  //! Iterator that outputs LIEF::Symbol&
  using it_symbols = ref_iterator<symbols_t>;

  //! Iterator that outputs const LIEF::Symbol&
  using it_const_symbols = const_ref_iterator<symbols_t>;

  //! Internal container
  using relocations_t = std::vector<Relocation*>;

  //! Iterator that outputs LIEF::Relocation&
  using it_relocations = ref_iterator<relocations_t>;

  //! Iterator that outputs const LIEF::Relocation&
  using it_const_relocations = const_ref_iterator<relocations_t>;

  public:
  Binary();
  virtual ~Binary();

  Binary& operator=(const Binary&);
  Binary(const Binary&);

  //! Executable format (ELF, PE, Mach-O) of the underlying binary
  EXE_FORMATS format() const;

  //! Return the abstract header of the binary
  Header header() const;

  //! Return an iterator over the abstracted symbols in which the elements **can** be modified
  it_symbols symbols();

  //! Return an iterator over the abstracted symbols in which the elements **can't** be modified
  it_const_symbols  symbols() const;

  //! Check if a Symbol with the given name exists
  bool has_symbol(const std::string& name) const;

  //! Return the Symbol with the given name
  //! If the symbol does not exist, return a nullptr
  const Symbol* get_symbol(const std::string& name) const;

  Symbol* get_symbol(const std::string& name);

  //! Return an iterator over the binary's sections (LIEF::Section)
  it_sections sections();
  it_const_sections sections() const;

  //! Remove **all** the sections in the underlying binary
  virtual void remove_section(const std::string& name, bool clear = false) = 0;

  //! Return an iterator over the binary relocation (LIEF::Relocation)
  it_relocations       relocations();
  it_const_relocations relocations() const;

  //! Binary's entrypoint (if any)
  virtual uint64_t entrypoint() const = 0;

  //! Binary's name
  const std::string& name() const;

  //! Binary's original size
  uint64_t original_size() const;

  //! Return the functions exported by the binary
  functions_t exported_functions() const;

  //! Return libraries which are imported by the binary
  std::vector<std::string> imported_libraries() const;

  //! Return functions imported by the binary
  functions_t imported_functions() const;

  //! Return the address of the given function name
  virtual uint64_t get_function_address(const std::string& func_name) const;

  //! Method so that a ``visitor`` can visit us
  void accept(Visitor& visitor) const override;

  std::vector<uint64_t> xref(uint64_t address) const;

  //! Patch the content at virtual address @p address with @p patch_value
  //!
  //! @param[in] address        Address to patch
  //! @param[in] patch_value    Patch to apply
  //! @param[in] addr_type      Specify if the address should be used as an
  //!                           absolute virtual address or a RVA
  virtual void patch_address(uint64_t address, const std::vector<uint8_t>& patch_value,
                             VA_TYPES addr_type = VA_TYPES::AUTO) = 0;

  //! Patch the address with the given value
  //!
  //! @param[in] address      Address to patch
  //! @param[in] patch_value  Patch to apply
  //! @param[in] size         Size of the value in **bytes** (1, 2, ... 8)
  //! @param[in] addr_type    Specify if the address should be used as an absolute virtual address or an RVA
  virtual void patch_address(uint64_t address, uint64_t patch_value, size_t size = sizeof(uint64_t),
                             VA_TYPES addr_type = VA_TYPES::AUTO) = 0;

  //! Return the content located at the given virtual address
  virtual std::vector<uint8_t> get_content_from_virtual_address(uint64_t virtual_address,
                                        uint64_t size, VA_TYPES addr_type = VA_TYPES::AUTO) const = 0;

  //! Change the binary's name
  void name(const std::string& name);

  //! @brief Change binary's original size.
  //!
  //! @warning
  //! This function should be used carefully as some optimizations
  //! can be performed with this value
  void original_size(uint64_t size);

  //! Check if the binary is position independent
  virtual bool is_pie() const = 0;

  //! Check if the binary uses ``NX`` protection
  virtual bool has_nx() const = 0;

  //! Default image base address if the ASLR is not enabled.
  virtual uint64_t imagebase() const = 0;

  //! Constructor functions that are called prior any other functions
  virtual LIEF::Binary::functions_t ctor_functions() const = 0;

  //! Convert the given offset into a virtual address.
  //!
  //! @param[in] offset   The offset to convert.
  //! @param[in] slide    If not 0, it will replace the default base address (if any)
  virtual uint64_t offset_to_virtual_address(uint64_t offset, uint64_t slide = 0) const = 0;

  virtual std::ostream& print(std::ostream& os) const;

  //! Build & transform the Binary object representation into a *real* executable
  virtual void write(const std::string& name) = 0;

  LIEF_API friend std::ostream& operator<<(std::ostream& os, const Binary& binary);

  protected:
  EXE_FORMATS format_ = EXE_FORMATS::FORMAT_UNKNOWN;
  std::string name_;

  uint64_t original_size_ = 0;

  // These functions need to be overloaded by the object that claims to extend this Abstract Binary
  virtual Header get_abstract_header() const = 0;
  virtual symbols_t get_abstract_symbols() = 0;
  virtual sections_t get_abstract_sections() = 0;
  virtual relocations_t get_abstract_relocations() = 0;

  virtual functions_t  get_abstract_exported_functions() const = 0;
  virtual functions_t  get_abstract_imported_functions() const = 0;
  virtual std::vector<std::string>  get_abstract_imported_libraries() const = 0;
};
}

#endif
<commit_msg>Fix Binary API conflict from redundant qualifier<commit_after>/* Copyright 2017 - 2022 R. Thomas
 * Copyright 2017 - 2022 Quarkslab
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef LIEF_ABSTRACT_BINARY_H_
#define LIEF_ABSTRACT_BINARY_H_

#include <vector>
#include <memory>

#include "LIEF/types.hpp"
#include "LIEF/visibility.h"
#include "LIEF/Object.hpp"
#include "LIEF/iterators.hpp"

#include "LIEF/Abstract/Header.hpp"
#include "LIEF/Abstract/Function.hpp"

//! LIEF namespace
namespace LIEF {
class Section;
class Relocation;
class Symbol;

//! Abstract binary that exposes an uniform API for the
//! different executable file formats
class LIEF_API Binary : public Object {

  public:

  //! Type of a virtual address
  enum class VA_TYPES {
    AUTO = 0, ///< Try to guess if it's relative or not
    RVA  = 1, ///< Relative
    VA   = 2, ///< Absolute
  };

  using functions_t = std::vector<Function>;

  //! Internal container
  using sections_t = std::vector<Section*>;

  //! Iterator that outputs LIEF::Section&
  using it_sections = ref_iterator<sections_t>;

  //! Iterator that outputs const LIEF::Section&
  using it_const_sections = const_ref_iterator<sections_t>;

  //! Internal container
  using symbols_t = std::vector<Symbol*>;

  //! Iterator that outputs LIEF::Symbol&
  using it_symbols = ref_iterator<symbols_t>;

  //! Iterator that outputs const LIEF::Symbol&
  using it_const_symbols = const_ref_iterator<symbols_t>;

  //! Internal container
  using relocations_t = std::vector<Relocation*>;

  //! Iterator that outputs LIEF::Relocation&
  using it_relocations = ref_iterator<relocations_t>;

  //! Iterator that outputs const LIEF::Relocation&
  using it_const_relocations = const_ref_iterator<relocations_t>;

  public:
  Binary();
  virtual ~Binary();

  Binary& operator=(const Binary&);
  Binary(const Binary&);

  //! Executable format (ELF, PE, Mach-O) of the underlying binary
  EXE_FORMATS format() const;

  //! Return the abstract header of the binary
  Header header() const;

  //! Return an iterator over the abstracted symbols in which the elements **can** be modified
  it_symbols symbols();

  //! Return an iterator over the abstracted symbols in which the elements **can't** be modified
  it_const_symbols  symbols() const;

  //! Check if a Symbol with the given name exists
  bool has_symbol(const std::string& name) const;

  //! Return the Symbol with the given name
  //! If the symbol does not exist, return a nullptr
  const Symbol* get_symbol(const std::string& name) const;

  Symbol* get_symbol(const std::string& name);

  //! Return an iterator over the binary's sections (LIEF::Section)
  it_sections sections();
  it_const_sections sections() const;

  //! Remove **all** the sections in the underlying binary
  virtual void remove_section(const std::string& name, bool clear = false) = 0;

  //! Return an iterator over the binary relocation (LIEF::Relocation)
  it_relocations       relocations();
  it_const_relocations relocations() const;

  //! Binary's entrypoint (if any)
  virtual uint64_t entrypoint() const = 0;

  //! Binary's name
  const std::string& name() const;

  //! Binary's original size
  uint64_t original_size() const;

  //! Return the functions exported by the binary
  functions_t exported_functions() const;

  //! Return libraries which are imported by the binary
  std::vector<std::string> imported_libraries() const;

  //! Return functions imported by the binary
  functions_t imported_functions() const;

  //! Return the address of the given function name
  virtual uint64_t get_function_address(const std::string& func_name) const;

  //! Method so that a ``visitor`` can visit us
  void accept(Visitor& visitor) const override;

  std::vector<uint64_t> xref(uint64_t address) const;

  //! Patch the content at virtual address @p address with @p patch_value
  //!
  //! @param[in] address        Address to patch
  //! @param[in] patch_value    Patch to apply
  //! @param[in] addr_type      Specify if the address should be used as an
  //!                           absolute virtual address or a RVA
  virtual void patch_address(uint64_t address, const std::vector<uint8_t>& patch_value,
                             VA_TYPES addr_type = VA_TYPES::AUTO) = 0;

  //! Patch the address with the given value
  //!
  //! @param[in] address      Address to patch
  //! @param[in] patch_value  Patch to apply
  //! @param[in] size         Size of the value in **bytes** (1, 2, ... 8)
  //! @param[in] addr_type    Specify if the address should be used as an absolute virtual address or an RVA
  virtual void patch_address(uint64_t address, uint64_t patch_value, size_t size = sizeof(uint64_t),
                             VA_TYPES addr_type = VA_TYPES::AUTO) = 0;

  //! Return the content located at the given virtual address
  virtual std::vector<uint8_t> get_content_from_virtual_address(uint64_t virtual_address,
                                        uint64_t size, VA_TYPES addr_type = VA_TYPES::AUTO) const = 0;

  //! Change the binary's name
  void name(const std::string& name);

  //! @brief Change binary's original size.
  //!
  //! @warning
  //! This function should be used carefully as some optimizations
  //! can be performed with this value
  void original_size(uint64_t size);

  //! Check if the binary is position independent
  virtual bool is_pie() const = 0;

  //! Check if the binary uses ``NX`` protection
  virtual bool has_nx() const = 0;

  //! Default image base address if the ASLR is not enabled.
  virtual uint64_t imagebase() const = 0;

  //! Constructor functions that are called prior any other functions
  virtual functions_t ctor_functions() const = 0;

  //! Convert the given offset into a virtual address.
  //!
  //! @param[in] offset   The offset to convert.
  //! @param[in] slide    If not 0, it will replace the default base address (if any)
  virtual uint64_t offset_to_virtual_address(uint64_t offset, uint64_t slide = 0) const = 0;

  virtual std::ostream& print(std::ostream& os) const;

  //! Build & transform the Binary object representation into a *real* executable
  virtual void write(const std::string& name) = 0;

  LIEF_API friend std::ostream& operator<<(std::ostream& os, const Binary& binary);

  protected:
  EXE_FORMATS format_ = EXE_FORMATS::FORMAT_UNKNOWN;
  std::string name_;

  uint64_t original_size_ = 0;

  // These functions need to be overloaded by the object that claims to extend this Abstract Binary
  virtual Header get_abstract_header() const = 0;
  virtual symbols_t get_abstract_symbols() = 0;
  virtual sections_t get_abstract_sections() = 0;
  virtual relocations_t get_abstract_relocations() = 0;

  virtual functions_t  get_abstract_exported_functions() const = 0;
  virtual functions_t  get_abstract_imported_functions() const = 0;
  virtual std::vector<std::string>  get_abstract_imported_libraries() const = 0;
};
}

#endif
<|endoftext|>


<commit_before>/*
	Nazara Engine

	Copyright (C) 2012 Jérôme "Lynix" Leclercq (Lynix680@gmail.com)

	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.
*/

#ifndef NAZARA_PREREQUESITES_HPP
#define NAZARA_PREREQUESITES_HPP

#if __cplusplus < 201103L
	#error Nazara requires a C++11 compliant compiler
#endif

// Version du moteur
#define NAZARA_VERSION_MAJOR 0
#define NAZARA_VERSION_MINOR 1

#include <Nazara/Core/Config.hpp>

///TODO: Rajouter des tests d'identification de compilateurs
// NAZARA_THREADLOCAL n'existe qu'en attendant le support complet de thread_local
#if defined(__BORLANDC__)
	#define NAZARA_COMPILER_BORDLAND
	#define NAZARA_DEPRECATED(txt)
	#define NAZARA_FUNCTION __FUNC__
	#define NAZARA_THREADLOCAL __declspec(thread)
#elif defined(__clang__)
	#define NAZARA_COMPILER_CLANG
	#define NAZARA_DEPRECATED(txt) __attribute__((__deprecated__(txt)))
	#define NAZARA_FUNCTION __PRETTY_FUNCTION__
	#define NAZARA_THREADLOCAL __declspec(thread)
#elif defined(__GNUC__) || defined(__MINGW32__)
	#define NAZARA_COMPILER_GCC
	#define NAZARA_DEPRECATED(txt) __attribute__((__deprecated__(txt)))
	#define NAZARA_FUNCTION __PRETTY_FUNCTION__
	#define NAZARA_THREADLOCAL __thread

	#ifdef __MINGW32__
		#define NAZARA_COMPILER_MINGW
		#ifdef __MINGW64_VERSION_MAJOR
			#define NAZARA_COMPILER_MINGW_W64
		#endif
	#endif
#elif defined(__INTEL_COMPILER) || defined(__ICL)
	#define NAZARA_COMPILER_INTEL
	#define NAZARA_DEPRECATED(txt)
	#define NAZARA_FUNCTION __FUNCTION__
	#define NAZARA_THREADLOCAL __thread
#elif defined(_MSC_VER)
	#define NAZARA_COMPILER_MSVC
	#define NAZARA_DEPRECATED(txt) __declspec(deprecated(txt))
	#define NAZARA_FUNCTION __FUNCSIG__
	#define NAZARA_THREADLOCAL __declspec(thread)
#else
	#define NAZARA_COMPILER_UNKNOWN
	#define NAZARA_DEPRECATED(txt)
	#define NAZARA_FUNCTION __func__ // __func__ est standard depuis le C++11
	#define NAZARA_THREADLOCAL thread_local
	#error This compiler is not fully supported
#endif

#define NazaraUnused(a) (void) a

#if defined(_WIN32) || defined(__WIN32__)
	#define NAZARA_PLATFORM_WINDOWS

	#if !defined(NAZARA_STATIC)
		#ifdef NAZARA_BUILD
			#define NAZARA_API __declspec(dllexport)
		#else
			#define NAZARA_API __declspec(dllimport)
		#endif
	#else
		#define NAZARA_API
	#endif

	// Des defines pour le header Windows
	#if defined(NAZARA_BUILD) // Pour ne pas entrer en conflit avec les defines de l'application ou d'une autre bibliothèque
		#ifndef WIN32_LEAN_AND_MEAN
			#define WIN32_LEAN_AND_MEAN
		#endif

		#ifndef NOMINMAX
			#define NOMINMAX
		#endif

		#if NAZARA_CORE_WINDOWS_VISTA
			// Version de Windows minimale : Vista
			#define NAZARA_WINNT 0x0600
		#else
			#define NAZARA_WINNT 0x0501
		#endif

		// Pour ne pas casser le define déjà en place s'il est applicable
		#if defined(_WIN32_WINNT)
			#if _WIN32_WINNT < NAZARA_WINNT
				#undef _WIN32_WINNT
				#define _WIN32_WINNT NAZARA_WINNT
			#endif
		#else
			#define _WIN32_WINNT NAZARA_WINNT
		#endif
	#endif
#elif defined(__linux__) || defined(linux) || defined(__linux)
	#define NAZARA_PLATFORM_LINUX
	#define NAZARA_PLATFORM_POSIX

	#if !defined(NAZARA_STATIC) && defined(NAZARA_COMPILER_GCC)
		#define NAZARA_API __attribute__((visibility ("default")))
	#else
		#define NAZARA_API
	#endif
/*#elif defined(__APPLE__) || defined(macintosh) || defined(Macintosh)
	#define NAZARA_API
	#define NAZARA_PLATFORM_MACOS
	#define NAZARA_PLATFORM_POSIX
#elif defined(__FreeBSD__)
	#define NAZARA_API
	#define NAZARA_PLATFORM_FREEBSD
	#define NAZARA_PLATFORM_POSIX*/
#else
	// À commenter pour tenter quand même une compilation
	#error This operating system is not fully supported by the Nazara Engine

	#define NAZARA_PLATFORM_UNKNOWN
	#define NAZARA_API
#endif

#if defined(_WIN64) ||  defined(__amd64__) || defined(__x86_64__) || defined(__ia64__) || defined(__ia64) || \
    defined(_M_IA64) || defined(__itanium__) || defined(__MINGW64__)
	#define NAZARA_PLATFORM_X64
#endif

#if !defined(NAZARA_DEBUG) && !defined(NDEBUG)
	#define NDEBUG
#endif

#include <cstdint>

static_assert(sizeof(int8_t)  == 1, "int8_t is not of the correct size" );
static_assert(sizeof(int16_t) == 2, "int16_t is not of the correct size");
static_assert(sizeof(int32_t) == 4, "int32_t is not of the correct size");
static_assert(sizeof(int64_t) == 8, "int64_t is not of the correct size");

static_assert(sizeof(uint8_t)  == 1, "uint8_t is not of the correct size" );
static_assert(sizeof(uint16_t) == 2, "uint16_t is not of the correct size");
static_assert(sizeof(uint32_t) == 4, "uint32_t is not of the correct size");
static_assert(sizeof(uint64_t) == 8, "uint64_t is not of the correct size");

typedef int8_t nzInt8;
typedef uint8_t nzUInt8;

typedef int16_t nzInt16;
typedef uint16_t nzUInt16;

typedef int32_t nzInt32;
typedef uint32_t nzUInt32;

typedef int64_t nzInt64;
typedef uint64_t nzUInt64;

#endif // NAZARA_PREREQUESITES_HPP
<commit_msg>Rename NAZARA_PLATFORM_X64 to NAZARA_PLATFORM_x64<commit_after>/*
	Nazara Engine

	Copyright (C) 2012 Jérôme "Lynix" Leclercq (Lynix680@gmail.com)

	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.
*/

#ifndef NAZARA_PREREQUESITES_HPP
#define NAZARA_PREREQUESITES_HPP

#if __cplusplus < 201103L
	#error Nazara requires a C++11 compliant compiler
#endif

// Version du moteur
#define NAZARA_VERSION_MAJOR 0
#define NAZARA_VERSION_MINOR 1

#include <Nazara/Core/Config.hpp>

///TODO: Rajouter des tests d'identification de compilateurs
// NAZARA_THREADLOCAL n'existe qu'en attendant le support complet de thread_local
#if defined(__BORLANDC__)
	#define NAZARA_COMPILER_BORDLAND
	#define NAZARA_DEPRECATED(txt)
	#define NAZARA_FUNCTION __FUNC__
	#define NAZARA_THREADLOCAL __declspec(thread)
#elif defined(__clang__)
	#define NAZARA_COMPILER_CLANG
	#define NAZARA_DEPRECATED(txt) __attribute__((__deprecated__(txt)))
	#define NAZARA_FUNCTION __PRETTY_FUNCTION__
	#define NAZARA_THREADLOCAL __declspec(thread)
#elif defined(__GNUC__) || defined(__MINGW32__)
	#define NAZARA_COMPILER_GCC
	#define NAZARA_DEPRECATED(txt) __attribute__((__deprecated__(txt)))
	#define NAZARA_FUNCTION __PRETTY_FUNCTION__
	#define NAZARA_THREADLOCAL __thread

	#ifdef __MINGW32__
		#define NAZARA_COMPILER_MINGW
		#ifdef __MINGW64_VERSION_MAJOR
			#define NAZARA_COMPILER_MINGW_W64
		#endif
	#endif
#elif defined(__INTEL_COMPILER) || defined(__ICL)
	#define NAZARA_COMPILER_INTEL
	#define NAZARA_DEPRECATED(txt)
	#define NAZARA_FUNCTION __FUNCTION__
	#define NAZARA_THREADLOCAL __thread
#elif defined(_MSC_VER)
	#define NAZARA_COMPILER_MSVC
	#define NAZARA_DEPRECATED(txt) __declspec(deprecated(txt))
	#define NAZARA_FUNCTION __FUNCSIG__
	#define NAZARA_THREADLOCAL __declspec(thread)
#else
	#define NAZARA_COMPILER_UNKNOWN
	#define NAZARA_DEPRECATED(txt)
	#define NAZARA_FUNCTION __func__ // __func__ est standard depuis le C++11
	#define NAZARA_THREADLOCAL thread_local
	#error This compiler is not fully supported
#endif

#define NazaraUnused(a) (void) a

#if defined(_WIN32) || defined(__WIN32__)
	#define NAZARA_PLATFORM_WINDOWS

	#if !defined(NAZARA_STATIC)
		#ifdef NAZARA_BUILD
			#define NAZARA_API __declspec(dllexport)
		#else
			#define NAZARA_API __declspec(dllimport)
		#endif
	#else
		#define NAZARA_API
	#endif

	// Des defines pour le header Windows
	#if defined(NAZARA_BUILD) // Pour ne pas entrer en conflit avec les defines de l'application ou d'une autre bibliothèque
		#ifndef WIN32_LEAN_AND_MEAN
			#define WIN32_LEAN_AND_MEAN
		#endif

		#ifndef NOMINMAX
			#define NOMINMAX
		#endif

		#if NAZARA_CORE_WINDOWS_VISTA
			// Version de Windows minimale : Vista
			#define NAZARA_WINNT 0x0600
		#else
			#define NAZARA_WINNT 0x0501
		#endif

		// Pour ne pas casser le define déjà en place s'il est applicable
		#if defined(_WIN32_WINNT)
			#if _WIN32_WINNT < NAZARA_WINNT
				#undef _WIN32_WINNT
				#define _WIN32_WINNT NAZARA_WINNT
			#endif
		#else
			#define _WIN32_WINNT NAZARA_WINNT
		#endif
	#endif
#elif defined(__linux__) || defined(linux) || defined(__linux)
	#define NAZARA_PLATFORM_LINUX
	#define NAZARA_PLATFORM_POSIX

	#if !defined(NAZARA_STATIC) && defined(NAZARA_COMPILER_GCC)
		#define NAZARA_API __attribute__((visibility ("default")))
	#else
		#define NAZARA_API
	#endif
/*#elif defined(__APPLE__) || defined(macintosh) || defined(Macintosh)
	#define NAZARA_API
	#define NAZARA_PLATFORM_MACOS
	#define NAZARA_PLATFORM_POSIX
#elif defined(__FreeBSD__)
	#define NAZARA_API
	#define NAZARA_PLATFORM_FREEBSD
	#define NAZARA_PLATFORM_POSIX*/
#else
	// À commenter pour tenter quand même une compilation
	#error This operating system is not fully supported by the Nazara Engine

	#define NAZARA_PLATFORM_UNKNOWN
	#define NAZARA_API
#endif

#if defined(_WIN64) ||  defined(__amd64__) || defined(__x86_64__) || defined(__ia64__) || defined(__ia64) || \
    defined(_M_IA64) || defined(__itanium__) || defined(__MINGW64__)
	#define NAZARA_PLATFORM_x64
#endif

#if !defined(NAZARA_DEBUG) && !defined(NDEBUG)
	#define NDEBUG
#endif

#include <cstdint>

static_assert(sizeof(int8_t)  == 1, "int8_t is not of the correct size" );
static_assert(sizeof(int16_t) == 2, "int16_t is not of the correct size");
static_assert(sizeof(int32_t) == 4, "int32_t is not of the correct size");
static_assert(sizeof(int64_t) == 8, "int64_t is not of the correct size");

static_assert(sizeof(uint8_t)  == 1, "uint8_t is not of the correct size" );
static_assert(sizeof(uint16_t) == 2, "uint16_t is not of the correct size");
static_assert(sizeof(uint32_t) == 4, "uint32_t is not of the correct size");
static_assert(sizeof(uint64_t) == 8, "uint64_t is not of the correct size");

typedef int8_t nzInt8;
typedef uint8_t nzUInt8;

typedef int16_t nzInt16;
typedef uint16_t nzUInt16;

typedef int32_t nzInt32;
typedef uint32_t nzUInt32;

typedef int64_t nzInt64;
typedef uint64_t nzUInt64;

#endif // NAZARA_PREREQUESITES_HPP
<|endoftext|>


<commit_before>#ifndef ALEPH_TOPOLOGY_IO_GML_HH__
#define ALEPH_TOPOLOGY_IO_GML_HH__

#include <fstream>
#include <map>
#include <set>
#include <regex>
#include <sstream>
#include <stack>
#include <string>
#include <vector>

#include <aleph/utilities/String.hh>

namespace aleph
{

namespace topology
{

namespace io
{

/**
  @class GMLReader
  @brief Parses files in GML (Graph Modeling Language) format

  This is a simple reader for graphs in GML format. It suports a basic
  subset of the GML specification, viz. the specification of different
  attributes for nodes, as well as weight specifications for edges.

  Currently, the following attributes will be read:

  - \c id (for nodes)
  - \c label (for nodes)
  - \c source (for edges)
  - \c target (for edges)
  - \c weight (for edges)
*/

class GMLReader
{
public:

  template <class SimplicialComplex> void operator()( const std::string& filename, SimplicialComplex& K )
  {
    std::ifstream in( filename );
    if( !in )
      throw std::runtime_error( "Unable to read input file" );

    this->operator()( in, K );
  }

  template <class SimplicialComplex> void operator()( std::ifstream& in, SimplicialComplex& K )
  {
    _nodes.clear();
    _edges.clear();

    using namespace aleph::utilities;

    using Simplex           = typename SimplicialComplex::ValueType;
    using DataType          = typename Simplex::DataType;
    using VertexType        = typename Simplex::VertexType;

    std::string line;
    std::set<std::string> levels     = { "graph", "node", "edge" };
    std::set<std::string> attributes = { "id", "label", "source", "target", "value", "weight" };

    auto isLevel = [&levels] ( const std::string& name )
    {
      return levels.find( name ) != levels.end();
    };

    auto isAttribute = [&attributes] ( const std::string& name )
    {
      return attributes.find( name ) != attributes.end();
    };

    // Specifies the current level the parser is in. May be either one
    // of the known levels above.
    std::stack<std::string> currentLevel;

    // Last level that was read by the parser. If an open bracket '[' is
    // identified, this will become the current level.
    std::string lastLevel;

    Graph graph;
    Node node;
    Edge edge;

    std::regex reAttribute = std::regex( "([[:alpha:]]+)[[:space:]]*.*" );
    std::regex reKeyValue  = std::regex( "([[:alpha:]]+)[[:space:]]+([[:alnum:]\\.]+)" );
    std::regex reLabel     = std::regex( "(label)[[:space:]]+\"([^\"]+)\"" );

    while( std::getline( in, line ) )
    {
      line        = trim( line );
      auto tokens = split( line );

      // Skip comment lines. This is somewhat wasteful because I am
      // splitting the complete string even though I merely need to
      // know the first token.
      if( tokens.empty() == false && ( tokens.front() == "comment" || tokens.front() == "Creator" ) )
        continue;

      // A new level may also be opened "inline" by specifying a name
      // and the opening bracket at the same time.
      bool newLevel = isLevel( line ) || ( tokens.size() == 2 && tokens.back() == "[" && isLevel( tokens.front() ) );

      // Detecting a new level
      if( newLevel )
      {
        auto level = tokens.size() == 2 ? tokens.front() : line;

        if( lastLevel.empty() )
          lastLevel = level;
        else
          throw std::runtime_error( "Encountered incorrectly-nested levels" );

        // Only store the level directly when it has been specified
        // inline
        if( tokens.size() == 2 )
        {
          currentLevel.push( level );
          lastLevel = "";
        }
      }

      // Opening a new level
      else if( line == "[" )
      {
        currentLevel.push( lastLevel );
        lastLevel = "";
      }

      // Closing a new level
      else if( line == "]" )
      {
        if( currentLevel.top() == "node" )
          _nodes.push_back( node );
        else if( currentLevel.top() == "edge" )
          _edges.push_back( edge );

        // Reset node and edge data structure to fill them again once
        // a new level is being encountered.
        node = {};
        edge = {};

        currentLevel.pop();
      }

      // Check for attributes
      else
      {
        if( currentLevel.empty() )
          throw std::runtime_error( "Expected a non-empty current level" );

        std::smatch matches;

        auto* dict = currentLevel.top() == "node" ? &node.dict
                                                  : currentLevel.top() == "edge" ? &edge.dict
                                                                                : currentLevel.top() == "graph" ? &graph.dict
                                                                                : throw std::runtime_error( "Current level is unknown" );

        if( std::regex_match( line, matches, reAttribute ) )
        {
          auto name = matches[1];
          if( isAttribute( name ) )
          {
            // Special matching for labels
            if( name == "label" )
              std::regex_match( line, matches, reLabel );

            // Regular matching for all other attributes
            else
              std::regex_match( line, matches, reKeyValue );

            auto value = matches[2];

            if( name == "id" )
              node.id = value;
            else if( name == "source" )
              edge.source = value;
            else if( name == "target" )
              edge.target = value;

            // Just add it to the dictionary of optional values
            else
             dict->operator[]( name ) = value;
          }
          // Skip unknown attributes...
          else
          {
          }
        }
      }
    }

    // Creates nodes (vertices) ----------------------------------------

    std::set<std::string> nodeIDs;

    for( auto&& node : _nodes )
    {
      auto pair = nodeIDs.insert( node.id );
      if( !pair.second )
        throw std::runtime_error( "Duplicate node id '" + node.id + "'" );
    }

    // Lambda expression for creating a numerical ID out of a parsed ID. In
    // case non-numerical IDs are being used in the source file this Lambda
    // expression ensures that internal IDs always start with a zero.
    auto getID = [&nodeIDs] ( const std::string& id )
    {
      // Try to be smart: If the node ID can be converted into the
      // vertex type, we use the converted number instead.
      try
      {
        auto convertedID = std::stoll( id );
        return static_cast<VertexType>( convertedID );
      }
      catch( std::out_of_range& e )
      {
        throw;
      }
      catch( std::invalid_argument& )
      {
        return static_cast<VertexType>(
          std::distance( nodeIDs.begin(), nodeIDs.find( id ) )
        );
      }
    };

    std::vector<Simplex> simplices;
    simplices.reserve( _nodes.size() + _edges.size() );

    for( auto&& node : _nodes )
    {
      auto id = getID( node.id );

      if( node.dict.find( "weight" ) != node.dict.end() )
        simplices.push_back( Simplex( id, convert<DataType>( node.dict.at( "weight" ) ) ) );
      else if( node.dict.find( "value" ) != node.dict.end() )
        simplices.push_back( Simplex( id, convert<DataType>( node.dict.at( "value" ) ) ) );
      else
        simplices.push_back( Simplex( id ) );
    }

    // Create edges ----------------------------------------------------

    auto getSimplexByID = [&simplices] ( VertexType id )
    {
      auto position = std::find_if( simplices.begin(), simplices.end(),
                                    [&id] ( const Simplex& s )
                                    {
                                      return s.dimension() == 0 && s[0] == id;
                                    } );

      if( position != simplices.end() )
        return *position;
      else
        throw std::runtime_error( "Querying unknown simplex for edge creation" );
    };

    for( auto&& edge : _edges )
    {
      auto u = getID( edge.source );
      auto v = getID( edge.target );

      // No optional data attached; need to create weight based on node
      // weights, if those are available.
      if( edge.dict.find( "weight" ) == edge.dict.end() && edge.dict.find( "value" ) == edge.dict.end() )
      {
        // TODO: This is very slow and could be sped up by maintaining
        // the simplex ID somewhere else with faster access.
        auto uSimplex = getSimplexByID( u );
        auto vSimplex = getSimplexByID( v );

        // TODO: Permit the usage of other weight assignment strategies
        // here, for example by using a functor.
        auto data = std::max( uSimplex.data(), vSimplex.data() );

        simplices.push_back( Simplex( {u,v}, data ) );
      }

      // Use converted weight
      else if( edge.dict.find( "weight" ) != edge.dict.end() )
        simplices.push_back( Simplex( {u,v}, convert<DataType>( edge.dict.at( "weight" ) ) ) );
      else if( edge.dict.find( "value" ) != edge.dict.end() )
        simplices.push_back( Simplex( {u,v}, convert<DataType>( edge.dict.at( "value" ) ) ) );
    }

    _graph = graph;
    K      = SimplicialComplex( simplices.begin(), simplices.end() );
  }

  /**
    Retrieves a map of attribute values for each node. The attributes
    will be assigned to the node ID. Empty attributes signify that no
    such information is available.
  */

  std::map<std::string, std::string> getNodeAttribute( const std::string& attribute ) const
  {
    std::map<std::string, std::string> map;

    for( auto&& node : _nodes )
    {
      if( node.dict.find( attribute ) == node.dict.end() )
        map[ node.id ] = std::string();
      else
        map[ node.id ] = node.dict.at( attribute );
    }

    return map;
  }

private:

  /** Describes a parsed graph along with all of its attributes */
  struct Graph
  {
    std::map<std::string, std::string> dict; // all remaining attributes
  };

  /** Describes a parsed node along with all of its attributes */
  struct Node
  {
    std::string id;

    std::map<std::string, std::string> dict; // all remaining attributes
  };

  /** Describes a parsed edge along with all of its attributes */
  struct Edge
  {
    std::string source;
    std::string target;

    std::map<std::string, std::string> dict; // all remaining attributes
  };

  // Local storage -----------------------------------------------------
  //
  // Variables in this section contain the result of the last parsing
  // process. This is useful when clients are querying attributes.

  Graph _graph;

  std::vector<Node> _nodes;
  std::vector<Edge> _edges;
};

/**
  @class GMLWriter
  @brief Writes files in GML (Graph Modeling Language) format

  This is a simple writer for graphs in GML format. It suports a basic
  subset of the GML specification, viz. the specification of different
  attributes for nodes, as well as weight specifications for edges.

  Given a simplicial complex, it will store it as a weighted graph.

  Currently, the following attributes will be written:

  * \c id (for nodes)
  * \c source (for edges)
  * \c target (for edges)
  * \c weight (for edges)
*/

class GMLWriter
{
public:

  template <class SimplicialComplex> void operator()( const std::string& filename, SimplicialComplex& K )
  {
    std::ofstream out( filename );
    if( !out )
      throw std::runtime_error( "Unable to open output file" );

    this->operator()( out, K );
  }

  template <class SimplicialComplex> void operator()( std::ostream& out, SimplicialComplex& K )
  {
    std::ostringstream streamNodes;
    std::ostringstream streamEdges;

    for( auto&& simplex : K )
    {
      if( simplex.dimension() == 0 )
      {
        streamNodes << "  node [\n"
                    << "    id " << *simplex.begin() << "\n"
                    << "  ]\n";
      }
      else if( simplex.dimension() == 1 )
      {
        auto u = *( simplex.begin()     );
        auto v = *( simplex.begin() + 1 );

        streamEdges << "  edge [\n"
                    << "    source " << u << "\n"
                    << "    target " << v << "\n"
                    << "    weight " << simplex.data() << "\n"
                    << "  ]\n";
      }
    }

    out << "graph [\n"
        << "  directed 0\n"
        << streamNodes.str() << "\n"
        << streamEdges.str() << "\n"
        << "]\n";
  }
};

} // namespace io

} // namespace topology

} // namespace aleph

#endif
<commit_msg>Improved performance of `GML` file parsing<commit_after>#ifndef ALEPH_TOPOLOGY_IO_GML_HH__
#define ALEPH_TOPOLOGY_IO_GML_HH__

#include <fstream>
#include <map>
#include <set>
#include <regex>
#include <sstream>
#include <stack>
#include <string>
#include <unordered_map>
#include <vector>

#include <aleph/utilities/String.hh>

namespace aleph
{

namespace topology
{

namespace io
{

/**
  @class GMLReader
  @brief Parses files in GML (Graph Modeling Language) format

  This is a simple reader for graphs in GML format. It suports a basic
  subset of the GML specification, viz. the specification of different
  attributes for nodes, as well as weight specifications for edges.

  Currently, the following attributes will be read:

  - \c id (for nodes)
  - \c label (for nodes)
  - \c source (for edges)
  - \c target (for edges)
  - \c weight (for edges)
*/

class GMLReader
{
public:

  template <class SimplicialComplex> void operator()( const std::string& filename, SimplicialComplex& K )
  {
    std::ifstream in( filename );
    if( !in )
      throw std::runtime_error( "Unable to read input file" );

    this->operator()( in, K );
  }

  template <class SimplicialComplex> void operator()( std::ifstream& in, SimplicialComplex& K )
  {
    _nodes.clear();
    _edges.clear();

    using namespace aleph::utilities;

    using Simplex           = typename SimplicialComplex::ValueType;
    using DataType          = typename Simplex::DataType;
    using VertexType        = typename Simplex::VertexType;

    std::string line;
    std::set<std::string> levels     = { "graph", "node", "edge" };
    std::set<std::string> attributes = { "id", "label", "source", "target", "value", "weight" };

    auto isLevel = [&levels] ( const std::string& name )
    {
      return levels.find( name ) != levels.end();
    };

    auto isAttribute = [&attributes] ( const std::string& name )
    {
      return attributes.find( name ) != attributes.end();
    };

    // Specifies the current level the parser is in. May be either one
    // of the known levels above.
    std::stack<std::string> currentLevel;

    // Last level that was read by the parser. If an open bracket '[' is
    // identified, this will become the current level.
    std::string lastLevel;

    Graph graph;
    Node node;
    Edge edge;

    std::regex reAttribute = std::regex( "([[:alpha:]]+)[[:space:]]*.*" );
    std::regex reKeyValue  = std::regex( "([[:alpha:]]+)[[:space:]]+([[:alnum:]\\.]+)" );
    std::regex reLabel     = std::regex( "(label)[[:space:]]+\"([^\"]+)\"" );

    while( std::getline( in, line ) )
    {
      line        = trim( line );
      auto tokens = split( line );

      // Skip comment lines. This is somewhat wasteful because I am
      // splitting the complete string even though I merely need to
      // know the first token.
      if( tokens.empty() == false && ( tokens.front() == "comment" || tokens.front() == "Creator" ) )
        continue;

      // A new level may also be opened "inline" by specifying a name
      // and the opening bracket at the same time.
      bool newLevel = isLevel( line ) || ( tokens.size() == 2 && tokens.back() == "[" && isLevel( tokens.front() ) );

      // Detecting a new level
      if( newLevel )
      {
        auto level = tokens.size() == 2 ? tokens.front() : line;

        if( lastLevel.empty() )
          lastLevel = level;
        else
          throw std::runtime_error( "Encountered incorrectly-nested levels" );

        // Only store the level directly when it has been specified
        // inline
        if( tokens.size() == 2 )
        {
          currentLevel.push( level );
          lastLevel = "";
        }
      }

      // Opening a new level
      else if( line == "[" )
      {
        currentLevel.push( lastLevel );
        lastLevel = "";
      }

      // Closing a new level
      else if( line == "]" )
      {
        if( currentLevel.top() == "node" )
          _nodes.push_back( node );
        else if( currentLevel.top() == "edge" )
          _edges.push_back( edge );

        // Reset node and edge data structure to fill them again once
        // a new level is being encountered.
        node = {};
        edge = {};

        currentLevel.pop();
      }

      // Check for attributes
      else
      {
        if( currentLevel.empty() )
          throw std::runtime_error( "Expected a non-empty current level" );

        std::smatch matches;

        auto* dict = currentLevel.top() == "node" ? &node.dict
                                                  : currentLevel.top() == "edge" ? &edge.dict
                                                                                : currentLevel.top() == "graph" ? &graph.dict
                                                                                : throw std::runtime_error( "Current level is unknown" );

        if( std::regex_match( line, matches, reAttribute ) )
        {
          auto name = matches[1];
          if( isAttribute( name ) )
          {
            // Special matching for labels
            if( name == "label" )
              std::regex_match( line, matches, reLabel );

            // Regular matching for all other attributes
            else
              std::regex_match( line, matches, reKeyValue );

            auto value = matches[2];

            if( name == "id" )
              node.id = value;
            else if( name == "source" )
              edge.source = value;
            else if( name == "target" )
              edge.target = value;

            // Just add it to the dictionary of optional values
            else
             dict->operator[]( name ) = value;
          }
          // Skip unknown attributes...
          else
          {
          }
        }
      }
    }

    // Creates nodes (vertices) ----------------------------------------

    std::set<std::string> nodeIDs;

    for( auto&& node : _nodes )
    {
      auto pair = nodeIDs.insert( node.id );
      if( !pair.second )
        throw std::runtime_error( "Duplicate node id '" + node.id + "'" );
    }

    // Lambda expression for creating a numerical ID out of a parsed ID. In
    // case non-numerical IDs are being used in the source file this Lambda
    // expression ensures that internal IDs always start with a zero.
    auto getID = [&nodeIDs] ( const std::string& id )
    {
      // Try to be smart: If the node ID can be converted into the
      // vertex type, we use the converted number instead.
      try
      {
        auto convertedID = std::stoll( id );
        return static_cast<VertexType>( convertedID );
      }
      catch( std::out_of_range& e )
      {
        throw;
      }
      catch( std::invalid_argument& )
      {
        return static_cast<VertexType>(
          std::distance( nodeIDs.begin(), nodeIDs.find( id ) )
        );
      }
    };

    std::vector<Simplex> simplices;
    simplices.reserve( _nodes.size() + _edges.size() );

    // Maps an ID directly to its corresponding simplex in order to
    // facilitate the assignment of weights.
    std::unordered_map<VertexType, Simplex> id_to_simplex;

    for( auto&& node : _nodes )
    {
      auto id = getID( node.id );

      if( node.dict.find( "weight" ) != node.dict.end() )
        simplices.push_back( Simplex( id, convert<DataType>( node.dict.at( "weight" ) ) ) );
      else if( node.dict.find( "value" ) != node.dict.end() )
        simplices.push_back( Simplex( id, convert<DataType>( node.dict.at( "value" ) ) ) );
      else
        simplices.push_back( Simplex( id ) );

      id_to_simplex[id] = simplices.back();
    }

    // Create edges ----------------------------------------------------

    for( auto&& edge : _edges )
    {
      auto u = getID( edge.source );
      auto v = getID( edge.target );

      // No optional data attached; need to create weight based on node
      // weights, if those are available.
      if( edge.dict.find( "weight" ) == edge.dict.end() && edge.dict.find( "value" ) == edge.dict.end() )
      {
        auto uSimplex = id_to_simplex.at(u);
        auto vSimplex = id_to_simplex.at(v);

        // TODO: Permit the usage of other weight assignment strategies
        // here, for example by using a functor.
        auto data = std::max( uSimplex.data(), vSimplex.data() );

        simplices.push_back( Simplex( {u,v}, data ) );
      }

      // Use converted weight
      else if( edge.dict.find( "weight" ) != edge.dict.end() )
        simplices.push_back( Simplex( {u,v}, convert<DataType>( edge.dict.at( "weight" ) ) ) );
      else if( edge.dict.find( "value" ) != edge.dict.end() )
        simplices.push_back( Simplex( {u,v}, convert<DataType>( edge.dict.at( "value" ) ) ) );
    }

    _graph = graph;
    K      = SimplicialComplex( simplices.begin(), simplices.end() );
  }

  /**
    Retrieves a map of attribute values for each node. The attributes
    will be assigned to the node ID. Empty attributes signify that no
    such information is available.
  */

  std::map<std::string, std::string> getNodeAttribute( const std::string& attribute ) const
  {
    std::map<std::string, std::string> map;

    for( auto&& node : _nodes )
    {
      if( node.dict.find( attribute ) == node.dict.end() )
        map[ node.id ] = std::string();
      else
        map[ node.id ] = node.dict.at( attribute );
    }

    return map;
  }

private:

  /** Describes a parsed graph along with all of its attributes */
  struct Graph
  {
    std::map<std::string, std::string> dict; // all remaining attributes
  };

  /** Describes a parsed node along with all of its attributes */
  struct Node
  {
    std::string id;

    std::map<std::string, std::string> dict; // all remaining attributes
  };

  /** Describes a parsed edge along with all of its attributes */
  struct Edge
  {
    std::string source;
    std::string target;

    std::map<std::string, std::string> dict; // all remaining attributes
  };

  // Local storage -----------------------------------------------------
  //
  // Variables in this section contain the result of the last parsing
  // process. This is useful when clients are querying attributes.

  Graph _graph;

  std::vector<Node> _nodes;
  std::vector<Edge> _edges;
};

/**
  @class GMLWriter
  @brief Writes files in GML (Graph Modeling Language) format

  This is a simple writer for graphs in GML format. It suports a basic
  subset of the GML specification, viz. the specification of different
  attributes for nodes, as well as weight specifications for edges.

  Given a simplicial complex, it will store it as a weighted graph.

  Currently, the following attributes will be written:

  * \c id (for nodes)
  * \c source (for edges)
  * \c target (for edges)
  * \c weight (for edges)
*/

class GMLWriter
{
public:

  template <class SimplicialComplex> void operator()( const std::string& filename, SimplicialComplex& K )
  {
    std::ofstream out( filename );
    if( !out )
      throw std::runtime_error( "Unable to open output file" );

    this->operator()( out, K );
  }

  template <class SimplicialComplex> void operator()( std::ostream& out, SimplicialComplex& K )
  {
    std::ostringstream streamNodes;
    std::ostringstream streamEdges;

    for( auto&& simplex : K )
    {
      if( simplex.dimension() == 0 )
      {
        streamNodes << "  node [\n"
                    << "    id " << *simplex.begin() << "\n"
                    << "  ]\n";
      }
      else if( simplex.dimension() == 1 )
      {
        auto u = *( simplex.begin()     );
        auto v = *( simplex.begin() + 1 );

        streamEdges << "  edge [\n"
                    << "    source " << u << "\n"
                    << "    target " << v << "\n"
                    << "    weight " << simplex.data() << "\n"
                    << "  ]\n";
      }
    }

    out << "graph [\n"
        << "  directed 0\n"
        << streamNodes.str() << "\n"
        << streamEdges.str() << "\n"
        << "]\n";
  }
};

} // namespace io

} // namespace topology

} // namespace aleph

#endif
<|endoftext|>


<commit_before>#ifndef _BLISPP_MATRIX_HPP_
#define _BLISPP_MATRIX_HPP_

#include "blis++.hpp"

namespace blis
{

struct trans_op_t
{
    objbits_t info;

    constexpr trans_op_t(trans_t trans = BLIS_NO_TRANSPOSE) : info(trans) {}

    bool transpose() const
    {
        return bli_obj_onlytrans_status(*this);
    }

    bool conjugate() const
    {
        return bli_obj_conj_status(*this);
    }

    operator trans_t() const { return (trans_t)bli_obj_conjtrans_status(*this); }
};

namespace transpose
{
    constexpr trans_op_t T(BLIS_TRANSPOSE);
    constexpr trans_op_t C(BLIS_CONJ_NO_TRANSPOSE);
    constexpr trans_op_t H(BLIS_CONJ_TRANSPOSE);
}

namespace detail
{
    template <typename T> using if_complex =
        typename std::enable_if<is_complex<T>::value>::type;
}

template <typename T>
class Matrix : private obj_t
{
    public:
        typedef T type;
        typedef typename real_type<T>::type real_type;

    private:
        bool _is_view;

    protected:
        void create()
        {
            _is_view = true;
            memset(static_cast<obj_t*>(this), 0, sizeof(obj_t));
        }

        void create(const Matrix& other)
        {
            _is_view = false;

            create(other.length(), other.width(),
                   other.row_stride(), other.col_stride());

            Matrix other_no_trans(length(), width(),
                                  const_cast<Matrix&>(other).data(),
                                  row_stride(), col_stride());

            bli_copym(other_no_trans, this);

            this->conjtrans(other.conjtrans());
        }

        void create(Matrix&& other)
        {
            memcpy(static_cast<obj_t*>(this),
                   static_cast<obj_t*>(&other), sizeof(obj_t));

            _is_view = other._is_view;
            other._is_view = true;
        }

        void create(double r, double i)
        {
            _is_view = false;
            bli_obj_scalar_init_detached(datatype<type>::value, this);
            bli_setsc(r, i, this);
        }

        void create(dim_t m, dim_t n)
        {
            _is_view = false;
            bli_obj_create(datatype<type>::value, m, n, 0, 0, this);
        }

        void create(dim_t m, dim_t n, inc_t rs, inc_t cs)
        {
            _is_view = false;
            bli_obj_create(datatype<type>::value, m, n, rs, cs, this);
        }

        void create(dim_t m, dim_t n, type* p)
        {
            _is_view = true;
            bli_obj_create_with_attached_buffer(datatype<type>::value, m, n, p, 1, m, this);
        }

        void create(dim_t m, dim_t n, type* p, inc_t rs, inc_t cs)
        {
            _is_view = true;
            bli_obj_create_with_attached_buffer(datatype<type>::value, m, n, p, rs, cs, this);
        }

        void free()
        {
            mem_t* mem_p = bli_obj_pack_mem(*this);

            if (!bli_mem_is_unalloc(mem_p))
            {
                bli_mem_release(mem_p);
            }

            if (!_is_view) bli_obj_free(this);
        }

        Matrix(double r, double i)
        {
            create(r, i);
        }

    public:
        Matrix()
        {
            create();
        }

        Matrix(const Matrix& other)
        {
            create(other);
        }

        Matrix(Matrix&& other)
        {
            create(std::move(other));
        }

        Matrix(dim_t m, dim_t n)
        {
            create(m, n);
        }

        Matrix(dim_t m, dim_t n, inc_t rs, inc_t cs)
        {
            create(m, n, rs, cs);
        }

        explicit Matrix(type* p)
        {
            create(1, 1, p);
        }

        Matrix(dim_t m, dim_t n, type* p)
        {
            create(m, n, p);
        }

        Matrix(dim_t m, dim_t n, type* p, inc_t rs, inc_t cs)
        {
            create(m, n, p, rs, cs);
        }

        ~Matrix()
        {
            free();
        }

        Matrix& operator=(const Matrix& other)
        {
            reset(other);
            return *this;
        }

        Matrix& operator=(Matrix&& other)
        {
            reset(std::move(other));
            return *this;
        }

        Matrix& operator=(const type& val)
        {
            Matrix<T> s(real(val), imag(val));
            bli_setm(s, this);
            return *this;
        }

        void reset()
        {
            free();
            create();
        }

        void reset(const Matrix& other)
        {
            if (&other == this) return;
            free();
            create(other);
        }

        void reset(Matrix&& other)
        {
            if (&other == this) return;
            free();
            create(std::move(other));
        }

        void reset(real_type r, real_type i)
        {
            free();
            create(r, i);
        }

        void reset(const type& val)
        {
            free();
            create(real(val), imag(val));
        }

        void reset(dim_t m, dim_t n)
        {
            free();
            create(m, n, 1, m);
        }

        void reset(dim_t m, dim_t n, inc_t rs, inc_t cs)
        {
            free();
            create(m, n, rs, cs);
        }

        void reset(type* p)
        {
            free();
            create(1, 1, p, 1, 1);
        }

        void reset(dim_t m, dim_t n, type* p)
        {
            free();
            create(m, n, p, 1, m);
        }

        void reset(dim_t m, dim_t n, type* p, inc_t rs, inc_t cs)
        {
            free();
            create(m, n, p, rs, cs);
        }

        bool is_view() const
        {
            return _is_view;
        }

        bool is_transposed() const
        {
            return bli_obj_has_trans(*this);
        }

        bool transpose()
        {
            bool old = is_transposed();
            bli_obj_toggle_trans(*this);
            return old;
        }

        bool transpose(bool trans)
        {
            bool old = is_transposed();
            bli_obj_set_onlytrans(trans ? BLIS_TRANSPOSE : BLIS_NO_TRANSPOSE, *this);
            return old;
        }

        trans_t transpose(trans_t trans)
        {
            trans_t old = bli_obj_onlytrans_status(*this);
            bli_obj_set_onlytrans(trans, *this);
            return old;
        }

        bool is_conjugated() const
        {
            return bli_obj_has_conj(*this);
        }

        bool conjugate()
        {
            bool old = is_conjugated();
            bli_obj_toggle_conj(*this);
            return old;
        }

        bool conjugate(bool conj)
        {
            bool old = is_conjugated();
            bli_obj_set_conj(conj ? BLIS_CONJUGATE : BLIS_NO_CONJUGATE, *this);
            return old;
        }

        conj_t conjugate(conj_t conj)
        {
            conj_t old = bli_obj_conj_status(*this);
            bli_obj_set_conj(conj, *this);
            return old;
        }

        trans_t conjtrans() const
        {
            return (trans_t)bli_obj_conjtrans_status(*this);
        }

        trans_t conjtrans(trans_op_t conjtrans)
        {
            trans_t old = this->conjtrans();
            bli_obj_set_conjtrans(conjtrans, *this);
            return old;
        }

        dim_t length() const
        {
            return bli_obj_length(*this);
        }

        dim_t length(dim_t m)
        {
            dim_t old = length();
            bli_obj_set_length(m, *this);
            return old;
        }

        dim_t width() const
        {
            return bli_obj_width(*this);
        }

        dim_t width(dim_t n)
        {
            dim_t old = width();
            bli_obj_set_width(n, *this);
            return old;
        }

        inc_t row_stride() const
        {
            return bli_obj_row_stride(*this);
        }

        inc_t row_stride(inc_t rs)
        {
            inc_t old = row_stride();
            bli_obj_set_strides(rs, col_stride(), *this);
            return old;
        }

        inc_t col_stride() const
        {
            return bli_obj_col_stride(*this);
        }

        inc_t col_stride(inc_t cs)
        {
            inc_t old = col_stride();
            bli_obj_set_strides(row_stride(), cs, *this);
            return old;
        }

        void shift_down(dim_t m)
        {
            bli_obj_set_buffer(data()+m*row_stride(), *this);
        }

        void shift_up(dim_t m)
        {
            shift_down(-m);
        }

        void shift_right(dim_t n)
        {
            bli_obj_set_buffer(data()+n*col_stride(), *this);
        }

        void shift_left(dim_t n)
        {
            shift_right(-n);
        }

        void shift_down()
        {
            shift_down(length());
        }

        void shift_up()
        {
            shift_up(length());
        }

        void shift_right()
        {
            shift_right(width());
        }

        void shift_left()
        {
            shift_left(width());
        }

        type* data()
        {
            return (type*)bli_obj_buffer(*this);
        }

        const type* data() const
        {
            return (const type*)bli_obj_buffer(*this);
        }

        operator obj_t*()
        {
            return this;
        }

        operator const obj_t*() const
        {
            return this;
        }

        Matrix operator^(trans_op_t trans)
        {
            Matrix view(length(), width(), *this, row_stride(), col_stride());

            if (trans.transpose()) view.transpose();
            if (trans.conjugate()) view.conjugate();

            return view;
        }

        friend void swap(Matrix& a, Matrix& b)
        {
            char tmp[sizeof(Matrix)];
            memcpy(tmp,  &a, sizeof(Matrix));
            memcpy( &a,  &b, sizeof(Matrix));
            memcpy( &b, tmp, sizeof(Matrix));
        }
};

}

#endif
<commit_msg>Remove ambiguous reset() overload.<commit_after>#ifndef _BLISPP_MATRIX_HPP_
#define _BLISPP_MATRIX_HPP_

#include "blis++.hpp"

namespace blis
{

struct trans_op_t
{
    objbits_t info;

    constexpr trans_op_t(trans_t trans = BLIS_NO_TRANSPOSE) : info(trans) {}

    bool transpose() const
    {
        return bli_obj_onlytrans_status(*this);
    }

    bool conjugate() const
    {
        return bli_obj_conj_status(*this);
    }

    operator trans_t() const { return (trans_t)bli_obj_conjtrans_status(*this); }
};

namespace transpose
{
    constexpr trans_op_t T(BLIS_TRANSPOSE);
    constexpr trans_op_t C(BLIS_CONJ_NO_TRANSPOSE);
    constexpr trans_op_t H(BLIS_CONJ_TRANSPOSE);
}

namespace detail
{
    template <typename T> using if_complex =
        typename std::enable_if<is_complex<T>::value>::type;
}

template <typename T>
class Matrix : private obj_t
{
    public:
        typedef T type;
        typedef typename real_type<T>::type real_type;

    private:
        bool _is_view;

    protected:
        void create()
        {
            _is_view = true;
            memset(static_cast<obj_t*>(this), 0, sizeof(obj_t));
        }

        void create(const Matrix& other)
        {
            _is_view = false;

            create(other.length(), other.width(),
                   other.row_stride(), other.col_stride());

            Matrix other_no_trans(length(), width(),
                                  const_cast<Matrix&>(other).data(),
                                  row_stride(), col_stride());

            bli_copym(other_no_trans, this);

            this->conjtrans(other.conjtrans());
        }

        void create(Matrix&& other)
        {
            memcpy(static_cast<obj_t*>(this),
                   static_cast<obj_t*>(&other), sizeof(obj_t));

            _is_view = other._is_view;
            other._is_view = true;
        }

        void create(double r, double i)
        {
            _is_view = false;
            bli_obj_scalar_init_detached(datatype<type>::value, this);
            bli_setsc(r, i, this);
        }

        void create(dim_t m, dim_t n)
        {
            _is_view = false;
            bli_obj_create(datatype<type>::value, m, n, 0, 0, this);
        }

        void create(dim_t m, dim_t n, inc_t rs, inc_t cs)
        {
            _is_view = false;
            bli_obj_create(datatype<type>::value, m, n, rs, cs, this);
        }

        void create(dim_t m, dim_t n, type* p)
        {
            _is_view = true;
            bli_obj_create_with_attached_buffer(datatype<type>::value, m, n, p, 1, m, this);
        }

        void create(dim_t m, dim_t n, type* p, inc_t rs, inc_t cs)
        {
            _is_view = true;
            bli_obj_create_with_attached_buffer(datatype<type>::value, m, n, p, rs, cs, this);
        }

        void free()
        {
            mem_t* mem_p = bli_obj_pack_mem(*this);

            if (!bli_mem_is_unalloc(mem_p))
            {
                bli_mem_release(mem_p);
            }

            if (!_is_view) bli_obj_free(this);
        }

        Matrix(double r, double i)
        {
            create(r, i);
        }

    public:
        Matrix()
        {
            create();
        }

        Matrix(const Matrix& other)
        {
            create(other);
        }

        Matrix(Matrix&& other)
        {
            create(std::move(other));
        }

        Matrix(dim_t m, dim_t n)
        {
            create(m, n);
        }

        Matrix(dim_t m, dim_t n, inc_t rs, inc_t cs)
        {
            create(m, n, rs, cs);
        }

        explicit Matrix(type* p)
        {
            create(1, 1, p);
        }

        Matrix(dim_t m, dim_t n, type* p)
        {
            create(m, n, p);
        }

        Matrix(dim_t m, dim_t n, type* p, inc_t rs, inc_t cs)
        {
            create(m, n, p, rs, cs);
        }

        ~Matrix()
        {
            free();
        }

        Matrix& operator=(const Matrix& other)
        {
            reset(other);
            return *this;
        }

        Matrix& operator=(Matrix&& other)
        {
            reset(std::move(other));
            return *this;
        }

        Matrix& operator=(const type& val)
        {
            Matrix<T> s(real(val), imag(val));
            bli_setm(s, this);
            return *this;
        }

        void reset()
        {
            free();
            create();
        }

        void reset(const Matrix& other)
        {
            if (&other == this) return;
            free();
            create(other);
        }

        void reset(Matrix&& other)
        {
            if (&other == this) return;
            free();
            create(std::move(other));
        }

        void reset(const type& val)
        {
            free();
            create(real(val), imag(val));
        }

        void reset(dim_t m, dim_t n)
        {
            free();
            create(m, n, 1, m);
        }

        void reset(dim_t m, dim_t n, inc_t rs, inc_t cs)
        {
            free();
            create(m, n, rs, cs);
        }

        void reset(type* p)
        {
            free();
            create(1, 1, p, 1, 1);
        }

        void reset(dim_t m, dim_t n, type* p)
        {
            free();
            create(m, n, p, 1, m);
        }

        void reset(dim_t m, dim_t n, type* p, inc_t rs, inc_t cs)
        {
            free();
            create(m, n, p, rs, cs);
        }

        bool is_view() const
        {
            return _is_view;
        }

        bool is_transposed() const
        {
            return bli_obj_has_trans(*this);
        }

        bool transpose()
        {
            bool old = is_transposed();
            bli_obj_toggle_trans(*this);
            return old;
        }

        bool transpose(bool trans)
        {
            bool old = is_transposed();
            bli_obj_set_onlytrans(trans ? BLIS_TRANSPOSE : BLIS_NO_TRANSPOSE, *this);
            return old;
        }

        trans_t transpose(trans_t trans)
        {
            trans_t old = bli_obj_onlytrans_status(*this);
            bli_obj_set_onlytrans(trans, *this);
            return old;
        }

        bool is_conjugated() const
        {
            return bli_obj_has_conj(*this);
        }

        bool conjugate()
        {
            bool old = is_conjugated();
            bli_obj_toggle_conj(*this);
            return old;
        }

        bool conjugate(bool conj)
        {
            bool old = is_conjugated();
            bli_obj_set_conj(conj ? BLIS_CONJUGATE : BLIS_NO_CONJUGATE, *this);
            return old;
        }

        conj_t conjugate(conj_t conj)
        {
            conj_t old = bli_obj_conj_status(*this);
            bli_obj_set_conj(conj, *this);
            return old;
        }

        trans_t conjtrans() const
        {
            return (trans_t)bli_obj_conjtrans_status(*this);
        }

        trans_t conjtrans(trans_op_t conjtrans)
        {
            trans_t old = this->conjtrans();
            bli_obj_set_conjtrans(conjtrans, *this);
            return old;
        }

        dim_t length() const
        {
            return bli_obj_length(*this);
        }

        dim_t length(dim_t m)
        {
            dim_t old = length();
            bli_obj_set_length(m, *this);
            return old;
        }

        dim_t width() const
        {
            return bli_obj_width(*this);
        }

        dim_t width(dim_t n)
        {
            dim_t old = width();
            bli_obj_set_width(n, *this);
            return old;
        }

        inc_t row_stride() const
        {
            return bli_obj_row_stride(*this);
        }

        inc_t row_stride(inc_t rs)
        {
            inc_t old = row_stride();
            bli_obj_set_strides(rs, col_stride(), *this);
            return old;
        }

        inc_t col_stride() const
        {
            return bli_obj_col_stride(*this);
        }

        inc_t col_stride(inc_t cs)
        {
            inc_t old = col_stride();
            bli_obj_set_strides(row_stride(), cs, *this);
            return old;
        }

        void shift_down(dim_t m)
        {
            bli_obj_set_buffer(data()+m*row_stride(), *this);
        }

        void shift_up(dim_t m)
        {
            shift_down(-m);
        }

        void shift_right(dim_t n)
        {
            bli_obj_set_buffer(data()+n*col_stride(), *this);
        }

        void shift_left(dim_t n)
        {
            shift_right(-n);
        }

        void shift_down()
        {
            shift_down(length());
        }

        void shift_up()
        {
            shift_up(length());
        }

        void shift_right()
        {
            shift_right(width());
        }

        void shift_left()
        {
            shift_left(width());
        }

        type* data()
        {
            return (type*)bli_obj_buffer(*this);
        }

        const type* data() const
        {
            return (const type*)bli_obj_buffer(*this);
        }

        operator obj_t*()
        {
            return this;
        }

        operator const obj_t*() const
        {
            return this;
        }

        Matrix operator^(trans_op_t trans)
        {
            Matrix view(length(), width(), *this, row_stride(), col_stride());

            if (trans.transpose()) view.transpose();
            if (trans.conjugate()) view.conjugate();

            return view;
        }

        friend void swap(Matrix& a, Matrix& b)
        {
            char tmp[sizeof(Matrix)];
            memcpy(tmp,  &a, sizeof(Matrix));
            memcpy( &a,  &b, sizeof(Matrix));
            memcpy( &b, tmp, sizeof(Matrix));
        }
};

}

#endif
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: attrlist.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: dvo $ $Date: 2001-02-06 10:41:54 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include <vector>

#ifndef _OSL_MUTEX_HXX_
#include <osl/mutex.hxx>
#endif

#include <rtl/uuid.h>
#include <rtl/memory.h>

#include <assert.h>

#include "attrlist.hxx"

using namespace ::rtl;
using namespace ::osl;
using namespace ::com::sun::star;

struct SvXMLTagAttribute_Impl
{
    SvXMLTagAttribute_Impl(){}
    SvXMLTagAttribute_Impl( const OUString &sName, const OUString &sType,
                         const OUString &sValue )
    {
        this->sName     = sName;
        this->sType     = sType;
        this->sValue    = sValue;
    }

    OUString sName;
    OUString sType;
    OUString sValue;
};

struct SvXMLAttributeList_Impl
{
    SvXMLAttributeList_Impl()
    {
        // performance improvement during adding
        vecAttribute.reserve(20);
    }
    ::std::vector<struct SvXMLTagAttribute_Impl> vecAttribute;
};

sal_Int16 SAL_CALL SvXMLAttributeList::getLength(void) throw( ::com::sun::star::uno::RuntimeException )
{
    return m_pImpl->vecAttribute.size();
}

SvXMLAttributeList::SvXMLAttributeList( const SvXMLAttributeList &r )
{
    m_pImpl = new SvXMLAttributeList_Impl;
    *m_pImpl = *(r.m_pImpl);
}

OUString SAL_CALL SvXMLAttributeList::getNameByIndex(sal_Int16 i) throw( ::com::sun::star::uno::RuntimeException )
{
    if( i < m_pImpl->vecAttribute.size() ) {
        return m_pImpl->vecAttribute[i].sName;
    }
    return OUString();
}

OUString SAL_CALL SvXMLAttributeList::getTypeByIndex(sal_Int16 i) throw( ::com::sun::star::uno::RuntimeException )
{
    if( i < m_pImpl->vecAttribute.size() ) {
        return m_pImpl->vecAttribute[i].sType;
    }
    return OUString();
}

OUString SAL_CALL  SvXMLAttributeList::getValueByIndex(sal_Int16 i) throw( ::com::sun::star::uno::RuntimeException )
{
    if( i < m_pImpl->vecAttribute.size() ) {
        return m_pImpl->vecAttribute[i].sValue;
    }
    return OUString();

}

OUString SAL_CALL SvXMLAttributeList::getTypeByName( const OUString& sName ) throw( ::com::sun::star::uno::RuntimeException )
{
    ::std::vector<struct SvXMLTagAttribute_Impl>::iterator ii = m_pImpl->vecAttribute.begin();

    for( ; ii != m_pImpl->vecAttribute.end() ; ii ++ ) {
        if( (*ii).sName == sName ) {
            return (*ii).sType;
        }
    }
    return OUString();
}

OUString SAL_CALL SvXMLAttributeList::getValueByName(const OUString& sName) throw( ::com::sun::star::uno::RuntimeException )
{
    ::std::vector<struct SvXMLTagAttribute_Impl>::iterator ii = m_pImpl->vecAttribute.begin();

    for( ; ii != m_pImpl->vecAttribute.end() ; ii ++ ) {
        if( (*ii).sName == sName ) {
            return (*ii).sValue;
        }
    }
    return OUString();
}

uno::Reference< ::com::sun::star::util::XCloneable >  SvXMLAttributeList::createClone() throw( ::com::sun::star::uno::RuntimeException )
{
    uno::Reference< ::com::sun::star::util::XCloneable >  r = new SvXMLAttributeList( *this );
    return r;
}

SvXMLAttributeList::SvXMLAttributeList()
{
    m_pImpl = new SvXMLAttributeList_Impl;
}

SvXMLAttributeList::~SvXMLAttributeList()
{
    delete m_pImpl;
}

void SvXMLAttributeList::AddAttribute(  const OUString &sName ,
                                        const OUString &sType ,
                                        const OUString &sValue )
{
    m_pImpl->vecAttribute.push_back( SvXMLTagAttribute_Impl( sName , sType , sValue ) );
}

void SvXMLAttributeList::Clear()
{
    m_pImpl->vecAttribute.clear();

    assert( ! getLength() );
}

void SvXMLAttributeList::RemoveAttribute( const OUString sName )
{
    ::std::vector<struct SvXMLTagAttribute_Impl>::iterator ii = m_pImpl->vecAttribute.begin();

    for( ; ii != m_pImpl->vecAttribute.end() ; ii ++ ) {
        if( (*ii).sName == sName ) {
            m_pImpl->vecAttribute.erase( ii );
            break;
        }
    }
}

void SvXMLAttributeList::SetAttributeList( const uno::Reference< ::com::sun::star::xml::sax::XAttributeList >  &r )
{
    Clear();
    AppendAttributeList( r );
}

void SvXMLAttributeList::AppendAttributeList( const uno::Reference< ::com::sun::star::xml::sax::XAttributeList >  &r )
{
    assert( r.is() );

    sal_Int32 nMax = r->getLength();
    sal_Int32 nTotalSize = m_pImpl->vecAttribute.size() + nMax;
    m_pImpl->vecAttribute.reserve( nTotalSize );

    for( sal_Int32 i = 0 ; i < nMax ; i ++ ) {
        m_pImpl->vecAttribute.push_back( SvXMLTagAttribute_Impl(
            r->getNameByIndex( i ) ,
            r->getTypeByIndex( i ) ,
            r->getValueByIndex( i )));
    }

    assert( nTotalSize == getLength());
}

// XUnoTunnel & co
const uno::Sequence< sal_Int8 > & SvXMLAttributeList::getUnoTunnelId() throw()
{
    static uno::Sequence< sal_Int8 > * pSeq = 0;
    if( !pSeq )
    {
        Guard< Mutex > aGuard( Mutex::getGlobalMutex() );
        if( !pSeq )
        {
            static uno::Sequence< sal_Int8 > aSeq( 16 );
            rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
            pSeq = &aSeq;
        }
    }
    return *pSeq;
}

SvXMLAttributeList* SvXMLAttributeList::getImplementation( uno::Reference< uno::XInterface > xInt ) throw()
{
    uno::Reference< lang::XUnoTunnel > xUT( xInt, uno::UNO_QUERY );
    if( xUT.is() )
        return (SvXMLAttributeList*)xUT->getSomething( SvXMLAttributeList::getUnoTunnelId() );
    else
        return NULL;
}

// XUnoTunnel
sal_Int64 SAL_CALL SvXMLAttributeList::getSomething( const uno::Sequence< sal_Int8 >& rId )
    throw( uno::RuntimeException )
{
    if( rId.getLength() == 16 && 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
                                                         rId.getConstArray(), 16 ) )
    {
        return (sal_Int64)this;
    }
    return 0;
}

<commit_msg>#79771#; copy the strings in a constructor<commit_after>/*************************************************************************
 *
 *  $RCSfile: attrlist.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: sab $ $Date: 2001-06-26 07:26:50 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include <vector>

#ifndef _OSL_MUTEX_HXX_
#include <osl/mutex.hxx>
#endif

#include <rtl/uuid.h>
#include <rtl/memory.h>

#include <assert.h>

#include "attrlist.hxx"

using namespace ::rtl;
using namespace ::osl;
using namespace ::com::sun::star;

struct SvXMLTagAttribute_Impl
{
    SvXMLTagAttribute_Impl(){}
    SvXMLTagAttribute_Impl( const OUString &rName, const OUString &rType,
                         const OUString &rValue )
        : sName(rName),
        sType(rType),
        sValue(rValue)
    {
    }

    OUString sName;
    OUString sType;
    OUString sValue;
};

struct SvXMLAttributeList_Impl
{
    SvXMLAttributeList_Impl()
    {
        // performance improvement during adding
        vecAttribute.reserve(20);
    }
    ::std::vector<struct SvXMLTagAttribute_Impl> vecAttribute;
};

sal_Int16 SAL_CALL SvXMLAttributeList::getLength(void) throw( ::com::sun::star::uno::RuntimeException )
{
    return m_pImpl->vecAttribute.size();
}

SvXMLAttributeList::SvXMLAttributeList( const SvXMLAttributeList &r )
{
    m_pImpl = new SvXMLAttributeList_Impl;
    *m_pImpl = *(r.m_pImpl);
}

OUString SAL_CALL SvXMLAttributeList::getNameByIndex(sal_Int16 i) throw( ::com::sun::star::uno::RuntimeException )
{
    if( i < m_pImpl->vecAttribute.size() ) {
        return m_pImpl->vecAttribute[i].sName;
    }
    return OUString();
}

OUString SAL_CALL SvXMLAttributeList::getTypeByIndex(sal_Int16 i) throw( ::com::sun::star::uno::RuntimeException )
{
    if( i < m_pImpl->vecAttribute.size() ) {
        return m_pImpl->vecAttribute[i].sType;
    }
    return OUString();
}

OUString SAL_CALL  SvXMLAttributeList::getValueByIndex(sal_Int16 i) throw( ::com::sun::star::uno::RuntimeException )
{
    if( i < m_pImpl->vecAttribute.size() ) {
        return m_pImpl->vecAttribute[i].sValue;
    }
    return OUString();

}

OUString SAL_CALL SvXMLAttributeList::getTypeByName( const OUString& sName ) throw( ::com::sun::star::uno::RuntimeException )
{
    ::std::vector<struct SvXMLTagAttribute_Impl>::iterator ii = m_pImpl->vecAttribute.begin();

    for( ; ii != m_pImpl->vecAttribute.end() ; ii ++ ) {
        if( (*ii).sName == sName ) {
            return (*ii).sType;
        }
    }
    return OUString();
}

OUString SAL_CALL SvXMLAttributeList::getValueByName(const OUString& sName) throw( ::com::sun::star::uno::RuntimeException )
{
    ::std::vector<struct SvXMLTagAttribute_Impl>::iterator ii = m_pImpl->vecAttribute.begin();

    for( ; ii != m_pImpl->vecAttribute.end() ; ii ++ ) {
        if( (*ii).sName == sName ) {
            return (*ii).sValue;
        }
    }
    return OUString();
}

uno::Reference< ::com::sun::star::util::XCloneable >  SvXMLAttributeList::createClone() throw( ::com::sun::star::uno::RuntimeException )
{
    uno::Reference< ::com::sun::star::util::XCloneable >  r = new SvXMLAttributeList( *this );
    return r;
}

SvXMLAttributeList::SvXMLAttributeList()
{
    m_pImpl = new SvXMLAttributeList_Impl;
}

SvXMLAttributeList::~SvXMLAttributeList()
{
    delete m_pImpl;
}

void SvXMLAttributeList::AddAttribute(  const OUString &sName ,
                                        const OUString &sType ,
                                        const OUString &sValue )
{
    m_pImpl->vecAttribute.push_back( SvXMLTagAttribute_Impl( sName , sType , sValue ) );
}

void SvXMLAttributeList::Clear()
{
    m_pImpl->vecAttribute.clear();

    assert( ! getLength() );
}

void SvXMLAttributeList::RemoveAttribute( const OUString sName )
{
    ::std::vector<struct SvXMLTagAttribute_Impl>::iterator ii = m_pImpl->vecAttribute.begin();

    for( ; ii != m_pImpl->vecAttribute.end() ; ii ++ ) {
        if( (*ii).sName == sName ) {
            m_pImpl->vecAttribute.erase( ii );
            break;
        }
    }
}

void SvXMLAttributeList::SetAttributeList( const uno::Reference< ::com::sun::star::xml::sax::XAttributeList >  &r )
{
    Clear();
    AppendAttributeList( r );
}

void SvXMLAttributeList::AppendAttributeList( const uno::Reference< ::com::sun::star::xml::sax::XAttributeList >  &r )
{
    assert( r.is() );

    sal_Int32 nMax = r->getLength();
    sal_Int32 nTotalSize = m_pImpl->vecAttribute.size() + nMax;
    m_pImpl->vecAttribute.reserve( nTotalSize );

    for( sal_Int32 i = 0 ; i < nMax ; i ++ ) {
        m_pImpl->vecAttribute.push_back( SvXMLTagAttribute_Impl(
            r->getNameByIndex( i ) ,
            r->getTypeByIndex( i ) ,
            r->getValueByIndex( i )));
    }

    assert( nTotalSize == getLength());
}

// XUnoTunnel & co
const uno::Sequence< sal_Int8 > & SvXMLAttributeList::getUnoTunnelId() throw()
{
    static uno::Sequence< sal_Int8 > * pSeq = 0;
    if( !pSeq )
    {
        Guard< Mutex > aGuard( Mutex::getGlobalMutex() );
        if( !pSeq )
        {
            static uno::Sequence< sal_Int8 > aSeq( 16 );
            rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
            pSeq = &aSeq;
        }
    }
    return *pSeq;
}

SvXMLAttributeList* SvXMLAttributeList::getImplementation( uno::Reference< uno::XInterface > xInt ) throw()
{
    uno::Reference< lang::XUnoTunnel > xUT( xInt, uno::UNO_QUERY );
    if( xUT.is() )
        return (SvXMLAttributeList*)xUT->getSomething( SvXMLAttributeList::getUnoTunnelId() );
    else
        return NULL;
}

// XUnoTunnel
sal_Int64 SAL_CALL SvXMLAttributeList::getSomething( const uno::Sequence< sal_Int8 >& rId )
    throw( uno::RuntimeException )
{
    if( rId.getLength() == 16 && 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
                                                         rId.getConstArray(), 16 ) )
    {
        return (sal_Int64)this;
    }
    return 0;
}

<|endoftext|>