changeset 16384:a8d9ee3766db

* hook-fcn.h: Commit file omitted from previous changeset.
author John W. Eaton <jwe@octave.org>
date Thu, 28 Mar 2013 02:49:07 -0400
parents 3cacd597464d
children a1690c3e93eb
files libinterp/interpfcn/hook-fcn.h
diffstat 1 files changed, 278 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/interpfcn/hook-fcn.h	Thu Mar 28 02:49:07 2013 -0400
@@ -0,0 +1,278 @@
+/*
+
+Copyright (C) 2013 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if !defined (octave_hook_fcn_h)
+#define octave_hook_fcn_h 1
+
+#include <string>
+
+#include "oct-obj.h"
+#include "ov.h"
+#include "ov-fcn-handle.h"
+#include "parse.h"
+#include "variables.h"
+
+class
+base_hook_function
+{
+public:
+
+  friend class hook_function;
+
+  base_hook_function (void) : count (1) { }
+
+  base_hook_function (const base_hook_function&) : count (1) { }
+
+  virtual ~base_hook_function (void) { }
+
+  virtual std::string id (void) { return std::string (); }
+
+  virtual bool is_valid (void) { return false; }
+
+  virtual void eval (const octave_value_list&) { }
+
+protected:
+
+  size_t count;
+};
+
+class
+hook_function
+{
+public:
+
+  hook_function (void)
+  {
+    static base_hook_function nil_rep;
+    rep = &nil_rep;
+    rep->count++;
+  }
+
+  hook_function (const octave_value& f,
+                 const octave_value& d = octave_value ());
+
+  ~hook_function (void)
+  {
+    if (--rep->count == 0)
+      delete rep;
+  }
+
+  hook_function (const hook_function& hf)
+    : rep (hf.rep)
+  {
+    rep->count++;
+  }
+
+  hook_function& operator = (const hook_function& hf)
+  {
+    if (rep != hf.rep)
+      {
+        if (--rep->count == 0)
+          delete rep;
+
+        rep = hf.rep;
+        rep->count++;
+      }
+
+    return *this;
+  }
+
+  std::string id (void) { return rep->id (); }
+
+  bool is_valid (void) { return rep->is_valid (); }
+
+  void eval (const octave_value_list& initial_args)
+  {
+    rep->eval (initial_args);
+  }
+
+private:
+
+  base_hook_function *rep;
+};
+
+class
+named_hook_function : public base_hook_function
+{
+public:
+
+  named_hook_function (const std::string& n, const octave_value& d)
+    : name (n), data (d)
+  { }
+
+  void eval (const octave_value_list& initial_args)
+  {
+    octave_value_list args = initial_args;
+
+    if (data.is_defined ())
+      args.append (data);
+
+    feval (name, args, 0);
+  }
+
+  std::string id (void) { return name; }
+
+  bool is_valid (void) { return is_valid_function (name); }
+
+private:
+
+  std::string name;
+
+  octave_value data;
+};
+
+class
+fcn_handle_hook_function : public base_hook_function
+{
+public:
+
+  fcn_handle_hook_function (const octave_value& fh_arg, const octave_value& d)
+    : ident (), valid (false), fcn_handle (fh_arg), data (d)
+  {
+    octave_fcn_handle *fh = fcn_handle.fcn_handle_value (true);
+
+    if (fh)
+      {
+        valid = true;
+
+        std::ostringstream buf;
+        buf << fh;
+        ident = fh->fcn_name () + ":" + buf.str ();
+      }
+  }
+
+  void eval (const octave_value_list& initial_args)
+  {
+    octave_value_list args = initial_args;
+
+    if (data.is_defined ())
+      args.append (data);
+
+    fcn_handle.do_multi_index_op (0, args);
+  }
+
+  std::string id (void) { return ident; }
+
+  bool is_valid (void) { return valid; }
+
+private:
+
+  std::string ident;
+
+  bool valid;
+
+  octave_value fcn_handle;
+
+  octave_value data;
+};
+
+hook_function::hook_function (const octave_value& f, const octave_value& d)
+{
+  if (f.is_string ())
+    {
+      std::string name = f.string_value ();
+
+      rep = new named_hook_function (name, d);
+    }
+  else if (f.is_function_handle ())
+    {
+      rep = new fcn_handle_hook_function (f, d);
+    }
+  else
+    error ("invalid hook function");
+}
+
+class
+hook_function_list
+{
+public:
+
+  typedef std::map<std::string, hook_function> map_type;
+
+  typedef map_type::iterator iterator;
+  typedef map_type::const_iterator const_iterator;
+
+  hook_function_list (void) : fcn_map () { }
+
+  ~hook_function_list (void) { }
+
+  hook_function_list (const hook_function_list& lst)
+    : fcn_map (lst.fcn_map)
+  { }
+
+  hook_function_list& operator = (const hook_function_list& lst)
+  {
+    if (&lst != this)
+      fcn_map = lst.fcn_map;
+
+    return *this;
+  }
+
+  bool empty (void) const { return fcn_map.empty (); }
+
+  void clear (void) { fcn_map.clear (); }
+
+  void insert (const std::string& id, const hook_function& f)
+  {
+    fcn_map[id] = f;
+  }
+
+  iterator find (const std::string& id)
+  {
+    return fcn_map.find (id);
+  }
+
+  const_iterator find (const std::string& id) const
+  {
+    return fcn_map.find (id);
+  }
+
+  iterator end (void) { return fcn_map.end (); }
+
+  const_iterator end (void) const { return fcn_map.end (); }
+
+  void erase (iterator p) { fcn_map.erase (p); }
+
+  void run (const octave_value_list& initial_args = octave_value_list ())
+  {
+    iterator p = fcn_map.begin ();
+
+    while (p != fcn_map.end ())
+      {
+        std::string hook_fcn_id = p->first;
+        hook_function hook_fcn = p->second;
+
+        iterator q = p++;
+
+        if (hook_fcn.is_valid ())
+          hook_fcn.eval (initial_args);
+        else
+          fcn_map.erase (q);
+      }
+  }
+
+private:
+
+  map_type fcn_map;
+};
+
+#endif