<commit_before>#include <osg/Geometry>
#include <osgDB/ObjectWrapper>
#include <osgDB/InputStream>
#include <osgDB/OutputStream>

BEGIN_USER_TABLE( AttributeBinding, osg::Geometry );
    ADD_USER_VALUE( BIND_OFF );
    ADD_USER_VALUE( BIND_OVERALL );
    ADD_USER_VALUE( BIND_PER_PRIMITIVE_SET );    
    lookup->add("BIND_PER_PRIMITIVE",3); //ADD_USER_VALUE( BIND_PER_PRIMITIVE );
    ADD_USER_VALUE( BIND_PER_VERTEX );
END_USER_TABLE()

USER_READ_FUNC( AttributeBinding, readAttributeBinding )
USER_WRITE_FUNC( AttributeBinding, writeAttributeBinding )

static osg::Array* readArray( osgDB::InputStream& is)
{
    osg::ref_ptr<osg::Array> array;
    bool hasArray = false;
    is >> is.PROPERTY("Array") >> hasArray;
    if ( hasArray ) array = is.readArray();

    bool hasIndices = false;
    is >> is.PROPERTY("Indices") >> hasIndices;
    if ( hasIndices )
    {
        osg::ref_ptr<osg::Array> indices_array = is.readArray();
        osg::ref_ptr<osg::IndexArray> indices = dynamic_cast<osg::IndexArray*>( indices_array.get() );
        if (array.valid() && indices.valid()) array->setUserData(indices.get());
    }

    is >> is.PROPERTY("Binding");
    int binding = readAttributeBinding(is);
    if (array.valid()) array->setBinding(static_cast<osg::Array::Binding>(binding));

    int normalizeValue = 0;
    is >> is.PROPERTY("Normalize") >> normalizeValue;
    if (array.valid()) array->setNormalize(normalizeValue!=0);
    
    return array.release();
}

static void writeArray( osgDB::OutputStream& os, const osg::Array* array)
{
    os << os.PROPERTY("Array") << (array!=0);
    if ( array!=0 ) os << array;
    else os << std::endl;

    const osg::IndexArray* indices = (array!=0) ? dynamic_cast<const osg::IndexArray*>(array->getUserData()) : 0;
    os << os.PROPERTY("Indices") << (indices!=0);
    if ( indices!=0 ) os << indices;
    else os << std::endl;

    os << os.PROPERTY("Binding"); writeAttributeBinding(os, (array!=0) ? static_cast<osg::Geometry::AttributeBinding>(array->getBinding()) : osg::Geometry::BIND_OFF); os << std::endl;
    os << os.PROPERTY("Normalize") << ((array!=0 && array->getNormalize()) ? 1:0) << std::endl;
}

#define ADD_ARRAYDATA_FUNCTIONS( ORIGINAL_PROP, PROP ) \
    static bool check##ORIGINAL_PROP( const osg::Geometry& geom ) \
    { return geom.get##PROP()!=0; } \
    static bool read##ORIGINAL_PROP( osgDB::InputStream& is, osg::Geometry& geom ) { \
        is >> is.BEGIN_BRACKET; \
        osg::Array* array = readArray(is); \
        geom.set##PROP(array); \
        is >> is.END_BRACKET; \
        return true; \
    } \
    static bool write##ORIGINAL_PROP( osgDB::OutputStream& os, const osg::Geometry& geom ) { \
        os << os.BEGIN_BRACKET << std::endl; \
        writeArray(os, geom.get##PROP()); \
        os << os.END_BRACKET << std::endl; \
        return true; \
    }

ADD_ARRAYDATA_FUNCTIONS( VertexData, VertexArray )
ADD_ARRAYDATA_FUNCTIONS( NormalData, NormalArray )
ADD_ARRAYDATA_FUNCTIONS( ColorData, ColorArray )
ADD_ARRAYDATA_FUNCTIONS( SecondaryColorData, SecondaryColorArray )
ADD_ARRAYDATA_FUNCTIONS( FogCoordData, FogCoordArray )

