1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 2012-2021 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING.  If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if ! defined (octave_cdef_package_h)
27 #define octave_cdef_package_h 1
28 
29 #include "octave-config.h"
30 
31 #include <map>
32 #include <set>
33 #include <string>
34 
35 #include "oct-refcount.h"
36 
37 #include "cdef-object.h"
38 #include "ov.h"
39 
40 namespace octave
41 {
42   class interpreter;
43 
44   class
45   cdef_package : public cdef_meta_object
46   {
47     friend class cdef_class;
48 
49   private:
50 
51     class
52     cdef_package_rep : public cdef_meta_object_rep
53     {
54     public:
55 
cdef_package_rep(void)56       cdef_package_rep (void) : cdef_meta_object_rep (), member_count (0) { }
57 
58       cdef_package_rep& operator = (const cdef_package_rep&) = delete;
59 
60       ~cdef_package_rep (void) = default;
61 
copy(void)62       cdef_object_rep * copy (void) const { return new cdef_package_rep (*this); }
63 
is_package(void)64       bool is_package (void) const { return true; }
65 
get_name(void)66       std::string get_name (void) const { return get("Name").string_value (); }
67 
set_name(const std::string & nm)68       void set_name (const std::string& nm) { put ("Name", nm); }
69 
70       void install_class (const cdef_class& cls, const std::string& nm);
71 
72       void install_function (const octave_value& fcn, const std::string& nm);
73 
74       void install_package (const cdef_package& pack, const std::string& nm);
75 
76       Cell get_classes (void) const;
77 
78       Cell get_functions (void) const;
79 
80       Cell get_packages (void) const;
81 
static_count(void)82       octave_idx_type static_count (void) const { return member_count; }
83 
destroy(void)84       void destroy (void)
85       {
86         if (member_count)
87           {
88             m_count++;
89             cdef_package lock (this);
90 
91             member_count = 0;
92             class_map.clear ();
93             package_map.clear ();
94           }
95         else
96           delete this;
97       }
98 
99       octave_value_list
100       meta_subsref (const std::string& type,
101                     const std::list<octave_value_list>& idx, int nargout);
102 
103       void meta_release (void);
104 
meta_accepts_postfix_index(char type)105       bool meta_accepts_postfix_index (char type) const
106       {
107         return (type == '.');
108       }
109 
110       octave_value find (const std::string& nm);
111 
112     private:
113 
114       std::string full_name;
115       std::map<std::string, cdef_class> class_map;
116       std::map<std::string, octave_value> function_map;
117       std::map<std::string, cdef_package> package_map;
118 
119       // The number of registered members in this package (classes, packages).
120       // This only accounts for the members that back-reference to this package.
121       octave_idx_type member_count;
122 
123       typedef std::map<std::string, cdef_class>::iterator class_iterator;
124       typedef std::map<std::string, cdef_class>::const_iterator class_const_iterator;
125       typedef std::map<std::string, octave_value>::iterator function_iterator;
126       typedef std::map<std::string, octave_value>::const_iterator
127         function_const_iterator;
128       typedef std::map<std::string, cdef_package>::iterator package_iterator;
129       typedef std::map<std::string, cdef_package>::const_iterator
130         package_const_iterator;
131 
cdef_package_rep(const cdef_package_rep & p)132       cdef_package_rep (const cdef_package_rep& p)
133         : cdef_meta_object_rep (p), full_name (p.full_name),
134           class_map (p.class_map), function_map (p.function_map),
135           package_map (p.package_map), member_count (p.member_count)
136       { }
137 
wrap(void)138       cdef_package wrap (void)
139       {
140         m_count++;
141         return cdef_package (this);
142       }
143     };
144 
145   public:
146 
cdef_package(void)147     cdef_package (void) : cdef_meta_object () { }
148 
cdef_package(const std::string & nm)149     cdef_package (const std::string& nm)
150       : cdef_meta_object (new cdef_package_rep ())
151     {
152       get_rep ()->set_name (nm);
153     }
154 
cdef_package(const cdef_package & pack)155     cdef_package (const cdef_package& pack) : cdef_meta_object (pack) { }
156 
cdef_package(const cdef_object & obj)157     cdef_package (const cdef_object& obj)
158       : cdef_meta_object (obj)
159     {
160       // This should never happen...
161       if (! is_package ())
162         error ("internal error: invalid assignment from %s to meta.package object",
163                class_name ().c_str ());
164     }
165 
166     cdef_package& operator = (const cdef_package& pack)
167     {
168       cdef_object::operator = (pack);
169 
170       return *this;
171     }
172 
173     ~cdef_package (void) = default;
174 
install_class(const cdef_class & cls,const std::string & nm)175     void install_class (const cdef_class& cls, const std::string& nm)
176     {
177       get_rep ()->install_class (cls, nm);
178     }
179 
install_function(const octave_value & fcn,const std::string & nm)180     void install_function (const octave_value& fcn, const std::string& nm)
181     {
182       get_rep ()->install_function (fcn, nm);
183     }
184 
install_package(const cdef_package & pack,const std::string & nm)185     void install_package (const cdef_package& pack, const std::string& nm)
186     {
187       get_rep ()->install_package (pack, nm);
188     }
189 
get_classes(void)190     Cell get_classes (void) const
191     {
192       return get_rep ()->get_classes ();
193     }
194 
get_functions(void)195     Cell get_functions (void) const
196     {
197       return get_rep ()->get_functions ();
198     }
199 
get_packages(void)200     Cell get_packages (void) const
201     {
202       return get_rep ()->get_packages ();
203     }
204 
get_name(void)205     std::string get_name (void) const { return get_rep ()->get_name (); }
206 
find(const std::string & nm)207     octave_value find (const std::string& nm)
208     {
209       return get_rep ()->find (nm);
210     }
211 
212   private:
213 
get_rep(void)214     cdef_package_rep * get_rep (void)
215     {
216       return dynamic_cast<cdef_package_rep *> (cdef_object::get_rep ());
217     }
218 
get_rep(void)219     const cdef_package_rep * get_rep (void) const
220     {
221       return dynamic_cast<const cdef_package_rep *> (cdef_object::get_rep ());
222     }
223 
224     friend void install_classdef (interpreter& interp);
225   };
226 }
227 
228 #endif
229