From ed54e4945c9f96583742b93a1ea07b543cb2f042 Mon Sep 17 00:00:00 2001 From: "darin%meer.net" Date: Wed, 3 Dec 2003 07:50:05 +0000 Subject: [PATCH] vtable_hide git-svn-id: svn://10.0.0.236/trunk@149976 18797224-902f-48f8-a5cc-f745e15eee43 --- vtable_hide/string/Makefile | 8 + vtable_hide/string/nsCharTraits.cpp | 3 + vtable_hide/string/nsCharTraits.h | 40 ++ vtable_hide/string/nsStrRef.cpp | 543 ++++++++++++++++++++++++++++ vtable_hide/string/nsStrRef.h | 514 ++++++++++++++++++++++++++ vtable_hide/string/test.cpp | 62 ++++ vtable_hide/string/tt.cc | 28 ++ vtable_hide/string/types.h | 28 ++ vtable_hide/vtable_foo/Makefile | 13 + vtable_hide/vtable_foo/libfoo++.cc | 41 +++ vtable_hide/vtable_foo/libfoo.c | 65 ++++ vtable_hide/vtable_foo/libfoo.h | 18 + vtable_hide/vtable_foo/test | Bin 0 -> 20102 bytes vtable_hide/vtable_foo/test++ | Bin 0 -> 42867 bytes vtable_hide/vtable_foo/test.cc | 17 + vtable_hide/vtable_hide.tar.gz | Bin 0 -> 1493 bytes vtable_hide/vtable_hide/Makefile | 11 + vtable_hide/vtable_hide/inner.h | 12 + vtable_hide/vtable_hide/shim.cc | 98 +++++ vtable_hide/vtable_hide/shim.h | 17 + vtable_hide/vtable_hide/test.cc | 70 ++++ 21 files changed, 1588 insertions(+) create mode 100644 vtable_hide/string/Makefile create mode 100644 vtable_hide/string/nsCharTraits.cpp create mode 100644 vtable_hide/string/nsCharTraits.h create mode 100644 vtable_hide/string/nsStrRef.cpp create mode 100644 vtable_hide/string/nsStrRef.h create mode 100644 vtable_hide/string/test.cpp create mode 100644 vtable_hide/string/tt.cc create mode 100644 vtable_hide/string/types.h create mode 100644 vtable_hide/vtable_foo/Makefile create mode 100644 vtable_hide/vtable_foo/libfoo++.cc create mode 100644 vtable_hide/vtable_foo/libfoo.c create mode 100644 vtable_hide/vtable_foo/libfoo.h create mode 100755 vtable_hide/vtable_foo/test create mode 100755 vtable_hide/vtable_foo/test++ create mode 100644 vtable_hide/vtable_foo/test.cc create mode 100644 vtable_hide/vtable_hide.tar.gz create mode 100644 vtable_hide/vtable_hide/Makefile create mode 100644 vtable_hide/vtable_hide/inner.h create mode 100644 vtable_hide/vtable_hide/shim.cc create mode 100644 vtable_hide/vtable_hide/shim.h create mode 100644 vtable_hide/vtable_hide/test.cc diff --git a/vtable_hide/string/Makefile b/vtable_hide/string/Makefile new file mode 100644 index 00000000000..333f3e40737 --- /dev/null +++ b/vtable_hide/string/Makefile @@ -0,0 +1,8 @@ +CXXFLAGS = -g -Os -Wall -fno-exceptions +#CXXFLAGS = -g -Wall -fno-exceptions +test: test.o nsStrRef.o nsCharTraits.o +nsStrRef.o: nsStrRef.cpp nsStrRef.h nsCharTraits.h types.h Makefile +nsCharTraits: nsCharTraits.cpp nsCharTraits.h types.h Makefile +test.o: test.cpp nsStrRef.h nsCharTraits.h types.h Makefile +clean: + rm -f *.o test diff --git a/vtable_hide/string/nsCharTraits.cpp b/vtable_hide/string/nsCharTraits.cpp new file mode 100644 index 00000000000..b011c1fadf7 --- /dev/null +++ b/vtable_hide/string/nsCharTraits.cpp @@ -0,0 +1,3 @@ +#include "nsCharTraits.h" + +const char *nsCharTraits::empty_string = ""; diff --git a/vtable_hide/string/nsCharTraits.h b/vtable_hide/string/nsCharTraits.h new file mode 100644 index 00000000000..cdde39a54be --- /dev/null +++ b/vtable_hide/string/nsCharTraits.h @@ -0,0 +1,40 @@ +/* vim:set ts=2 sw=2 et cindent: */ +#ifndef nsCharTraits_h__ +#define nsCharTraits_h__ + +#include "types.h" // XXX temporary +#include + +template struct nsCharTraits {}; + +NS_SPECIALIZE_TEMPLATE +struct nsCharTraits +{ + public: + typedef char char_type; + + typedef PRInt32 (* comparator_func) + (const char_type *a, const char_type *b, int n); + + static const char_type *empty_string; + + static PRInt32 case_sensitive_comparator(const char_type *a, + const char_type *b, int n) + { return (PRInt32) memcmp(a, b, n); } + + static PRUint32 length_of(const char_type *data) + { return (PRUint32) ::strlen(data); } + + static void copy(char_type *dest, const char_type *src, PRUint32 len) + { ::memcpy(dest, src, len); } + + static void move(char_type *dest, const char_type *src, PRUint32 len) + { ::memmove(dest, src, len); } + + static const char_type *find_char(const char_type *start, + const char_type *end, + char_type c) + { return (const char_type *) ::memchr(start, c, end - start); } +}; + +#endif // nsCharTraits_h__ diff --git a/vtable_hide/string/nsStrRef.cpp b/vtable_hide/string/nsStrRef.cpp new file mode 100644 index 00000000000..abae158ba92 --- /dev/null +++ b/vtable_hide/string/nsStrRef.cpp @@ -0,0 +1,543 @@ +// vim:set ts=2 sw=2 et cindent: + +#include +#include "nsStrRef.h" + +//----------------------------------------------------------------------------- +// nsStrFragment methods: + +nsStrFragment::char_type +nsStrFragment::Last() const +{ + char_type last; + + if (mLength > 0) + { + last = mData[mLength - 1]; + } + else + { + NS_ERROR("|Last()| on an empty string"); + last = char_type(0); // BOGUS + } + + return last; +} + +PRUint32 +nsStrFragment::CountChar(char_type c) const +{ + PRUint32 result = 0; + + const char_type *start = mData; + const char_type *end = mData + mLength; + + while (start && start != end) + { + start = char_traits::find_char(start, end, c); + if (start) + { + ++result; + ++start; + } + } + return result; +} + +PRInt32 +nsStrFragment::FindChar(char_type c, PRUint32 offset) const +{ + const char_type *p = char_traits::find_char(mData + offset, + mData + mLength, c); + if (p) + return p - mData; + + return -1; // XXX kNotFound +} + +PRBool +nsStrFragment::Equals(const self_type &ref) const +{ + return mLength == ref.mLength && + char_traits::case_sensitive_comparator(mData, ref.mData, mLength) == 0; +} + +PRBool +nsStrFragment::Equals(const self_type &ref, comparator_func comp) const +{ + return mLength == ref.mLength && + comp(mData, ref.mData, mLength) == 0; +} + +PRInt32 +nsStrFragment::CompareTo(const self_type &ref) const +{ + if (mLength > ref.mLength) + return 1; + + if (mLength < ref.mLength) + return -1; + + return char_traits::case_sensitive_comparator(mData, ref.mData, mLength); +} + +PRInt32 +nsStrFragment::CompareTo(const self_type &ref, comparator_func comp) const +{ + if (mLength > ref.mLength) + return 1; + + if (mLength < ref.mLength) + return -1; + + return comp(mData, ref.mData, mLength); +} + +//----------------------------------------------------------------------------- +// reference counted buffer methods: + +inline void StrIncrementRef(void *data) +{ + PRInt32 *buf = ((PRInt32 *) data) - 1; + PR_AtomicIncrement(buf); +} + +inline void StrDecrementRef(void *data) +{ + PRInt32 *buf = ((PRInt32 *) data) - 1; + if (PR_AtomicDecrement(buf) == 0) + { + printf(">>> calling free on %p [%s]\n", data, (const char *) data); + free(buf); + } +} + +inline void *StrAllocateSharedBuf(size_t n) +{ + PRInt32 *buf = (PRInt32 *) malloc(n + sizeof(PRUint32)); + if (buf) + { + buf[0] = 1; + buf++; + } + return buf; +} + +//----------------------------------------------------------------------------- +// nsStrRef methods: + +nsStrRef::~nsStrRef() +{ + if (mData) + ReleaseData(); +} + +void +nsStrRef::ReleaseData() +{ + NS_ASSERTION(mData, "should not call ReleaseData with null mData"); + + if (!(mFlags & F_DEPEND)) + { + if (mFlags & F_SHARED) + { + StrDecrementRef(mData); + } + else + { + printf(">>> calling free on %p [%s]\n", mData, mData); + free(mData); + } + } +} + +void +nsStrRef::Adopt(char_type *data, PRUint32 dataLen) +{ + if (mData) + ReleaseData(); + + if (dataLen == PR_UINT32_MAX) + dataLen = char_traits::length_of(data); + + mData = data; + mLength = dataLen; + mFlags = 0; +} + +void +nsStrRef::Assign(const char_type *data, PRUint32 dataLen) +{ + if (dataLen == PR_UINT32_MAX) + dataLen = char_traits::length_of(data); + + // do not release mData until we've created the new buffer. this allows for + // the case where data might reference part of mData. + + char_type *buf = + (char_type *) StrAllocateSharedBuf((dataLen + 1) * sizeof(char_type)); + if (buf) + { + char_traits::copy(buf, data, dataLen); + buf[dataLen] = 0; + + // okay, now we can safely release mData + if (mData) + ReleaseData(); + + mData = buf; + mLength = dataLen; + mFlags = F_SHARED; + + printf(">>> new buffer at %p [%s]\n", mData, mData); + } +} + +void +nsStrRef::Assign(const self_type &ref) +{ + // self-assign is a no-op + if (this == &ref) + return; + + if (ref.mFlags & F_SHARED) + { + // since ref.mData is reference counted, we can safely release our mData. + ReleaseData(); + + mData = ref.mData; + mLength = ref.mLength; + mFlags = ref.mFlags; + + StrIncrementRef(mData); + } + else + Assign(ref.mData, ref.mLength); +} + +void +nsStrRef::Assign(const fragment_tuple_type &tuple) +{ + PRUint32 len = tuple.Length(); + + char_type *buf = + (char_type *) StrAllocateSharedBuf((len + 1) * sizeof(char_type)); + if (buf) + { + tuple.WriteTo(buf, len); + buf[len] = char_type(0); + + ReleaseData(); + + mData = buf; + mLength = len; + mFlags = nsStrRef::F_SHARED; + } +} + +void +nsStrRef::SetIsVoid(PRBool val) +{ + if (val) + { + ReleaseData(); + + mData = NS_CONST_CAST(char_type *, char_traits::empty_string); + mLength = 0; + mFlags = F_DEPEND | F_ISVOID; + } + else + { + mFlags &= ~F_ISVOID; + } +} + +//----------------------------------------------------------------------------- +// nsStrFragmentTuple methods: + +PRUint32 +nsStrFragmentTuple::Length() const +{ + // + // fragments are enumerated right to left + // + PRUint32 len = mFragB.Length(); + if (mHead) + len += mHead->Length(); + else + len += mFragA.Length(); + return len; +} + +void +nsStrFragmentTuple::WriteTo(char_type *buf, PRUint32 end) const +{ + // we need to write out data into buf, ending at end. so our data + // needs to preceed |end| exactly. we trust that the buffer was + // properly sized! + + char_traits::copy(buf + end - mFragB.Length(), mFragB.get(), mFragB.Length()); + + end -= mFragB.Length(); + + if (mHead) + mHead->WriteTo(buf, end); + else + char_traits::copy(buf + end - mFragA.Length(), mFragA.get(), mFragA.Length()); +} + +PRBool +nsStrFragmentTuple::IsDependentOn(const char_type *start, + const char_type *end) const +{ + // + // fragments are enumerated right to left + // + PRBool dependent = mFragB.IsDependentOn(start, end); + if (!dependent) + { + if (mHead) + dependent = mHead->IsDependentOn(start, end); + else + dependent = mFragA.IsDependentOn(start ,end); + } + return dependent; +} + +//----------------------------------------------------------------------------- +// nsStrBuf methods: + +void +nsStrBuf::Assign(const char_type *data, PRUint32 dataLen) +{ + if (dataLen == PR_UINT32_MAX) + dataLen = char_traits::length_of(data); + + Assign(nsStrFragment(data, dataLen)); +} + +void +nsStrBuf::Assign(const ref_type &ref) +{ + // self-assign is a no-op + if (this == &ref) + return; + + // avoid copying if possible... + + // XXX for some strange reason GCC 3.2.2 requires this cast + if (NS_STATIC_CAST(const self_type &, ref).mFlags & F_SHARED) + nsStrRef::Assign(ref); + else + Assign(NS_STATIC_CAST(const fragment_type &, ref)); +} + +void +nsStrBuf::Assign(const fragment_type &frag) +{ + // self-assign is a no-op + if (this == &frag) + return; + + PRUint32 len = frag.Length(); + + // check if the fragment depends on mData + if (frag.IsDependentOn(mData, mData + mLength)) + { + nsStrAutoBuf temp(frag); + Assign(temp); + return; + } + + if (EnsureCapacity(len + 1, PR_FALSE)) + { + char_traits::copy(mData, frag.get(), len); + mData[len] = char_type(0); + mLength = len; + } +} + +void +nsStrBuf::Assign(const fragment_tuple_type &tuple) +{ + PRUint32 len = tuple.Length(); + + printf("+++ %s [f=0x%x c=%u len=%u]\n", __PRETTY_FUNCTION__, mFlags, mCapacity, len); + + // check if the fragment tuple depends on mData + if (tuple.IsDependentOn(mData, mData + mLength)) + { + nsStrAutoBuf temp(tuple); + Assign(temp); + return; + } + + if (EnsureCapacity(len + 1, PR_FALSE)) + { + tuple.WriteTo(mData, len); + mData[len] = char_type(0); + mLength = len; + } +} + +void +nsStrBuf::Replace(PRUint32 cutOffset, PRUint32 cutLength, const char_type *data, PRUint32 dataLen) +{ + if (dataLen == PR_UINT32_MAX) + dataLen = char_traits::length_of(data); + + Replace(cutOffset, cutLength, nsStrFragment(data, dataLen)); +} + +void +nsStrBuf::Replace(PRUint32 cutOffset, PRUint32 cutLength, + const fragment_type &frag) +{ + // check if the fragment depends on mData + if (frag.IsDependentOn(mData, mData + mLength)) + { + nsStrAutoBuf temp(frag); + Replace(cutOffset, cutLength, temp); + return; + } + + PRUint32 fragLen = frag.Length(); + + PRUint32 newLen = mLength - cutLength + fragLen; + if (EnsureCapacity(newLen + 1, PR_TRUE)) + { + // make space for new substring. may require that we move part + // of the existing string. + if (fragLen != cutLength && cutOffset + cutLength < mLength) + { + PRUint32 from = cutOffset + cutLength; + PRUint32 fromLen = mLength - from; + PRUint32 to = cutOffset + fragLen; + char_traits::move(mData + to, mData + from, fromLen); + } + + if (fragLen) + char_traits::copy(mData + cutOffset, frag.get(), fragLen); + + mData[newLen] = char_type(0); + mLength = newLen; + } +} + +void +nsStrBuf::Replace(PRUint32 cutOffset, PRUint32 cutLength, + const fragment_tuple_type &tuple) +{ + // check if the fragment depends on mData + if (tuple.IsDependentOn(mData, mData + mLength)) + { + nsStrAutoBuf temp(tuple); + Replace(cutOffset, cutLength, temp); + return; + } + + PRUint32 tupleLen = tuple.Length(); + + PRUint32 newLen = mLength - cutLength + tupleLen; + if (EnsureCapacity(newLen + 1, PR_TRUE)) + { + // make space for new substring. may require that we move part + // of the existing string. + if (tupleLen != cutLength && cutOffset + cutLength < mLength) + { + PRUint32 from = cutOffset + cutLength; + PRUint32 fromLen = mLength - from; + PRUint32 to = cutOffset + tupleLen; + char_traits::move(mData + to, mData + from, fromLen); + } + + if (tupleLen) + tuple.WriteTo(mData + cutOffset, tupleLen); + + mData[newLen] = char_type(0); + mLength = newLen; + } +} + +void +nsStrBuf::SetLength(PRUint32 len) +{ + EnsureCapacity(len + 1, PR_TRUE); + mData[len] = 0; + mLength = len; +} + +PRBool +nsStrBuf::EnsureCapacity(PRUint32 capacity, PRBool preserveData) +{ + // EnsureCapacity is called in preparation for writing. So, if we have a + // reference to a shared buffer, then we need to go ahead and drop that + // shared reference. + + if (mFlags & F_SHARED) + { + char *buf = (char *) malloc(capacity * sizeof(char_type)); + if (!buf) + return PR_FALSE; + + if (preserveData) + { + PRUint32 maxLength = capacity - 1; + if (mLength > maxLength) + mLength = maxLength; + char_traits::copy(buf, mData, mLength); + buf[mLength] = char_type(0); + } + + ReleaseData(); + + mData = buf; + mCapacity = capacity; + mFlags = F_CAPACITYSET; + } + else + { + if (!(mFlags & F_CAPACITYSET)) + { + // maybe someone called nsStrRef::Adopt + mCapacity = mLength + 1; + } + + if (capacity > mCapacity) + { + printf(">>> increasing capacity\n"); + + // use doubling algorithm when forced to increase available capacity + PRUint32 temp = mCapacity; + while (temp < capacity) + temp <<= 1; + capacity = temp; + + char *buf; + if (mFlags & F_DEPEND) + { + // we cannot realloc the existing buffer because we do not own it. + buf = (char *) malloc(capacity * sizeof(char_type)); + if (!buf) + return PR_FALSE; + + if (preserveData) + char_traits::copy(buf, mData, mLength + 1); + + mFlags &= ~F_DEPEND; + } + else + { + buf = (char *) realloc(mData, capacity * sizeof(char_type)); + if (!buf) + return PR_FALSE; + } + + mData = buf; + mCapacity = capacity; + + printf(" new capacity = %u\n", mCapacity); + } + } + return PR_TRUE; +} diff --git a/vtable_hide/string/nsStrRef.h b/vtable_hide/string/nsStrRef.h new file mode 100644 index 00000000000..af1f956c8e5 --- /dev/null +++ b/vtable_hide/string/nsStrRef.h @@ -0,0 +1,514 @@ +// vim:set ts=2 sw=2 et cindent: +#ifndef nsStrRef_h__ +#define nsStrRef_h__ + +#include "types.h" // XXX temporary +#include "nsCharTraits.h" + +class nsStrRef; +class nsStrDependentRef; +class nsStrAutoRef; +class nsStrFragment; +class nsStrFragmentTuple; + +//----------------------------------------------------------------------------- + +// container for an immutable string fragment, which is not necessarily +// null-terminated. + +class nsStrFragment +{ + public: + typedef NS_CHAR char_type; + typedef nsStrFragment self_type; + typedef nsCharTraits char_traits; + typedef char_traits::comparator_func comparator_func; + + nsStrFragment() + : mData(NS_CONST_CAST(char_type *, char_traits::empty_string)) + , mLength(0) {} + + nsStrFragment(const char_type *data, PRUint32 length) + : mData(NS_CONST_CAST(char_type *, data)), mLength(length) {} + + // default copy constructor is appropriate + + const char_type *get() const { return mData; } + + PRUint32 Length() const { return mLength; } + + PRBool IsEmpty() const { return mLength == 0; } + + // character access + + char_type First() const { return mData[0]; } + char_type Last() const; + + PRUint32 CountChar(char_type c) const; + + PRInt32 FindChar(char_type c, PRUint32 offset = 0) const; + + // comparison + + PRBool Equals(const self_type &ref) const; + PRBool Equals(const self_type &ref, comparator_func c) const; + + PRInt32 CompareTo(const self_type &ref) const; + PRInt32 CompareTo(const self_type &ref, comparator_func c) const; + + // returns true if this fragment is dependent on (i.e., overlapping with) + // the given char sequence. + PRBool IsDependentOn(const char_type *start, const char_type *end) const + { return (mData >= start) && (mData < end); } + + // XXX more functions... + + protected: + + // helper constructor for subclasses + nsStrFragment(char_type *data) + : mData(data) {} + nsStrFragment(char_type *data, PRUint32 length) + : mData(data), mLength(length) {} + + // mData is non-const in this class since subclasses may manipulate it. + char_type *mData; + PRUint32 mLength; +}; + +//----------------------------------------------------------------------------- + +// container for a null-terminated, immutable string of characters. since the +// string data is immutable, this class permits sharing of the underyling +// string data between threads. assignment between nsStrRef instances is +// optimized to avoid copying. + +class nsStrRef : public nsStrFragment +{ + public: + typedef nsStrRef self_type; + typedef nsStrFragment fragment_type; + typedef nsStrFragmentTuple fragment_tuple_type; + + ~nsStrRef(); + + // constructors + + nsStrRef() + : nsStrFragment(), mFlags(F_DEPEND) {} + + nsStrRef(const char_type *data, PRUint32 dataLen = PR_UINT32_MAX) + : nsStrFragment(nsnull) { Assign(data, dataLen); } + + explicit + nsStrRef(const self_type &ref) + : nsStrFragment(nsnull) { Assign(ref); } + + explicit + nsStrRef(const fragment_type &frag) + : nsStrFragment(nsnull) { Assign(frag); } + + explicit + nsStrRef(const fragment_tuple_type &tuple) + : nsStrFragment(nsnull) { Assign(tuple); } + + // adopt given null-terminated raw string + + void Adopt(char_type *data, PRUint32 dataLen = PR_UINT32_MAX); + + // assign into string reference + + void Assign(const char_type c) + { Assign(&c, 1); } + + void Assign(const char_type *data, PRUint32 dataLen = PR_UINT32_MAX); + + void Assign(const self_type &ref); + + void Assign(const fragment_type &frag) + { Assign(frag.get(), frag.Length()); } + + void Assign(const fragment_tuple_type &tuple); + + // assignment operators + + self_type &operator=(const self_type &ref) + { Assign(ref); return *this; } + + self_type &operator=(const fragment_type &frag) + { Assign(frag); return *this; } + + self_type &operator=(const fragment_tuple_type &tuple) + { Assign(tuple); return *this; } + + // support for voiding a string + + PRBool IsVoid() const { return mFlags & F_ISVOID; } + void SetIsVoid(PRBool); + + protected: + + // helper constructor for subclasses + nsStrRef(char_type *data, PRUint32 length, PRUint32 flags) + : nsStrFragment(data, length), mFlags(flags) {} + + void ReleaseData(); + + enum + { + F_DEPEND = 0x1, // if set, then we do not own mData + F_SHARED = 0x2, // if set, then mData can be shared + F_ISVOID = 0x4 // if set, then the string is void + }; + PRUint32 mFlags; + PRUint32 mCapacity; +}; + +//----------------------------------------------------------------------------- + +// container for a null-terminated, immutable string of characters that is +// not owned by the container. this class is designed to be used as a wrapper +// around raw string literals so as to avoid copying the string literal. + +class nsStrDependentRef : public nsStrRef +{ + public: + typedef nsStrDependentRef self_type; + + // constructors + + explicit + nsStrDependentRef(const char_type *data) + { mFlags = F_DEPEND; Rebind(data); } + + nsStrDependentRef(const char_type *data, PRUint32 length) + { mFlags = F_DEPEND; Rebind(data, length); } + + nsStrDependentRef(const char_type *start, const char_type *end) + { mFlags = F_DEPEND; Rebind(start, end); } + + void Rebind(const char_type *data) + { Rebind(data, char_traits::length_of(data)); } + + void Rebind(const char_type *data, PRUint32 length) + { + NS_ASSERTION(data, + "nsStrDependentRef must wrap a non-NULL buffer"); + NS_ASSERTION(!data[length], + "nsStrDependentRef must wrap only null-terminated buffer"); + mData = NS_CONST_CAST(char_type *, data); + mLength = length; + } + + void Rebind(const char_type *start, const char_type *end) + { Rebind(start, end - start); } + + private: + // NOT TO BE IMPLEMENTED + void operator=(const self_type &); +}; + +#define NS_STR_NAMED_LITERAL(name, val) nsStrDependentRef name(val, sizeof(val)-1) +#define NS_STR_LITERAL(val) nsStrDependentRef(val, sizeof(val)-1) + +//----------------------------------------------------------------------------- + +// substring helpers + +inline const nsStrFragment +Substring(const nsStrFragment &frag, PRUint32 offset, PRUint32 length) +{ + return nsStrFragment(frag.get() + offset, length); +} + +inline const nsStrFragment +Substring(const NS_CHAR *data, PRUint32 length) +{ + return nsStrFragment(data, length); +} + +inline const nsStrFragment +Substring(const NS_CHAR *start, const NS_CHAR *end) +{ + return nsStrFragment(start, end - start); +} + +inline const nsStrFragment +StringHead(const nsStrFragment &frag, PRUint32 length) +{ + return nsStrFragment(frag.get(), length); +} + +inline const nsStrFragment +StringTail(const nsStrFragment &frag, PRUint32 length) +{ + return nsStrFragment(frag.get() + frag.Length() - length, length); +} + +//----------------------------------------------------------------------------- + +// the fragment tuple represents a concatenation of string fragments. +class nsStrFragmentTuple +{ + public: + typedef NS_CHAR char_type; + typedef nsCharTraits char_traits; + + nsStrFragmentTuple(const nsStrFragment &a, const nsStrFragment &b) + : mHead(nsnull) + , mFragA(a) + , mFragB(b) {} + + nsStrFragmentTuple(const nsStrFragmentTuple &head, const nsStrFragment &frag) + : mHead(&head) + , mFragA(frag) // this fragment is ignored when head != null + , mFragB(frag) + {} + + // computes the aggregate string length + PRUint32 Length() const; + + // writes the aggregate string to the given buffer. bufLen is assumed to + // be equal to or greater than the value returned by the Length() method. + // the string written to |buf| is not null-terminated. + void WriteTo(char_type *buf, PRUint32 bufLen) const; + + // returns true if this tuple is dependent on (i.e., overlapping with) + // the given char sequence. + PRBool IsDependentOn(const char_type *start, const char_type *end) const; + + protected: + const nsStrFragmentTuple *mHead; + const nsStrFragment &mFragA; + const nsStrFragment &mFragB; +}; + +inline const nsStrFragmentTuple +operator+(const nsStrFragment &a, const nsStrFragment &b) +{ + return nsStrFragmentTuple(a, b); +} + +inline const nsStrFragmentTuple +operator+(const nsStrFragmentTuple &a, const nsStrFragment &b) +{ + return nsStrFragmentTuple(a, b); +} + +//----------------------------------------------------------------------------- + +#if 0 + +// a container for a null-terminated, mutable string buffer. this class +// provides high-level string editing functions. + +class nsStrBuf : public nsStrRef +{ + public: + typedef nsStrRef ref_type; + typedef nsStrBuf self_type; + + // constructors + + nsStrBuf() + : nsStrRef(), mCapacity(0) {} + + explicit + nsStrBuf(const char_type *data) + : nsStrRef(), mCapacity(0) { Assign(data); } + + nsStrBuf(const char_type *data, PRUint32 dataLen) + : nsStrRef(), mCapacity(0) { Assign(data, dataLen); } + + explicit + nsStrBuf(const ref_type &ref) + : nsStrRef(), mCapacity(0) { Assign(ref); } + + explicit + nsStrBuf(const fragment_type &frag) + : nsStrRef(), mCapacity(0) { Assign(frag); } + + explicit + nsStrBuf(const fragment_tuple_type &tuple) + : nsStrRef(), mCapacity(0) { Assign(tuple); } + + // assign into string buffer + + void Assign(const char_type c) + { Assign(&c, 1); } + + void Assign(const char_type *data, PRUint32 dataLen = PR_UINT32_MAX); + + void Assign(const ref_type &ref); + + void Assign(const fragment_type &frag); + + void Assign(const fragment_tuple_type &tuple); + + // assignment operators + + self_type &operator=(const self_type &buf) + { Assign(buf); return *this; } + + self_type &operator=(const ref_type &ref) + { Assign(ref); return *this; } + + self_type &operator=(const fragment_type &frag) + { Assign(frag); return *this; } + + self_type &operator=(const fragment_tuple_type &tuple) + { Assign(tuple); return *this; } + + // replace part of string buffer + + void Replace(PRUint32 cutOffset, PRUint32 cutLength, char_type c) + { Replace(cutOffset, cutLength, &c, 1); } + + void Replace(PRUint32 cutOffset, PRUint32 cutLength, + const char_type *data, PRUint32 dataLen = PR_UINT32_MAX); + + void Replace(PRUint32 cutOffset, PRUint32 cutLength, + const fragment_type &frag); + + void Replace(PRUint32 cutOffset, PRUint32 cutLength, + const fragment_tuple_type &tuple); + + // append to string buffer + + void Append(char_type c) + { Replace(mLength, 0, &c, 1); } + + void Append(const char_type *data, PRUint32 dataLen = PR_UINT32_MAX) + { Replace(mLength, 0, data, dataLen); } + + void Append(const fragment_type &frag) + { Replace(mLength, 0, frag); } + + void Append(const fragment_tuple_type &tuple) + { Replace(mLength, 0, tuple); } + + self_type &operator+=(char_type c) + { Append(c); return *this; } + + self_type &operator+=(const char_type *data) + { Append(data); return *this; } + + self_type &operator+=(const fragment_type &frag) + { Append(frag); return *this; } + + self_type &operator+=(const fragment_tuple_type &tuple) + { Append(tuple); return *this; } + + // insert into string buffer + + void Insert(PRUint32 offset, char_type c) + { Replace(offset, 0, &c, 1); } + + void Insert(PRUint32 offset, const char_type *data, + PRUint32 dataLen = PR_UINT32_MAX) + { Replace(offset, 0, data, dataLen); } + + void Insert(PRUint32 offset, const fragment_type &frag) + { Replace(offset, 0, frag); } + + void Insert(PRUint32 offset, const fragment_tuple_type &tuple) + { Replace(offset, 0, tuple); } + + // cut out section of string buffer + + void Cut(PRUint32 cutOffset, PRUint32 cutLength) + { Replace(cutOffset, cutLength, + nsStrFragment(char_traits::empty_string, PRUint32(0))); } + + void SetCapacity(PRUint32 capacity) + { EnsureCapacity(capacity, PR_TRUE); } + + void SetLength(PRUint32 length); + + void Truncate(PRUint32 length) + { + NS_ASSERTION(length <= mLength, "|Trunate()| cannot make a string longer"); + SetLength(length); + } + + protected: + + // helper constructor for subclasses + nsStrBuf(char_type *data, PRUint32 length, PRUint32 flags, PRUint32 capacity) + : nsStrRef(data, length, flags), mCapacity(capacity) {} + + PRBool EnsureCapacity(PRUint32 capacity, PRBool preserveData); + + // additional values for mFlags + enum + { + F_CAPACITYSET = 0x10 // if set, then mCapacity applies to mData + }; + + // holds the current size of the buffer at mData + PRUint32 mCapacity; +}; +#endif + +//----------------------------------------------------------------------------- + +// subclass of nsStrBuf that makes use of fixed storage for small strings. +// this class is designed to be allocated on the stack. + +class nsStrAutoBuf : public nsStrBuf +{ + public: + typedef nsStrRef ref_type; + typedef nsStrBuf self_type; + + // constructors + + nsStrAutoBuf() + : nsStrBuf(mFixed, 0, F_DEPEND | F_CAPACITYSET, sizeof(mFixed)) + { mFixed[0] = char_type(0); } + + explicit + nsStrAutoBuf(const char_type *data) + : nsStrBuf(mFixed, 0, F_DEPEND | F_CAPACITYSET, sizeof(mFixed)) + { Assign(data); } + + nsStrAutoBuf(const char_type *data, PRUint32 dataLen) + : nsStrBuf(mFixed, 0, F_DEPEND | F_CAPACITYSET, sizeof(mFixed)) + { Assign(data, dataLen); } + + explicit + nsStrAutoBuf(const ref_type &ref) + : nsStrBuf(mFixed, 0, F_DEPEND | F_CAPACITYSET, sizeof(mFixed)) + { Assign(ref); } + + explicit + nsStrAutoBuf(const fragment_type &frag) + : nsStrBuf(mFixed, 0, F_DEPEND | F_CAPACITYSET, sizeof(mFixed)) + { Assign(frag); } + + explicit + nsStrAutoBuf(const fragment_tuple_type &tuple) + : nsStrBuf(mFixed, 0, F_DEPEND | F_CAPACITYSET, sizeof(mFixed)) + { Assign(tuple); } + + // assign + + self_type &operator=(const self_type &buf) + { Assign(buf); return *this; } + + self_type &operator=(const ref_type &ref) + { Assign(ref); return *this; } + + self_type &operator=(const fragment_type &frag) + { Assign(frag); return *this; } + + self_type &operator=(const fragment_tuple_type &tuple) + { Assign(tuple); return *this; } + + protected: + char_type mFixed[64]; // this is in use if F_DEPEND is set. +}; + +//----------------------------------------------------------------------------- + +#endif // nsStrRef_h__ diff --git a/vtable_hide/string/test.cpp b/vtable_hide/string/test.cpp new file mode 100644 index 00000000000..94c96637ed2 --- /dev/null +++ b/vtable_hide/string/test.cpp @@ -0,0 +1,62 @@ +#include +#include "nsStrRef.h" + +void func(const char *p) +{ + printf("--%s--\n", p); +} + +void concat_and_print(const nsStrRef &a, const nsStrRef &b) +{ + nsStrRef r(a + b); + printf("%s\n", r.get()); +} + +int main() +{ + nsStrRef a("howdy"); + NS_STR_NAMED_LITERAL(b, "howdy"); + printf("%s %s %d\n", a.get(), b.get(), a.Equals(b)); + + nsStrRef d; + d.Assign('x'); + printf("%s\n", d.get()); + + nsStrRef r(Substring(a, 1, 3)); + printf("%s\n", r.get()); + + nsStrDependentRef c("foopity"); + r = a + nsStrRef("/balance/") + b + c + nsStrDependentRef("bob"); + printf("%s\n", r.get()); + + func(nsStrRef("xyz").get()); + + nsStrDependentRef aa("foo"), bb("bar"); + concat_and_print(aa, bb); + + nsStrAutoBuf a_buf; + + a_buf = Substring(aa, 1, 2) + r; + printf("1:%s\n", a_buf.get()); + + a_buf = NS_STR_LITERAL("$w$") + a_buf + NS_STR_LITERAL("$you$"); + printf("2:%s\n", a_buf.get()); + + a_buf.Append(NS_STR_LITERAL("--") + r + NS_STR_LITERAL("--") + r); + printf("3:%s\n", a_buf.get()); + + a_buf.Insert(10, "((xyz))"); + printf("4:%s\n", a_buf.get()); + +/* + nsStrRef &a_ref = a_buf; + a_ref.Assign(NS_STR_LITERAL("one day on the road")); +*/ + + a_buf += aa + NS_STR_LITERAL("[[ ") + a_buf + NS_STR_LITERAL(" ]]") + c; + printf("5:%s\n", a_buf.get()); + + a_buf.Replace(0, 5, a); + printf("6:%s\n", a_buf.get()); + return 0; +} diff --git a/vtable_hide/string/tt.cc b/vtable_hide/string/tt.cc new file mode 100644 index 00000000000..9718000e7fc --- /dev/null +++ b/vtable_hide/string/tt.cc @@ -0,0 +1,28 @@ + +class A +{ +public: + A(int x, int y, int z) + : _x(x), _y(y), _z(z) {} +private: + int _x, _y, _z; +}; + +class B +{ +public: + B(int x, int y, int z) + { _x = x; + _z = z; + _y = y; + } +private: + int _x, _y, _z; +}; + +int main() +{ + A a(1, 2, 3); + B b(1, 2, 3); + return 0; +} diff --git a/vtable_hide/string/types.h b/vtable_hide/string/types.h new file mode 100644 index 00000000000..14d8f684c06 --- /dev/null +++ b/vtable_hide/string/types.h @@ -0,0 +1,28 @@ +/* vim:set ts=2 sw=2 et cindent: */ + +#ifndef str_types_h__ +#define str_types_h__ + +/* -------------------------------------------------------------------------- */ +#include +typedef int PRInt32; +typedef unsigned int PRUint32; +typedef unsigned int PRBool; +#define PR_TRUE 1 +#define PR_FALSE 0 +typedef char NS_CHAR; +#define NS_CHAR_SIZE sizeof(NS_CHAR) +#define NS_COM +#define NS_ASSERTION(x, s) if (!(x)) printf("### ASSERTION [%s]: %s\n", # x, s) +#define NS_ERROR(s) printf("### ERROR: %s\n", s) +#define PR_MIN(x,y) ((x) < (y) ? (x) : (y)) +#define NS_CONST_CAST(x,y) const_cast(y) +#define NS_STATIC_CAST(x,y) static_cast(y) +#define nsnull 0 +#define NS_SPECIALIZE_TEMPLATE template <> +#define PR_AtomicIncrement(x) (++(*(x))) +#define PR_AtomicDecrement(x) (--(*(x))) +#define PR_UINT32_MAX PRUint32(-1) +/* -------------------------------------------------------------------------- */ + +#endif diff --git a/vtable_hide/vtable_foo/Makefile b/vtable_hide/vtable_foo/Makefile new file mode 100644 index 00000000000..d2c48c64992 --- /dev/null +++ b/vtable_hide/vtable_foo/Makefile @@ -0,0 +1,13 @@ +# vim:set ts=8 sw=8 noet: + +all: libfoo.so libfoo++.so test test++ +libfoo.so: libfoo.c Makefile + gcc -g -fPIC -shared $< -o $@ +libfoo++.so: libfoo++.cc Makefile + gcc -g -fPIC -fno-exceptions -shared $< -o $@ -lsupc++ +test: test.cc libfoo.h Makefile + gcc -g -fno-exceptions $< -o $@ -L. -lfoo -lsupc++ +test++: test.cc libfoo.h Makefile + gcc -g -fno-exceptions $< -o $@ -L. -lfoo++ -lsupc++ +clean: + rm -f test libfoo.so diff --git a/vtable_hide/vtable_foo/libfoo++.cc b/vtable_hide/vtable_foo/libfoo++.cc new file mode 100644 index 00000000000..52ec986c2e8 --- /dev/null +++ b/vtable_hide/vtable_foo/libfoo++.cc @@ -0,0 +1,41 @@ +#include +#include + +class Foo +{ +public: + static Foo sFoo; + + Foo() {} + virtual ~Foo() + { + printf("~Foo [this=%p]\n", this); + } + virtual int meth1() + { + if ( *((int *) this) == *((int *) &sFoo) ) + printf("vptrs match\n"); + printf("meth1 [this=%p]\n", this); + } + virtual int meth2(const char *s) + { printf("meth2 [this=%p s=\"%s\"]\n", this, s); } + virtual int meth3(int x, const char *s) + { printf("meth3 [this=%p x=%d s=\"%s\"]\n", this, x, s); } + virtual int meth4(int x, const char *s, char c) + { printf("meth4 [this=%p x=%d s=\"%s\" c=%c]\n", this, x, s, c); } +}; + +Foo Foo::sFoo; + +extern "C" Foo * +CreateFoo() +{ +/* + Foo *f = (Foo *) malloc(sizeof(Foo)); + + new (f) Foo(); + + return f; +*/ + return new Foo(); +} diff --git a/vtable_hide/vtable_foo/libfoo.c b/vtable_hide/vtable_foo/libfoo.c new file mode 100644 index 00000000000..802c45b87d5 --- /dev/null +++ b/vtable_hide/vtable_foo/libfoo.c @@ -0,0 +1,65 @@ +struct Foo; +struct FooMethods; + +struct FooMethods +{ + void (* dtor)(struct Foo * const); + int (* meth1)(struct Foo * const); + int (* meth2)(struct Foo *, const char *); + int (* meth3)(struct Foo *, int, const char *); + int (* meth4)(struct Foo *, int, const char *, char); + void (* dummy1)(struct Foo *); + void (* dummy2)(struct Foo *); +}; + +struct Foo +{ + struct FooMethods *vptr; + int x; +}; + +static void foo_dtor(struct Foo * const self) +{ + printf("foo_dtor [self=%p]\n", self); +} + +static int foo_meth1(struct Foo *self) +{ + printf("foo_meth1 [self=%p]\n", self); +} + +static int foo_meth2(struct Foo *self, const char *s) +{ + printf("foo_meth2 [self=%p s=\"%s\"]\n", self, s); +} + +static int foo_meth3(struct Foo *self, int x, const char *s) +{ + printf("foo_meth3 [self=%p x=%d s=\"%s\"]\n", self, x, s); +} + +static int foo_meth4(struct Foo *self, int x, const char *s, char c) +{ + printf("foo_meth4 [self=%p x=%d s=\"%s\" c=%c]\n", self, x, s, c); +} + +static void foo_dummy(struct Foo *self) +{ + printf("foo_dummy [self=%p]\n", self); +} + +static struct FooMethods foo_methods = { + &foo_dtor, + &foo_dummy, + &foo_meth1, + &foo_meth2, + &foo_meth3, + &foo_meth4, +}; + +struct Foo *CreateFoo() +{ + struct Foo *f = (struct Foo *) malloc(sizeof(struct Foo)); + f->vptr = &foo_methods; + return f; +} diff --git a/vtable_hide/vtable_foo/libfoo.h b/vtable_hide/vtable_foo/libfoo.h new file mode 100644 index 00000000000..a01e05d584a --- /dev/null +++ b/vtable_hide/vtable_foo/libfoo.h @@ -0,0 +1,18 @@ +/* vim:set ts=2 sw=2 et cindent: */ + +#ifndef LIBFOO_H__ +#define LIBFOO_H__ + +class Foo +{ +public: + virtual ~Foo() { } + virtual int meth1() = 0; + virtual int meth2(const char *) = 0; + virtual int meth3(int, const char *) = 0; + virtual int meth4(int, const char *, char) = 0; +}; + +extern "C" Foo * CreateFoo(); + +#endif diff --git a/vtable_hide/vtable_foo/test b/vtable_hide/vtable_foo/test new file mode 100755 index 0000000000000000000000000000000000000000..752a285ffff7eb0f552e3c72fff5e1b37f123435 GIT binary patch literal 20102 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 literal 0 HcmV?d00001 diff --git a/vtable_hide/vtable_foo/test++ b/vtable_hide/vtable_foo/test++ new file mode 100755 index 0000000000000000000000000000000000000000..c9331a9dc2e27eb8d04f680f7ba1d459cee53579 GIT binary patch literal 42867 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 literal 0 HcmV?d00001 diff --git a/vtable_hide/vtable_foo/test.cc b/vtable_hide/vtable_foo/test.cc new file mode 100644 index 00000000000..1ddde9a19db --- /dev/null +++ b/vtable_hide/vtable_foo/test.cc @@ -0,0 +1,17 @@ +#include +#include "libfoo.h" + +int main() +{ + Foo *f = CreateFoo(); + if (f) + { + f->meth1(); + f->meth2("hello"); + f->meth3(10, "hello"); + f->meth4(10, "hello", 'x'); + f->~Foo(); + // free(f); + } + return 0; +} diff --git a/vtable_hide/vtable_hide.tar.gz b/vtable_hide/vtable_hide.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..99e5e34d20158bec14150aab1b72273b8725cb74 GIT binary patch literal 1493 zcmV;`1uFU05YT35k#_x8s+iLGY=X-4^Pm4&95Ma+GA>-cNeB0I^DP85x|226} zJ?7J0+puiQ>aLu7{`_0LUUL4H-R>fPyJdCuz}odjHqrn5{P*FC&H51)zytgc(Xb8C z^|0MH4C4EJ5Hu1-G-b1+pbu(v96e5faZW=VlY3)4nc!jr|0dAzc+j9rht35HcmxM0 z&U9qM>D+;vS!9SV<8h*5xJBNpc<5R->#*=V{>Y#@F%CjFG{vS^H z{Ev@h=Qg(Ff3wrf^1s)zW&Yc(W|{vFLC42w0dN?1DHoXe`;0sO!liH$36}*&)6;CK zq7$}~n~8I`Vqlh$D1tW&K||xl0GNmDiU``ruK;gRP-W@BkV}iP&m6s?1k5VjD4t(L z5Sq^=V|4(xlHpU4;cSfo)W=o8T=0UxWL&_q3ag~0Um}ANt|Lz(uSCZr)S`88u+Csa zrg$}KQ8f{LLBdqD9x375LE`oKQe4dDKJ;VP;6jE)hau-{%qE>d)7m%-#e(?oDP2?3 zH-_Fe29XQTtU#lYNcZ~*FT4{|77d@x|GwmvI>;Z@ffBqm3d&c4v)uynrpjSCeCB2r zROIe7a%UK~+eFc#O^AkZu2>(O>lA~6o=_b2}$cUd>z5042qh?#x{FL<3w(3xsQr{1>4i$^ccF{VWjj8L> zFw%RdW5Yu|^NomxDP*a;kj*zBiMh=O@ zNxXh)qK3RfjZ^7lr#K~@?4Xa=LFl`cc+I6g?l}w6XT45c`JBIG9Ep%P;tr=*T#`=5 z1} z`Tnmf`|fRQ#s8h8|68qA59jSxuWOh6{~>6fdD!(m)t5)p(a6}xUyRdi!ociYV0Ov| zsLHD<^0lkEP^qAcyGsO-zhor_@F|~&Y4+Rm$s`)6Qmus3F0UX#4YMbmKHEGko3@@+ zl|=QQbWyhD!s2S!DgJLZTMGYMy)yqFg0|y-tOtb$ zz}LMAR2RMvK28}mLM{U2+~P(snXV&1&Me*uks&KNNzM621fAQ!z3?-n)vd6BT>|Xf zmcAHXLt0-~x3>zx@gB{6;?No1Ac@fsll!ub=w=bjX-F{4a>b0;M>-N9hq`_g$|u%M zf}bM!tiq;41l|$Vbbh7c%_2E=>7Eh_^pxC$#DwPac%quWLOEQP^55o_!z5OX&@pdk zkT$}Lx1;mF{yhKVx1V2)E?)os%8aP*RY47nQ`rXL=`dAuBqyqy`6h*X|n zk~J@0${G+mk*fh(X8A47$U3zAGFMP!gC`ky%6YO@SXLc-LBgVAE0rYnP*;hsc2X9) zT&20EpD303`J>zGf1dLAFYehpx3TU0*TlzO^8Rc0H2!OLOZ@i`l)V4c*%uyw*-Re7 vt>LvIHjDqQc{gfGI>vn=jpn~CUvMRrR8mPLl~htmJEDI9o`?j504M+eCcOQ@ literal 0 HcmV?d00001 diff --git a/vtable_hide/vtable_hide/Makefile b/vtable_hide/vtable_hide/Makefile new file mode 100644 index 00000000000..d44e7a284d8 --- /dev/null +++ b/vtable_hide/vtable_hide/Makefile @@ -0,0 +1,11 @@ +# vim:set noet ts=4 sw=4: + +all: test +shim.o: shim.cc shim.h inner.h Makefile + gcc -c -g -fno-exceptions $< -o $@ +test.o: test.cc shim.h inner.h Makefile + gcc -c -g -fno-exceptions $< -o $@ +test: test.o shim.o + gcc $^ -o $@ -lsupc++ +clean: + rm -f *.o test diff --git a/vtable_hide/vtable_hide/inner.h b/vtable_hide/vtable_hide/inner.h new file mode 100644 index 00000000000..a8b37a5cb04 --- /dev/null +++ b/vtable_hide/vtable_hide/inner.h @@ -0,0 +1,12 @@ +#ifndef inner_h__ +#define inner_h__ + +class Inner +{ + public: + virtual ~Inner() {} + virtual void foo(int x) = 0; + virtual void bar(int x, const char *s) = 0; +}; + +#endif diff --git a/vtable_hide/vtable_hide/shim.cc b/vtable_hide/vtable_hide/shim.cc new file mode 100644 index 00000000000..22f40fe239d --- /dev/null +++ b/vtable_hide/vtable_hide/shim.cc @@ -0,0 +1,98 @@ +// vim:set cindent: + +#include +#include +#include "shim.h" +#include "inner.h" + +class InnerImpl : public Inner +{ + public: + InnerImpl() {} + + virtual ~InnerImpl() + { + printf("InnerImpl::~InnerImpl [this=%p]\n", this); + ShimDtor((Shim *) this); + } + + virtual void foo(int x) + { + printf("InnerImpl::foo [this=%p x=%d]\n", this, x); + ShimFoo((Shim *) this, x); + } + + virtual void bar(int x, const char *s) + { + printf("InnerImpl::bar [this=%p x=%d s=\"%s\"]\n", this, x, s); + ShimBar((Shim *) this, x, s); + } +}; + +// placement new +inline void *operator new(size_t size, Shim *s) { return s; } + +static Shim +GetOurImpl() +{ + Shim ourImpl; + new (&ourImpl) InnerImpl(); + return ourImpl; +} +static Shim gOurImpl = GetOurImpl(); +#define IS_EXTERNAL_IMPL(self) (self->vptr != gOurImpl.vptr) + +void ShimCtor(Shim *self) +{ + printf("ShimCtor [self=%p]\n", self); + + new (self) InnerImpl(); + + /* + * initialize our members after placement new since sizeof InnerImpl + * may be bigger than sizeof(void *) + */ + + self->data = 0; + self->length = 1; + self->flags = 2; +} + +void ShimDtor(Shim *self) +{ + printf("ShimDtor [self=%p]\n", self); + + if (IS_EXTERNAL_IMPL(self)) + { + ((Inner *) self)->~Inner(); + return; + } + + printf(" ++ running our dtor!\n"); +} + +void ShimFoo(Shim *self, int x) +{ + printf("ShimFoo [self=%p x=%d]\n", self, x); + + if (IS_EXTERNAL_IMPL(self)) + { + ((Inner *) self)->foo(x); + return; + } + + printf(" ++ running our foo!\n"); +} + +void ShimBar(Shim *self, int x, const char *s) +{ + printf("ShimBar [self=%p x=%d s=\"%s\"]\n", self, x, s); + + if (IS_EXTERNAL_IMPL(self)) + { + ((Inner *) self)->bar(x, s); + return; + } + + printf(" ++ running our bar!\n"); +} diff --git a/vtable_hide/vtable_hide/shim.h b/vtable_hide/vtable_hide/shim.h new file mode 100644 index 00000000000..3c641027bba --- /dev/null +++ b/vtable_hide/vtable_hide/shim.h @@ -0,0 +1,17 @@ +#ifndef shim_h__ +#define shim_h__ + +struct Shim +{ + void *vptr; + char *data; + int length; + int flags; +}; + +void ShimCtor(Shim *); +void ShimDtor(Shim *); +void ShimFoo(Shim *, int x); +void ShimBar(Shim *, int x, const char *s); + +#endif diff --git a/vtable_hide/vtable_hide/test.cc b/vtable_hide/vtable_hide/test.cc new file mode 100644 index 00000000000..b2c8775a347 --- /dev/null +++ b/vtable_hide/vtable_hide/test.cc @@ -0,0 +1,70 @@ +// vim:set cindent: + +#include +#include "shim.h" +#include "inner.h" + +class Outer +{ + private: + Shim shim; + + public: + Outer() { ShimCtor(&shim); } + ~Outer() { ShimDtor(&shim); } + + void foo(int x) { ShimFoo(&shim, x); } + void bar(int x, const char *s) { ShimBar(&shim, x,s); } +}; + +class ExtImpl : public Inner +{ + public: + ExtImpl() {} + + virtual ~ExtImpl() + { + printf(" -- ExtImpl::~ExtImpl [this=%p]\n", this); + } + + virtual void foo(int x) + { + printf(" -- ExtImpl::foo [this=%p x=%d]\n", this, x); + } + + virtual void bar(int x, const char *s) + { + printf(" -- ExtImpl::bar [this=%p x=%d s=\"%s\"]\n", this, x, s); + } +}; + +int main() +{ + printf("\ntest use of our class directly:\n\n"); + { + Outer outer; + outer.foo(10); + outer.bar(10, "hello"); + } + + printf("\n\ntest use of embedders class, interpreted as if it were our class:\n\n"); + { + ExtImpl *ext = new ExtImpl(); + Outer *outer = reinterpret_cast(ext); + outer->foo(5); + outer->bar(5, "world"); + delete outer; + } + + printf("\n\ntest use of our class, interpreted as if it were abstract class:\n\n"); + { + Outer *outer = new Outer(); + Inner *inner = reinterpret_cast(outer); + inner->foo(1); + inner->bar(1, "crazy"); + delete inner; + } + + printf("\n"); + return 0; +}