<commit_before>// WinClient.hh for Fluxbox - an X11 Window manager
// Copyright (c) 2003 Henrik Kinnunen (fluxgen(at)users.sourceforge.net)
//
// 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.

// $Id: WinClient.hh,v 1.15 2003/09/29 14:58:15 rathnor Exp $

#ifndef WINCLIENT_HH
#define WINCLIENT_HH

#include "Window.hh"
#include "Subject.hh"
#include "FbWindow.hh"

#include <X11/Xutil.h>
#include <string>

class BScreen;
class Strut;

/// Holds client window info
class WinClient:public FbTk::FbWindow {
public:
    typedef std::list<WinClient *> TransientList;

    WinClient(Window win, BScreen &screen, FluxboxWindow *fbwin = 0);

    ~WinClient();
    void updateRect(int x, int y, unsigned int width, unsigned int height);
    bool sendFocus(); // returns whether we sent a message or not
                      // i.e. whether we assume the focus will get taken
    void sendClose(bool forceful = false);
    // not aware of anything that makes this false at present
    inline bool isClosable() const { return true; }
    void reparent(Window win, int x, int y);
    bool getAttrib(XWindowAttributes &attr) const;
    bool getWMName(XTextProperty &textprop) const;
    bool getWMIconName(XTextProperty &textprop) const;
    /// @return name member of class structure
    const std::string &getWMClassName() const;
    /// @return class member of class structure
    const std::string &getWMClassClass() const;
    /// updates from wm class hints
    void updateWMClassHint();
    void updateWMProtocols();

    inline const std::string &getTitle() const { return m_title; }
    void updateTitle();
    void updateIconTitle();
    BScreen &screen() { return m_screen; }
    const BScreen &screen() const { return m_screen; }
    /// notifies when this client dies
    FbTk::Subject &dieSig() { return m_diesig; }

    /// updates transient window information
    void updateTransientInfo();
    WinClient *transientFor() { return transient_for; }
    const WinClient *transientFor() const { return transient_for; }
    TransientList &transientList() { return transients; }
    const TransientList &transientList() const { return transients; }
    bool isTransient() const { return transient_for != 0; }

    bool isModal() const { return m_modal > 0; }
    void addModal(); // some transient of ours (or us) is modal
    void removeModal(); // some transient (or us) is no longer modal

    bool operator == (const FluxboxWindow &win) const {
        return (m_win == &win);
    }

    void setStrut(Strut *strut);
    void clearStrut();

    bool focus(); // calls Window->setCurrentClient to give focus to this client

    const std::string &title() const { return m_title; }
    const std::string &iconTitle() const { return m_icon_title; }
    const FluxboxWindow *fbwindow() const { return m_win; }
    FluxboxWindow *fbwindow() { return m_win; }

    static const int PropBlackboxHintsElements = 5;
    static const int PropMwmHintsElements = 3;

    void updateBlackboxHints();
    void updateMWMHints();
    void updateWMHints();
    void updateWMNormalHints();

    /**
     * Changes width and height to the nearest (lower) value
     * that conforms to it's size hints.
     *
     * display_* give the values that would be displayed
     * to the user when resizing.
     * We use pointers for display_* since they are optional.
     */
    void applySizeHints(int &width, int &height, int *display_width = 0, int *display_height = 0);

    // grouping is tracked by remembering the window to the left in the group
    Window getGroupLeftWindow() const;
    void setGroupLeftWindow(Window win);
    bool hasGroupLeftWindow() const;

    // does this client have a pending unmap or destroy event?
    bool validateClient() const;

    inline int gravity() const { return m_win_gravity; }

    /**
       !! TODO !!
       remove or move these to private
     */

    WinClient *transient_for; // which window are we a transient for?
    std::list<WinClient *> transients;  // which windows are our transients?
    Window window_group;

    int x, y, old_bw;
    unsigned int
        min_width, min_height, max_width, max_height, width_inc, height_inc,
        min_aspect_x, min_aspect_y, max_aspect_x, max_aspect_y,
        base_width, base_height;
    unsigned long initial_state, normal_hint_flags, wm_hint_flags;

    // this structure only contains 3 elements... the Motif 2.0 structure contains
    // 5... we only need the first 3... so that is all we will define
    typedef struct MwmHints {
        unsigned long flags;       // Motif wm flags
        unsigned long functions;   // Motif wm functions
        unsigned long decorations; // Motif wm decorations
    } MwmHints;

    FluxboxWindow *m_win;
    class WinClientSubj: public FbTk::Subject {
    public:
        explicit WinClientSubj(WinClient &client):m_winclient(client) { }
        WinClient &winClient() { return m_winclient; }
    private:
        WinClient &m_winclient;
    };

    inline int getFocusMode() const { return m_focus_mode; }
    inline const FluxboxWindow::BlackboxHints *getBlackboxHint() const {
        return m_blackbox_hint; }
    void saveBlackboxAttribs(FluxboxWindow::BlackboxAttributes &blackbox_attribs);
    inline const MwmHints *getMwmHint() const { return m_mwm_hint; }

    enum { F_NOINPUT = 0, F_PASSIVE, F_LOCALLYACTIVE, F_GLOBALLYACTIVE };

private:
    // number of transients which we are modal for
    // or indicates that we are modal if don't have any transients
    int m_modal;
    bool send_focus_message, send_close_message;

    int m_win_gravity;

    std::string m_title, m_icon_title;
    std::string m_class_name, m_instance_name;

    FluxboxWindow::BlackboxHints *m_blackbox_hint;
    MwmHints *m_mwm_hint;

    int m_focus_mode;

    WinClientSubj m_diesig;
    BScreen &m_screen;

    Strut *m_strut;

};

#endif // WINCLIENT_HH
<commit_msg>rearrangement and some minor style cleaning<commit_after>// WinClient.hh for Fluxbox - an X11 Window manager
// Copyright (c) 2003 Henrik Kinnunen (fluxgen(at)users.sourceforge.net)
//
// 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.

// $Id: WinClient.hh,v 1.16 2003/12/17 01:20:49 fluxgen Exp $

#ifndef WINCLIENT_HH
#define WINCLIENT_HH

#include "Window.hh"
#include "Subject.hh"
#include "FbWindow.hh"

#include <X11/Xutil.h>
#include <string>

class BScreen;
class Strut;

/// Holds client window info
class WinClient:public FbTk::FbWindow {
public:
    typedef std::list<WinClient *> TransientList;
    // this structure only contains 3 elements... the Motif 2.0 structure contains
    // 5... we only need the first 3... so that is all we will define
    typedef struct MwmHints {
        unsigned long flags;       // Motif wm flags
        unsigned long functions;   // Motif wm functions
        unsigned long decorations; // Motif wm decorations
    } MwmHints;

    WinClient(Window win, BScreen &screen, FluxboxWindow *fbwin = 0);

    ~WinClient();

    void updateRect(int x, int y, unsigned int width, unsigned int height);

    bool sendFocus(); // returns whether we sent a message or not
                      // i.e. whether we assume the focus will get taken
    void sendClose(bool forceful = false);
    // not aware of anything that makes this false at present
    inline bool isClosable() const { return true; }
    void reparent(Window win, int x, int y);

    void addModal(); // some transient of ours (or us) is modal
    void removeModal(); // some transient (or us) is no longer modal

    /// updates from wm class hints
    void updateWMClassHint();
    void updateWMProtocols();

    void updateTitle();
    void updateIconTitle();
    /// updates transient window information
    void updateTransientInfo();

    void updateBlackboxHints();
    void updateMWMHints();
    void updateWMHints();
    void updateWMNormalHints();

    void setStrut(Strut *strut);
    void clearStrut();

    bool focus(); // calls Window->setCurrentClient to give focus to this client

    /**
     * Changes width and height to the nearest (lower) value
     * that conforms to it's size hints.
     *
     * display_* give the values that would be displayed
     * to the user when resizing.
     * We use pointers for display_* since they are optional.
     */
    void applySizeHints(int &width, int &height, int *display_width = 0, int *display_height = 0);

    void setGroupLeftWindow(Window win);

    void saveBlackboxAttribs(FluxboxWindow::BlackboxAttributes &blackbox_attribs);

    // does this client have a pending unmap or destroy event?
    bool validateClient() const;

    //
    // accessors
    //

    bool getAttrib(XWindowAttributes &attr) const;
    bool getWMName(XTextProperty &textprop) const;
    bool getWMIconName(XTextProperty &textprop) const;
    /// @return name member of class structure
    const std::string &getWMClassName() const;
    /// @return class member of class structure
    const std::string &getWMClassClass() const;

    BScreen &screen() { return m_screen; }
    const BScreen &screen() const { return m_screen; }
    /// notifies when this client dies
    FbTk::Subject &dieSig() { return m_diesig; }

    inline WinClient *transientFor() { return transient_for; }
    inline const WinClient *transientFor() const { return transient_for; }
    inline TransientList &transientList() { return transients; }
    inline const TransientList &transientList() const { return transients; }
    inline bool isTransient() const { return transient_for != 0; }

    inline bool isModal() const { return m_modal > 0; }

    inline bool operator == (const FluxboxWindow &win) const {
        return (m_win == &win);
    }

    inline const std::string &title() const { return m_title; }
    inline const std::string &iconTitle() const { return m_icon_title; }
    inline const FluxboxWindow *fbwindow() const { return m_win; }
    inline FluxboxWindow *fbwindow() { return m_win; }
    inline int gravity() const { return m_win_gravity; }

    bool hasGroupLeftWindow() const;
    // grouping is tracked by remembering the window to the left in the group
    Window getGroupLeftWindow() const;

    inline int getFocusMode() const { return m_focus_mode; }
    inline const FluxboxWindow::BlackboxHints *getBlackboxHint() const { return m_blackbox_hint; }
    inline const MwmHints *getMwmHint() const { return m_mwm_hint; }

    static const int PropBlackboxHintsElements = 5;
    static const int PropMwmHintsElements = 3;

    /**
       !! TODO !!
       remove or move these to private
     */

    WinClient *transient_for; // which window are we a transient for?
    std::list<WinClient *> transients;  // which windows are our transients?
    Window window_group;

    int x, y, old_bw;
    unsigned int
        min_width, min_height, max_width, max_height, width_inc, height_inc,
        min_aspect_x, min_aspect_y, max_aspect_x, max_aspect_y,
        base_width, base_height;
    unsigned long initial_state, normal_hint_flags, wm_hint_flags;

    FluxboxWindow *m_win;
    class WinClientSubj: public FbTk::Subject {
    public:
        explicit WinClientSubj(WinClient &client):m_winclient(client) { }
        WinClient &winClient() { return m_winclient; }
    private:
        WinClient &m_winclient;
    };

    enum FocusMode { F_NOINPUT = 0, F_PASSIVE, F_LOCALLYACTIVE, F_GLOBALLYACTIVE };

private:
    // number of transients which we are modal for
    // or indicates that we are modal if don't have any transients
    int m_modal;
    bool send_focus_message, send_close_message;

    int m_win_gravity;

    std::string m_title, m_icon_title;
    std::string m_class_name, m_instance_name;

    FluxboxWindow::BlackboxHints *m_blackbox_hint;
    MwmHints *m_mwm_hint;

    int m_focus_mode;

