//.............................................................................. // // This file is part of the Jancy toolkit. // // Jancy is distributed under the MIT license. // For details see accompanying license.txt file, // the public copy of which is also available at: // http://tibbo.com/downloads/archive/jancy/license.txt // //.............................................................................. // Downcasting or casting to a pointer-to-char (or similar) type represents a // critical threat to security since this makes it possible to overwrite a // pointer validator with random data, thus damaging the validator itself. // To prevent this from happening, Jancy separates all types into two // categories: POD types and non-POD types. Non-POD types are the ones with // meta-data (i.e. classes, safe pointers and aggregates containing other // non-POD types). Casts from and to non-POD types are only allowed when it's // safe to do so (e.g. in upcasts or casts to const POD pointer). // To perform downcasts of non-POD types, the developer must use a dynamic cast // operator. This will translate into a call to the Jancy runtime support // routine, which will return the resulting pointer or 'null' if the requested // downcast is not available. //.............................................................................. struct Vector { double m_x; double m_y; double m_z; } // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . struct EulerAngles { double m_alpha; double m_beta; double m_gamma; } // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . // not a POD in C++, but it is in Jancy (because this contains no meta-info) struct Transform: EulerAngles, Vector { } // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . // non-POD struct TaggedTransform: Transform { char const* m_tag; } //.............................................................................. foo (TaggedTransform* taggedTransform) { // upcasts are always OK, no cast operator is needed Transform* transform = taggedTransform; EulerAngles* angles = taggedTransform; Vector* vector = taggedTransform; // non-POD pointers cannot be cast to POD non-const pointers in order to // prevent damaging meta-data // char* p = (char*) taggedTransform; // <-- error // non-POD pointers can be cast to POD const pointers for reading char const* c = (char const*) taggedTransform; printf ( "foo (taggedTransform = %x)\n" "{\n" " transform = %x;\n" " angles = %x;\n" " vector = %x;\n" " c = %x;\n" " }\n", taggedTransform, transform, angles, vector, c ); } // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . bar (Vector* vector) { // POD types can be cast to each other using the cast operator... Transform* transform1 = (Transform*) vector; // ...even if they aren't related via the base-child hierarchy EulerAngles* angles1 = (EulerAngles*) vector; // non-POD types cannot be cast to (unless it's an upcast, of course) // TaggedTransform const* p = (TaggedTransform const*) vector; // <-- error // dynamic cast operator is available for performing safe dynamic downcasts TaggedTransform* taggedTransform = dynamic (TaggedTransform*) vector; // dynamic cast is also applicable to POD types Transform* transform2 = dynamic (Transform*) vector; EulerAngles* angles2 = dynamic (EulerAngles*) vector; printf ( "bar (vector = %x)\n" "{\n" " transform1 = %x;\n" " transform2 = %x;\n" " angles1 = %x;\n" " angles2 = %x;\n" " taggedTransform = %x;\n" "}\n", vector, transform1, transform2, angles1, angles2, taggedTransform ); } //.............................................................................. // entry point int main () { printf ("main ()\n"); TaggedTransform taggedTransform; foo (taggedTransform); bar (taggedTransform); Transform transform; bar (transform); Vector vector; bar (vector); return 0; } //..............................................................................