#define ADD_ARRAYLIST_FUNCTIONS( ORIGINAL_PROP, PROP, LISTNAME ) \
    static bool check##ORIGINAL_PROP( const osg::Geometry& geom ) \
    { return geom.get##LISTNAME().size()>0; } \
    static bool read##ORIGINAL_PROP( osgDB::InputStream& is, osg::Geometry& geom ) { \
        unsigned int size = is.readSize(); is >> is.BEGIN_BRACKET; \
        for ( unsigned int i=0; i<size; ++i ) { \
            is >> is.PROPERTY("Data") >> is.BEGIN_BRACKET; \
            osg::Array* array = readArray(is); \
            geom.set##PROP(i, array); \
            is >> is.END_BRACKET; } \
        is >> is.END_BRACKET; \
        return true; \
    } \
    static bool write##ORIGINAL_PROP( osgDB::OutputStream& os, const osg::Geometry& geom ) { \
        const osg::Geometry::ArrayList& LISTNAME = geom.get##LISTNAME(); \
        os.writeSize(LISTNAME.size()); os << os.BEGIN_BRACKET << std::endl; \
        for ( osg::Geometry::ArrayList::const_iterator itr=LISTNAME.begin(); \
              itr!=LISTNAME.end(); ++itr ) { \
            os << os.PROPERTY("Data") << os.BEGIN_BRACKET << std::endl; \
            writeArray(os, itr->get()); os << os.END_BRACKET << std::endl; \
        } \
        os << os.END_BRACKET << std::endl; \
        return true; \
    }

ADD_ARRAYLIST_FUNCTIONS( TexCoordData, TexCoordArray, TexCoordArrayList )
ADD_ARRAYLIST_FUNCTIONS( VertexAttribData, VertexAttribArray, VertexAttribArrayList )

struct GeometryFinishedObjectReadCallback : public osgDB::FinishedObjectReadCallback
{
    virtual void objectRead(osgDB::InputStream&, osg::Object& obj)
    {
        osg::Geometry& geometry = static_cast<osg::Geometry&>(obj);
        if (geometry.getUseVertexBufferObjects())
        {
            geometry.setUseVertexBufferObjects(false);
            geometry.setUseVertexBufferObjects(true);
        }
    }
};

// implement backwards compatibility with reading/writing the FastPathHint
static bool checkFastPathHint( const osg::Geometry& geom ) { return false; }
static bool readFastPathHint( osgDB::InputStream& is, osg::Geometry& geom )
{ 
    bool value = false;
    if ( is.isBinary() )
    {
        is >> value;
    }
    else if ( is.matchString("FastPathHint") )
    {
        is >> value;
    }
    return true;
}
static bool writeFastPathHint( osgDB::OutputStream& os, const osg::Geometry& geom )
{
    return true;
}

REGISTER_OBJECT_WRAPPER( Geometry,
                         new osg::Geometry,
                         osg::Geometry,
                         "osg::Object osg::Drawable osg::Geometry" )
{
    ADD_LIST_SERIALIZER( PrimitiveSetList, osg::Geometry::PrimitiveSetList );  // _primitives
    ADD_USER_SERIALIZER( VertexData );  // _vertexData
    ADD_USER_SERIALIZER( NormalData );  // _normalData
    ADD_USER_SERIALIZER( ColorData );  // _colorData
    ADD_USER_SERIALIZER( SecondaryColorData );  // _secondaryColorData
    ADD_USER_SERIALIZER( FogCoordData );  // _fogCoordData
    ADD_USER_SERIALIZER( TexCoordData );  // _texCoordList
    ADD_USER_SERIALIZER( VertexAttribData );  // _vertexAttribList

    ADD_USER_SERIALIZER( FastPathHint );  // _fastPathHint

    wrapper->addFinishedObjectReadCallback( new GeometryFinishedObjectReadCallback() );
}
<commit_msg>From <NAME>, "Sorry for my very slow response because of some personal issues. I found that new Geometry serializers can't work with old .osgb files. The modified FastPathHint serializer doesn't correctly read from the stream and thus jumbles following inputs. The file attached can be placed in osgWrappers/serializers/osg to fix that problem.<commit_after>#include <osg/Geometry>
#include <osgDB/ObjectWrapper>
#include <osgDB/InputStream>
#include <osgDB/OutputStream>

