Date: prev next · Thread: first prev next last
2010 Archives by date, by thread · List index


Just to throw out here some code to play with strings.

Taking unostrings.cxx there's some template cunning which generates
objects with the same layout as a OString, but without any constructors,
so that the StaticInit_OString macro generates OString-alike objects
which require effectively 0 setup time and can be shoved by the linker
into the rodata section.

16unistrings.cxx then extends this to add support for the "u" 16bit
string literals as found in c++0x (g++ --std=c++0x) and taking advantage
that wchar_t being 16bits in msvc the (though untested) "L" identifier
there. This would have the downside that the string literal storage in
the binary is now double the size it is now, but the upside that we
completely elide ::createFromAscii and/or the OUString constructor and
elide their destructors too of course.

Catch is though, that because OStrings and OUStrings do shallow copies,
copying one of these magic-strings about the place leaves it very
possible that a shallow-copy of the string will outlive the "stack
string" and die horribly. So to be safe the OString/OUString copy
methods would have to be tweaked to do a deep copy when one of these
shows up. But if the stack strings were only passed around by reference,
then they wouldn't need to get copied. A big plus I see here is the
potential to remove the very large number of string constructors which
are run during startup.

As an aside, an easy hack for small optimizations already is to replace
stuff like

rtl::OUString aFoo(rtl::OUString::createFromAscii("foo")); 
and
rtl::OUString aFoo = rtl::OUString::createFromAscii("foo");
with
rtl::OUString aFoo(RTL_CONSTASCII_USTRINGPARAM("foo"));

seeing as the final example is a titchy optimization over the other
examples, Added this as an easy hack to 
http://wiki.documentfoundation.org/Development/Easy_Hacks#Use_RTL_CONSTASCII_USTRINGPARAM_macro

C.
#include <stdio.h>

//start copy and paste from sal for illustration purpores

#define SAL_STRING_STATIC_FLAG 0x40000000

typedef struct _rtl_String
{
    int refCount; /* opaque */
    int length;
    char buffer[1];
} rtl_String;


class OString
{
public:
    rtl_String * pData;

private:
    class DO_NOT_ACQUIRE;

    /** @internal */
    OString( rtl_String * value, DO_NOT_ACQUIRE * )
    {
        pData = value;
    }

private:
    OString();

public:
    const char * getStr() const
    {
        return pData->buffer;
    }
};

//end copy and paste from sal for illustration purpores

template <size_t len> struct StaticInit__rtl_String__Tmpl
{
    const int refCount; /* opaque */
    const int length;
    const char buffer[len];
};

template <size_t len> struct StaticInit_OString__Tmpl
{
    const StaticInit__rtl_String__Tmpl<len> *pData;
    operator const OString&() const { return *reinterpret_cast<const OString*>(this); }
};

#define StaticInit_OString(name, str) \
    const StaticInit__rtl_String__Tmpl<sizeof(str)> name##_aImpl = {SAL_STRING_STATIC_FLAG|1, 
sizeof(str)-1, { str } }; \
    const StaticInit_OString__Tmpl<sizeof(str)> name = {&name##_aImpl}

static StaticInit_OString(rodata_example, "hello world"); 

StaticInit_OString(data_example, "another"); 

void other (const OString &thing)
{
        fprintf(stderr, "result is %s\n", thing.getStr());
}

int main(void)
{
    fprintf(stderr, "c: %s %d\n", rodata_example.pData->buffer, rodata_example.pData->length);

    other(rodata_example);

    other(data_example);

    StaticInit_OString(data_foo, "foo"); 

    other(data_foo);

    return 0;
}
#include <stdio.h>
#include <exception>

//start copy and paste from sal for illustration purpores

#define SAL_STRING_STATIC_FLAG 0x40000000

#define RTL_CONSTASCII_USTRINGPARAM( constAsciiStr ) constAsciiStr, 
((sal_Int32)(sizeof(constAsciiStr)-1)), RTL_TEXTENCODING_ASCII_US

typedef struct _rtl_uString
{
    int refCount; /* opaque */
    int length;
    unsigned short buffer[1];
} rtl_uString;


class OUString
{
public:
    rtl_uString * pData;

private:
    class DO_NOT_ACQUIRE;

    /** @internal */
    OUString( rtl_uString * value, DO_NOT_ACQUIRE * )
    {
        pData = value;
    }

private:
    OUString();

public:
    const unsigned short * getStr() const
    {
        return pData->buffer;
    }
};

//end copy and paste from sal for illustration purpores

#if defined __GXX_EXPERIMENTAL_CXX0X__
#  define SAL_DECLARE_UTF16(str) u ## str
    typedef char16_t utf16_type;
#elif (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x550)
#  define SAL_DECLARE_UTF16(str) U ## str
    typedef unsigned short utf16_type;
#elif __SIZEOF_WCHAR_T__ == 2
#  define SAL_DECLARE_UTF16(str) L ## str
    typedef wchar_t utf16_type;
#else
    typedef unsigned short utf16_type;
#endif

#ifdef SAL_DECLARE_UTF16

template <size_t len> struct StaticInit__rtl_uString__Tmpl
{
    const int refCount; /* opaque */
    const int length;
    const utf16_type buffer[len];
};

template <size_t len> struct StaticInit_OUString__Tmpl
{
    const StaticInit__rtl_uString__Tmpl<len> *pData;
    operator const OUString&() const { return *reinterpret_cast<const OUString*>(this); }
};

#  define StaticInit_OUString(name, str) \
    const StaticInit__rtl_uString__Tmpl<sizeof(SAL_DECLARE_UTF16(str))/sizeof(unsigned short)> 
name##_aImpl = {SAL_STRING_STATIC_FLAG|1, sizeof(SAL_DECLARE_UTF16(str))/sizeof(unsigned short)-1, 
{ SAL_DECLARE_UTF16(str) } }; \
    const StaticInit_OUString__Tmpl<sizeof(SAL_DECLARE_UTF16(str))/sizeof(unsigned short)> name = 
{&name##_aImpl}
#else
#  define StaticInit_OUString(name, str) \
    const OUString name(RTL_CONSTASCII_USTRINGPARAM(str));
#endif

static StaticInit_OUString(rodata_example, "hello world"); 

StaticInit_OUString(data_example, "another"); 

void other (const OUString &thing)
{
        fprintf(stderr, "result is %s\n", thing.getStr());
}

int main(void)
{
    fprintf(stderr, "c: %p %d\n", rodata_example.pData->buffer, rodata_example.pData->length);

    other(rodata_example);

    other(data_example);

    StaticInit_OUString(data_foo, "foo"); 

    other(data_foo);

    return 0;
}

Context


Privacy Policy | Impressum (Legal Info) | Copyright information: Unless otherwise specified, all text and images on this website are licensed under the Creative Commons Attribution-Share Alike 3.0 License. This does not include the source code of LibreOffice, which is licensed under the Mozilla Public License (MPLv2). "LibreOffice" and "The Document Foundation" are registered trademarks of their corresponding registered owners or are in actual use as trademarks in one or more countries. Their respective logos and icons are also subject to international copyright laws. Use thereof is explained in our trademark policy.