[API CHANGE] Deprecate css.registry.XSimpleRegistry::mergeKey

...and let its implementations just throw a RuntimeException, now that regmerge
has been removed in "[API CHANGE] Remove deprecated idlc and regmerge from the
SDK".  Deprecate css.registry.MergeConflictException along with it (though
stoc/source/implementationregistration/ still uses it internally).  And remove
the previously unused include/registry/writer.hxx along with the newly unused
include/registry/writer.h, RegistryTypeWriter, and RegistryTypeReader.

Change-Id: I10fd286617975dc0ef9f74460a3a3eab8060939d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123615
Tested-by: Jenkins
Reviewed-by: Stephan Bergmann <[email protected]>
diff --git a/include/registry/refltype.hxx b/include/registry/refltype.hxx
index 0ca5803..5278e37 100644
--- a/include/registry/refltype.hxx
+++ b/include/registry/refltype.hxx
@@ -23,17 +23,6 @@
#include <registry/types.hxx>
#include <sal/types.h>

/** specifies the type source of a binary type blob.

    Currently only RT_UNO_IDL type is used.
 */
enum RTTypeSource
{
    RT_UNO_IDL,
    RT_CORBA_IDL,
    RT_JAVA
};

/** specifies a helper class for const values.

    This class is used for easy handling of constants or enum values
@@ -55,20 +44,6 @@
    }
};

/** deprecated.

    An earlier version of UNO used a unique identifier for interfaces. In the
    current version of UNO this uik was eliminated and this type is no longer used.
 */
struct RTUik
{
    sal_uInt32 m_Data1;
    sal_uInt16 m_Data2;
    sal_uInt16 m_Data3;
    sal_uInt32 m_Data4;
    sal_uInt32 m_Data5;
};

/// specifies the calling convention for type reader/writer api
#define TYPEREG_CALLTYPE SAL_CALL

diff --git a/include/registry/registry.hxx b/include/registry/registry.hxx
index b98b1e9..ccc19c5 100644
--- a/include/registry/registry.hxx
+++ b/include/registry/registry.hxx
@@ -40,7 +40,6 @@
    RegError    (REGISTRY_CALLTYPE *openRegistry)       (rtl_uString*, RegHandle*, RegAccessMode);
    RegError    (REGISTRY_CALLTYPE *closeRegistry)      (RegHandle);
    RegError    (REGISTRY_CALLTYPE *destroyRegistry)    (RegHandle, rtl_uString*);
    RegError    (REGISTRY_CALLTYPE *mergeKey)           (RegHandle, RegKeyHandle, rtl_uString*, rtl_uString*, sal_Bool, sal_Bool);
    void        (REGISTRY_CALLTYPE *acquireKey)         (RegKeyHandle);
    void        (REGISTRY_CALLTYPE *releaseKey)         (RegKeyHandle);
    sal_Bool    (REGISTRY_CALLTYPE *isKeyReadOnly)      (RegKeyHandle);
@@ -154,25 +153,6 @@
    */
    inline RegError destroy(const OUString& registryName);

    /** merges the registry information of the specified key with the registry
        information of the specified file.

        All existing keys will be extended and existing key values will be overwritten.
        @param  rKey references a currently open key. The key which information is merged by this
                     function is a subkey of this key
        @param  keyName specifies the name of the key which will be merged.
                        If keyName is an empty string the registry information under the key specified
                        by rKey is merged with the information from the specified file.
        @param  regFileName specifies the file containing the registry information.
        @param  bReport if TRUE the function reports warnings on stdout if a key already exists.
        @return RegError::NO_ERROR if succeeds else an error code. If it returns an error the registry will
                restore the state before merging.
    */
    inline RegError mergeKey(RegistryKey& rKey,
                                const OUString& keyName,
                                const OUString& regFileName,
                                bool bReport);

    friend class RegistryKey;
    friend class RegistryKeyArray;
    friend class RegistryKeyNames;
@@ -1050,10 +1030,4 @@
        return ret;
    }

inline RegError Registry::mergeKey(RegistryKey& rKey,
                                         const OUString& keyName,
                                         const OUString& regFileName,
                                         bool bReport)
    {  return m_pApi->mergeKey(m_hImpl, rKey.m_hImpl, keyName.pData, regFileName.pData, false/*bWarnings*/, bReport); }

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/registry/writer.h b/include/registry/writer.h
deleted file mode 100644
index 8f07437..0000000
--- a/include/registry/writer.h
+++ /dev/null
@@ -1,262 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#ifndef INCLUDED_REGISTRY_WRITER_H
#define INCLUDED_REGISTRY_WRITER_H

#include <registry/regdllapi.h>
#include <registry/types.hxx>
#include <registry/version.h>

#include <rtl/ustring.h>
#include <sal/types.h>

#ifdef __cplusplus
extern "C" {
#endif

/**
   Creates a type writer working on a binary blob that represents a UNOIDL type.

   <p>Operations on a returned handle are not multi-thread&ndash;safe.</p>

   @param version the version of the created type writer; must not be negative

   @param documentation the documentation; must not be null

   @param fileName the file name; must not be null (deprecated, use an empty string)

   @param typeClass the type class of the created type writer

   @param published whether the created type writer is published; for a type
   class that cannot be published, this should be false

   @param typeName the type name of the created type writer; must not be null

   @param superTypeCount the number of super types of the created type writer

   @param fieldCount the number of fields of the created type writer

   @param methodCount the number of methods of the created type writer

   @param referenceCount the number of references of the created type writer

   @return a handle on the type writer; if an out-of-memory condition occurs,
   null is returned, and no type writer is created

   @since UDK 3.2.0
 */
REG_DLLPUBLIC void * typereg_writer_create(
    typereg_Version version, rtl_uString const * documentation,
    rtl_uString const * fileName, RTTypeClass typeClass, sal_Bool published,
    rtl_uString const * typeName, sal_uInt16 superTypeCount,
    sal_uInt16 fieldCount, sal_uInt16 methodCount, sal_uInt16 referenceCount)
    SAL_THROW_EXTERN_C();

/**
   Destroys a type writer.

   @param handle a handle on a type writer obtained from a call to
   <code>typereg_writer_create</code>; must not be null

   @since UDK 3.2.0
 */
REG_DLLPUBLIC void typereg_writer_destroy(void * handle) SAL_THROW_EXTERN_C();

/**
   Sets the type name of a super type of a type writer.

   @param handle a handle on a type writer; must not be null

   @param index a valid index into the range of super types of the given type
   writer

   @param typeName the super type name; must not be null

   @return false iff an out-of-memory condition occurred, in which case the type
   writer is not modified

   @since UDK 3.2.0
 */
REG_DLLPUBLIC sal_Bool typereg_writer_setSuperTypeName(
    void const * handle, sal_uInt16 index, rtl_uString const * typeName)
        SAL_THROW_EXTERN_C();

/**
   Sets the data of a field of a type writer.

   @param handle a handle on a type writer; must not be null

   @param index a valid index into the range of fields of the given type writer

   @param documentation the documentation of the field; must not be null

   @param fileName the file name of the field; must not be null (deprecated, use an empty string)

   @param flags the flags of the field

   @param name the name of the field; must not be null

   @param typeName the type name of the field; must not be null

   @param valueType the type of the value of the field

   @param valueValue the value of the value of the field

   @return false iff an out-of-memory condition occurred, in which case the type
   writer is not modified

   @since UDK 3.2.0
 */
REG_DLLPUBLIC sal_Bool typereg_writer_setFieldData(
    void * handle, sal_uInt16 index, rtl_uString const * documentation,
    rtl_uString const * fileName, RTFieldAccess flags, rtl_uString const * name,
    rtl_uString const * typeName, RTValueType valueType,
    RTConstValueUnion valueValue)
    SAL_THROW_EXTERN_C();

/**
   Sets the data of a method of a type writer.

   @param handle a handle on a type writer; must not be null

   @param index a valid index into the range of methods of the given type writer

   @param documentation the documentation of the method; must not be null

   @param flags the flags of the method

   @param name the name of the method; must not be null

   @param returnTypeName the return type name of the method; must not be null

   @param parameterCount the number of parameters of the method

   @param exceptionCount the number of exceptions of the method

   @return false iff an out-of-memory condition occurred, in which case the type
   writer is not modified

   @since UDK 3.2.0
 */
REG_DLLPUBLIC sal_Bool typereg_writer_setMethodData(
    void * handle, sal_uInt16 index, rtl_uString const * documentation,
    RTMethodMode flags, rtl_uString const * name,
    rtl_uString const * returnTypeName, sal_uInt16 parameterCount,
    sal_uInt16 exceptionCount)
    SAL_THROW_EXTERN_C();

/**
   Sets the data of a parameter of a method of a type writer.

   @param handle a handle on a type writer; must not be null

   @param methodIndex a valid index into the range of methods of the given type
   writer

   @param parameterIndex a valid index into the range of parameters of the given
   method

   @param flags the flags of the parameter

   @param name the name of the parameter; must not be null

   @param typeName the type name of the parameter; must not be null

   @return false iff an out-of-memory condition occurred, in which case the type
   writer is not modified

   @since UDK 3.2.0
 */
REG_DLLPUBLIC sal_Bool typereg_writer_setMethodParameterData(
    void const * handle, sal_uInt16 methodIndex, sal_uInt16 parameterIndex,
    RTParamMode flags, rtl_uString const * name, rtl_uString const * typeName)
    SAL_THROW_EXTERN_C();

/**
   Sets an exception type name of a method of a type writer.

   @param handle a handle on a type writer; must not be null

   @param methodIndex a valid index into the range of methods of the given type
   writer

   @param exceptionIndex a valid index into the range of exceptions of the given
   method

   @param typeName the exception type name; must not be null

   @return false iff an out-of-memory condition occurred, in which case the type
   writer is not modified

   @since UDK 3.2.0
 */
REG_DLLPUBLIC sal_Bool typereg_writer_setMethodExceptionTypeName(
    void const * handle, sal_uInt16 methodIndex, sal_uInt16 exceptionIndex,
    rtl_uString const * typeName)
    SAL_THROW_EXTERN_C();

/**
   Sets the data of a reference of a type writer.

   @param handle a handle on a type writer; must not be null

   @param index a valid index into the range of references of the given type
   writer

   @param documentation the documentation of the reference; must not be null

   @param sort the sort of the reference

   @param flags the flags of the reference

   @param typeName the type name of the reference; must not be null

   @return false iff an out-of-memory condition occurred, in which case the type
   writer is not modified

   @since UDK 3.2.0
 */
REG_DLLPUBLIC sal_Bool typereg_writer_setReferenceData(
    void * handle, sal_uInt16 index, rtl_uString const * documentation,
    RTReferenceType sort, RTFieldAccess flags, rtl_uString const * typeName)
    SAL_THROW_EXTERN_C();

/**
   Returns the blob of a type writer.

   @param handle a handle on a type writer; must not be null

   @param size an out-parameter obtaining the size of the blob; must not be null

   @return a (byte-aligned) pointer to the blob; the returned pointer and the
   returned <code>size</code> remain valid until the next function is called on
   the given type writer; if an out-of-memory condition occurs, null is returned
   and <code>size</code> is not modified
 */
REG_DLLPUBLIC void const * typereg_writer_getBlob(void * handle, sal_uInt32 * size)
    SAL_THROW_EXTERN_C();

#ifdef __cplusplus
}
#endif

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/registry/writer.hxx b/include/registry/writer.hxx
deleted file mode 100644
index 4bf6724..0000000
--- a/include/registry/writer.hxx
+++ /dev/null
@@ -1,291 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#ifndef INCLUDED_REGISTRY_WRITER_HXX
#define INCLUDED_REGISTRY_WRITER_HXX