BEGIN_USER_TABLE( AttributeBinding, osg::Geometry );
    ADD_USER_VALUE( BIND_OFF );
    ADD_USER_VALUE( BIND_OVERALL );
    ADD_USER_VALUE( BIND_PER_PRIMITIVE_SET );    
    lookup->add("BIND_PER_PRIMITIVE",3); //ADD_USER_VALUE( BIND_PER_PRIMITIVE );
    ADD_USER_VALUE( BIND_PER_VERTEX );
END_USER_TABLE()

USER_READ_FUNC( AttributeBinding, readAttributeBinding )
USER_WRITE_FUNC( AttributeBinding, writeAttributeBinding )

static osg::Array* readArray( osgDB::InputStream& is)
{
    osg::ref_ptr<osg::Array> array;
    bool hasArray = false;
    is >> is.PROPERTY("Array") >> hasArray;
    if ( hasArray ) array = is.readArray();

    bool hasIndices = false;
    is >> is.PROPERTY("Indices") >> hasIndices;
    if ( hasIndices )
    {
        osg::ref_ptr<osg::Array> indices_array = is.readArray();
        osg::ref_ptr<osg::IndexArray> indices = dynamic_cast<osg::IndexArray*>( indices_array.get() );
        if (array.valid() && indices.valid()) array->setUserData(indices.get());
    }

    is >> is.PROPERTY("Binding");
    int binding = readAttributeBinding(is);
    if (array.valid()) array->setBinding(static_cast<osg::Array::Binding>(binding));

    int normalizeValue = 0;
    is >> is.PROPERTY("Normalize") >> normalizeValue;
    if (array.valid()) array->setNormalize(normalizeValue!=0);
    
    return array.release();
}

static void writeArray( osgDB::OutputStream& os, const osg::Array* array)
{
    os << os.PROPERTY("Array") << (array!=0);
    if ( array!=0 ) os << array;
    else os << std::endl;

    const osg::IndexArray* indices = (array!=0) ? dynamic_cast<const osg::IndexArray*>(array->getUserData()) : 0;
    os << os.PROPERTY("Indices") << (indices!=0);
    if ( indices!=0 ) os << indices;
    else os << std::endl;

    os << os.PROPERTY("Binding"); writeAttributeBinding(os, (array!=0) ? static_cast<osg::Geometry::AttributeBinding>(array->getBinding()) : osg::Geometry::BIND_OFF); os << std::endl;
    os << os.PROPERTY("Normalize") << ((array!=0 && array->getNormalize()) ? 1:0) << std::endl;
}

#define ADD_ARRAYDATA_FUNCTIONS( ORIGINAL_PROP, PROP ) \
    static bool check##ORIGINAL_PROP( const osg::Geometry& geom ) \
    { return geom.get##PROP()!=0; } \
    static bool read##ORIGINAL_PROP( osgDB::InputStream& is, osg::Geometry& geom ) { \
        is >> is.BEGIN_BRACKET; \
        osg::Array* array = readArray(is); \
        geom.set##PROP(array); \
        is >> is.END_BRACKET; \
        return true; \
    } \
    static bool write##ORIGINAL_PROP( osgDB::OutputStream& os, const osg::Geometry& geom ) { \
        os << os.BEGIN_BRACKET << std::endl; \
        writeArray(os, geom.get##PROP()); \
        os << os.END_BRACKET << std::endl; \
        return true; \
    }

ADD_ARRAYDATA_FUNCTIONS( VertexData, VertexArray )
ADD_ARRAYDATA_FUNCTIONS( NormalData, NormalArray )
ADD_ARRAYDATA_FUNCTIONS( ColorData, ColorArray )
ADD_ARRAYDATA_FUNCTIONS( SecondaryColorData, SecondaryColorArray )
ADD_ARRAYDATA_FUNCTIONS( FogCoordData, FogCoordArray )