    WinClientSubj m_diesig;
    BScreen &m_screen;

    Strut *m_strut;

};

#endif // WINCLIENT_HH
<|endoftext|>


<commit_before>/*
Copyright (c) 2016-2017 stoyan shopov

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.
*/
#include <QMessageBox>

#include "cortexm0.hxx"
#include "target.hxx"

static Target		* target;
static Sforth		* sforth;

extern "C"
{
void do_target_fetch(void)		{ auto x = sforth->getResults(1); if (x.size() != 1) Util::panic(); sforth->push(target->readWord(x.at(0))); }
void do_target_register_fetch(void)	{ Util::panic("access the cached register here"); }
void do_panic(void)		{ Util::panic(); }
}

const int CortexM0::register_count = 16,
	CortexM0::program_counter_register_number = 15,
	CortexM0::stack_pointer_register_number = 13,
	CortexM0::return_address_register_number = /*! \todo	extract this from the .debug_frame dwarf cie program */ 14,
	CortexM0::cfa_register_number = /*! \todo	extract this from the .debug_frame dwarf cie program */ 13;

void CortexM0::readRawRegistersFromTarget()
{
	int i;
	registers.clear();
	sforth->evaluate("unwound-registers\n");
	auto r = sforth->getResults(1);
	if (r.size() != 1)
		return;
	for (i = 0; i < register_count; registers.push_back(*(uint32_t*)(r.at(0) + i ++ * sizeof(uint32_t))));
}

CortexM0::CortexM0(Sforth * sforth_engine, Target *target_controller)
{
	sforth = sforth_engine;
	target = target_controller;
	QFile f(":/sforth/unwinder.fs");
	f.open(QFile::ReadOnly);
	sforth->push(register_count);
	sforth->evaluate(f.readAll() + '\n');
}

void CortexM0::setTargetController(Target *target_controller)
{
	target = target_controller;
}

void CortexM0::primeUnwinder()
{
int i;
	registers.clear();
	for (i = 0; i < register_count; registers.push_back(target->readRawUncachedRegister(i++)));
}

bool CortexM0::unwindFrame(const QString & unwind_code, uint32_t start_address, uint32_t unwind_address)
{
int i;
uint32_t cfa;
	for (i = 0; i < registers.size(); sforth->push(registers.at(i++)));
	sforth->evaluate("init-unwinder-round\n");
	sforth->evaluate(QString("%1 to current-address %2 to unwind-address ").arg(start_address).arg(unwind_address) + unwind_code + '\n');
	auto r = sforth->getResults(1);
	if (r.size() == 0)
	{
		/* evaluation probably aborted due to unsupported unwinding rules */
		QMessageBox::critical(0, "register frame unwinding aborted", "register frame unwinding aborted\nsee the sforth execution log for more details");
		return false;
	}
	if (r.size() != 1 || r.at(0) != 0xffffffff)
		return false;
	sforth->evaluate("fetch-cfa-value\n");
	if ((r = sforth->getResults(1)).size() != 1)
		return false;
	cfa = r.at(0);
	readRawRegistersFromTarget();
	if (registers.size() != register_count)
		return false;
	registers.at(program_counter_register_number) = registers.at(return_address_register_number);
	registers.at(cfa_register_number) = cfa;
	return true;
}

bool CortexM0::architecturalUnwind()
{
	sforth->evaluate("architectural-unwind\n");
	auto r = sforth->getResults(1);
	if (r.size() != 1 || r.at(0) != 0xffffffff)
		return false;
	readRawRegistersFromTarget();
	return true;
}
<commit_msg>bugfix<commit_after>/*
Copyright (c) 2016-2017 stoyan shopov

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.
*/
#include <QMessageBox>

#include "cortexm0.hxx"
#include "target.hxx"

static Target		* target;
static Sforth		* sforth;

extern "C"
{
void do_target_fetch(void)		{ auto x = sforth->getResults(1); if (x.size() != 1) Util::panic(); sforth->push(target->readWord(x.at(0))); }
void do_target_register_fetch(void)	{ Util::panic("access the cached register here"); }
void do_panic(void)		{ Util::panic(); }
}

const int CortexM0::register_count = 16,
	CortexM0::program_counter_register_number = 15,
	CortexM0::stack_pointer_register_number = 13,
	CortexM0::return_address_register_number = /*! \todo	extract this from the .debug_frame dwarf cie program */ 14,
	CortexM0::cfa_register_number = /*! \todo	extract this from the .debug_frame dwarf cie program */ 13;

void CortexM0::readRawRegistersFromTarget()
{
	int i;
	registers.clear();
	sforth->evaluate("unwound-registers\n");
	auto r = sforth->getResults(1);
	if (r.size() != 1)
		return;
        for (i = 0; i < register_count; registers.push_back(*(cell *)(r.at(0) + i ++ * sizeof(cell))));
}

CortexM0::CortexM0(Sforth * sforth_engine, Target *target_controller)
{
	sforth = sforth_engine;
	target = target_controller;
	QFile f(":/sforth/unwinder.fs");
	f.open(QFile::ReadOnly);
	sforth->push(register_count);
	sforth->evaluate(f.readAll() + '\n');
}

void CortexM0::setTargetController(Target *target_controller)
{
	target = target_controller;
}

void CortexM0::primeUnwinder()
{
int i;
	registers.clear();
	for (i = 0; i < register_count; registers.push_back(target->readRawUncachedRegister(i++)));
}

bool CortexM0::unwindFrame(const QString & unwind_code, uint32_t start_address, uint32_t unwind_address)
{
int i;
uint32_t cfa;
	for (i = 0; i < registers.size(); sforth->push(registers.at(i++)));
	sforth->evaluate("init-unwinder-round\n");
	sforth->evaluate(QString("%1 to current-address %2 to unwind-address ").arg(start_address).arg(unwind_address) + unwind_code + '\n');
	auto r = sforth->getResults(1);
	if (r.size() == 0)
	{
		/* evaluation probably aborted due to unsupported unwinding rules */
		QMessageBox::critical(0, "register frame unwinding aborted", "register frame unwinding aborted\nsee the sforth execution log for more details");
		return false;
	}
	if (r.size() != 1 || r.at(0) != 0xffffffff)
		return false;
	sforth->evaluate("fetch-cfa-value\n");
	if ((r = sforth->getResults(1)).size() != 1)
		return false;
	cfa = r.at(0);
	readRawRegistersFromTarget();
	if (registers.size() != register_count)
		return false;
	registers.at(program_counter_register_number) = registers.at(return_address_register_number);
	registers.at(cfa_register_number) = cfa;
	return true;
}

bool CortexM0::architecturalUnwind()
{
	sforth->evaluate("architectural-unwind\n");
	auto r = sforth->getResults(1);
	if (r.size() != 1 || r.at(0) != 0xffffffff)
		return false;
	readRawRegistersFromTarget();
	return true;
}
<|endoftext|>


<commit_before>#include <vector>
#include <queue>
#include <climits>
#include <iostream>
#include <tuple>

using namespace std;

typedef pair<int, int> edge;

// https://en.wikipedia.org/wiki/Prim%27s_algorithm
auto prim(vector<vector<edge>> &g) {
    size_t n = g.size();
    vector<bool> used(n);
    vector<int> pred(n, -1);
    vector<int> prio(n, INT_MAX);
    prio[0] = 0;
    priority_queue<edge, vector<edge>, greater<edge>> q;
    q.push({prio[0], 0});
    long long tree_weight = 0;

    while (!q.empty()) {
        auto[w, u] = q.top();
        q.pop();

        if (used[u])
            continue;
        used[u] = true;
        tree_weight += w;

        for (auto[v, weight] : g[u]) {
            if (!used[v] && prio[v] > weight) {
                prio[v] = weight;
                pred[v] = u;
                q.push({weight, v});
            }
        }
    }
    return make_tuple(tree_weight, pred);
}

int main() {
    vector<vector<edge>> g(3);
    g[0].push_back({1, 10});
    g[1].push_back({0, 10});
    g[1].push_back({2, 10});
    g[2].push_back({1, 10});
    g[2].push_back({0, 5});
    g[0].push_back({2, 5});

    auto[tree_weight, pred] = prim(g);
    cout << tree_weight << endl;
}
<commit_msg>update<commit_after>#include <vector>
#include <queue>
#include <climits>
#include <iostream>
#include <tuple>

using namespace std;

typedef pair<int, int> edge;

// https://en.wikipedia.org/wiki/Prim%27s_algorithm
auto prim(vector<vector<edge>> &g) {
    size_t n = g.size();
    vector<int> pred(n, -1);
    vector<int> prio(n, INT_MAX);
    prio[0] = 0;
    priority_queue<edge, vector<edge>, greater<edge>> q;
    q.push({prio[0], 0});
    long long tree_weight = 0;

    while (!q.empty()) {
        auto[w, u] = q.top();
        q.pop();

        if (prio[u] != w)
            continue;
        tree_weight += w;

        for (auto[v, weight] : g[u]) {
            if (prio[v] > weight) {
                prio[v] = weight;
                pred[v] = u;
                q.push({weight, v});
            }
        }
    }
    return make_tuple(tree_weight, pred);
}

int main() {
    vector<vector<edge>> g(3);
    g[0].push_back({1, 10});
    g[1].push_back({0, 10});
    g[1].push_back({2, 10});
    g[2].push_back({1, 10});
    g[2].push_back({0, 5});
    g[0].push_back({2, 5});

    auto[tree_weight, pred] = prim(g);
    cout << tree_weight << endl;
}
<|endoftext|>


<commit_before>#include <cstdint>
#include <iostream>
#include <memory>

using namespace std;

template <typename K, typename V> class Node {
public:
  Node(const K &key, const V &value) : key(key), value(value) {
    this->left = unique_ptr<Node<K, V>>(nullptr);
    this->right = unique_ptr<Node<K, V>>(nullptr);
  }
  const K key;
  V value;
  unique_ptr<Node<K, V>> left;
  unique_ptr<Node<K, V>> right;

  // recursive method.
  uint64_t size() const {
    return 1 + (left ? left->size() : 0) + (right ? right->size() : 0);
  }
  // recursive method.
  uint64_t depth() const {
    return 1 + max(left ? left->depth() : 0, right ? right->depth() : 0);
  }
};