#include <registry/writer.h>
#include <registry/refltype.hxx>
#include <registry/types.hxx>
#include <registry/version.h>

#include <rtl/ustring.hxx>
#include <sal/types.h>

#include <new>

namespace typereg {

/**
   A type writer working on a binary blob that represents a UNOIDL type.

   <p>Instances of this class are not multi-thread&ndash;safe.</p>

   @since UDK 3.2.0
 */
class Writer {
public:
    /**
       Creates a type writer.

       @param version the version of the created type writer; must not be
       negative

       @param documentation the documentation

       @param fileName the file name (deprecated, use an empty string)

       @param typeClass the type class of the created type writer

       @param published whether the created type writer is published; for a type
       class that cannot be published, this should be false

       @param typeName the type name of the created type writer

       @param superTypeCount the number of super types of the created type
       writer

       @param fieldCount the number of fields of the created type writer

       @param methodCount the number of methods of the created type writer

       @param referenceCount the number of references of the created type writer

       @exception std::bad_alloc is raised if an out-of-memory condition occurs
     */
    Writer(
        typereg_Version version, OUString const & documentation,
        OUString const & fileName, RTTypeClass typeClass, bool published,
        OUString const & typeName, sal_uInt16 superTypeCount,
        sal_uInt16 fieldCount, sal_uInt16 methodCount,
        sal_uInt16 referenceCount):
        m_handle(
            typereg_writer_create(
                version, documentation.pData, fileName.pData, typeClass,
                published, typeName.pData, superTypeCount, fieldCount,
                methodCount, referenceCount))
    {
        if (m_handle == nullptr) {
            throw std::bad_alloc();
        }
    }

    /**
       Destroys this <code>Writer</code> instance.
     */
    ~Writer() {
        typereg_writer_destroy(m_handle);
    }

    /**
       Sets the type name of a super type of this type writer.

       @param index a valid index into the range of super types of this type
       writer

       @param typeName the super type name

       @exception std::bad_alloc is raised if an out-of-memory condition occurs
     */
    void setSuperTypeName(sal_uInt16 index, OUString const & typeName) {
        if (!typereg_writer_setSuperTypeName(m_handle, index, typeName.pData)) {
            throw std::bad_alloc();
        }
    }

    /**
       Sets the data of a field of this type writer.

       @param index a valid index into the range of fields of this type writer

       @param documentation the documentation of the field

       @param fileName the file name of the field (deprecated, use an empty string)

       @param flags the flags of the field

       @param name the name of the field

       @param typeName the type name of the field

       @param value the value of the field

       @exception std::bad_alloc is raised if an out-of-memory condition occurs
     */
    void setFieldData(
        sal_uInt16 index, OUString const & documentation,
        OUString const & fileName, RTFieldAccess flags, OUString const & name,
        OUString const & typeName, RTConstValue const & value)
    {
        if (!typereg_writer_setFieldData(
                m_handle, index, documentation.pData, fileName.pData, flags,
                name.pData, typeName.pData, value.m_type, value.m_value))
        {
            throw std::bad_alloc();
        }
    }

    /**
       Sets the data of a method of this type writer.

       @param index a valid index into the range of methods of this type writer

       @param documentation the documentation of the method

       @param flags the flags of the method

       @param name the name of the method

       @param returnTypeName the return type name of the method

       @param parameterCount the number of parameters of the method

       @param exceptionCount the number of exceptions of the method

       @exception std::bad_alloc is raised if an out-of-memory condition occurs
     */
    void setMethodData(
        sal_uInt16 index, OUString const & documentation,
        RTMethodMode flags, OUString const & name,
        OUString const & returnTypeName, sal_uInt16 parameterCount,
        sal_uInt16 exceptionCount)
    {
        if (!typereg_writer_setMethodData(
                m_handle, index, documentation.pData, flags, name.pData,
                returnTypeName.pData, parameterCount, exceptionCount))
        {
            throw std::bad_alloc();
        }
    }

    /**
       Sets the data of a parameter of a method of this type writer.

       @param methodIndex a valid index into the range of methods of this type
       writer

       @param parameterIndex a valid index into the range of parameters of the
       given method

       @param flags the flags of the parameter

       @param name the name of the parameter

       @param typeName the type name of the parameter

       @exception std::bad_alloc is raised if an out-of-memory condition occurs
     */
    void setMethodParameterData(
        sal_uInt16 methodIndex, sal_uInt16 parameterIndex,
        RTParamMode flags, OUString const & name,
        OUString const & typeName) const
    {
        if (!typereg_writer_setMethodParameterData(
                m_handle, methodIndex, parameterIndex, flags, name.pData,
                typeName.pData))
        {
            throw std::bad_alloc();
        }
    }

    /**
       Sets an exception type name of a method of this type writer.

       @param methodIndex a valid index into the range of methods of this type
       writer

       @param exceptionIndex a valid index into the range of exceptions of the
       given method

       @param typeName the exception type name

       @exception std::bad_alloc is raised if an out-of-memory condition occurs
     */
    void setMethodExceptionTypeName(
        sal_uInt16 methodIndex, sal_uInt16 exceptionIndex,
        OUString const & typeName)
    {
        if (!typereg_writer_setMethodExceptionTypeName(
                m_handle, methodIndex, exceptionIndex, typeName.pData))
        {
            throw std::bad_alloc();
        }
    }

    /**
       Sets the data of a reference of this type writer.

       @param index a valid index into the range of references of this type
       writer

       @param documentation the documentation of the reference

       @param sort the sort of the reference

       @param flags the flags of the reference

       @param typeName the type name of the reference

       @exception std::bad_alloc is raised if an out-of-memory condition occurs
     */
    void setReferenceData(
        sal_uInt16 index, OUString const & documentation,
        RTReferenceType sort, RTFieldAccess flags,
        OUString const & typeName)
    {
        if (!typereg_writer_setReferenceData(
                m_handle, index, documentation.pData, sort, flags,
                typeName.pData))
        {
            throw std::bad_alloc();
        }
    }

    /**
       Returns the blob of this type writer.

       @param size an out-parameter obtaining the size of the blob

       @return a (byte-aligned) pointer to the blob; the returned pointer and
       the returned <code>size</code> remain valid until the next function is
       called on this type writer

       @exception std::bad_alloc is raised if an out-of-memory condition occurs
       (in which case <code>size</code> is not modified
     */
    void const * getBlob(sal_uInt32 * size) {
        void const * p = typereg_writer_getBlob(m_handle, size);
        if (p == nullptr) {
            throw std::bad_alloc();
        }
        return p;
    }

private:
    Writer(Writer const &) = delete;
    Writer& operator =(Writer const &) = delete;

    void * m_handle;
};

}

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/registry/IwyuFilter_registry.yaml b/registry/IwyuFilter_registry.yaml
index 7acf6c9..4b2a6b7 100644
--- a/registry/IwyuFilter_registry.yaml
+++ b/registry/IwyuFilter_registry.yaml
@@ -7,8 +7,6 @@
    registry/source/reflwrit.cxx:
    # OSL_BIGENDIAN is being checked
    - osl/endian.h
    # Needed for correct linker visibility
    - registry/writer.h
    registry/source/reflread.cxx:
    # OSL_BIGENDIAN is being checked
    - osl/endian.h
diff --git a/registry/source/reflread.cxx b/registry/source/reflread.cxx
index 57884e1..f31c6e1 100644
--- a/registry/source/reflread.cxx
+++ b/registry/source/reflread.cxx
@@ -27,9 +27,9 @@
#include <sal/types.h>
#include <osl/endian.h>
#include <osl/diagnose.h>
#include "reflread.hxx"
#include <sal/log.hxx>

#include <registry/refltype.hxx>
#include <registry/typereg_reader.hxx>
#include <registry/version.h>

@@ -1213,13 +1213,6 @@
    }
}

static TypeReaderImpl TYPEREG_CALLTYPE createEntry(const sal_uInt8* buffer, sal_uInt32 len)
{
    void * handle;
    typereg_reader_create(buffer, len, &handle);
    return handle;
}

void TYPEREG_CALLTYPE typereg_reader_acquire(void * hEntry)
{
    TypeRegistryEntry* pEntry = static_cast<TypeRegistryEntry*>(hEntry);
@@ -1294,23 +1287,6 @@
}


static void TYPEREG_CALLTYPE getSuperTypeName(TypeReaderImpl hEntry, rtl_uString** pSuperTypeName)
{
    TypeRegistryEntry* pEntry = static_cast<TypeRegistryEntry*>(hEntry);
    if (pEntry != nullptr && pEntry->m_nSuperTypes != 0) {
        try {
            const char* pTmp = pEntry->m_pCP->readUTF8NameConstant(pEntry->readUINT16(pEntry->m_offset_SUPERTYPES )); //+ (index * sizeof(sal_uInt16))));
            rtl_string2UString(
                pSuperTypeName, pTmp, pTmp == nullptr ? 0 : rtl_str_getLength(pTmp),
                RTL_TEXTENCODING_UTF8, OSTRING_TO_OUSTRING_CVTFLAGS);
            return;
        } catch (BlopObject::BoundsError &) {
            SAL_WARN("registry", "bad data");
        }
    }
    rtl_uString_new(pSuperTypeName);
}

void TYPEREG_CALLTYPE typereg_reader_getDocumentation(void * hEntry, rtl_uString** pDoku)
{
    TypeRegistryEntry* pEntry = static_cast<TypeRegistryEntry*>(hEntry);
@@ -1355,11 +1331,6 @@
    return pEntry->m_pFields->m_numOfEntries;
}

static sal_uInt32 TYPEREG_CALLTYPE getFieldCount(TypeReaderImpl hEntry)
{
    return typereg_reader_getFieldCount(hEntry);
}

void TYPEREG_CALLTYPE typereg_reader_getFieldName(void * hEntry, rtl_uString** pFieldName, sal_uInt16 index)
{
    TypeRegistryEntry* pEntry = static_cast<TypeRegistryEntry*>(hEntry);
@@ -1419,13 +1390,6 @@
    return true;
}

static RTValueType TYPEREG_CALLTYPE getFieldConstValue(TypeReaderImpl hEntry, sal_uInt16 index, RTConstValueUnion* value)
{
    RTValueType t = RT_TYPE_NONE;
    typereg_reader_getFieldValue(hEntry, index, &t, value);
    return t;
}

void TYPEREG_CALLTYPE typereg_reader_getFieldDocumentation(void * hEntry, rtl_uString** pDoku, sal_uInt16 index)
{
    TypeRegistryEntry* pEntry = static_cast<TypeRegistryEntry*>(hEntry);
@@ -1689,72 +1653,4 @@
    rtl_uString_new(pSuperTypeName);
}

RegistryTypeReader::RegistryTypeReader(const sal_uInt8* buffer,
                                              sal_uInt32 bufferLen)
    : m_hImpl(nullptr)
{
    m_hImpl = createEntry(buffer, bufferLen);
}

RegistryTypeReader::~RegistryTypeReader()
{ typereg_reader_release(m_hImpl); }

RTTypeClass RegistryTypeReader::getTypeClass() const
{  return typereg_reader_getTypeClass(m_hImpl); }

OUString RegistryTypeReader::getTypeName() const
{
    OUString sRet;
    typereg_reader_getTypeName(m_hImpl, &sRet.pData);
    return sRet;
}

OUString RegistryTypeReader::getSuperTypeName() const
{
    OUString sRet;
    ::getSuperTypeName(m_hImpl, &sRet.pData);
    return sRet;
}