#define ADD_ARRAYLIST_FUNCTIONS( ORIGINAL_PROP, PROP, LISTNAME ) \
    static bool check##ORIGINAL_PROP( const osg::Geometry& geom ) \
    { return geom.get##LISTNAME().size()>0; } \
    static bool read##ORIGINAL_PROP( osgDB::InputStream& is, osg::Geometry& geom ) { \
        unsigned int size = is.readSize(); is >> is.BEGIN_BRACKET; \
        for ( unsigned int i=0; i<size; ++i ) { \
            is >> is.PROPERTY("Data") >> is.BEGIN_BRACKET; \
            osg::Array* array = readArray(is); \
            geom.set##PROP(i, array); \
            is >> is.END_BRACKET; } \
        is >> is.END_BRACKET; \
        return true; \
    } \
    static bool write##ORIGINAL_PROP( osgDB::OutputStream& os, const osg::Geometry& geom ) { \
        const osg::Geometry::ArrayList& LISTNAME = geom.get##LISTNAME(); \
        os.writeSize(LISTNAME.size()); os << os.BEGIN_BRACKET << std::endl; \
        for ( osg::Geometry::ArrayList::const_iterator itr=LISTNAME.begin(); \
              itr!=LISTNAME.end(); ++itr ) { \
            os << os.PROPERTY("Data") << os.BEGIN_BRACKET << std::endl; \
            writeArray(os, itr->get()); os << os.END_BRACKET << std::endl; \
        } \
        os << os.END_BRACKET << std::endl; \
        return true; \
    }

ADD_ARRAYLIST_FUNCTIONS( TexCoordData, TexCoordArray, TexCoordArrayList )
ADD_ARRAYLIST_FUNCTIONS( VertexAttribData, VertexAttribArray, VertexAttribArrayList )

struct GeometryFinishedObjectReadCallback : public osgDB::FinishedObjectReadCallback
{
    virtual void objectRead(osgDB::InputStream&, osg::Object& obj)
    {
        osg::Geometry& geometry = static_cast<osg::Geometry&>(obj);
        if (geometry.getUseVertexBufferObjects())
        {
            geometry.setUseVertexBufferObjects(false);
            geometry.setUseVertexBufferObjects(true);
        }
    }
};

// implement backwards compatibility with reading/writing the FastPathHint
static bool checkFastPathHint( const osg::Geometry& geom ) { return false; }
static bool readFastPathHint( osgDB::InputStream& is, osg::Geometry& geom )
{ 
    // Compatibility info:
    //   Previous Geometry wrapper (before 3.1.8) require a bool fast-path serializer.
    //   It saves "FastPathHint true" in ascii mode and a single [bool] in binary mode.
    //   Becoming a user serializer, the serializer will first read the name "FastPathHint"
    //   or a [bool] in the checking process, then call the reading function as here. So,
    //   we will only need to read one more bool variable in ascii mode; otherwise do nothing
    bool value = false;
    if ( !is.isBinary() ) is >> value;
    return true;
}
static bool writeFastPathHint( osgDB::OutputStream& os, const osg::Geometry& geom )
{
    return true;
}

REGISTER_OBJECT_WRAPPER( Geometry,
                         new osg::Geometry,
                         osg::Geometry,
                         "osg::Object osg::Drawable osg::Geometry" )
{
    ADD_LIST_SERIALIZER( PrimitiveSetList, osg::Geometry::PrimitiveSetList );  // _primitives
    ADD_USER_SERIALIZER( VertexData );  // _vertexData
    ADD_USER_SERIALIZER( NormalData );  // _normalData
    ADD_USER_SERIALIZER( ColorData );  // _colorData
    ADD_USER_SERIALIZER( SecondaryColorData );  // _secondaryColorData
    ADD_USER_SERIALIZER( FogCoordData );  // _fogCoordData
    ADD_USER_SERIALIZER( TexCoordData );  // _texCoordList
    ADD_USER_SERIALIZER( VertexAttribData );  // _vertexAttribList

    ADD_USER_SERIALIZER( FastPathHint );  // _fastPathHint

    wrapper->addFinishedObjectReadCallback( new GeometryFinishedObjectReadCallback() );
}

{'fraction_non_alphanumeric': 0.1362074118350269, 'fraction_numerical': 0.002615062761506276, 'mean_word_length': 3.5112908661948095, 'pattern_counts': {'":': 0, '<': 134, '<?xml version=': 0, '>': 110, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6806015', 'n_tokens_mistral': 4349, 'n_tokens_neox': 4300, 'n_words': 885}