template <typename K, typename V> class Tree {
  unique_ptr<Node<K, V>> root;
  const V EMPTY;

public:
  void put(const K &key, const V &value) {
    if (!root) {
      root = unique_ptr<Node<K, V>>(new Node<K, V>(key, value));
      return;
    }
    auto ptr = root.get(); // traversing unique_ptr.
    while (ptr) {
      if (ptr->key > key) {
        if (ptr->left) {
          ptr = ptr->left.get();
        } else {
          ptr->left = unique_ptr<Node<K, V>>(new Node<K, V>(key, value));
          break;
        }
      } else if (ptr->key < key) {
        if (ptr->right) {
          ptr = ptr->right.get();
        } else {
          ptr->right = unique_ptr<Node<K, V>>(new Node<K, V>(key, value));
          break;
        }
      } else {
        ptr->value = value;
        break;
      }
    }
  }
  bool contains(const K &key) const {
    if (!root) {
      return false;
    }
    auto ptr = root.get(); // traversing unique_ptr.
    while (ptr) {
      if (ptr->key > key) {
        if (ptr->left) {
          ptr = ptr->left.get();
        } else {
          return false;
        }
      } else if (ptr->key < key) {
        if (ptr->right) {
          ptr = ptr->right.get();
        } else {
          return false;
        }
      } else {
        return true;
      }
    }
    return false;
  }
  const V &get(const K &key) {
    if (!root) {
      return EMPTY;
    }
    auto ptr = root.get(); // traversing unique_ptr.
    while (ptr) {
      if (ptr->key > key) {
        if (ptr->left) {
          ptr = ptr->left.get();
        } else {
          return EMPTY;
        }
      } else if (ptr->key < key) {
        if (ptr->right) {
          ptr = ptr->right.get();
        } else {
          return EMPTY;
        }
      } else {
        return ptr->value;
      }
    }
    return EMPTY;
  }
  const uint64_t size() const {
    if (!root) {
      return 0;
    }
    return root->size();
  }
  const uint64_t depth() const {
    if (!root) {
      return 0;
    }
    return root->depth();
  }
};

int main() {
  Tree<int, string> t;
  string foo = "foo";
  for (auto i = 0; i < 10; i++) {
    for (auto j = 0; j < 10; j++) {
      t.put(i + j * 10, foo);
    }
  }
  cout << "size:  " << t.size() << endl;
  cout << "depth: " << t.depth() << endl;
  for (auto i = 0; i < 100; i++) {
    if (!t.contains(i)) {
      cout << "does not contain " << i << endl;
    }
    if (t.get(i) != foo) {
      cout << "does not contain the correct value " << i << endl;
    }
  }
}
<commit_msg>implemented remove()<commit_after>#include <cstdint>
#include <iostream>
#include <memory>

using namespace std;

template <typename K, typename V> class Node {
public:
  Node(const K &key, const V &value) : key(key), value(value) {
    this->left = unique_ptr<Node<K, V>>(nullptr);
    this->right = unique_ptr<Node<K, V>>(nullptr);
  }
  const K key;
  V value;
  unique_ptr<Node<K, V>> left;
  unique_ptr<Node<K, V>> right;

  // recursive method.
  uint64_t size() const {
    return 1 + (left ? left->size() : 0) + (right ? right->size() : 0);
  }
  // recursive method.
  uint64_t depth() const {
    return 1 + max(left ? left->depth() : 0, right ? right->depth() : 0);
  }
};

template <typename K, typename V> class Tree {
  unique_ptr<Node<K, V>> root;
  const V EMPTY;

public:
  void put(const K &key, const V &value) {
    if (!root) {
      root = unique_ptr<Node<K, V>>(new Node<K, V>(key, value));
      return;
    }
    auto ptr = root.get(); // traversing unique_ptr.
    while (ptr) {
      if (ptr->key > key) {
        if (ptr->left) {
          ptr = ptr->left.get();
        } else {
          ptr->left = unique_ptr<Node<K, V>>(new Node<K, V>(key, value));
          break;
        }
      } else if (ptr->key < key) {
        if (ptr->right) {
          ptr = ptr->right.get();
        } else {
          ptr->right = unique_ptr<Node<K, V>>(new Node<K, V>(key, value));
          break;
        }
      } else {
        ptr->value = value;
        break;
      }
    }
  }
  bool remove(const K &key) {
    if (!root) {
      return false;
    }
    unique_ptr<Node<K, V>> *parentptr = &root;
    Node<K, V> *ptr = root.get();
    while (ptr) {
      if (ptr->key > key) {
        if (ptr->left) {
          parentptr = &(ptr->left);
          ptr = ptr->left.get();
        } else {
          return false;
        }
      } else if (ptr->key < key) {
        if (ptr->right) {
          parentptr = &(ptr->right);
          ptr = ptr->right.get();
        } else {
          return false;
        }
      } else {
        // found the element!
        if (!ptr->left && ptr->right) {
          *parentptr = move(ptr->right);
        } else if (!ptr->right && ptr->left) {
          *parentptr = move(ptr->left);
        } else if (!ptr->left && !ptr->right) {
          parentptr->reset();
        } else {
          // contains both :(. remove and append to right.
          auto right = move(ptr->right);
          *parentptr = move(ptr->left);
          Node<K, V>* appendpoint = parentptr->get();
          while (appendpoint->right) {
            appendpoint = appendpoint->right.get();
          }
          (appendpoint)->right = move(right);
        }
        return true;
      }
    }
    return false;
  }
  bool contains(const K &key) const {
    if (!root) {
      return false;
    }
    auto ptr = root.get(); // traversing unique_ptr.
    while (ptr) {
      if (ptr->key > key) {
        if (ptr->left) {
          ptr = ptr->left.get();
        } else {
          return false;
        }
      } else if (ptr->key < key) {
        if (ptr->right) {
          ptr = ptr->right.get();
        } else {
          return false;
        }
      } else {
        return true;
      }
    }
    return false;
  }
  const V &get(const K &key) {
    if (!root) {
      return EMPTY;
    }
    auto ptr = root.get(); // traversing unique_ptr.
    while (ptr) {
      if (ptr->key > key) {
        if (ptr->left) {
          ptr = ptr->left.get();
        } else {
          return EMPTY;
        }
      } else if (ptr->key < key) {
        if (ptr->right) {
          ptr = ptr->right.get();
        } else {
          return EMPTY;
        }
      } else {
        return ptr->value;
      }
    }
    return EMPTY;
  }
  const uint64_t size() const {
    if (!root) {
      return 0;
    }
    return root->size();
  }
  const uint64_t depth() const {
    if (!root) {
      return 0;
    }
    return root->depth();
  }
};

int main() {
  Tree<int, string> t;
  string foo = "foo";
  for (auto i = 0; i < 10; i++) {
    for (auto j = 0; j < 10; j++) {
      t.put(i + j * 10, foo);
    }
  }
  cout << "size:  " << t.size() << endl;
  cout << "depth: " << t.depth() << endl;
  for (auto i = 0; i < 100; i++) {
    if (!t.contains(i)) {
      cout << "does not contain " << i << endl;
    }
    if (t.get(i) != foo) {
      cout << "does not contain the correct value " << i << endl;
    }
  }
  for (auto j = 9; j >= 0; j--) {
    for (auto i = 9; i >= 0; i--) {
      t.remove(i + j * 10);
    }
  }
  Tree<int, string> t2;
  t2.put(1, "a");
  t2.put(0, "b");
  t2.put(2, "c");
  t2.remove(1);
  t2.remove(0);
  t2.remove(2);
  cout << t2.size() << endl;
  cout << t2.depth() << endl;
}
<|endoftext|>


<commit_before>/////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2001  MandrakeSoft S.A.
//
//    MandrakeSoft S.A.
//    43, rue d'Aboukir
//    75002 Paris - France
//    http://www.linux-mandrake.com/
//    http://www.mandrakesoft.com/
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  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

#define NEED_CPU_REG_SHORTCUTS 1
#include "bochs.h"
#define LOG_THIS BX_CPU_THIS_PTR

#if BX_SUPPORT_X86_64==0
// Make life easier for merging code.
#define RAX EAX
#define RBX EBX
#define RCX ECX
#define RDX EDX
#endif

/* Get CPU version information. */
static Bit32u get_cpu_version_information()
{
  Bit32u family = 0, model = 0, stepping = 0;
  Bit32u extended_model = 0;
  Bit32u extended_family = 0;

  /* ****** */
  /*  i486  */
  /* ****** */

#if BX_CPU_LEVEL == 4
    family = 4;

#if BX_SUPPORT_FPU
    model = 1;		// 486dx
    stepping = 3;
#else
    model = 2;		// 486sx
    stepping = 3;
#endif

  /* **************** */
  /*  i586 (Pentium)  */
  /* **************** */

#elif BX_CPU_LEVEL == 5
    family   = 5;
    model    = 1;	// Pentium (60,66)
    stepping = 3;

  /* ****** */
  /*  i686  */
  /* ****** */

#elif BX_CPU_LEVEL == 6

#if BX_SUPPORT_SSE >= 2		// Pentium 4 processor
/*
     The model, family, and processor type for the first
     processor in the Intel Pentium 4 family is as follows:
		* Model-0000B
		* Family-1111B
		* Processor Type-00B (OEM)
*/
    model    = 0;
    family   = 0x0F;
    stepping = 3;

#if BX_SUPPORT_X86_64
    model = 2;    	// Hammer returns what?
#endif

#else			// Pentium Pro/Pentium II/Pentium III processor
    family   = 6;
    model    = 8;
    stepping = 3;
#endif

#else
    BX_PANIC(("CPUID family ID not implemented for CPU LEVEL > 6"));
#endif

  return (extended_family << 20) |
         (extended_model << 16) |
         (family << 8) |
         (model<<4) | stepping;
}

/* Get CPU extended feature flags. */
static Bit32u get_extended_cpuid_features()
{
  Bit32u features = 0;	// start with none

#if BX_SUPPORT_PNI
      features |= 0x01; // report PNI
#endif

  return features;
}

/* Get CPU feature flags. Returned by CPUID functions 1 and 80000001.  */
static Bit32u get_std_cpuid_features()
{
  Bit32u features = 0; // start with none

      // EAX:       CPU Version Infromation
      //   [3:0]   Stepping ID
      //   [7:4]   Model: starts at 1
      //   [11:8]  Family: 4=486, 5=Pentium, 6=PPro, ...
      //   [13:12] Type: 0=OEM, 1=overdrive, 2=dual cpu, 3=reserved
      //   [31:14] Reserved
      // EBX:
      //   [7:0]   Brand ID
      //   [15:8]  CFLUSH cache line size (value*8 = cache line size in bytes)
      //   [23:16] Number of logical processors in one physical processor
      //   [31:24] Local Apic ID
      // ECX:       Feature Flags::Extended
      //   [0:0]   PNI
      //   [3:3]   MONITOR/MWAIT
      //   [7:7]   Enchanced Intel Speedstep Technology
      // EDX:       Feature Flags
      //   [0:0]   FPU on chip
      //   [1:1]   VME: Virtual-8086 Mode enhancements
      //   [2:2]   DE: Debug Extensions (I/O breakpoints)
      //   [3:3]   PSE: Page Size Extensions
      //   [4:4]   TSC: Time Stamp Counter
      //   [5:5]   MSR: RDMSR and WRMSR support
      //   [6:6]   PAE: Physical Address Extensions
      //   [7:7]   MCE: Machine Check Exception
      //   [8:8]   CXS: CMPXCHG8B instruction
      //   [9:9]   APIC: APIC on Chip
      //   [10:10] Reserved
      //   [11:11] SYSENTER/SYSEXIT support
      //   [12:12] MTRR: Memory Type Range Reg
      //   [13:13] PGE/PTE Global Bit
      //   [14:14] MCA: Machine Check Architecture
      //   [15:15] CMOV: Cond Mov/Cmp Instructions
      //   [22:16] Reserved
      //   [23:23] MMX Technology
      //   [24]    FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available)
      //   [25]    SSE: SSE Extensions
      //   [26]    SSE2: SSE2 Extensions
      //   [28]    Reserved
      //   [29]    TM: Therm Monitor
      //   [31:30] Reserved

#if BX_SUPPORT_FPU
      features |= 0x01;
#endif

#if (BX_CPU_LEVEL >= 5)
      features |= (1<< 8);  // Support CMPXCHG8B instruction
      features |= (1<< 4);  // implement TSC
      features |= (1<< 5);  // support RDMSR/WRMSR

#if BX_SUPPORT_MMX
      features |= (1<<23);  // support MMX
#endif

#endif

#if BX_CPU_LEVEL == 6
      features |= (1<<15);  // Implement CMOV instructions.
      features |= (1<<24);  // Implement FSAVE/FXRSTOR instructions.
#if BX_SUPPORT_APIC
      features |= (1<< 9);   // APIC on chip
#endif
#if BX_SUPPORT_SSE >= 1
      features |= (1<<25);  // support SSE
#endif
#if BX_SUPPORT_SSE >= 2
      features |= (1<<26);  // support SSE2
#endif
#endif

#if BX_SUPPORT_4MEG_PAGES
      features |= (1<< 3);  // Support Page-Size Extension (4M pages)
#endif
#if BX_SupportGlobalPages
      features |= (1<<13);  // Support Global pages.
#endif
#if BX_SupportPAE
      features |= (1<< 6);  // Support PAE.
#endif

#if BX_SUPPORT_SEP
      features |= (1<<11);  // SYSENTER/SYSEXIT
#endif

  return features;
}