sal_uInt32 RegistryTypeReader::getFieldCount() const
{   return ::getFieldCount(m_hImpl); }

OUString RegistryTypeReader::getFieldName( sal_uInt16 index ) const
{
    OUString sRet;
    typereg_reader_getFieldName(m_hImpl, &sRet.pData, index);
    return sRet;
}

OUString RegistryTypeReader::getFieldType( sal_uInt16 index ) const
{
    OUString sRet;
    typereg_reader_getFieldTypeName(m_hImpl, &sRet.pData, index);
    return sRet;
}

RTFieldAccess RegistryTypeReader::getFieldAccess( sal_uInt16 index ) const
{  return typereg_reader_getFieldFlags(m_hImpl, index); }

RTConstValue RegistryTypeReader::getFieldConstValue( sal_uInt16 index ) const
{
    RTConstValue ret;
    ret.m_type = ::getFieldConstValue(m_hImpl, index, &ret.m_value);
    return ret;
}

OUString RegistryTypeReader::getFieldDoku( sal_uInt16 index ) const
{
    OUString sRet;
    typereg_reader_getFieldDocumentation(m_hImpl, &sRet.pData, index);
    return sRet;
}

OUString RegistryTypeReader::getFieldFileName( sal_uInt16 index ) const
{
    OUString sRet;
    typereg_reader_getFieldFileName(m_hImpl, &sRet.pData, index);
    return sRet;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/registry/source/reflread.hxx b/registry/source/reflread.hxx
deleted file mode 100644
index 5fc4282..0000000
--- a/registry/source/reflread.hxx
+++ /dev/null
@@ -1,114 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#ifndef INCLUDED_REGISTRY_SOURCE_REFLREAD_HXX
#define INCLUDED_REGISTRY_SOURCE_REFLREAD_HXX

#include <registry/refltype.hxx>
#include <rtl/ustring.hxx>

/// Implementation handle
typedef void* TypeReaderImpl;

/** RegistryTypeReades reads a binary type blob.

    This class provides the necessary functions to read type information
    for all kinds of types of a type blob.

    @deprecated
    use typereg::Reader instead
*/
class RegistryTypeReader
{
public:

    /** Constructor.

        @param buffer points to the binary data block.
        @param bufferLen specifies the size of the binary data block.
     */
    RegistryTypeReader(const sal_uInt8* buffer,
                              sal_uInt32 bufferLen);

    /// Destructor. The Destructor frees the data block if the copyData flag was TRUE.
    ~RegistryTypeReader();

    /** returns the typeclass of the type represented by this blob.

        This function will always return the type class without the internal
        RT_TYPE_PUBLISHED flag set.
     */
    RTTypeClass      getTypeClass() const;

    /** returns the full qualified name of the type.
     */
    OUString  getTypeName() const;

    /** returns the full qualified name of the supertype.
     */
    OUString  getSuperTypeName() const;

    /** returns the number of fields (attributes/properties, enum values or number
        of constants in a module).

     */
    sal_uInt32       getFieldCount() const;

    /** returns the name of the field specified by index.
     */
    OUString  getFieldName( sal_uInt16 index ) const;

    /** returns the full qualified name of the field specified by index.
     */
    OUString  getFieldType( sal_uInt16 index ) const;

    /** returns the access mode of the field specified by index.
     */
    RTFieldAccess    getFieldAccess( sal_uInt16 index ) const;

    /** returns the value of the field specified by index.

        This function returns the value of an enum value or of a constant.
     */
    RTConstValue     getFieldConstValue( sal_uInt16 index ) const;

    /** returns the documentation string for the field specified by index.

        Each field of a type can have their own documentation.
     */
    OUString  getFieldDoku( sal_uInt16 index ) const;

    /** returns the IDL filename of the field specified by index.

        The IDL filename of a field can differ from the filename of the ype itself
        because modules and also constants can be defined in different IDL files.
     */
    OUString  getFieldFileName( sal_uInt16 index ) const;

private:
    RegistryTypeReader(RegistryTypeReader const &) = delete;
    void operator =(RegistryTypeReader const &) = delete;

    /// stores the handle of an implementation class
    TypeReaderImpl                                              m_hImpl;
};

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/registry/source/reflwrit.cxx b/registry/source/reflwrit.cxx
index 8f8e833..7517f24 100644
--- a/registry/source/reflwrit.cxx
+++ b/registry/source/reflwrit.cxx
@@ -18,49 +18,15 @@
 */


#include <new>
#include <memory>
#include <algorithm>
#include <sal/types.h>
#include <osl/endian.h>
#include <rtl/string.hxx>
#include <rtl/ustring.hxx>
#include <rtl/ustring.h>

#include "reflwrit.hxx"
#include <registry/refltype.hxx>
#include <registry/version.h>
#include <registry/writer.h>

#include "reflcnst.hxx"


namespace {

OString toByteString(rtl_uString const * str) {
    return OString(
        str->buffer, str->length, RTL_TEXTENCODING_UTF8,
        OUSTRING_TO_OSTRING_CVTFLAGS);
}

}

const sal_Unicode NULL_WSTRING[1] = { 0 };

#define BLOP_OFFSET_MAGIC       0
#define BLOP_OFFSET_SIZE        (BLOP_OFFSET_MAGIC + sizeof(sal_uInt32))
#define BLOP_OFFSET_MINOR       (BLOP_OFFSET_SIZE + sizeof(sal_uInt32))
#define BLOP_OFFSET_MAJOR       (BLOP_OFFSET_MINOR + sizeof(sal_uInt16))
#define BLOP_OFFSET_N_ENTRIES   (BLOP_OFFSET_MAJOR + sizeof(sal_uInt16))
#define BLOP_HEADER_N_ENTRIES   6

#define BLOP_FIELD_N_ENTRIES        6

#define BLOP_METHOD_N_ENTRIES   5

#define BLOP_PARAM_N_ENTRIES    3

#define BLOP_REFERENCE_N_ENTRIES    4

sal_uInt32 UINT16StringLen(const sal_uInt8* wstring)
{
    if (!wstring) return 0;
@@ -159,1178 +125,4 @@
    return (sizeof(sal_uInt32) + sizeof(sal_uInt32));
}

/**************************************************************************

    buffer write functions

**************************************************************************/

namespace {

/**************************************************************************

    struct CPInfo

**************************************************************************/

struct CPInfo
{
    union
    {
        const char*         aUtf8;
        RTUik*              aUik;
        RTConstValueUnion   aConst;
    } m_value;
    struct CPInfo*  m_next;
    CPInfoTag       m_tag;
    sal_uInt16      m_index;

    CPInfo(CPInfoTag tag, struct CPInfo* prev);

    sal_uInt32 getBlopSize() const;

    sal_uInt32 toBlop(sal_uInt8* buffer);
};

CPInfo::CPInfo(CPInfoTag tag, struct CPInfo* prev)
    : m_next(nullptr)
    , m_tag(tag)
    , m_index(0)
{
    if (prev)
    {
        m_index = prev->m_index + 1;
        prev->m_next = this;
    }
}

sal_uInt32 CPInfo::getBlopSize() const
{
    sal_uInt32 size = sizeof(sal_uInt32) /* size */ + sizeof(sal_uInt16) /* tag */;

    switch (m_tag)
    {
        case CP_TAG_CONST_BOOL:
            size += sizeof(sal_uInt8);
            break;
        case CP_TAG_CONST_BYTE:
            size += sizeof(sal_uInt8);
            break;
        case CP_TAG_CONST_INT16:
            size += sizeof(sal_Int16);
            break;
        case CP_TAG_CONST_UINT16:
            size += sizeof(sal_uInt16);
            break;
        case CP_TAG_CONST_INT32:
            size += sizeof(sal_Int32);
            break;
        case CP_TAG_CONST_UINT32:
            size += sizeof(sal_uInt32);
            break;
        case CP_TAG_CONST_INT64:
              size += sizeof(sal_Int64);
            break;
        case CP_TAG_CONST_UINT64:
            size += sizeof(sal_uInt64);
            break;
        case CP_TAG_CONST_FLOAT:
            size += sizeof(sal_uInt32);
            break;
        case CP_TAG_CONST_DOUBLE:
            size += sizeof(sal_uInt32) + sizeof(sal_uInt32);
            break;
        case CP_TAG_CONST_STRING:
            size += (rtl_ustr_getLength(m_value.aConst.aString) + 1) * sizeof(sal_uInt16);
            break;
        case CP_TAG_UTF8_NAME:
            size += strlen(m_value.aUtf8) + 1;
            break;
        case CP_TAG_UIK:
            size += sizeof(sal_uInt32) + sizeof(sal_uInt16) + sizeof(sal_uInt16) + sizeof(sal_uInt32) + sizeof(sal_uInt32);
            break;
        default:
            break;
    }

    return size;
}


sal_uInt32 CPInfo::toBlop(sal_uInt8* buffer)
{
    sal_uInt8* buff = buffer;

    buff += writeUINT32(buff, getBlopSize());
    buff += writeUINT16(buff, static_cast<sal_uInt16>(m_tag));

    switch (m_tag)
    {
        case CP_TAG_CONST_BOOL:
            buff += writeBYTE(buff, static_cast<sal_uInt8>(m_value.aConst.aBool));
            break;
        case CP_TAG_CONST_BYTE:
            buff += writeBYTE(
                buff, static_cast< sal_uInt8 >(m_value.aConst.aByte));
            break;
        case CP_TAG_CONST_INT16:
            buff += writeINT16(buff, m_value.aConst.aShort);
            break;
        case CP_TAG_CONST_UINT16:
            buff += writeINT16(buff, m_value.aConst.aUShort);
            break;
        case CP_TAG_CONST_INT32:
            buff += writeINT32(buff, m_value.aConst.aLong);
            break;
        case CP_TAG_CONST_UINT32:
            buff += writeUINT32(buff, m_value.aConst.aULong);
            break;
        case CP_TAG_CONST_INT64:
            buff += writeUINT64(buff, m_value.aConst.aHyper);
            break;
        case CP_TAG_CONST_UINT64:
            buff += writeUINT64(buff, m_value.aConst.aUHyper);
            break;
        case CP_TAG_CONST_FLOAT:
            buff += writeFloat(buff, m_value.aConst.aFloat);
            break;
        case CP_TAG_CONST_DOUBLE:
            buff += writeDouble(buff, m_value.aConst.aDouble);
            break;
        case CP_TAG_CONST_STRING:
            buff += writeString(buff, m_value.aConst.aString);
            break;
        case CP_TAG_UTF8_NAME:
            buff += writeUtf8(buff, m_value.aUtf8);
            break;
        case CP_TAG_UIK:
            buff += writeUINT32(buff, m_value.aUik->m_Data1);
            buff += writeUINT16(buff, m_value.aUik->m_Data2);
            buff += writeUINT16(buff, m_value.aUik->m_Data3);
            buff += writeUINT32(buff, m_value.aUik->m_Data4);
            buff += writeUINT32(buff, m_value.aUik->m_Data5);
            break;
        default:
            break;
    }

    return (buff - buffer);
}


/**************************************************************************

    class FieldEntry

**************************************************************************/

class FieldEntry
{

public:

    OString           m_name;
    OString           m_typeName;
    OString           m_doku;
    OString           m_fileName;
    RTFieldAccess     m_access;
    RTValueType       m_constValueType;
    RTConstValueUnion m_constValue;

    FieldEntry();
    ~FieldEntry();

    void setData(const OString&    name,
                 const OString&    typeName,
                 const OString&    doku,
                 const OString&    fileName,
                 RTFieldAccess     access,
                 RTValueType       constValueType,
                 RTConstValueUnion constValue);
        // throws std::bad_alloc
};

FieldEntry::FieldEntry()
    : m_access(RTFieldAccess::INVALID)
    , m_constValueType(RT_TYPE_NONE)
{
}

FieldEntry::~FieldEntry()
{
    if (
        (m_constValueType == RT_TYPE_STRING) &&
        m_constValue.aString &&
        (m_constValue.aString != NULL_WSTRING)
       )
    {
        delete[] m_constValue.aString;
    }
}

void FieldEntry::setData(const OString&    name,
                         const OString&    typeName,
                         const OString&    doku,
                         const OString&    fileName,
                         RTFieldAccess      access,
                         RTValueType        constValueType,
                         RTConstValueUnion  constValue)
{
    std::unique_ptr<sal_Unicode[]> newValue;
    if (constValueType == RT_TYPE_STRING && constValue.aString != nullptr) {
        sal_Int32 n = rtl_ustr_getLength(constValue.aString) + 1;
        newValue.reset(new sal_Unicode[n]);
        memcpy(newValue.get(), constValue.aString, n * sizeof (sal_Unicode));
    }

    m_name = name;
    m_typeName = typeName;
    m_doku = doku;
    m_fileName = fileName;

    if (
        (m_constValueType == RT_TYPE_STRING) &&
        m_constValue.aString &&
        (m_constValue.aString != NULL_WSTRING)
       )
    {
        delete[] m_constValue.aString;
    }

    m_access = access;
    m_constValueType = constValueType;

    if (m_constValueType == RT_TYPE_STRING)
    {
        if (constValue.aString == nullptr)
            m_constValue.aString = NULL_WSTRING;
        else
        {
            m_constValue.aString = newValue.release();
        }
    }
    else
    {
        m_constValue = constValue;
    }
}

/**************************************************************************

    class ParamEntry

**************************************************************************/

class ParamEntry
{
public:

    OString     m_typeName;
    OString     m_name;
    RTParamMode m_mode;

    ParamEntry();

    void setData(const OString& typeName,
                 const OString& name,
                 RTParamMode    mode);
};

ParamEntry::ParamEntry()
    : m_mode(RT_PARAM_INVALID)
{
}

void ParamEntry::setData(const OString& typeName,
                         const OString& name,
                         RTParamMode    mode)
{
    m_name = name;
    m_typeName = typeName;
    m_mode = mode;
}

/**************************************************************************

    class ReferenceEntry

**************************************************************************/

class ReferenceEntry
{
public:

    OString         m_name;
    OString         m_doku;
    RTReferenceType m_type;
    RTFieldAccess   m_access;

    ReferenceEntry();

    void setData(const OString&     name,
                 RTReferenceType    refType,
                 const OString&     doku,
                 RTFieldAccess      access);
};

ReferenceEntry::ReferenceEntry()
    : m_type(RTReferenceType::INVALID)
    , m_access(RTFieldAccess::INVALID)
{
}

void ReferenceEntry::setData(const OString&    name,
                             RTReferenceType   refType,
                             const OString&    doku,
                             RTFieldAccess     access)
{
    m_name = name;
    m_doku = doku;
    m_type = refType;
    m_access = access;
}

/**************************************************************************

    class MethodEntry

**************************************************************************/

class MethodEntry
{
public:

    OString         m_name;
    OString         m_returnTypeName;
    RTMethodMode    m_mode;
    sal_uInt16      m_paramCount;
    std::unique_ptr<ParamEntry[]> m_params;
    sal_uInt16      m_excCount;
    std::unique_ptr<OString[]>    m_excNames;
    OString         m_doku;

    MethodEntry();

    void setData(const OString&    name,
                 const OString&    returnTypeName,
                 RTMethodMode      mode,
                 sal_uInt16        paramCount,
                 sal_uInt16        excCount,
                 const OString&    doku);

    void setExcName(sal_uInt16 excIndex, const OString& name) const;

protected:

    void reallocParams(sal_uInt16 size);
    void reallocExcs(sal_uInt16 size);
};

MethodEntry::MethodEntry()
    : m_mode(RTMethodMode::INVALID)
    , m_paramCount(0)
    , m_excCount(0)
{
}

void MethodEntry::setData(const OString&    name,
                          const OString&    returnTypeName,
                          RTMethodMode      mode,
                          sal_uInt16        paramCount,
                          sal_uInt16        excCount,
                          const OString&    doku)
{
    m_name = name;
    m_returnTypeName = returnTypeName;
    m_doku = doku;

    m_mode = mode;

    reallocParams(paramCount);
    reallocExcs(excCount);
}

void MethodEntry::setExcName(sal_uInt16 excIndex, const OString& name) const
{
    if (excIndex < m_excCount)
    {
        m_excNames[excIndex] = name;
    }
}

void MethodEntry::reallocParams(sal_uInt16 size)
{
    ParamEntry* newParams;

    if (size)
        newParams = new ParamEntry[size];
    else
        newParams = nullptr;

    if (m_paramCount)
    {
        sal_uInt16 i;
        sal_uInt16 mn = std::min(size, m_paramCount);

        for (i = 0; i < mn; i++)
        {
            newParams[i].setData(m_params[i].m_typeName, m_params[i].m_name, m_params[i].m_mode);
        }

        m_params.reset();
    }

    m_paramCount = size;
    m_params.reset( newParams );
}

void MethodEntry::reallocExcs(sal_uInt16 size)
{
    OString* newExcNames;

    if (size)
        newExcNames = new OString[size];
    else
        newExcNames = nullptr;

    sal_uInt16 i;
    sal_uInt16 mn = std::min(size, m_excCount);

    for (i = 0; i < mn; i++)
    {
        newExcNames[i] = m_excNames[i];
    }

    m_excCount = size;
    m_excNames.reset( newExcNames );
}


/**************************************************************************

    class TypeRegistryEntry

**************************************************************************/

class TypeWriter
{

public:

    sal_uInt32          m_refCount;
    typereg_Version     m_version;
    RTTypeClass         m_typeClass;
    OString             m_typeName;
    sal_uInt16          m_nSuperTypes;
    std::unique_ptr<OString[]>
                        m_superTypeNames;
    OString             m_doku;
    OString             m_fileName;
    sal_uInt16          m_fieldCount;
    FieldEntry*         m_fields;
    sal_uInt16          m_methodCount;
    MethodEntry*        m_methods;
    sal_uInt16          m_referenceCount;
    ReferenceEntry*     m_references;

    std::unique_ptr<sal_uInt8[]> m_blop;
    sal_uInt32          m_blopSize;

    TypeWriter(typereg_Version version,
               OString const & documentation,
               OString const & fileName,
               RTTypeClass      RTTypeClass,
               bool             published,
               const OString&   typeName,
               sal_uInt16       superTypeCount,
               sal_uInt16       FieldCount,
               sal_uInt16       methodCount,
               sal_uInt16       referenceCount);

    ~TypeWriter();

    void setSuperType(sal_uInt16 index, OString const & name) const;

    void createBlop(); // throws std::bad_alloc
};

TypeWriter::TypeWriter(typereg_Version version,
                       OString const & documentation,
                       OString const & fileName,
                       RTTypeClass      RTTypeClass,
                       bool             published,
                       const OString&   typeName,
                       sal_uInt16       superTypeCount,
                       sal_uInt16       fieldCount,
                       sal_uInt16       methodCount,
                       sal_uInt16       referenceCount)
    : m_refCount(1)
    , m_version(version)
    , m_typeClass(
        static_cast< enum RTTypeClass >(
            RTTypeClass | (published ? RT_TYPE_PUBLISHED : 0)))
     , m_typeName(typeName)
    , m_nSuperTypes(superTypeCount)
    , m_doku(documentation)
    , m_fileName(fileName)
    , m_fieldCount(fieldCount)
    , m_fields(nullptr)
    , m_methodCount(methodCount)
    , m_methods(nullptr)
    , m_referenceCount(referenceCount)
    , m_references(nullptr)
    , m_blopSize(0)
{
    if (m_nSuperTypes > 0)
    {
        m_superTypeNames.reset( new OString[m_nSuperTypes] );
    }

    if (m_fieldCount)
        m_fields = new FieldEntry[fieldCount];

    if (m_methodCount)
        m_methods = new MethodEntry[methodCount];

    if (m_referenceCount)
        m_references = new ReferenceEntry[referenceCount];
}

TypeWriter::~TypeWriter()
{
    if (m_fieldCount)
        delete[] m_fields;

    if (m_methodCount)
        delete[] m_methods;

    if (m_referenceCount)
        delete[] m_references;
}

void TypeWriter::setSuperType(sal_uInt16 index, OString const & name) const
{
    m_superTypeNames[index] = name;
}

void TypeWriter::createBlop()
{
    //TODO: Fix memory leaks that occur when std::bad_alloc is thrown

    std::unique_ptr<sal_uInt8[]>  pBlopFields;
    std::unique_ptr<sal_uInt8[]>  pBlopMethods;
    std::unique_ptr<sal_uInt8[]>  pBlopReferences;
    sal_uInt8*  pBuffer             = nullptr;
    sal_uInt32  blopFieldsSize      = 0;
    sal_uInt32  blopMethodsSize     = 0;
    sal_uInt32  blopReferenceSize   = 0;

    CPInfo  root(CP_TAG_INVALID, nullptr);
    sal_uInt16  cpIndexThisName = 0;
    std::unique_ptr<sal_uInt16[]> cpIndexSuperNames;
    sal_uInt16  cpIndexDoku = 0;
    sal_uInt16  cpIndexFileName = 0;
    CPInfo* pInfo = nullptr;

    sal_uInt16  entrySize = sizeof(sal_uInt16);
    sal_uInt32  blopHeaderEntrySize = BLOP_OFFSET_N_ENTRIES + entrySize + (BLOP_HEADER_N_ENTRIES * entrySize);
    sal_uInt32  blopFieldEntrySize = BLOP_FIELD_N_ENTRIES * entrySize;
    sal_uInt32  blopMethodEntrySize = BLOP_METHOD_N_ENTRIES * entrySize;
    sal_uInt32  blopParamEntrySize = BLOP_PARAM_N_ENTRIES * entrySize;
    sal_uInt32  blopReferenceEntrySize = BLOP_REFERENCE_N_ENTRIES * entrySize;

    sal_uInt32 blopSize = blopHeaderEntrySize;

    // create CP entry for this name
    pInfo = new CPInfo(CP_TAG_UTF8_NAME, &root);
    pInfo->m_value.aUtf8 = m_typeName.getStr();
    cpIndexThisName = pInfo->m_index;

    // nSuperTypes
    blopSize += entrySize;

    // create CP entry for super names
    if (m_nSuperTypes)
    {
        blopSize += m_nSuperTypes * entrySize;

        cpIndexSuperNames.reset(new sal_uInt16[m_nSuperTypes]);

        for (sal_uInt32 i=0; i < m_nSuperTypes; i++)
        {
            pInfo = new CPInfo(CP_TAG_UTF8_NAME, pInfo);
            pInfo->m_value.aUtf8 = m_superTypeNames[i].getStr();
            cpIndexSuperNames[i] = pInfo->m_index;
        }
    }

    // create CP entry for doku
    if (!m_doku.isEmpty())
    {
        pInfo = new CPInfo(CP_TAG_UTF8_NAME, pInfo);
        pInfo->m_value.aUtf8 = m_doku.getStr();
        cpIndexDoku = pInfo->m_index;
    }

    // create CP entry for idl source filename
    if (!m_fileName.isEmpty())
    {
        pInfo = new CPInfo(CP_TAG_UTF8_NAME, pInfo);
        pInfo->m_value.aUtf8 = m_fileName.getStr();
        cpIndexFileName = pInfo->m_index;
    }

    // fields blop
    blopSize += sizeof(sal_uInt16); // fieldCount + nFieldEntries

    if (m_fieldCount)
    {
        sal_uInt16 cpIndexName = 0;
        sal_uInt16 cpIndexTypeName = 0;
        sal_uInt16 cpIndexValue = 0;
        sal_uInt16 cpIndexDoku2 = 0;
        sal_uInt16 cpIndexFileName2 = 0;

        // nFieldEntries + n fields
        blopFieldsSize = sizeof(sal_uInt16) + (m_fieldCount * blopFieldEntrySize);

        blopSize += blopFieldsSize;

        pBlopFields.reset(new sal_uInt8[blopFieldsSize]);
        pBuffer = pBlopFields.get();

        pBuffer += writeUINT16(pBuffer, BLOP_FIELD_N_ENTRIES);

        for (sal_uInt16 i = 0; i < m_fieldCount; i++)
        {
            cpIndexName = 0;
            cpIndexTypeName = 0;
            cpIndexValue = 0;
            cpIndexDoku2 = 0;
            cpIndexFileName2 = 0;

            pBuffer += writeUINT16(pBuffer, static_cast<sal_uInt16>(m_fields[i].m_access));

            if (!m_fields[i].m_name.isEmpty())
            {
                pInfo = new CPInfo(CP_TAG_UTF8_NAME, pInfo);
                pInfo->m_value.aUtf8 = m_fields[i].m_name.getStr();
                cpIndexName = pInfo->m_index;
            }
            pBuffer += writeUINT16(pBuffer, cpIndexName);

            if (!m_fields[i].m_typeName.isEmpty())
            {
                pInfo = new CPInfo(CP_TAG_UTF8_NAME, pInfo);
                pInfo->m_value.aUtf8 = m_fields[i].m_typeName.getStr();
                cpIndexTypeName = pInfo->m_index;
            }
            pBuffer += writeUINT16(pBuffer, cpIndexTypeName);

            if (m_fields[i].m_constValueType != RT_TYPE_NONE)
            {
                pInfo = new CPInfo(static_cast<CPInfoTag>(m_fields[i].m_constValueType), pInfo);
                pInfo->m_value.aConst = m_fields[i].m_constValue;
                cpIndexValue = pInfo->m_index;
            }
            pBuffer += writeUINT16(pBuffer, cpIndexValue);

            if (!m_fields[i].m_doku.isEmpty())
            {
                pInfo = new CPInfo(CP_TAG_UTF8_NAME, pInfo);
                pInfo->m_value.aUtf8 = m_fields[i].m_doku.getStr();
                cpIndexDoku2 = pInfo->m_index;
            }
            pBuffer += writeUINT16(pBuffer, cpIndexDoku2);

            if (!m_fields[i].m_fileName.isEmpty())
            {
                pInfo = new CPInfo(CP_TAG_UTF8_NAME, pInfo);
                pInfo->m_value.aUtf8 = m_fields[i].m_fileName.getStr();
                cpIndexFileName2 = pInfo->m_index;
            }
            pBuffer += writeUINT16(pBuffer, cpIndexFileName2);
        }
    }

    // methods blop
    blopSize += sizeof(sal_uInt16); // methodCount

    if (m_methodCount)
    {
        std::unique_ptr<sal_uInt16[]> pMethodEntrySize( new sal_uInt16[m_methodCount] );
        sal_uInt16  cpIndexName = 0;
        sal_uInt16  cpIndexReturn = 0;
        sal_uInt16  cpIndexDoku2 = 0;

        // nMethodEntries + nParamEntries
        blopMethodsSize = (2 * sizeof(sal_uInt16));

        for (sal_uInt16 i = 0; i < m_methodCount; i++)
        {
            pMethodEntrySize[i] = static_cast<sal_uInt16>( blopMethodEntrySize +                                 // header
                  sizeof(sal_uInt16) +                                  // parameterCount
                  (m_methods[i].m_paramCount * blopParamEntrySize) +    // exceptions
                  sizeof(sal_uInt16) +                                  // exceptionCount
                  (m_methods[i].m_excCount * sizeof(sal_uInt16)) );     // exceptions

            blopMethodsSize += pMethodEntrySize[i];
        }

        pBlopMethods.reset(new sal_uInt8[blopMethodsSize]);

        blopSize += blopMethodsSize;

        pBuffer = pBlopMethods.get();

        pBuffer += writeUINT16(pBuffer, BLOP_METHOD_N_ENTRIES);
        pBuffer += writeUINT16(pBuffer, BLOP_PARAM_N_ENTRIES );

        for (sal_uInt16 i = 0; i < m_methodCount; i++)
        {
            cpIndexReturn = 0;
            cpIndexDoku2 = 0;

            pBuffer += writeUINT16(pBuffer, pMethodEntrySize[i]);
            pBuffer += writeUINT16(
                pBuffer,
                sal::static_int_cast< sal_uInt16 >(m_methods[i].m_mode));

            if (!m_methods[i].m_name.isEmpty())
            {
                pInfo = new CPInfo(CP_TAG_UTF8_NAME, pInfo);
                pInfo->m_value.aUtf8 = m_methods[i].m_name.getStr();
                cpIndexName = pInfo->m_index;
            }
            pBuffer += writeUINT16(pBuffer, cpIndexName);
            cpIndexName = 0;

            if (!m_methods[i].m_returnTypeName.isEmpty())
            {
                pInfo = new CPInfo(CP_TAG_UTF8_NAME, pInfo);
                pInfo->m_value.aUtf8 = m_methods[i].m_returnTypeName.getStr();
                cpIndexReturn = pInfo->m_index;
            }
            pBuffer += writeUINT16(pBuffer, cpIndexReturn);

            if (!m_methods[i].m_doku.isEmpty())
            {
                pInfo = new CPInfo(CP_TAG_UTF8_NAME, pInfo);
                pInfo->m_value.aUtf8 = m_methods[i].m_doku.getStr();
                cpIndexDoku2 = pInfo->m_index;
            }
            pBuffer += writeUINT16(pBuffer, cpIndexDoku2);

            sal_uInt16 j;

            pBuffer += writeUINT16(pBuffer, m_methods[i].m_paramCount);

            for (j = 0; j < m_methods[i].m_paramCount; j++)
            {
                if (!m_methods[i].m_params[j].m_typeName.isEmpty())
                {
                    pInfo = new CPInfo(CP_TAG_UTF8_NAME, pInfo);
                    pInfo->m_value.aUtf8 = m_methods[i].m_params[j].m_typeName.getStr();
                    cpIndexName = pInfo->m_index;
                }
                pBuffer += writeUINT16(pBuffer, cpIndexName);
                cpIndexName = 0;

                pBuffer += writeUINT16(
                    pBuffer,
                    sal::static_int_cast< sal_uInt16 >(
                        m_methods[i].m_params[j].m_mode));

                if (!m_methods[i].m_params[j].m_name.isEmpty())
                {
                    pInfo = new CPInfo(CP_TAG_UTF8_NAME, pInfo);
                    pInfo->m_value.aUtf8 = m_methods[i].m_params[j].m_name.getStr();
                    cpIndexName = pInfo->m_index;
                }
                pBuffer += writeUINT16(pBuffer, cpIndexName);
                cpIndexName = 0;
            }

            pBuffer += writeUINT16(pBuffer, m_methods[i].m_excCount);

            for (j = 0; j < m_methods[i].m_excCount; j++)
            {
                if (!m_methods[i].m_excNames[j].isEmpty())
                {
                    pInfo = new CPInfo(CP_TAG_UTF8_NAME, pInfo);
                    pInfo->m_value.aUtf8 = m_methods[i].m_excNames[j].getStr();
                    cpIndexName = pInfo->m_index;
                }
                pBuffer += writeUINT16(pBuffer, cpIndexName);
                cpIndexName = 0;
            }
        }
    }

    // reference blop
    blopSize += entrySize; // referenceCount

    if (m_referenceCount)
    {
        sal_uInt16 cpIndexName = 0;
        sal_uInt16 cpIndexDoku2 = 0;

        // nReferenceEntries + n references
        blopReferenceSize = entrySize + (m_referenceCount * blopReferenceEntrySize);

        blopSize += blopReferenceSize;

        pBlopReferences.reset(new sal_uInt8[blopReferenceSize]);
        pBuffer = pBlopReferences.get();

        pBuffer += writeUINT16(pBuffer, BLOP_REFERENCE_N_ENTRIES);

        for (sal_uInt16 i = 0; i < m_referenceCount; i++)
        {
            pBuffer += writeUINT16(
                pBuffer,
                sal::static_int_cast< sal_uInt16 >(m_references[i].m_type));

            cpIndexName = 0;
            cpIndexDoku2 = 0;

            if (!m_references[i].m_name.isEmpty())
            {
                pInfo = new CPInfo(CP_TAG_UTF8_NAME, pInfo);
                pInfo->m_value.aUtf8 = m_references[i].m_name.getStr();
                cpIndexName = pInfo->m_index;
            }
            pBuffer += writeUINT16(pBuffer, cpIndexName);

            if (!m_references[i].m_doku.isEmpty())
            {
                pInfo = new CPInfo(CP_TAG_UTF8_NAME, pInfo);
                pInfo->m_value.aUtf8 = m_references[i].m_doku.getStr();
                cpIndexDoku2 = pInfo->m_index;
            }
            pBuffer += writeUINT16(pBuffer, cpIndexDoku2);

            pBuffer += writeUINT16(pBuffer, static_cast<sal_uInt16>(m_references[i].m_access));
        }
    }


    // get CP infos blop-length
    pInfo = root.m_next;
    sal_uInt32 cpBlopSize = 0;
    sal_uInt16 cpCount = 0;

    while (pInfo)
    {
        cpBlopSize += pInfo->getBlopSize();
        cpCount++;
        pInfo = pInfo->m_next;
    }

    blopSize += cpBlopSize;
    blopSize += sizeof(sal_uInt16);   // constantPoolCount

    // write all in flat buffer

    sal_uInt8 * blop = new sal_uInt8[blopSize];

    pBuffer = blop;

    // Assumes two's complement arithmetic with modulo-semantics:
    pBuffer += writeUINT32(pBuffer, magic + m_version);
    pBuffer += writeUINT32(pBuffer, blopSize);
    pBuffer += writeUINT16(pBuffer, minorVersion);
    pBuffer += writeUINT16(pBuffer, majorVersion);
    pBuffer += writeUINT16(pBuffer, BLOP_HEADER_N_ENTRIES);

    pBuffer += writeUINT16(pBuffer, sal_uInt16(RT_UNO_IDL));
    pBuffer += writeUINT16(pBuffer, static_cast<sal_uInt16>(m_typeClass));
    pBuffer += writeUINT16(pBuffer, cpIndexThisName);
    pBuffer += writeUINT16(pBuffer, 0); // cpIndexUik
    pBuffer += writeUINT16(pBuffer, cpIndexDoku);
    pBuffer += writeUINT16(pBuffer, cpIndexFileName);

    // write supertypes
    pBuffer += writeUINT16(pBuffer, m_nSuperTypes);
    if (m_nSuperTypes)
    {
        for (sal_uInt32 i=0; i < m_nSuperTypes; i++)
        {
            pBuffer += writeUINT16(pBuffer, cpIndexSuperNames[i]);
        }
        cpIndexSuperNames.reset();
    }

    pBuffer += writeUINT16(pBuffer, cpCount);

    // write and delete CP infos
    pInfo = root.m_next;

    while (pInfo)
    {
        CPInfo* pNextInfo = pInfo->m_next;

        pBuffer += pInfo->toBlop(pBuffer);
        delete pInfo;

        pInfo = pNextInfo;
    }

    auto writeList = [&pBuffer](
        sal_uInt16 count, sal_uInt8 * data, sal_uInt32 size)
    {
        pBuffer += writeUINT16(pBuffer, count);
        if (size != 0) {
            memcpy(pBuffer, data, size);
            pBuffer += size;
        }
    };

    // write fields
    writeList(m_fieldCount, pBlopFields.get(), blopFieldsSize);

    // write methods
    writeList(m_methodCount, pBlopMethods.get(), blopMethodsSize);

    // write references
    writeList(m_referenceCount, pBlopReferences.get(), blopReferenceSize);

    m_blop.reset( blop );
    m_blopSize = blopSize;
}

} // unnamed namespace

/**************************************************************************

    C-API

**************************************************************************/

extern "C" {

static void TYPEREG_CALLTYPE release(TypeWriterImpl hEntry)
{
    TypeWriter* pEntry = static_cast<TypeWriter*>(hEntry);

    if (pEntry != nullptr)
    {
        if (--pEntry->m_refCount == 0)
            delete pEntry;
    }
}

sal_Bool TYPEREG_CALLTYPE typereg_writer_setFieldData(
    void * handle, sal_uInt16 index, rtl_uString const * documentation,
    rtl_uString const * fileName, RTFieldAccess flags, rtl_uString const * name,
    rtl_uString const * typeName, RTValueType valueType,
    RTConstValueUnion valueValue)
    SAL_THROW_EXTERN_C()
{
    try {
        static_cast< TypeWriter * >(handle)->m_fields[index].setData(
            toByteString(name), toByteString(typeName),
            toByteString(documentation), toByteString(fileName), flags,
            valueType, valueValue);
    } catch (std::bad_alloc &) {
        return false;
    }
    return true;
}

static void TYPEREG_CALLTYPE setFieldData(TypeWriterImpl    hEntry,
                                          sal_uInt16        index,
                                          rtl_uString const * name,
                                          rtl_uString const * typeName,
                                          rtl_uString const * doku,
                                          rtl_uString const * fileName,
                                          RTFieldAccess     access,
                                          RTValueType       valueType,
                                          RTConstValueUnion constValue)
{
    typereg_writer_setFieldData(
        hEntry, index, doku, fileName, access, name, typeName, valueType,
        constValue);
}

sal_Bool TYPEREG_CALLTYPE typereg_writer_setMethodData(
    void * handle, sal_uInt16 index, rtl_uString const * documentation,
    RTMethodMode flags, rtl_uString const * name,
    rtl_uString const * returnTypeName, sal_uInt16 parameterCount,
    sal_uInt16 exceptionCount)
    SAL_THROW_EXTERN_C()
{
    try {
        static_cast< TypeWriter * >(handle)->m_methods[index].setData(
            toByteString(name), toByteString(returnTypeName), flags,
            parameterCount, exceptionCount, toByteString(documentation));
    } catch (std::bad_alloc &) {
        return false;
    }
    return true;
}

sal_Bool TYPEREG_CALLTYPE typereg_writer_setMethodParameterData(
    void const * handle, sal_uInt16 methodIndex, sal_uInt16 parameterIndex,
    RTParamMode flags, rtl_uString const * name, rtl_uString const * typeName)
    SAL_THROW_EXTERN_C()
{
    try {
        static_cast< TypeWriter const * >(handle)->
            m_methods[methodIndex].m_params[parameterIndex].setData(
                toByteString(typeName), toByteString(name), flags);
    } catch (std::bad_alloc &) {
        return false;
    }
    return true;
}

sal_Bool TYPEREG_CALLTYPE typereg_writer_setMethodExceptionTypeName(
    void const * handle, sal_uInt16 methodIndex, sal_uInt16 exceptionIndex,
    rtl_uString const * typeName)
    SAL_THROW_EXTERN_C()
{
    try {
        static_cast< TypeWriter const * >(handle)->m_methods[methodIndex].setExcName(
            exceptionIndex, toByteString(typeName));
    } catch (std::bad_alloc &) {
        return false;
    }
    return true;
}

void const * TYPEREG_CALLTYPE typereg_writer_getBlob(void * handle, sal_uInt32 * size)
    SAL_THROW_EXTERN_C()
{
    TypeWriter * writer = static_cast< TypeWriter * >(handle);
    if (!writer->m_blop) {
        try {
            writer->createBlop();
        } catch (std::bad_alloc &) {
            *size = 0;
            return nullptr;
        }
    }
    *size = writer->m_blopSize;
    return writer->m_blop.get();
}

static const sal_uInt8* TYPEREG_CALLTYPE getBlop(TypeWriterImpl hEntry)
{
    sal_uInt32 size;
    return static_cast< sal_uInt8 const * >(
        typereg_writer_getBlob(hEntry, &size));
}

static sal_uInt32 TYPEREG_CALLTYPE getBlopSize(TypeWriterImpl hEntry)
{
    sal_uInt32 size;
    typereg_writer_getBlob(hEntry, &size);
    return size;
}

sal_Bool TYPEREG_CALLTYPE typereg_writer_setReferenceData(
    void * handle, sal_uInt16 index, rtl_uString const * documentation,
    RTReferenceType sort, RTFieldAccess flags, rtl_uString const * typeName)
    SAL_THROW_EXTERN_C()
{
    try {
        static_cast< TypeWriter * >(handle)->m_references[index].setData(
            toByteString(typeName), sort, toByteString(documentation), flags);
    } catch (std::bad_alloc &) {
        return false;
    }
    return true;
}

void * TYPEREG_CALLTYPE typereg_writer_create(
    typereg_Version version, rtl_uString const * documentation,
    rtl_uString const * fileName, RTTypeClass typeClass, sal_Bool published,
    rtl_uString const * typeName, sal_uInt16 superTypeCount,
    sal_uInt16 fieldCount, sal_uInt16 methodCount, sal_uInt16 referenceCount)
    SAL_THROW_EXTERN_C()
{
    try {
        return new TypeWriter(
            version, toByteString(documentation), toByteString(fileName),
            typeClass, published, toByteString(typeName), superTypeCount,
            fieldCount, methodCount, referenceCount);
    } catch (std::bad_alloc &) {
        return nullptr;
    }
}

void TYPEREG_CALLTYPE typereg_writer_destroy(void * handle) SAL_THROW_EXTERN_C() {
    delete static_cast< TypeWriter * >(handle);
}

sal_Bool TYPEREG_CALLTYPE typereg_writer_setSuperTypeName(
    void const * handle, sal_uInt16 index, rtl_uString const * typeName)
    SAL_THROW_EXTERN_C()
{
    try {
        static_cast< TypeWriter const * >(handle)->setSuperType(
            index, toByteString(typeName));
    } catch (std::bad_alloc &) {
        return false;
    }
    return true;
}

static TypeWriterImpl TYPEREG_CALLTYPE createEntry(
    RTTypeClass typeClass, rtl_uString const * typeName, rtl_uString const * superTypeName,
    sal_uInt16 fieldCount)
{
    OUString empty;
    sal_uInt16 superTypeCount = rtl_uString_getLength(superTypeName) == 0
        ? 0 : 1;
    TypeWriterImpl t = typereg_writer_create(
        TYPEREG_VERSION_0, empty.pData, empty.pData, typeClass, false, typeName,
        superTypeCount, fieldCount, 0/*methodCount*/, 0/*referenceCount*/);
    if (superTypeCount > 0) {
        typereg_writer_setSuperTypeName(t, 0, superTypeName);
    }
    return t;
}

}

RegistryTypeWriter::RegistryTypeWriter(RTTypeClass               RTTypeClass,
                                              const OUString&    typeName,
                                              const OUString&    superTypeName,
                                              sal_uInt16                fieldCount)
    : m_hImpl(nullptr)
{
    m_hImpl = createEntry(RTTypeClass,
                                  typeName.pData,
                                  superTypeName.pData,
                                  fieldCount);
}

RegistryTypeWriter::~RegistryTypeWriter()
{
    release(m_hImpl);
}

void RegistryTypeWriter::setFieldData( sal_uInt16              index,
                                              const OUString&    name,
                                              const OUString&    typeName,
                                              const OUString&    doku,
                                              const OUString&    fileName,
                                              RTFieldAccess           access,
                                              const RTConstValue&     constValue)
{
    ::setFieldData(m_hImpl, index, name.pData, typeName.pData, doku.pData, fileName.pData, access, constValue.m_type, constValue.m_value);
}

const sal_uInt8* RegistryTypeWriter::getBlop()
{
    return ::getBlop(m_hImpl);
}

sal_uInt32 RegistryTypeWriter::getBlopSize()
{
    return ::getBlopSize(m_hImpl);
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/registry/source/reflwrit.hxx b/registry/source/reflwrit.hxx
deleted file mode 100644
index 93cee06..0000000
--- a/registry/source/reflwrit.hxx
+++ /dev/null
@@ -1,103 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#ifndef INCLUDED_REGISTRY_SOURCE_REFLWRIT_HXX
#define INCLUDED_REGISTRY_SOURCE_REFLWRIT_HXX

#include <registry/types.hxx>
#include <rtl/ustring.hxx>

class RTConstValue;

/// Implementation handle
typedef void* TypeWriterImpl;

/** RegistryTypeWriter writes/creates a binary type blob.

    This class provides the necessary functions to write type information
    for all kinds of types into a blob.

    @deprecated
    use typereg::Writer instead
*/
class RegistryTypeWriter
{
public:

    /** Constructor.

        @param RTTypeClass specifies the type of the new blob.
        @param typeName specifies the full qualified type name with '/' as separator.
        @param superTypeName specifies the full qualified type name of the base type
                             with '/' as separator.
        @param fieldCount specifies the number of fields (eg. number of attributes/properties,
                          enum values or constants).
     */
    RegistryTypeWriter(RTTypeClass               RTTypeClass,
                              const OUString&    typeName,
                              const OUString&    superTypeName,
                              sal_uInt16                fieldCount);

    /** Destructor. The Destructor frees the internal data block.

        The pointer (returned by getBlop) will be set to NULL.
     */
    ~RegistryTypeWriter();

    /** sets the data for a field member of a type blob.

        @param index indicates the index of the field.
        @param name specifies the name.
        @param typeName specifies the full qualified typename.
        @param doku specifies the documentation string of the field.
        @param fileName specifies the name of the IDL file where the field is defined.
        @param access specifies the access mode of the field.
        @param constValue specifies the value of the field. The value is only interesting
                          for enum values or constants.
     */
    void setFieldData( sal_uInt16              index,
                              const OUString&    name,
                              const OUString&    typeName,
                              const OUString&    doku,
                              const OUString&    fileName,
                              RTFieldAccess           access,
                              const RTConstValue&     constValue);

    /** returns a pointer to the new type blob.

        The pointer will be invalid (NULL) if the instance of
        the RegistryTypeWriter will be destroyed.
     */
    const sal_uInt8*     getBlop();

    /** returns the size of the new type blob in bytes.
     */
    sal_uInt32       getBlopSize();

private:
    RegistryTypeWriter(RegistryTypeWriter const &) = delete;
    void operator =(RegistryTypeWriter const &) = delete;

    /// stores the handle of an implementation class
    TypeWriterImpl                                               m_hImpl;
};

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/registry/source/regimpl.cxx b/registry/source/regimpl.cxx
index 0d69c64..f33dbc7 100644
--- a/registry/source/regimpl.cxx
+++ b/registry/source/regimpl.cxx
@@ -32,10 +32,6 @@
#include <unistd.h>
#endif

#include "reflread.hxx"

#include "reflwrit.hxx"

#include <registry/reader.hxx>
#include <registry/refltype.hxx>
#include <registry/types.hxx>
@@ -850,402 +846,6 @@
    return RegError::NO_ERROR;
}

RegError ORegistry::loadKey(RegKeyHandle hKey, const OUString& regFileName,
                            bool bWarnings, bool bReport)
{
    ORegKey* pKey = static_cast< ORegKey* >(hKey);

    ORegistry aReg;
    RegError _ret = aReg.initRegistry(regFileName, RegAccessMode::READONLY);
    if (_ret != RegError::NO_ERROR)
        return _ret;
    ORegKey* pRootKey = aReg.getRootKey();

    REG_GUARD(m_mutex);

    OStoreDirectory::iterator   iter;
    OStoreDirectory             rStoreDir(pRootKey->getStoreDir());
    storeError                  _err = rStoreDir.first(iter);

    while (_err == store_E_None)
    {
        OUString const keyName(iter.m_pszName, iter.m_nLength);

        if (iter.m_nAttrib & STORE_ATTRIB_ISDIR)
        {
            _ret = loadAndSaveKeys(pKey, pRootKey, keyName, 0, bWarnings, bReport);
        }
        else
        {
            _ret = loadAndSaveValue(pKey, pRootKey, keyName, 0, bWarnings, bReport);
        }

        if (_ret == RegError::MERGE_ERROR)
            break;
        if (_ret == RegError::MERGE_CONFLICT && bWarnings)
            break;

        _err = rStoreDir.next(iter);
    }

    rStoreDir = OStoreDirectory();
    (void) aReg.releaseKey(pRootKey);
    return _ret;
}

RegError ORegistry::loadAndSaveValue(ORegKey* pTargetKey,
                                     ORegKey const * pSourceKey,
                                     const OUString& valueName,
                                     sal_uInt32 nCut,
                                     bool bWarnings,
                                     bool bReport)
{
    OStoreStream    rValue;
    RegValueType    valueType;
    sal_uInt32      valueSize;
    sal_uInt32      nSize;
    storeAccessMode sourceAccess = storeAccessMode::ReadWrite;
    OUString        sTargetPath(pTargetKey->getName());
    OUString        sSourcePath(pSourceKey->getName());

    if (pSourceKey->isReadOnly())
    {
        sourceAccess = storeAccessMode::ReadOnly;
    }

    if (nCut)
    {
        sTargetPath = sSourcePath.copy(nCut);
    } else
    {
        if (sTargetPath.getLength() > 1)
        {
            if (sSourcePath.getLength() > 1)
                sTargetPath += sSourcePath;
        } else
            sTargetPath = sSourcePath;
    }

    if (sTargetPath.getLength() > 1) sTargetPath += ROOT;
    if (sSourcePath.getLength() > 1) sSourcePath += ROOT;

    if (rValue.create(pSourceKey->getStoreFile(), sSourcePath, valueName, sourceAccess))
    {
        return RegError::VALUE_NOT_EXISTS;
    }

    std::vector<sal_uInt8> aBuffer(VALUE_HEADERSIZE);

    sal_uInt32  rwBytes;
    if (rValue.readAt(0, aBuffer.data(), VALUE_HEADERSIZE, rwBytes))
    {
        return RegError::INVALID_VALUE;
    }
    if (rwBytes != VALUE_HEADERSIZE)
    {
        return RegError::INVALID_VALUE;
    }

    RegError _ret = RegError::NO_ERROR;
    sal_uInt8   type = aBuffer[0];
    valueType = static_cast<RegValueType>(type);
    readUINT32(aBuffer.data() + VALUE_TYPEOFFSET, valueSize);

    nSize = VALUE_HEADERSIZE + valueSize;
    aBuffer.resize(nSize);

    if (rValue.readAt(0, aBuffer.data(), nSize, rwBytes))
    {
        return RegError::INVALID_VALUE;
    }
    if (rwBytes != nSize)
    {
        return RegError::INVALID_VALUE;
    }

    OStoreFile  rTargetFile(pTargetKey->getStoreFile());

    if (!rValue.create(rTargetFile, sTargetPath, valueName, storeAccessMode::ReadWrite))
    {
        if (valueType == RegValueType::BINARY)
        {
            _ret = checkBlop(
                rValue, sTargetPath, valueSize, aBuffer.data() + VALUE_HEADEROFFSET,
                bReport);
            if (_ret != RegError::NO_ERROR)
            {
                if (_ret == RegError::MERGE_ERROR ||
                    (_ret == RegError::MERGE_CONFLICT && bWarnings))
                {
                    return _ret;
                }
            } else
            {
                return _ret;
            }
        }
    }

    if (rValue.create(rTargetFile, sTargetPath, valueName, storeAccessMode::Create))
    {
        return RegError::INVALID_VALUE;
    }
    if (rValue.writeAt(0, aBuffer.data(), nSize, rwBytes))
    {
        return RegError::INVALID_VALUE;
    }

    if (rwBytes != nSize)
    {
        return RegError::INVALID_VALUE;
    }
    pTargetKey->setModified();

    return _ret;
}

RegError ORegistry::checkBlop(OStoreStream& rValue,
                              std::u16string_view sTargetPath,
                              sal_uInt32 srcValueSize,
                              sal_uInt8 const * pSrcBuffer,
                              bool bReport)
{
    RegistryTypeReader reader(pSrcBuffer, srcValueSize);

    if (reader.getTypeClass() == RT_TYPE_INVALID)
    {
        return RegError::INVALID_VALUE;
    }

    std::vector<sal_uInt8> aBuffer(VALUE_HEADERSIZE);
    sal_uInt32      rwBytes;
    OString         targetPath(OUStringToOString(sTargetPath, RTL_TEXTENCODING_UTF8));

    if (!rValue.readAt(0, aBuffer.data(), VALUE_HEADERSIZE, rwBytes) &&
        (rwBytes == VALUE_HEADERSIZE))
    {
        sal_uInt8 type = aBuffer[0];
        RegValueType valueType = static_cast<RegValueType>(type);
        sal_uInt32      valueSize;
        readUINT32(aBuffer.data() + VALUE_TYPEOFFSET, valueSize);

        if (valueType == RegValueType::BINARY)
        {
            aBuffer.resize(valueSize);
            if (!rValue.readAt(VALUE_HEADEROFFSET, aBuffer.data(), valueSize, rwBytes) &&
                (rwBytes == valueSize))
            {
                RegistryTypeReader reader2(aBuffer.data(), valueSize);

                if ((reader.getTypeClass() != reader2.getTypeClass())
                    || reader2.getTypeClass() == RT_TYPE_INVALID)
                {
                    if (bReport)
                    {
                        fprintf(stdout, "ERROR: values of blop from key \"%s\" has different types.\n",
                                targetPath.getStr());
                    }
                    return RegError::MERGE_ERROR;
                }

                if (reader.getTypeClass() == RT_TYPE_MODULE)
                {
                    if (reader.getFieldCount() > 0 &&
                        reader2.getFieldCount() > 0)
                    {
                        mergeModuleValue(rValue, reader, reader2);

                        return RegError::NO_ERROR;
                    } else
                    if (reader2.getFieldCount() > 0)
                    {
                        return RegError::NO_ERROR;
                    } else
                    {
                        return RegError::MERGE_CONFLICT;
                    }
                } else
                {
                    if (bReport)
                    {
                        fprintf(stderr, "WARNING: value of key \"%s\" already exists.\n",
                                targetPath.getStr());
                    }
                    return RegError::MERGE_CONFLICT;
                }
            } else
            {
                if (bReport)
                {
                    fprintf(stderr, "ERROR: values of key \"%s\" contains bad data.\n",
                            targetPath.getStr());
                }
                return RegError::MERGE_ERROR;
            }
        } else
        {
            if (bReport)
            {
                fprintf(stderr, "ERROR: values of key \"%s\" has different types.\n",
                        targetPath.getStr());
            }
            return RegError::MERGE_ERROR;
        }
    } else
    {
        return RegError::INVALID_VALUE;
    }
}

static sal_uInt32 checkTypeReaders(RegistryTypeReader const & reader1,
                                   RegistryTypeReader const & reader2,
                                   std::set< OUString >& nameSet)
{
    sal_uInt32 count=0;
    for (sal_uInt32 i=0 ; i < reader1.getFieldCount(); i++)
    {
        nameSet.insert(reader1.getFieldName(i));
        count++;
    }
    for (sal_uInt32 i=0 ; i < reader2.getFieldCount(); i++)
    {
        if (nameSet.insert(reader2.getFieldName(i)).second)
            count++;
    }
    return count;
}

RegError ORegistry::mergeModuleValue(OStoreStream& rTargetValue,
                                     RegistryTypeReader const & reader,
                                     RegistryTypeReader const & reader2)
{
    std::set< OUString > nameSet;
    sal_uInt32 count = checkTypeReaders(reader, reader2, nameSet);

    if (count == reader.getFieldCount())
        return RegError::NO_ERROR;

    sal_uInt16 index = 0;

    RegistryTypeWriter writer(reader.getTypeClass(),
                              reader.getTypeName(),
                              reader.getSuperTypeName(),
                              static_cast<sal_uInt16>(count));

    for (sal_uInt32 i=0 ; i < reader.getFieldCount(); i++)
    {
        writer.setFieldData(index,
                           reader.getFieldName(i),
                           reader.getFieldType(i),
                           reader.getFieldDoku(i),
                           reader.getFieldFileName(i),
                           reader.getFieldAccess(i),
                           reader.getFieldConstValue(i));
        index++;
    }
    for (sal_uInt32 i=0 ; i < reader2.getFieldCount(); i++)
    {
        if (nameSet.find(reader2.getFieldName(i)) == nameSet.end())
        {
            writer.setFieldData(index,
                               reader2.getFieldName(i),
                               reader2.getFieldType(i),
                               reader2.getFieldDoku(i),
                               reader2.getFieldFileName(i),
                               reader2.getFieldAccess(i),
                               reader2.getFieldConstValue(i));
            index++;
        }
    }

    const sal_uInt8*    pBlop = writer.getBlop();
    sal_uInt32          aBlopSize = writer.getBlopSize();

    sal_uInt8   type = sal_uInt8(RegValueType::BINARY);
    std::vector<sal_uInt8> aBuffer(VALUE_HEADERSIZE + aBlopSize);

    memcpy(aBuffer.data(), &type, 1);
    writeUINT32(aBuffer.data() + VALUE_TYPEOFFSET, aBlopSize);
    memcpy(aBuffer.data() + VALUE_HEADEROFFSET, pBlop, aBlopSize);

    sal_uInt32  rwBytes;
    if (rTargetValue.writeAt(0, aBuffer.data(), VALUE_HEADERSIZE+aBlopSize, rwBytes))
    {
        return RegError::INVALID_VALUE;
    }

    if (rwBytes != VALUE_HEADERSIZE+aBlopSize)
    {
        return RegError::INVALID_VALUE;
    }
    return RegError::NO_ERROR;
}

RegError ORegistry::loadAndSaveKeys(ORegKey* pTargetKey,
                                    ORegKey* pSourceKey,
                                    const OUString& keyName,
                                    sal_uInt32 nCut,
                                    bool bWarnings,
                                    bool bReport)
{
    RegError    _ret = RegError::NO_ERROR;
    OUString    sRelPath(pSourceKey->getName().copy(nCut));
    OUString    sFullPath;

    if(pTargetKey->getName().getLength() > 1)
        sFullPath += pTargetKey->getName();
    sFullPath += sRelPath;
    if (sRelPath.getLength() > 1 || sFullPath.isEmpty())
        sFullPath += ROOT;

    OUString sFullKeyName = sFullPath + keyName;

    OStoreDirectory rStoreDir;
    if (rStoreDir.create(pTargetKey->getStoreFile(), sFullPath, keyName, storeAccessMode::Create))
    {
        return RegError::CREATE_KEY_FAILED;
    }

    if (m_openKeyTable.count(sFullKeyName) > 0)
    {
        m_openKeyTable[sFullKeyName]->setDeleted(false);
    }

    ORegKey* pTmpKey = nullptr;
    _ret = pSourceKey->openKey(keyName, reinterpret_cast<RegKeyHandle*>(&pTmpKey));
    if (_ret != RegError::NO_ERROR)
        return _ret;

    OStoreDirectory::iterator   iter;
    OStoreDirectory             rTmpStoreDir(pTmpKey->getStoreDir());
    storeError                  _err = rTmpStoreDir.first(iter);

    while (_err == store_E_None)
    {
        OUString const sName(iter.m_pszName, iter.m_nLength);

        if (iter.m_nAttrib & STORE_ATTRIB_ISDIR)
        {
            _ret = loadAndSaveKeys(pTargetKey, pTmpKey,
                                   sName, nCut, bWarnings, bReport);
        } else
        {
            _ret = loadAndSaveValue(pTargetKey, pTmpKey,
                                    sName, nCut, bWarnings, bReport);
        }

        if (_ret == RegError::MERGE_ERROR)
            break;
        if (_ret == RegError::MERGE_CONFLICT && bWarnings)
            break;

        _err = rTmpStoreDir.next(iter);
    }

    pSourceKey->releaseKey(pTmpKey);
    return _ret;
}

ORegKey* ORegistry::getRootKey()
{
    m_openKeyTable[ROOT]->acquire();
diff --git a/registry/source/regimpl.hxx b/registry/source/regimpl.hxx
index 973a249..ecc7d1a 100644
--- a/registry/source/regimpl.hxx
+++ b/registry/source/regimpl.hxx
@@ -40,7 +40,6 @@
    osl::Guard< osl::Mutex > aGuard( mutex );

class ORegKey;
class RegistryTypeReader;

class ORegistry
{
@@ -76,11 +75,6 @@

    RegError    deleteKey(RegKeyHandle hKey, std::u16string_view keyName);

    RegError    loadKey(RegKeyHandle hKey,
                        const OUString& regFileName,
                        bool bWarnings,
                        bool bReport);

    RegError    dumpRegistry(RegKeyHandle hKey) const;

    ~ORegistry();
@@ -106,30 +100,6 @@

    RegError    deleteSubkeysAndValues(ORegKey* pKey);

    static RegError loadAndSaveValue(ORegKey* pTargetKey,
                                 ORegKey const * pSourceKey,
                                 const OUString& valueName,
                                 sal_uInt32 nCut,
                                 bool bWarnings,
                                 bool bReport);

    static RegError checkBlop(store::OStoreStream& rValue,
                          std::u16string_view sTargetPath,
                          sal_uInt32 srcValueSize,
                          sal_uInt8 const * pSrcBuffer,
                          bool bReport);

    static RegError mergeModuleValue(store::OStoreStream& rTargetValue,
                                 RegistryTypeReader const & reader,
                                 RegistryTypeReader const & reader2);

    RegError    loadAndSaveKeys(ORegKey* pTargetKey,
                                ORegKey* pSourceKey,
                                const OUString& keyName,
                                sal_uInt32 nCut,
                                bool bWarnings,
                                bool bReport);

    RegError    dumpValue(const OUString& sPath,
                          const OUString& sName,
                          sal_Int16 nSpace) const;
diff --git a/registry/source/registry.cxx b/registry/source/registry.cxx
index 1727dfc..a58a79c 100644
--- a/registry/source/registry.cxx
+++ b/registry/source/registry.cxx
@@ -213,55 +213,6 @@
}


//  mergeKey

static RegError REGISTRY_CALLTYPE mergeKey(RegHandle hReg,
                                              RegKeyHandle hKey,
                                           rtl_uString* keyName,
                                           rtl_uString* regFileName,
                                           sal_Bool bWarnings,
                                           sal_Bool bReport)
{
    ORegistry* pReg = static_cast< ORegistry* >(hReg);
    if (!pReg)
        return RegError::INVALID_REGISTRY;
    if (!pReg->isOpen())
        return RegError::REGISTRY_NOT_OPEN;

    ORegKey* pKey = static_cast< ORegKey* >(hKey);
    if (!pKey)
        return RegError::INVALID_KEY;
    if (pKey->getRegistry() != pReg)
        return RegError::INVALID_KEY;
    if (pKey->isDeleted())
        return RegError::INVALID_KEY;
    if (pKey->isReadOnly())
        return RegError::REGISTRY_READONLY;

    if (keyName->length)
    {
        ORegKey* pNewKey = nullptr;
        RegError _ret = pKey->createKey(OUString::unacquired(&keyName), reinterpret_cast<RegKeyHandle*>(&pNewKey));
        if (_ret != RegError::NO_ERROR)
            return _ret;

        _ret = pReg->loadKey(pNewKey, regFileName, bWarnings, bReport);
        if (_ret != RegError::NO_ERROR && (_ret != RegError::MERGE_CONFLICT || bWarnings))
        {
            if (pNewKey != pKey)
                (void) pKey->closeKey(pNewKey);
            else
                (void) pKey->releaseKey(pNewKey);
            return _ret;
        }

        return (pNewKey != pKey) ? pKey->closeKey(pNewKey) : pKey->releaseKey(pNewKey);
    }

    return pReg->loadKey(pKey, regFileName, bWarnings, bReport);
}


//  dumpRegistry

static RegError REGISTRY_CALLTYPE dumpRegistry(RegHandle hReg,
@@ -298,7 +249,6 @@
                               &openRegistry,
                               &closeRegistry,
                               &destroyRegistry,
                               &mergeKey,
                               &acquireKey,
                               &releaseKey,
                               &isKeyReadOnly,
diff --git a/solenv/clang-format/excludelist b/solenv/clang-format/excludelist
index 5fc99e2..2b02626 100644
--- a/solenv/clang-format/excludelist
+++ b/solenv/clang-format/excludelist
@@ -5506,8 +5506,6 @@
include/registry/registry.hxx
include/registry/typereg_reader.hxx
include/registry/version.h
include/registry/writer.h
include/registry/writer.hxx
include/rtl/alloc.h
include/rtl/bootstrap.h
include/rtl/bootstrap.hxx
@@ -7386,9 +7384,7 @@
registry/source/keyimpl.hxx
registry/source/reflcnst.hxx
registry/source/reflread.cxx
registry/source/reflread.hxx
registry/source/reflwrit.cxx
registry/source/reflwrit.hxx
registry/source/regimpl.cxx
registry/source/regimpl.hxx
registry/source/registry.cxx
diff --git a/stoc/source/defaultregistry/defaultregistry.cxx b/stoc/source/defaultregistry/defaultregistry.cxx
index 8666484..689aed7 100644
--- a/stoc/source/defaultregistry/defaultregistry.cxx
+++ b/stoc/source/defaultregistry/defaultregistry.cxx
@@ -1169,15 +1169,9 @@
}


void SAL_CALL NestedRegistryImpl::mergeKey( const OUString& aKeyName, const OUString& aUrl )
void SAL_CALL NestedRegistryImpl::mergeKey( const OUString&, const OUString& )
{
    Guard< Mutex > aGuard( m_mutex );
    if ( m_localReg.is() && m_localReg->isValid() )
    {
        m_localReg->mergeKey(aKeyName, aUrl);

        m_state++;
    }
    throw css::uno::RuntimeException("css.registry.NestedRegistry::mergeKey: not implemented");
}

} // namespace
diff --git a/stoc/source/simpleregistry/simpleregistry.cxx b/stoc/source/simpleregistry/simpleregistry.cxx
index 6291889..b873102 100644
--- a/stoc/source/simpleregistry/simpleregistry.cxx
+++ b/stoc/source/simpleregistry/simpleregistry.cxx
@@ -26,7 +26,6 @@
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/registry/InvalidRegistryException.hpp>
#include <com/sun/star/registry/InvalidValueException.hpp>
#include <com/sun/star/registry/MergeConflictException.hpp>
#include <com/sun/star/registry/RegistryKeyType.hpp>
#include <com/sun/star/registry/XRegistryKey.hpp>
#include <com/sun/star/registry/XSimpleRegistry.hpp>
@@ -903,29 +902,9 @@
}

