diff libinterp/octave-value/cdef-utils.cc @ 26772:d1419ac09564

split method, package, and property classes from cdef-class file * cdef-method.cc, cdef-method.h, cdef-package.cc, cdef-package.h, cdef-property.cc, cdef-property.h: New files. * libinterp/octave-value/module.mk: Update. * cdef-class.cc, cdef-class.h, cdef-manager.h, cdef-object.cc, cdef-utils.cc, cdef-utils.h, ov-classdef.cc: Adapt as needed for new file arrangement.
author John W. Eaton <jwe@octave.org>
date Fri, 22 Feb 2019 15:28:42 +0000
parents 2f847e3e8d6b
children 568c2ab2782d
line wrap: on
line diff
--- a/libinterp/octave-value/cdef-utils.cc	Fri Feb 22 14:51:29 2019 +0000
+++ b/libinterp/octave-value/cdef-utils.cc	Fri Feb 22 15:28:42 2019 +0000
@@ -25,7 +25,11 @@
 #endif
 
 #include "call-stack.h"
+#include "cdef-class.h"
 #include "cdef-manager.h"
+#include "cdef-method.h"
+#include "cdef-package.h"
+#include "cdef-property.h"
 #include "cdef-utils.h"
 #include "interpreter-private.h"
 #include "ov-classdef.h"
@@ -230,3 +234,115 @@
 
   return get_class_context (dummy_string, dummy_bool);
 }
+
+bool
+check_access (const cdef_class& cls, const octave_value& acc,
+              const std::string& meth_name, const std::string& prop_name,
+              bool is_prop_set)
+{
+  if (acc.is_string ())
+    {
+      std::string acc_s = acc.string_value ();
+
+      if (acc_s == "public")
+        return true;
+
+      cdef_class ctx = get_class_context ();
+
+      // The access is private or protected, this requires a
+      // valid class context.
+
+      if (ctx.ok ())
+        {
+          if (acc_s == "private")
+            return (ctx == cls);
+          else if (acc_s == "protected")
+            {
+              if (is_superclass (cls, ctx))
+                // Calling a protected method in a superclass.
+                return true;
+              else if (is_strict_superclass (ctx, cls))
+                {
+                  // Calling a protected method or property in a derived class.
+                  // This is only allowed if the context class knows about it
+                  // and has access to it.
+
+                  if (! meth_name.empty ())
+                    {
+                      cdef_method m = ctx.find_method (meth_name);
+
+                      if (m.ok ())
+                        return check_access (ctx, m.get ("Access"), meth_name);
+
+                      return false;
+                    }
+                  else if (! prop_name.empty ())
+                    {
+                      cdef_property p = ctx.find_property (prop_name);
+
+                      if (p.ok ())
+                        {
+                          octave_value p_access = p.get (is_prop_set ?
+                                                         "SetAccess" :
+                                                         "GetAccess");
+
+                          return check_access (ctx, p_access, meth_name,
+                                               prop_name, is_prop_set);
+                        }
+
+                      return false;
+                    }
+                  else
+                    panic_impossible ();
+                }
+
+              return false;
+            }
+          else
+            panic_impossible ();
+        }
+    }
+  else if (acc.isobject ())
+    {
+      cdef_class ctx = get_class_context ();
+
+      // At this point, a class context is always required.
+      if (ctx.ok ())
+        {
+          if (ctx == cls)
+            return true;
+
+          cdef_class acc_cls (to_cdef (acc));
+
+          if (is_superclass (acc_cls, ctx))
+            return true;
+        }
+    }
+  else if (acc.iscell ())
+    {
+      Cell acc_c = acc.cell_value ();
+
+      cdef_class ctx = get_class_context ();
+
+      // At this point, a class context is always required.
+
+      if (ctx.ok ())
+        {
+          if (ctx == cls)
+            return true;
+
+          for (int i = 0; i < acc.numel (); i++)
+            {
+              cdef_class acc_cls (to_cdef (acc_c(i)));
+
+              if (is_superclass (acc_cls, ctx))
+                return true;
+            }
+        }
+    }
+  else
+    error ("invalid property/method access in class `%s'",
+           cls.get_name ().c_str ());
+
+  return false;
+}