void BX_CPU_C::CPUID(bxInstruction_c *i)
{
#if BX_SUPPORT_X86_64
  unsigned features;
#endif

  invalidate_prefetch_q();

#if BX_CPU_LEVEL >= 4
  switch (EAX) {
    case 0:
      // EAX: highest input value understood by CPUID
#if BX_CPU_LEVEL <= 5
      RAX = 1;		// 486 and Pentium processors
#else
      RAX = 1;		// for Pentium Pro, Pentium II, Pentium 4 processors
			// should be 2, still not implemented
#endif
      // EBX: vendor ID string
      // EDX: vendor ID string
      // ECX: vendor ID string
#if BX_SUPPORT_X86_64
      RBX = 0x68747541; // "Auth"
      RDX = 0x69746e65; // "enti"
      RCX = 0x444d4163; // "cAMD"
#else
      RBX = 0x756e6547; // "Genu"
      RDX = 0x49656e69; // "ineI"
      RCX = 0x6c65746e; // "ntel"
#endif
      break;

    case 1:
      RAX = get_cpu_version_information();
      RBX = 0; // still not implemented
      RCX = get_extended_cpuid_features ();
      RDX = get_std_cpuid_features ();
      break;

#if 0
#if BX_CPU_LEVEL >= 6
    case 2:
      RAX = 0;	// cache and TLB information (still not implemented)
      RBX = 0;  // cache and TLB information (still not implemented)
      RCX = 0;  // cache and TLB information (still not implemented)
      RDX = 0;  // cache and TLB information (still not implemented)
#endif
#endif

    // Here should be extended information for Pentum 4 processor
    // still not implemented ...

#if BX_SUPPORT_X86_64
    // x86-64 functions
    case 0x80000000:
      // max function supported.
      RAX = 0x80000008;
      RBX = 0x68747541; // "Auth"
      RDX = 0x69746e65; // "enti"
      RCX = 0x444d4163; // "cAMD"
      break;

    case 0x80000001:
      // long mode supported.
      features = get_std_cpuid_features ();
      RAX = features;
      // Many of the bits in EDX are the same as EAX
      // [10:10] Reserved
      // [11:11] SYSCALL and SYSRET instructions
      // [18:19] Reserved
      // [20:20] No-Execute page protection
      // [21:21] Reserved
      // [22:22] AMD MMX Extensions
      // [25:28] Reserved
      // [29:29] Long Mode
      // [30:30] AMD 3DNow Extensions
      // [31:31] AMD 3DNow Intructions
      features = features & 0x0183F3FF;
      RDX = features | (1 << 29) | (1 << 11);
      RBX = 0;
      RCX = 0;
      RDX = 0; // Reserved, undefined
      break;

    case 0x80000008:
      // virtual & phys address size in low 2 bytes.
      RAX = 0x00003028;
      RBX = 0;
      RCX = 0;
      RDX = 0; // Reserved, undefined
      break;
#endif  // #if BX_SUPPORT_X86_64

    default:
      RAX = 0;
      RBX = 0;
      RCX = 0;
      RDX = 0; // Reserved, undefined
      break;
    }
#else
  BX_PANIC(("CPUID: not available on < late 486"));
#endif
}
<commit_msg>- fix bug preventing x86-64 detection<commit_after>/////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2001  MandrakeSoft S.A.
//
//    MandrakeSoft S.A.
//    43, rue d'Aboukir
//    75002 Paris - France
//    http://www.linux-mandrake.com/
//    http://www.mandrakesoft.com/
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  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

#define NEED_CPU_REG_SHORTCUTS 1
#include "bochs.h"
#define LOG_THIS BX_CPU_THIS_PTR

#if BX_SUPPORT_X86_64==0
// Make life easier for merging code.
#define RAX EAX
#define RBX EBX
#define RCX ECX
#define RDX EDX
#endif

/* Get CPU version information. */
static Bit32u get_cpu_version_information()
{
  Bit32u family = 0, model = 0, stepping = 0;
  Bit32u extended_model = 0;
  Bit32u extended_family = 0;

  /* ****** */
  /*  i486  */
  /* ****** */

#if BX_CPU_LEVEL == 4
    family = 4;

#if BX_SUPPORT_FPU
    model = 1;		// 486dx
    stepping = 3;
#else
    model = 2;		// 486sx
    stepping = 3;
#endif

  /* **************** */
  /*  i586 (Pentium)  */
  /* **************** */

#elif BX_CPU_LEVEL == 5
    family   = 5;
    model    = 1;	// Pentium (60,66)
    stepping = 3;

  /* ****** */
  /*  i686  */
  /* ****** */

#elif BX_CPU_LEVEL == 6

#if BX_SUPPORT_SSE >= 2		// Pentium 4 processor
/*
     The model, family, and processor type for the first
     processor in the Intel Pentium 4 family is as follows:
		* Model-0000B
		* Family-1111B
		* Processor Type-00B (OEM)
*/
    model    = 0;
    family   = 0x0F;
    stepping = 3;

#if BX_SUPPORT_X86_64
    model = 2;    	// Hammer returns what?
#endif

#else			// Pentium Pro/Pentium II/Pentium III processor
    family   = 6;
    model    = 8;
    stepping = 3;
#endif

#else
    BX_PANIC(("CPUID family ID not implemented for CPU LEVEL > 6"));
#endif

  return (extended_family << 20) |
         (extended_model << 16) |
         (family << 8) |
         (model<<4) | stepping;
}

/* Get CPU extended feature flags. */
static Bit32u get_extended_cpuid_features()
{
  Bit32u features = 0;	// start with none

#if BX_SUPPORT_PNI
      features |= 0x01; // report PNI
#endif

  return features;
}

/* Get CPU feature flags. Returned by CPUID functions 1 and 80000001.  */
static Bit32u get_std_cpuid_features()
{
  Bit32u features = 0; // start with none

      // EAX:       CPU Version Infromation
      //   [3:0]   Stepping ID
      //   [7:4]   Model: starts at 1
      //   [11:8]  Family: 4=486, 5=Pentium, 6=PPro, ...
      //   [13:12] Type: 0=OEM, 1=overdrive, 2=dual cpu, 3=reserved
      //   [31:14] Reserved
      // EBX:
      //   [7:0]   Brand ID
      //   [15:8]  CFLUSH cache line size (value*8 = cache line size in bytes)
      //   [23:16] Number of logical processors in one physical processor
      //   [31:24] Local Apic ID
      // ECX:       Feature Flags::Extended
      //   [0:0]   PNI
      //   [3:3]   MONITOR/MWAIT
      //   [7:7]   Enchanced Intel Speedstep Technology
      // EDX:       Feature Flags
      //   [0:0]   FPU on chip
      //   [1:1]   VME: Virtual-8086 Mode enhancements
      //   [2:2]   DE: Debug Extensions (I/O breakpoints)
      //   [3:3]   PSE: Page Size Extensions
      //   [4:4]   TSC: Time Stamp Counter
      //   [5:5]   MSR: RDMSR and WRMSR support
      //   [6:6]   PAE: Physical Address Extensions
      //   [7:7]   MCE: Machine Check Exception
      //   [8:8]   CXS: CMPXCHG8B instruction
      //   [9:9]   APIC: APIC on Chip
      //   [10:10] Reserved
      //   [11:11] SYSENTER/SYSEXIT support
      //   [12:12] MTRR: Memory Type Range Reg
      //   [13:13] PGE/PTE Global Bit
      //   [14:14] MCA: Machine Check Architecture
      //   [15:15] CMOV: Cond Mov/Cmp Instructions
      //   [22:16] Reserved
      //   [23:23] MMX Technology
      //   [24]    FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available)
      //   [25]    SSE: SSE Extensions
      //   [26]    SSE2: SSE2 Extensions
      //   [28]    Reserved
      //   [29]    TM: Therm Monitor
      //   [31:30] Reserved

#if BX_SUPPORT_FPU
      features |= 0x01;
#endif

#if (BX_CPU_LEVEL >= 5)
      features |= (1<< 8);  // Support CMPXCHG8B instruction
      features |= (1<< 4);  // implement TSC
      features |= (1<< 5);  // support RDMSR/WRMSR

#if BX_SUPPORT_MMX
      features |= (1<<23);  // support MMX
#endif

#endif

#if BX_CPU_LEVEL == 6
      features |= (1<<15);  // Implement CMOV instructions.
      features |= (1<<24);  // Implement FSAVE/FXRSTOR instructions.
#if BX_SUPPORT_APIC
      features |= (1<< 9);   // APIC on chip
#endif
#if BX_SUPPORT_SSE >= 1
      features |= (1<<25);  // support SSE
#endif
#if BX_SUPPORT_SSE >= 2
      features |= (1<<26);  // support SSE2
#endif
#endif

#if BX_SUPPORT_4MEG_PAGES
      features |= (1<< 3);  // Support Page-Size Extension (4M pages)
#endif
#if BX_SupportGlobalPages
      features |= (1<<13);  // Support Global pages.
#endif
#if BX_SupportPAE
      features |= (1<< 6);  // Support PAE.
#endif

#if BX_SUPPORT_SEP
      features |= (1<<11);  // SYSENTER/SYSEXIT
#endif

  return features;
}