void SimpleRegistry::mergeKey(
    OUString const & aKeyName, OUString const & aUrl)
    OUString const &, OUString const &)
{
    std::scoped_lock guard(mutex_);
    RegistryKey root;
    RegError err = registry_.openRootKey(root);
    if (err == RegError::NO_ERROR) {
        err = registry_.mergeKey(root, aKeyName, aUrl, false);
    }
    switch (err) {
    case RegError::NO_ERROR:
    case RegError::MERGE_CONFLICT:
        break;
    case RegError::MERGE_ERROR:
        throw css::registry::MergeConflictException(
            "com.sun.star.registry.SimpleRegistry.mergeKey:"
            " underlying Registry::mergeKey() = RegError::MERGE_ERROR",
            static_cast< cppu::OWeakObject * >(this));
    default:
        throw css::registry::InvalidRegistryException(
            "com.sun.star.registry.SimpleRegistry.mergeKey:"
            " underlying Registry::getRootKey/mergeKey() = " + OUString::number(static_cast<int>(err)),
            static_cast< OWeakObject * >(this));
    }
    throw css::uno::RuntimeException("css.registry.SimpleRegistry::mergeKey: not implemented");
}

}
diff --git a/udkapi/com/sun/star/registry/MergeConflictException.idl b/udkapi/com/sun/star/registry/MergeConflictException.idl
index fdf6a35..2d6ca3a 100644
--- a/udkapi/com/sun/star/registry/MergeConflictException.idl
+++ b/udkapi/com/sun/star/registry/MergeConflictException.idl
@@ -27,6 +27,8 @@

