summaryrefslogtreecommitdiff
path: root/gnulib-local/lib/moo.h
diff options
context:
space:
mode:
Diffstat (limited to 'gnulib-local/lib/moo.h')
-rw-r--r--gnulib-local/lib/moo.h248
1 files changed, 248 insertions, 0 deletions
diff --git a/gnulib-local/lib/moo.h b/gnulib-local/lib/moo.h
new file mode 100644
index 0000000..93a12b3
--- /dev/null
+++ b/gnulib-local/lib/moo.h
@@ -0,0 +1,248 @@
+/* Minimal object-oriented facilities for C.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2006.
+
+ This program 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.1 of the License, or
+ (at your option) any later version.
+
+ This program 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 program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* This file defines minimal facilities for object-oriented programming
+ style in ANSI C.
+
+ The facilities allow to define classes with single inheritance and
+ "virtual" methods.
+
+ Strict type checking is provided in combination with a C++ compiler:
+ The code compiles in ANSI C with less strict type checking; when
+ compiled with a C++ compiler, strict type checking is done.
+
+ In contrast to [OOC] and [OOPC], this implementation concentrates on the
+ bare essentials of an object-oriented programming style. It does not
+ provide features that are "sometimes useful", but not essential.
+
+ Features:
+ - Combination of fields and methods into a single object. YES
+ - Description of objects of same shape and same behaviour
+ by a class. YES
+ - Single inheritance. YES
+ - Multiple inheritance. NO
+ - Operator overloading (compile-time polymorphism). NO
+ - Virtual methods (run-time polymorphism). YES
+ - Information hiding: private/protected/public. private fields
+ - Static fields and methods. NO
+ - Constructors, destructors. NO
+ - 'new', 'delete'. NO
+ - Exception handling. NO
+ - Garbage collection. NO
+ - Templates / Generic classes with parameters. NO
+ - Namespaces. NO
+ - Hidden 'this' pointer in methods. NO
+ - Declaring or implementing several classes in the same file. NO
+
+ Rationale for NO:
+ - Multiple inheritance is not supported because programming languages
+ like Java and C# prove that they are not necessary. Modern design
+ patterns use delegation more often than composition; this reduces
+ the pressure to use multiple inheritance.
+ Multiple inheritance of "interfaces" (classes without fields) might
+ be considered, though.
+ - Operator overloading is not essential: The programmer can rename
+ methods so that they carry unambiguous method names. This also makes
+ the code more readable.
+ - Virtual methods are supported. Non-virtual methods are not: they
+ constitute an assumption about the possible subclasses which is more
+ often wrong than right. In other words, non-virtual methods are a
+ premature optimization - "the root of all evil", according to
+ Donald E. Knuth.
+ - Information hiding: 'protected' is not supported because it is always
+ inappropriate: it prohibits the use of the delegation design pattern.
+ 'private' is implemented on fields. There are no 'public' fields,
+ since the use of getters/setters allows for overriding in subclasses
+ and is more maintainable (ability to set breakpoints). On the other
+ hand, all methods are 'public'. 'private` methods are not supported
+ because methods with static linkage can be used instead.
+ - Static fields and methods are not supported because normal variables
+ and functions with static or extern linkage can be used instead.
+ - Constructors and destructors are not supported. The programmer can
+ define 'init' and 'do_free' methods himself.
+ - 'new', 'delete' are not supported because they only provide the
+ grouping of two lines of code into a single line of code.
+ - Exception handling is not supported because conventions with a return
+ code can be used instead.
+ - Garbage collection is not supported. Without it the programmer's life
+ is harder, but not impossible. The programmer has to think about
+ ownership of objects.
+ - Templates / Generic classes with parameters are not supported because
+ they are mostly used for container classes, and container classes can
+ be implemented in a simpler object-oriented way that requires only a
+ very limited form of class inheritance.
+ - Namespaces are not implemented, because they can be simulated by a
+ consistent naming convention.
+ - A hidden 'this' pointer in methods is not implemented. It reduces the
+ transparency of the code (because what looks like a variable access can
+ be an access through 'this') and is simply not needed.
+ - Declaring or implementing several classes in the same file is not
+ supported, because it is anyway good practice to define each class in
+ its own .oo.h / .oo.c file.
+
+ Syntax:
+
+ The syntax resembles C++, but deviates from C++ where the C++ syntax is
+ just too braindead.
+
+ A root class is declared in a .oo.h file:
+
+ struct rootfoo
+ {
+ methods:
+ int method1 (rootfoo_t x, ...); ...
+ };
+
+ and in the corresponding .oo.c file:
+
+ struct rootfoo
+ {
+ fields:
+ int field1; ...
+ };
+
+ A subclass is declared in a .oo.h file as well:
+
+ struct subclass : struct rootfoo
+ {
+ methods:
+ int method2 (subclass_t x, ...); ...
+ };
+
+ and in the corresponding .oo.c file:
+
+ struct subclass : struct rootfoo
+ {
+ fields:
+ int field2; ...
+ };
+
+ This defines:
+ - An incomplete type 'struct any_rootfoo_representation' or
+ 'struct subclass_representation', respectively. It denotes the memory
+ occupied by an object of the respective class. The prefix 'any_' is
+ present only for a root class.
+ - A type 'rootfoo_t' or 'subclass_t' that is equivalent to a pointer
+ 'struct any_rootfoo_representation *' or
+ 'struct subclass_representation *', respectively.
+ - A type 'struct rootfoo_implementation' or
+ 'struct subclass_implementation', respectively. It contains a virtual
+ function table for the corresponding type.
+ - A type 'struct rootfoo_representation_header' or
+ 'struct subclass_representation_header', respectively, that defines
+ the part of the memory representation containing the virtual function
+ table pointer.
+ - Functions 'rootfoo_method1 (rootfoo_t x, ...);' ...
+ 'subclass_method1 (subclass_t x, ...);' ...
+ 'subclass_method2 (subclass_t x, ...);' ...
+ that invoke the corresponding methods. They are realized as inline
+ functions if possible.
+ - A declaration of 'rootfoo_typeinfo' or 'subclass_typeinfo', respectively,
+ each being a typeinfo_t instance.
+ - A declaration of 'ROOTFOO_SUPERCLASSES' or 'SUBCLASS_SUPERCLASSES',
+ respectively, each being an initializer for an array of typeinfo_t.
+ - A declaration of 'ROOTFOO_SUPERCLASSES_LENGTH' or
+ 'SUBCLASS_SUPERCLASSES_LENGTH', respectively, each denoting the length
+ of that initializer.
+ - A declaration of 'rootfoo_vtable' or 'subclass_vtable', respectively,
+ being an instance of 'struct rootfoo_implementation' or
+ 'struct subclass_implementation', respectively.
+ - A header file "rootfoo.priv.h" or "subclass.priv.h" that defines the
+ private fields of 'struct rootfoo_representation' or
+ 'struct subclass_representation', respectively.
+
+ A class implementation looks like this, in a .oo.c file:
+
+ struct subclass : struct rootfoo
+ {
+ fields:
+ int field2; ...
+ };
+
+ int subclass::method1 (subclass_t x, ...) { ... } [optional]
+ int subclass::method2 (subclass_t x, ...) { ... }
+ ...
+
+ At the place of the second "struct subclass" definition, the type
+ 'struct subclass_representation' is expanded, and the macro 'super' is
+ defined, referring to the vtable of the superclass. For root classes,
+ 'super' is not defined. Also, 'subclass_typeinfo' is defined.
+
+ Each method subclass::method_i defines the implementation of a method
+ for the particular class. Its C name is subclass__method_i (not to be
+ confused with subclass_method_i, which is the externally visible function
+ that invokes this method).
+
+ Methods that are not defined implicitly inherited from the superclass.
+
+ At the end of the file, 'subclass_vtable' is defined, as well as
+ 'subclass_method1 (subclass_t x, ...);' ...
+ 'subclass_method2 (subclass_t x, ...);' ...
+ if they were not already defined as inline functions in the header file.
+
+ Object representation in memory:
+ - Objects have as their first field, called 'vtable', a pointer to a table
+ to data and function pointers that depend only on the class, not on the
+ object instance.
+ - One of the first fields of the vtable is a pointer to the
+ 'superclasses'; this is a NULL-terminated array of pointers to
+ typeinfo_t objects, starting with the class itself, then its
+ superclass etc.
+
+
+ [OOC] Axel-Tobias Schreiner: Object-oriented programming with ANSI-C. 1993.
+
+ [OOPC] Laurent Deniau: Object Oriented Programming in C. 2001.
+
+ */
+
+#ifndef _MOO_H
+#define _MOO_H
+
+/* Get size_t, abort(). */
+#include <stdlib.h>
+
+/* An object of this type is defined for each class. */
+typedef struct
+{
+ const char *classname;
+} typeinfo_t;
+
+/* IS_INSTANCE (OBJ, ROOTCLASSNAME, CLASSNAME)
+ tests whether an object is instance of a given class, given as lower case
+ class name. */
+#define IS_INSTANCE(obj,rootclassname,classname) \
+ (((const struct rootclassname##_representation_header *)(const struct any_##rootclassname##_representation *)(obj))->vtable->superclasses_length \
+ >= classname##_SUPERCLASSES_LENGTH \
+ && ((const struct rootclassname##_representation_header *)(const struct any_##rootclassname##_representation *)(obj))->vtable->superclasses \
+ [((const struct rootclassname##_representation_header *)(const struct any_##rootclassname##_representation *)(obj))->vtable->superclasses_length \
+ - classname##_SUPERCLASSES_LENGTH] \
+ == & classname##_typeinfo)
+/* This instance test consists of two comparisons. One could even optimize
+ this to a single comparison, by limiting the inheritance depth to a fixed
+ limit, for example, say, depth <= 10. The superclasses list would then
+ need to be stored in reverse order, from the root down to the class itself,
+ and be filled up with NULLs so that the array has length 10. The instance
+ test would look like this:
+ #define IS_INSTANCE(obj,rootclassname,classname) \
+ (((const struct rootclassname##_representation_header *)(const struct any_##rootclassname##_representation *)(obj))->vtable->superclasses \
+ [classname##_SUPERCLASSES_LENGTH - 1] \
+ == & classname##_typeinfo)
+ but the classname##_superclasses_length would no longer be available as a
+ simple sizeof expression. */
+
+#endif /* _MOO_H */