void BX_CPU_C::CPUID(bxInstruction_c *i)
{
#if BX_SUPPORT_X86_64
  unsigned features;
#endif

  invalidate_prefetch_q();

#if BX_CPU_LEVEL >= 4
  switch (EAX) {
    case 0:
      // EAX: highest input value understood by CPUID
#if BX_CPU_LEVEL <= 5
      RAX = 1;		// 486 and Pentium processors
#else
      RAX = 1;		// for Pentium Pro, Pentium II, Pentium 4 processors
			// should be 2, still not implemented
#endif
      // EBX: vendor ID string
      // EDX: vendor ID string
      // ECX: vendor ID string
#if BX_SUPPORT_X86_64
      RBX = 0x68747541; // "Auth"
      RDX = 0x69746e65; // "enti"
      RCX = 0x444d4163; // "cAMD"
#else
      RBX = 0x756e6547; // "Genu"
      RDX = 0x49656e69; // "ineI"
      RCX = 0x6c65746e; // "ntel"
#endif
      break;

    case 1:
      RAX = get_cpu_version_information();
      RBX = 0; // still not implemented
      RCX = get_extended_cpuid_features ();
      RDX = get_std_cpuid_features ();
      break;

#if 0
#if BX_CPU_LEVEL >= 6
    case 2:
      RAX = 0;	// cache and TLB information (still not implemented)
      RBX = 0;  // cache and TLB information (still not implemented)
      RCX = 0;  // cache and TLB information (still not implemented)
      RDX = 0;  // cache and TLB information (still not implemented)
#endif
#endif

    // Here should be extended information for Pentum 4 processor
    // still not implemented ...

#if BX_SUPPORT_X86_64
    // x86-64 functions
    case 0x80000000:
      // max function supported.
      RAX = 0x80000008;
      RBX = 0x68747541; // "Auth"
      RDX = 0x69746e65; // "enti"
      RCX = 0x444d4163; // "cAMD"
      break;

    case 0x80000001:
      // long mode supported.
      features = get_std_cpuid_features ();
      RAX = features;
      // Many of the bits in EDX are the same as EAX
      // [10:10] Reserved
      // [11:11] SYSCALL and SYSRET instructions
      // [18:19] Reserved
      // [20:20] No-Execute page protection
      // [21:21] Reserved
      // [22:22] AMD MMX Extensions
      // [25:28] Reserved
      // [29:29] Long Mode
      // [30:30] AMD 3DNow Extensions
      // [31:31] AMD 3DNow Intructions
      features = features & 0x0183F3FF;
      RDX = features | (1 << 29) | (1 << 11);
      RBX = 0;
      RCX = 0;
      break;

    case 0x80000008:
      // virtual & phys address size in low 2 bytes.
      RAX = 0x00003028;
      RBX = 0;
      RCX = 0;
      RDX = 0; // Reserved, undefined
      break;
#endif  // #if BX_SUPPORT_X86_64

    default:
      RAX = 0;
      RBX = 0;
      RCX = 0;
      RDX = 0; // Reserved, undefined
      break;
    }
#else
  BX_PANIC(("CPUID: not available on < late 486"));
#endif
}
<|endoftext|>


<commit_before>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "AbaqusUMATStress.h"
#include "Factory.h"
#include "MooseMesh.h"
#include "RankTwoTensor.h"
#include "RankFourTensor.h"

#ifdef LIBMESH_HAVE_DLOPEN
#include <dlfcn.h>
#endif

#define QUOTE(macro) stringifyName(macro)

registerMooseObject("TensorMechanicsApp", AbaqusUMATStress);

InputParameters
AbaqusUMATStress::validParams()
{
  InputParameters params = ComputeStressBase::validParams();
  params.addClassDescription("Coupling material to use Abaqus UMAT models in MOOSE");
  params.addRequiredParam<FileName>(
      "plugin", "The path to the compiled dynamic library for the plugin you want to use");
  params.addRequiredParam<std::vector<Real>>(
      "constant_properties", "Constant mechanical and thermal material properties (PROPS)");
  params.addRequiredParam<unsigned int>("num_state_vars",
                                        "The number of state variables this UMAT is going to use");
  return params;
}

AbaqusUMATStress::AbaqusUMATStress(const InputParameters & parameters)
  : ComputeStressBase(parameters),
    _plugin(getParam<FileName>("plugin")),
    _aqNSTATV(getParam<unsigned int>("num_state_vars")),
    _aqSTATEV(_aqNSTATV),
    _aqPROPS(getParam<std::vector<Real>>("constant_properties")),
    _aqNPROPS(_aqPROPS.size()),
    _stress_old(getMaterialPropertyOld<RankTwoTensor>(_base_name + "stress")),
    _total_strain(getMaterialProperty<RankTwoTensor>(_base_name + "total_strain")),
    _strain_increment(getMaterialProperty<RankTwoTensor>(_base_name + "strain_increment")),
    _jacobian_mult(declareProperty<RankFourTensor>(_base_name + "Jacobian_mult")),
    _Fbar(getMaterialPropertyOld<RankTwoTensor>(_base_name + "deformation_gradient")),
    _Fbar_old(getMaterialPropertyOld<RankTwoTensor>(_base_name + "deformation_gradient")),
    _state_var(declareProperty<std::vector<Real>>(_base_name + "state_var")),
    _state_var_old(getMaterialPropertyOld<std::vector<Real>>(_base_name + "state_var")),
    _elastic_strain_energy(declareProperty<Real>(_base_name + "elastic_strain_energy")),
    _plastic_dissipation(declareProperty<Real>(_base_name + "plastic_dissipation")),
    _creep_dissipation(declareProperty<Real>(_base_name + "creep_dissipation")),
    _material_timestep(declareProperty<Real>(_base_name + "material_timestep_limit"))
{
#ifndef METHOD
#error "The METHOD preprocessor symbol must be supplied by the build system."
#endif
  _plugin += std::string("-") + QUOTE(METHOD) + ".plugin";

  // Read mesh dimension and size UMAT arrays (we always size for full 3D)
  _aqNTENS = 6; // Size of the stress or strain component array (NDI+NSHR)
  _aqNSHR = 3;  // Number of engineering shear stress components
  _aqNDI = 3;   // Number of direct stress components (always 3)

  _aqDDSDDT.resize(_aqNTENS);
  _aqDRPLDE.resize(_aqNTENS);
  _aqSTRAN.resize(_aqNTENS);
  _aqDFGRD0.resize(9);
  _aqDFGRD1.resize(9);
  _aqSTRESS.resize(_aqNTENS);
  _aqDDSDDE.resize(_aqNTENS * _aqNTENS);
  _aqDSTRAN.resize(_aqNTENS);

  // Open the library
#ifdef LIBMESH_HAVE_DLOPEN
  _handle = dlopen(_plugin.c_str(), RTLD_LAZY);

  if (!_handle)
    paramError("plugin", "Cannot open library: ", dlerror());

  // Reset errors
  dlerror();

  // Snag the function pointer from the library
  {
    void * pointer = dlsym(_handle, "umat_");
    _umat = *reinterpret_cast<umat_t *>(&pointer);
  }

  // Catch errors
  const char * dlsym_error = dlerror();
  if (dlsym_error)
  {
    dlclose(_handle);
    paramError("plugin", "Cannot load symbol 'umat_': ", dlsym_error);
  }
#else
  paramError("plugin",
             "AbaqusUMATStress requires an operating system with support for the POSIX function "
             "'dlopen' to dynamically load UMAT plugins.");
#endif
}

AbaqusUMATStress::~AbaqusUMATStress()
{
#ifdef LIBMESH_HAVE_DLOPEN
  dlclose(_handle);
#endif
}

void
AbaqusUMATStress::initQpStatefulProperties()
{
  // Initialize state variable vector
  _state_var[_qp].resize(_aqNSTATV);
  for (int i = 0; i < _aqNSTATV; ++i)
    _state_var[_qp][i] = 0.0;
}

void
AbaqusUMATStress::computeProperties()
{
  // current element "number"
  _aqNOEL = _current_elem->id();

  // characteristic element length
  // TODO: check what Abaqus actually passes in here (likely ~ element_volume^(1/element_dim))
  _aqCELENT = std::numeric_limits<Real>::signaling_NaN();

  // Value of step time at the beginning of the current increment - Check
  _aqTIME[0] = _t;
  // Value of total time at the beginning of the current increment - Check
  _aqTIME[1] = _t - _dt;

  // Time increment
  _aqDTIME = _dt;

  ComputeStressBase::computeProperties();
}