/** is thrown if entries of two registries are contradictory in the context of
    XSimpleRegistry::mergeKey()e() method.

    @deprecated as XSimpleRegistry::mergeKey is deprecated as well
 */
published exception MergeConflictException: com::sun::star::uno::Exception
{
diff --git a/udkapi/com/sun/star/registry/XSimpleRegistry.idl b/udkapi/com/sun/star/registry/XSimpleRegistry.idl
index 342d264..13013a1 100644
--- a/udkapi/com/sun/star/registry/XSimpleRegistry.idl
+++ b/udkapi/com/sun/star/registry/XSimpleRegistry.idl
@@ -102,19 +102,10 @@
    boolean isReadOnly()
            raises( com::sun::star::registry::InvalidRegistryException );

    /** DEPRECATED: this method lacks a registry key (better than a URL).
    /** merges a registry under the specified key.

        merges a registry under the specified key.

        <p>If the key does not exist it will be created. Existing
        keys will be overridden from keys of registry specified by
        <var>aUrl</var>.

        @throws InvalidRegistryException
        if the registry is not open.

        @throws MergeConflictException
        if any differences occur during merging
        @deprecated The merge functionality is deprecated and not implemented.  Implementations will
        throw a com::sun::star::RuntimeException.
    */
    void mergeKey( [in] string aKeyName,
             [in] string aUrl )