diff options
Diffstat (limited to 'gnulib-local/lib/moo.h')
-rw-r--r-- | gnulib-local/lib/moo.h | 248 |
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 */ |