void
AbaqusUMATStress::computeQpStress()
{
  const Real * myDFGRD0 = &(_Fbar_old[_qp](0, 0));
  const Real * myDFGRD1 = &(_Fbar[_qp](0, 0));
  // copy because UMAT does not guarantee constness
  for (unsigned int i = 0; i < 9; ++i)
  {
    _aqDFGRD0[i] = myDFGRD0[i];
    _aqDFGRD1[i] = myDFGRD1[i];
  }

  // Recover "old" state variables
  for (int i = 0; i < _aqNSTATV; ++i)
    _aqSTATEV[i] = _state_var_old[_qp][i];

  // Pass through updated stress, total strain, and strain increment arrays
  static const std::array<Real, 6> strain_factor{{1, 1, 1, 2, 2, 2}};
  static const std::array<std::pair<unsigned int, unsigned int>, 6> component{
      {{0, 0}, {1, 1}, {2, 2}, {1, 2}, {0, 2}, {0, 1}}};
  for (int i = 0; i < _aqNTENS; ++i)
  {
    _aqSTRESS[i] = _stress_old[_qp](component[i].first, component[i].second);
    _aqSTRAN[i] = _total_strain[_qp](component[i].first, component[i].second) * strain_factor[i];
    _aqDSTRAN[i] =
        _strain_increment[_qp](component[i].first, component[i].second) * strain_factor[i];
  }

  // current coordinates
  for (unsigned int i = 0; i < LIBMESH_DIM; ++i)
    _aqCOORDS[i] = _q_point[_qp](i);

  // zero out Jacobian contribution
  for (int i = 0; i < _aqNTENS * _aqNTENS; ++i)
    _aqDDSDDE[i] = 0.0;

  // set PNEWDT to a large value
  _aqPNEWDT = std::numeric_limits<Real>::max();

  // Connection to extern statement
  _umat(_aqSTRESS.data(),
        _aqSTATEV.data(),
        _aqDDSDDE.data(),
        &_elastic_strain_energy[_qp],
        &_plastic_dissipation[_qp],
        &_creep_dissipation[_qp],
        &_aqRPL,
        _aqDDSDDT.data(),
        _aqDRPLDE.data(),
        &_aqDRPLDT,
        _aqSTRAN.data(),
        _aqDSTRAN.data(),
        _aqTIME.data(),
        &_aqDTIME,
        &_aqTEMP,
        &_aqDTEMP,
        &_aqPREDEF,
        &_aqDPRED,
        _aqCMNAME,
        &_aqNDI,
        &_aqNSHR,
        &_aqNTENS,
        &_aqNSTATV,
        _aqPROPS.data(),
        &_aqNPROPS,
        _aqCOORDS.data(),
        _aqDROT.data(),
        &_aqPNEWDT,
        &_aqCELENT,
        _aqDFGRD0.data(),
        _aqDFGRD1.data(),
        &_aqNOEL,
        &_qp,
        &_aqLAYER,
        &_aqKSPT,
        &_t_step,
        &_aqKINC);

  // Update state variables
  for (int i = 0; i < _aqNSTATV; ++i)
    _state_var[_qp][i] = _aqSTATEV[i];

  // determine the material timestep
  _material_timestep[_qp] = _aqPNEWDT < 1.0 ? _aqPNEWDT * _dt : std::numeric_limits<Real>::max();

  // Get new stress tensor - UMAT should update stress
  _stress[_qp] = RankTwoTensor(
      _aqSTRESS[0], _aqSTRESS[1], _aqSTRESS[2], _aqSTRESS[3], _aqSTRESS[4], _aqSTRESS[5]);

  // use DDSDDE as Jacobian mult
  _jacobian_mult[_qp].fillSymmetric21FromInputVector(std::array<Real, 21>{{
      _aqDDSDDE[0],  // C1111
      _aqDDSDDE[1],  // C1122
      _aqDDSDDE[2],  // C1133
      _aqDDSDDE[3],  // C1123
      _aqDDSDDE[4],  // C1113
      _aqDDSDDE[5],  // C1112
      _aqDDSDDE[7],  // C2222
      _aqDDSDDE[8],  // C2233
      _aqDDSDDE[9],  // C2223
      _aqDDSDDE[10], // C2213
      _aqDDSDDE[11], // C2212
      _aqDDSDDE[14], // C3333
      _aqDDSDDE[15], // C3323
      _aqDDSDDE[16], // C3313
      _aqDDSDDE[17], // C3312
      _aqDDSDDE[21], // C2323
      _aqDDSDDE[22], // C2313
      _aqDDSDDE[23], // C2312
      _aqDDSDDE[28], // C1313
      _aqDDSDDE[29], // C1312
      _aqDDSDDE[35]  // C1212
  }});
}
<commit_msg>Fix current Fbar (#18516)<commit_after>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "AbaqusUMATStress.h"
#include "Factory.h"
#include "MooseMesh.h"
#include "RankTwoTensor.h"
#include "RankFourTensor.h"

#ifdef LIBMESH_HAVE_DLOPEN
#include <dlfcn.h>
#endif

#define QUOTE(macro) stringifyName(macro)

registerMooseObject("TensorMechanicsApp", AbaqusUMATStress);

InputParameters
AbaqusUMATStress::validParams()
{
  InputParameters params = ComputeStressBase::validParams();
  params.addClassDescription("Coupling material to use Abaqus UMAT models in MOOSE");
  params.addRequiredParam<FileName>(
      "plugin", "The path to the compiled dynamic library for the plugin you want to use");
  params.addRequiredParam<std::vector<Real>>(
      "constant_properties", "Constant mechanical and thermal material properties (PROPS)");
  params.addRequiredParam<unsigned int>("num_state_vars",
                                        "The number of state variables this UMAT is going to use");
  return params;
}

AbaqusUMATStress::AbaqusUMATStress(const InputParameters & parameters)
  : ComputeStressBase(parameters),
    _plugin(getParam<FileName>("plugin")),
    _aqNSTATV(getParam<unsigned int>("num_state_vars")),
    _aqSTATEV(_aqNSTATV),
    _aqPROPS(getParam<std::vector<Real>>("constant_properties")),
    _aqNPROPS(_aqPROPS.size()),
    _stress_old(getMaterialPropertyOld<RankTwoTensor>(_base_name + "stress")),
    _total_strain(getMaterialProperty<RankTwoTensor>(_base_name + "total_strain")),
    _strain_increment(getMaterialProperty<RankTwoTensor>(_base_name + "strain_increment")),
    _jacobian_mult(declareProperty<RankFourTensor>(_base_name + "Jacobian_mult")),
    _Fbar(getMaterialProperty<RankTwoTensor>(_base_name + "deformation_gradient")),
    _Fbar_old(getMaterialPropertyOld<RankTwoTensor>(_base_name + "deformation_gradient")),
    _state_var(declareProperty<std::vector<Real>>(_base_name + "state_var")),
    _state_var_old(getMaterialPropertyOld<std::vector<Real>>(_base_name + "state_var")),
    _elastic_strain_energy(declareProperty<Real>(_base_name + "elastic_strain_energy")),
    _plastic_dissipation(declareProperty<Real>(_base_name + "plastic_dissipation")),
    _creep_dissipation(declareProperty<Real>(_base_name + "creep_dissipation")),
    _material_timestep(declareProperty<Real>(_base_name + "material_timestep_limit"))
{
#ifndef METHOD
#error "The METHOD preprocessor symbol must be supplied by the build system."
#endif
  _plugin += std::string("-") + QUOTE(METHOD) + ".plugin";

  // Read mesh dimension and size UMAT arrays (we always size for full 3D)
  _aqNTENS = 6; // Size of the stress or strain component array (NDI+NSHR)
  _aqNSHR = 3;  // Number of engineering shear stress components
  _aqNDI = 3;   // Number of direct stress components (always 3)

  _aqDDSDDT.resize(_aqNTENS);
  _aqDRPLDE.resize(_aqNTENS);
  _aqSTRAN.resize(_aqNTENS);
  _aqDFGRD0.resize(9);
  _aqDFGRD1.resize(9);
  _aqSTRESS.resize(_aqNTENS);
  _aqDDSDDE.resize(_aqNTENS * _aqNTENS);
  _aqDSTRAN.resize(_aqNTENS);

  // Open the library
#ifdef LIBMESH_HAVE_DLOPEN
  _handle = dlopen(_plugin.c_str(), RTLD_LAZY);

  if (!_handle)
    paramError("plugin", "Cannot open library: ", dlerror());

  // Reset errors
  dlerror();

  // Snag the function pointer from the library
  {
    void * pointer = dlsym(_handle, "umat_");
    _umat = *reinterpret_cast<umat_t *>(&pointer);
  }

  // Catch errors
  const char * dlsym_error = dlerror();
  if (dlsym_error)
  {
    dlclose(_handle);
    paramError("plugin", "Cannot load symbol 'umat_': ", dlsym_error);
  }
#else
  paramError("plugin",
             "AbaqusUMATStress requires an operating system with support for the POSIX function "
             "'dlopen' to dynamically load UMAT plugins.");
#endif
}

AbaqusUMATStress::~AbaqusUMATStress()
{
#ifdef LIBMESH_HAVE_DLOPEN
  dlclose(_handle);
#endif
}

void
AbaqusUMATStress::initQpStatefulProperties()
{
  // Initialize state variable vector
  _state_var[_qp].resize(_aqNSTATV);
  for (int i = 0; i < _aqNSTATV; ++i)
    _state_var[_qp][i] = 0.0;
}

void
AbaqusUMATStress::computeProperties()
{
  // current element "number"
  _aqNOEL = _current_elem->id();

  // characteristic element length
  // TODO: check what Abaqus actually passes in here (likely ~ element_volume^(1/element_dim))
  _aqCELENT = std::numeric_limits<Real>::signaling_NaN();

  // Value of step time at the beginning of the current increment - Check
  _aqTIME[0] = _t;
  // Value of total time at the beginning of the current increment - Check
  _aqTIME[1] = _t - _dt;

  // Time increment
  _aqDTIME = _dt;

  ComputeStressBase::computeProperties();
}

void
AbaqusUMATStress::computeQpStress()
{
  const Real * myDFGRD0 = &(_Fbar_old[_qp](0, 0));
  const Real * myDFGRD1 = &(_Fbar[_qp](0, 0));
  // copy because UMAT does not guarantee constness
  for (unsigned int i = 0; i < 9; ++i)
  {
    _aqDFGRD0[i] = myDFGRD0[i];
    _aqDFGRD1[i] = myDFGRD1[i];
  }

  // Recover "old" state variables
  for (int i = 0; i < _aqNSTATV; ++i)
    _aqSTATEV[i] = _state_var_old[_qp][i];

  // Pass through updated stress, total strain, and strain increment arrays
  static const std::array<Real, 6> strain_factor{{1, 1, 1, 2, 2, 2}};
  static const std::array<std::pair<unsigned int, unsigned int>, 6> component{
      {{0, 0}, {1, 1}, {2, 2}, {1, 2}, {0, 2}, {0, 1}}};
  for (int i = 0; i < _aqNTENS; ++i)
  {
    _aqSTRESS[i] = _stress_old[_qp](component[i].first, component[i].second);
    _aqSTRAN[i] = _total_strain[_qp](component[i].first, component[i].second) * strain_factor[i];
    _aqDSTRAN[i] =
        _strain_increment[_qp](component[i].first, component[i].second) * strain_factor[i];
  }

  // current coordinates
  for (unsigned int i = 0; i < LIBMESH_DIM; ++i)
    _aqCOORDS[i] = _q_point[_qp](i);

  // zero out Jacobian contribution
  for (int i = 0; i < _aqNTENS * _aqNTENS; ++i)
    _aqDDSDDE[i] = 0.0;

  // set PNEWDT to a large value
  _aqPNEWDT = std::numeric_limits<Real>::max();

  // Connection to extern statement
  _umat(_aqSTRESS.data(),
        _aqSTATEV.data(),
        _aqDDSDDE.data(),
        &_elastic_strain_energy[_qp],
        &_plastic_dissipation[_qp],
        &_creep_dissipation[_qp],
        &_aqRPL,
        _aqDDSDDT.data(),
        _aqDRPLDE.data(),
        &_aqDRPLDT,
        _aqSTRAN.data(),
        _aqDSTRAN.data(),
        _aqTIME.data(),
        &_aqDTIME,
        &_aqTEMP,
        &_aqDTEMP,
        &_aqPREDEF,
        &_aqDPRED,
        _aqCMNAME,
        &_aqNDI,
        &_aqNSHR,
        &_aqNTENS,
        &_aqNSTATV,
        _aqPROPS.data(),
        &_aqNPROPS,
        _aqCOORDS.data(),
        _aqDROT.data(),
        &_aqPNEWDT,
        &_aqCELENT,
        _aqDFGRD0.data(),
        _aqDFGRD1.data(),
        &_aqNOEL,
        &_qp,
        &_aqLAYER,
        &_aqKSPT,
        &_t_step,
        &_aqKINC);

  // Update state variables
  for (int i = 0; i < _aqNSTATV; ++i)
    _state_var[_qp][i] = _aqSTATEV[i];

  // determine the material timestep
  _material_timestep[_qp] = _aqPNEWDT < 1.0 ? _aqPNEWDT * _dt : std::numeric_limits<Real>::max();

  // Get new stress tensor - UMAT should update stress
  _stress[_qp] = RankTwoTensor(
      _aqSTRESS[0], _aqSTRESS[1], _aqSTRESS[2], _aqSTRESS[3], _aqSTRESS[4], _aqSTRESS[5]);

  // use DDSDDE as Jacobian mult
  _jacobian_mult[_qp].fillSymmetric21FromInputVector(std::array<Real, 21>{{
      _aqDDSDDE[0],  // C1111
      _aqDDSDDE[1],  // C1122
      _aqDDSDDE[2],  // C1133
      _aqDDSDDE[3],  // C1123
      _aqDDSDDE[4],  // C1113
      _aqDDSDDE[5],  // C1112
      _aqDDSDDE[7],  // C2222
      _aqDDSDDE[8],  // C2233
      _aqDDSDDE[9],  // C2223
      _aqDDSDDE[10], // C2213
      _aqDDSDDE[11], // C2212
      _aqDDSDDE[14], // C3333
      _aqDDSDDE[15], // C3323
      _aqDDSDDE[16], // C3313
      _aqDDSDDE[17], // C3312
      _aqDDSDDE[21], // C2323
      _aqDDSDDE[22], // C2313
      _aqDDSDDE[23], // C2312
      _aqDDSDDE[28], // C1313
      _aqDDSDDE[29], // C1312
      _aqDDSDDE[35]  // C1212
  }});
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: localschemasupplier.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 04:05:48 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/

#include "localschemasupplier.hxx"

#ifndef CONFIGMGR_LOCALBE_LOCALFILEHELPER_HXX_
#include "localfilehelper.hxx"
#endif

#ifndef _CONFIGMGR_OSLSTREAM_HXX_
#include "oslstream.hxx"
#endif // _CONFIGMGR_OSLSTREAM_HXX_

#ifndef CONFIGMGR_API_FACTORY_HXX_
#include "confapifactory.hxx"
#endif // CONFIGMGR_API_FACTORY_HXX_

#ifndef CONFIGMGR_SERVICEINFOHELPER_HXX_
#include "serviceinfohelper.hxx"
#endif // CONFIGMGR_SERVICEINFOHELPER_HXX_

#ifndef CONFIGMGR_BOOTSTRAP_HXX_
#include "bootstrap.hxx"
#endif
#ifndef _CONFIGMGR_FILEHELPER_HXX_
#include "filehelper.hxx"
#endif

#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif // _RTL_USTRBUF_HXX_

#ifndef _COM_SUN_STAR_UNO_XCOMPONENTCONTEXT_HPP_
#include <com/sun/star/uno/XComponentContext.hpp>
#endif
#ifndef _COM_SUN_STAR_CONFIGURATION_BACKEND_INSUFFICIENTACCESSRIGHTSEXCEPTION_HPP_
#include <com/sun/star/configuration/backend/InsufficientAccessRightsException.hpp>
#endif

#ifndef _OSL_FILE_HXX_
#include <osl/file.hxx>
#endif
#ifndef _OSL_PROCESS_H_
#include <osl/process.h>
#endif
#include <memory>

namespace configmgr { namespace localbe {

//==============================================================================

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

LocalSchemaSupplier::LocalSchemaSupplier(
        const uno::Reference<uno::XComponentContext>& xContext)
        : SingleBackendBase(mMutex), mFactory(xContext->getServiceManager(),uno::UNO_QUERY) {
}
//------------------------------------------------------------------------------

LocalSchemaSupplier::~LocalSchemaSupplier(void) {}
//------------------------------------------------------------------------------
static const rtl::OUString kSchemaDataUrl(
        RTL_CONSTASCII_USTRINGPARAM(CONTEXT_ITEM_PREFIX_"SchemaDataUrl")) ;

static const rtl::OUString kSchemaVersion(
        RTL_CONSTASCII_USTRINGPARAM(CONTEXT_ITEM_PREFIX_"SchemaVersion")) ;

void SAL_CALL LocalSchemaSupplier::initialize(
        const uno::Sequence<uno::Any>& aParameters)
    throw (uno::RuntimeException, uno::Exception,
           css::configuration::InvalidBootstrapFileException,
           backend::CannotConnectException,
           backend::BackendSetupException)
{
    if (aParameters.getLength() == 0) {
        throw lang::IllegalArgumentException(
                rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
                        "No parameters provided to LocalSchemaSupplier")),
                *this, 0) ;
    }
    uno::Reference<uno::XComponentContext> context ;

    for (sal_Int32 i = 0 ; i < aParameters.getLength() ; ++ i) {
        if (aParameters [i] >>= context) { break ; }
    }

    // Setting: schema version
    // TODO: Add support for repository-specific versions
    uno::Any const aSchemaVersionSetting = context->getValueByName(kSchemaVersion);
    aSchemaVersionSetting >>= mSchemaVersion;

    // Setting: schema diretory(ies)
    uno::Any const aSchemaDataSetting = context->getValueByName(kSchemaDataUrl);
    uno::Sequence< OUString > aSchemas;
    rtl::OUString schemas;

    if (aSchemaDataSetting >>= schemas)
    {
        fillFromBlankSeparated(schemas, aSchemas) ;
    }
    else
    {
        aSchemaDataSetting >>=  aSchemas;
    }
    //validate SchemaDataUrls
    mSchemaDataUrls.realloc(aSchemas.getLength());

    sal_Int32 nSchemaLocations =0;
    sal_Int32 nExistingSchemaLocations = 0;
    for (sal_Int32 j = 0; j < aSchemas.getLength(); ++j)
    {
        bool bOptional = checkOptionalArg(aSchemas[j]);

        if(!bOptional)
            validateFileURL(aSchemas[j],*this);
        else if (!isValidFileURL(aSchemas[j]))
            continue;

        OSL_ASSERT(isValidFileURL(aSchemas[j]));

        //NormalizeURL
        implEnsureAbsoluteURL(aSchemas[j]);
        if(!normalizeURL(aSchemas[j],*this,bOptional))
            continue;

        //now we have a correct file URL, which we will use
        mSchemaDataUrls[nSchemaLocations++]= aSchemas[j];
        if (!bOptional)
            checkFileExists(aSchemas[j],*this);

        else if(!FileHelper::fileExists(aSchemas[j]))
            continue; // skip the directory check

        checkIfDirectory(aSchemas[j],*this);
        ++nExistingSchemaLocations;
    }
    if (0 == nExistingSchemaLocations)
    {
        rtl::OUString sMsg = rtl::OUString::createFromAscii("LocalBackend: No schema directories found");
        throw backend::BackendSetupException(sMsg,*this, uno::Any()) ;
    }
    mSchemaDataUrls.realloc(nSchemaLocations);
}
//------------------------------------------------------------------------------

rtl::OUString SAL_CALL
    LocalSchemaSupplier::getSchemaVersion(const rtl::OUString& /*aComponent*/)
        throw (backend::BackendAccessException, lang::IllegalArgumentException,
                uno::RuntimeException)
{
    // TODO: Add support for repository-specific versions
    return mSchemaVersion;
}
//------------------------------------------------------------------------------
static const rtl::OUString kSchemaSuffix(RTL_CONSTASCII_USTRINGPARAM(".xcs")) ;
static const rtl::OUString kXMLSchemaParser(RTL_CONSTASCII_USTRINGPARAM(
            "com.sun.star.configuration.backend.xml.SchemaParser")) ;

uno::Reference<backend::XSchema> SAL_CALL
    LocalSchemaSupplier::getComponentSchema(const rtl::OUString& aComponent)
        throw (backend::BackendAccessException, lang::IllegalArgumentException,
                uno::RuntimeException)
{
    rtl::OUString subPath = componentToPath(aComponent) ;

    osl::File * schemaFile = NULL;
    OUString errorMessage;
    bool bInsufficientAccess = false;
    for (sal_Int32 ix = 0; ix < mSchemaDataUrls.getLength(); ++ix)
    {
        rtl::OUStringBuffer schemaUrl(mSchemaDataUrls[ix]) ;

        schemaUrl.append(subPath).append(kSchemaSuffix) ;

        OUString const aFileUrl = schemaUrl.makeStringAndClear();

        std::auto_ptr<osl::File> checkFile( new osl::File(aFileUrl) );
        osl::File::RC rc = checkFile->open(OpenFlag_Read) ;

        if (rc == osl::File::E_None)
        {
            schemaFile = checkFile.release();
            break;
        }
        else if (rc != osl::File::E_NOENT)
        {
            if (rc == osl::File::E_ACCES)
                bInsufficientAccess =true;

            // accumulate error messages
            rtl::OUStringBuffer sMsg(errorMessage);
            if (errorMessage.getLength())
                sMsg.appendAscii("LocalFile SchemaSupplier - Error accessing schema: ");

            sMsg.appendAscii("\n- Cannot open input file \"");
            sMsg.append(aFileUrl);
            sMsg.appendAscii("\" : ");
            sMsg.append(FileHelper::createOSLErrorString(rc));

            errorMessage = sMsg.makeStringAndClear();
        }
    }

    if (NULL == schemaFile)
    {
        if (errorMessage.getLength() != 0)
        {
            // a real error occured
            io::IOException ioe(errorMessage,*this);

            rtl::OUStringBuffer sMsg;
            sMsg.appendAscii("LocalFileLayer - Cannot readData: ").append(errorMessage);

            if (bInsufficientAccess)
                throw backend::InsufficientAccessRightsException(sMsg.makeStringAndClear(),*this,uno::makeAny(ioe));
            else
                throw backend::BackendAccessException(sMsg.makeStringAndClear(),*this,uno::makeAny(ioe));
        }
        // simply not found
        return NULL;
    }

    uno::Sequence<uno::Any> arguments(1) ;
    uno::Reference<io::XInputStream> stream( new OSLInputStreamWrapper(schemaFile, true) );

    arguments [0] <<= stream ;
    uno::Reference<backend::XSchema> schema(
            mFactory->createInstanceWithArguments(kXMLSchemaParser, arguments),
            uno::UNO_QUERY) ;

    if (!schema.is())
    {
        throw uno::RuntimeException(
                rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
                        "Cannot instantiate Schema Parser for ")) + aComponent,
                *this) ;
    }
    return schema ;
}
//------------------------------------------------------------------------------

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

static const sal_Char * const kImplementation =
                "com.sun.star.comp.configuration.backend.LocalSchemaSupplier" ;
static const sal_Char * const kSchemaService =
                "com.sun.star.configuration.backend.SchemaSupplier" ;
static const sal_Char * const kLocalService =
                "com.sun.star.configuration.backend.LocalSchemaSupplier" ;

static AsciiServiceName kServiceNames [] = {kLocalService, 0, kSchemaService, 0 } ;
static const ServiceImplementationInfo kServiceInfo = { kImplementation, kServiceNames,kServiceNames+2 } ;

const ServiceRegistrationInfo *getLocalSchemaSupplierServiceInfo()
{ return getRegistrationInfo(&kServiceInfo) ; }

uno::Reference<uno::XInterface> SAL_CALL
instantiateLocalSchemaSupplier(const CreationContext& xContext) {
    return *new LocalSchemaSupplier(xContext) ;
}
//------------------------------------------------------------------------------

static const rtl::OUString kImplementationName(
                            RTL_CONSTASCII_USTRINGPARAM(kImplementation)) ;

rtl::OUString SAL_CALL LocalSchemaSupplier::getName(void) {
    return kImplementationName ;
}
//------------------------------------------------------------------------------

rtl::OUString SAL_CALL LocalSchemaSupplier::getImplementationName(void)
    throw (uno::RuntimeException)
{
    return ServiceInfoHelper(&kServiceInfo).getImplementationName() ;
}
//------------------------------------------------------------------------------

sal_Bool SAL_CALL LocalSchemaSupplier::supportsService(
                                        const rtl::OUString& aServiceName)
    throw (uno::RuntimeException)
{
    return  ServiceInfoHelper(&kServiceInfo).supportsService(aServiceName);
}
//------------------------------------------------------------------------------

uno::Sequence<rtl::OUString> SAL_CALL LocalSchemaSupplier::getServices(void)
{
    return ServiceInfoHelper(&kServiceInfo).getSupportedServiceNames() ;
}
//------------------------------------------------------------------------------

uno::Sequence<rtl::OUString>
SAL_CALL LocalSchemaSupplier::getSupportedServiceNames(void)
    throw (uno::RuntimeException)
{
    return ServiceInfoHelper(&kServiceInfo).getSupportedServiceNames() ;
}

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

} } // configmgr.localbe
<commit_msg>INTEGRATION: CWS pchfix02 (1.4.60); FILE MERGED 2006/09/01 17:20:35 kaib 1.4.60.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: localschemasupplier.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-16 15:12:46 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_configmgr.hxx"

#include "localschemasupplier.hxx"

#ifndef CONFIGMGR_LOCALBE_LOCALFILEHELPER_HXX_
#include "localfilehelper.hxx"
#endif

#ifndef _CONFIGMGR_OSLSTREAM_HXX_
#include "oslstream.hxx"
#endif // _CONFIGMGR_OSLSTREAM_HXX_

#ifndef CONFIGMGR_API_FACTORY_HXX_
#include "confapifactory.hxx"
#endif // CONFIGMGR_API_FACTORY_HXX_

#ifndef CONFIGMGR_SERVICEINFOHELPER_HXX_
#include "serviceinfohelper.hxx"
#endif // CONFIGMGR_SERVICEINFOHELPER_HXX_

#ifndef CONFIGMGR_BOOTSTRAP_HXX_
#include "bootstrap.hxx"
#endif
#ifndef _CONFIGMGR_FILEHELPER_HXX_
#include "filehelper.hxx"
#endif

#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif // _RTL_USTRBUF_HXX_

#ifndef _COM_SUN_STAR_UNO_XCOMPONENTCONTEXT_HPP_
#include <com/sun/star/uno/XComponentContext.hpp>
#endif
#ifndef _COM_SUN_STAR_CONFIGURATION_BACKEND_INSUFFICIENTACCESSRIGHTSEXCEPTION_HPP_
#include <com/sun/star/configuration/backend/InsufficientAccessRightsException.hpp>
#endif

#ifndef _OSL_FILE_HXX_
#include <osl/file.hxx>
#endif
#ifndef _OSL_PROCESS_H_
#include <osl/process.h>
#endif
#include <memory>

namespace configmgr { namespace localbe {

//==============================================================================

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

LocalSchemaSupplier::LocalSchemaSupplier(
        const uno::Reference<uno::XComponentContext>& xContext)
        : SingleBackendBase(mMutex), mFactory(xContext->getServiceManager(),uno::UNO_QUERY) {
}
//------------------------------------------------------------------------------

LocalSchemaSupplier::~LocalSchemaSupplier(void) {}
//------------------------------------------------------------------------------
static const rtl::OUString kSchemaDataUrl(
        RTL_CONSTASCII_USTRINGPARAM(CONTEXT_ITEM_PREFIX_"SchemaDataUrl")) ;

static const rtl::OUString kSchemaVersion(
        RTL_CONSTASCII_USTRINGPARAM(CONTEXT_ITEM_PREFIX_"SchemaVersion")) ;

void SAL_CALL LocalSchemaSupplier::initialize(
        const uno::Sequence<uno::Any>& aParameters)
    throw (uno::RuntimeException, uno::Exception,
           css::configuration::InvalidBootstrapFileException,
           backend::CannotConnectException,
           backend::BackendSetupException)
{
    if (aParameters.getLength() == 0) {
        throw lang::IllegalArgumentException(
                rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
                        "No parameters provided to LocalSchemaSupplier")),
                *this, 0) ;
    }
    uno::Reference<uno::XComponentContext> context ;

    for (sal_Int32 i = 0 ; i < aParameters.getLength() ; ++ i) {
        if (aParameters [i] >>= context) { break ; }
    }

    // Setting: schema version
    // TODO: Add support for repository-specific versions
    uno::Any const aSchemaVersionSetting = context->getValueByName(kSchemaVersion);
    aSchemaVersionSetting >>= mSchemaVersion;

    // Setting: schema diretory(ies)
    uno::Any const aSchemaDataSetting = context->getValueByName(kSchemaDataUrl);
    uno::Sequence< OUString > aSchemas;
    rtl::OUString schemas;

    if (aSchemaDataSetting >>= schemas)
    {
        fillFromBlankSeparated(schemas, aSchemas) ;
    }
    else
    {
        aSchemaDataSetting >>=  aSchemas;
    }
    //validate SchemaDataUrls
    mSchemaDataUrls.realloc(aSchemas.getLength());

    sal_Int32 nSchemaLocations =0;
    sal_Int32 nExistingSchemaLocations = 0;
    for (sal_Int32 j = 0; j < aSchemas.getLength(); ++j)
    {
        bool bOptional = checkOptionalArg(aSchemas[j]);

        if(!bOptional)
            validateFileURL(aSchemas[j],*this);
        else if (!isValidFileURL(aSchemas[j]))
            continue;

        OSL_ASSERT(isValidFileURL(aSchemas[j]));

        //NormalizeURL
        implEnsureAbsoluteURL(aSchemas[j]);
        if(!normalizeURL(aSchemas[j],*this,bOptional))
            continue;

        //now we have a correct file URL, which we will use
        mSchemaDataUrls[nSchemaLocations++]= aSchemas[j];
        if (!bOptional)
            checkFileExists(aSchemas[j],*this);

        else if(!FileHelper::fileExists(aSchemas[j]))
            continue; // skip the directory check

        checkIfDirectory(aSchemas[j],*this);
        ++nExistingSchemaLocations;
    }
    if (0 == nExistingSchemaLocations)
    {
        rtl::OUString sMsg = rtl::OUString::createFromAscii("LocalBackend: No schema directories found");
        throw backend::BackendSetupException(sMsg,*this, uno::Any()) ;
    }
    mSchemaDataUrls.realloc(nSchemaLocations);
}
//------------------------------------------------------------------------------

rtl::OUString SAL_CALL
    LocalSchemaSupplier::getSchemaVersion(const rtl::OUString& /*aComponent*/)
        throw (backend::BackendAccessException, lang::IllegalArgumentException,
                uno::RuntimeException)
{
    // TODO: Add support for repository-specific versions
    return mSchemaVersion;
}
//------------------------------------------------------------------------------
static const rtl::OUString kSchemaSuffix(RTL_CONSTASCII_USTRINGPARAM(".xcs")) ;
static const rtl::OUString kXMLSchemaParser(RTL_CONSTASCII_USTRINGPARAM(
            "com.sun.star.configuration.backend.xml.SchemaParser")) ;

uno::Reference<backend::XSchema> SAL_CALL
    LocalSchemaSupplier::getComponentSchema(const rtl::OUString& aComponent)
        throw (backend::BackendAccessException, lang::IllegalArgumentException,
                uno::RuntimeException)
{
    rtl::OUString subPath = componentToPath(aComponent) ;

    osl::File * schemaFile = NULL;
    OUString errorMessage;
    bool bInsufficientAccess = false;
    for (sal_Int32 ix = 0; ix < mSchemaDataUrls.getLength(); ++ix)
    {
        rtl::OUStringBuffer schemaUrl(mSchemaDataUrls[ix]) ;

        schemaUrl.append(subPath).append(kSchemaSuffix) ;

        OUString const aFileUrl = schemaUrl.makeStringAndClear();

        std::auto_ptr<osl::File> checkFile( new osl::File(aFileUrl) );
        osl::File::RC rc = checkFile->open(OpenFlag_Read) ;

        if (rc == osl::File::E_None)
        {
            schemaFile = checkFile.release();
            break;
        }
        else if (rc != osl::File::E_NOENT)
        {
            if (rc == osl::File::E_ACCES)
                bInsufficientAccess =true;

            // accumulate error messages
            rtl::OUStringBuffer sMsg(errorMessage);
            if (errorMessage.getLength())
                sMsg.appendAscii("LocalFile SchemaSupplier - Error accessing schema: ");

            sMsg.appendAscii("\n- Cannot open input file \"");
            sMsg.append(aFileUrl);
            sMsg.appendAscii("\" : ");
            sMsg.append(FileHelper::createOSLErrorString(rc));

            errorMessage = sMsg.makeStringAndClear();
        }
    }

    if (NULL == schemaFile)
    {
        if (errorMessage.getLength() != 0)
        {
            // a real error occured
            io::IOException ioe(errorMessage,*this);

            rtl::OUStringBuffer sMsg;
            sMsg.appendAscii("LocalFileLayer - Cannot readData: ").append(errorMessage);

            if (bInsufficientAccess)
                throw backend::InsufficientAccessRightsException(sMsg.makeStringAndClear(),*this,uno::makeAny(ioe));
            else
                throw backend::BackendAccessException(sMsg.makeStringAndClear(),*this,uno::makeAny(ioe));
        }
        // simply not found
        return NULL;
    }

    uno::Sequence<uno::Any> arguments(1) ;
    uno::Reference<io::XInputStream> stream( new OSLInputStreamWrapper(schemaFile, true) );

    arguments [0] <<= stream ;
    uno::Reference<backend::XSchema> schema(
            mFactory->createInstanceWithArguments(kXMLSchemaParser, arguments),
            uno::UNO_QUERY) ;

    if (!schema.is())
    {
        throw uno::RuntimeException(
                rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
                        "Cannot instantiate Schema Parser for ")) + aComponent,
                *this) ;
    }
    return schema ;
}
//------------------------------------------------------------------------------

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

static const sal_Char * const kImplementation =
                "com.sun.star.comp.configuration.backend.LocalSchemaSupplier" ;
static const sal_Char * const kSchemaService =
                "com.sun.star.configuration.backend.SchemaSupplier" ;
static const sal_Char * const kLocalService =
                "com.sun.star.configuration.backend.LocalSchemaSupplier" ;

static AsciiServiceName kServiceNames [] = {kLocalService, 0, kSchemaService, 0 } ;
static const ServiceImplementationInfo kServiceInfo = { kImplementation, kServiceNames,kServiceNames+2 } ;

const ServiceRegistrationInfo *getLocalSchemaSupplierServiceInfo()
{ return getRegistrationInfo(&kServiceInfo) ; }

uno::Reference<uno::XInterface> SAL_CALL
instantiateLocalSchemaSupplier(const CreationContext& xContext) {
    return *new LocalSchemaSupplier(xContext) ;
}
//------------------------------------------------------------------------------

static const rtl::OUString kImplementationName(
                            RTL_CONSTASCII_USTRINGPARAM(kImplementation)) ;

rtl::OUString SAL_CALL LocalSchemaSupplier::getName(void) {
    return kImplementationName ;
}
//------------------------------------------------------------------------------

rtl::OUString SAL_CALL LocalSchemaSupplier::getImplementationName(void)
    throw (uno::RuntimeException)
{
    return ServiceInfoHelper(&kServiceInfo).getImplementationName() ;
}
//------------------------------------------------------------------------------

sal_Bool SAL_CALL LocalSchemaSupplier::supportsService(
                                        const rtl::OUString& aServiceName)
    throw (uno::RuntimeException)
{
    return  ServiceInfoHelper(&kServiceInfo).supportsService(aServiceName);
}
//------------------------------------------------------------------------------

uno::Sequence<rtl::OUString> SAL_CALL LocalSchemaSupplier::getServices(void)
{
    return ServiceInfoHelper(&kServiceInfo).getSupportedServiceNames() ;
}
//------------------------------------------------------------------------------

uno::Sequence<rtl::OUString>
SAL_CALL LocalSchemaSupplier::getSupportedServiceNames(void)
    throw (uno::RuntimeException)
{
    return ServiceInfoHelper(&kServiceInfo).getSupportedServiceNames() ;
}

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

} } // configmgr.localbe
<|endoftext|>