<commit_before>package com4j;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.Map;
import java.util.WeakHashMap;

/**
 *
 *
 * @author <NAME> (<EMAIL>)
 */
final class Wrapper implements InvocationHandler, Com4jObject {

    /**
     * interface pointer.
     */
    private int ptr;

    /**
     * Cached hash code. The value of IUnknown*
     */
    private int hashCode=0;

    /**
     * Cached of {@link MethodInfo} keyed by the method decl.
     *
     * TODO: revisit the cache design
     */
    private Map<Method,MethodInfo> cache = Collections.synchronizedMap(
        new WeakHashMap<Method,MethodInfo>());

    Wrapper(int ptr) {
        this.ptr = ptr;
    }

    int getPtr() {
        return ptr;
    }

    protected void finalize() throws Throwable {
        release();
    }

    private static final Object[] EMPTY_ARRAY = new Object[0];

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if(ptr==0)
            throw new IllegalStateException("COM object is already disposed");
        if(args==null)  // this makes the processing easier
            args = EMPTY_ARRAY;

        Class<?> declClazz = method.getDeclaringClass();

        if( declClazz==Com4jObject.class || declClazz==Object.class ) {
            // method declared on Com4jObject is not meant to be delegated.
            try {
                return method.invoke(this,args);
            } catch( IllegalAccessException e ) {
                throw new IllegalAccessError(e.getMessage());
            } catch( InvocationTargetException e ) {
                throw e.getTargetException();
            }
        }

        return getMethodInfo(method).invoke(ptr,args);
    }

    private MethodInfo getMethodInfo(Method method) {
        MethodInfo r = cache.get(method);
        if(r!=null)     return r;
        r = new MethodInfo(method);
        cache.put(method,r);
        return r;
    }

    public void release() {
        if(ptr!=0)
           Native.release(ptr);
        ptr=0;
    }

    public <T extends Com4jObject> boolean is( Class<T> comInterface ) {
        try {
            GUID iid = COM4J.getIID(comInterface);
            int nptr = Native.queryInterface(ptr, iid.v[0], iid.v[1] );
            Native.release(nptr);
            return true;
        } catch( ComException e ) {
            return false;
        }
    }

    public <T extends Com4jObject> T queryInterface( Class<T> comInterface ) {
        try {
            GUID iid = COM4J.getIID(comInterface);
            int nptr = Native.queryInterface(ptr, iid.v[0], iid.v[1] );
            return COM4J.wrap( comInterface, nptr );
        } catch( ComException e ) {
            return null;    // failed to cast
        }
    }

    public String toString() {
        return "ComObject:"+Integer.toHexString(ptr);
    }

    public final int hashCode() {
        if(ptr==0)
            throw new IllegalStateException("COM object is already disposed");

        if(hashCode==0) {
            hashCode = COM4J.queryInterface( ptr, COM4J.IID_IUnknown );
            Native.release(hashCode);
        }
        return hashCode;
    }

    public final boolean equals( Object rhs ) {
        if(!(rhs instanceof Com4jObject))   return false;
        return hashCode()==rhs.hashCode();
    }



    static class MethodInfo {
        final Method method;

        final int vtIndex;
        // list of params.code
        final int[] paramConvs;
        final NativeType[] params;
        final int returnIndex;
        final boolean returnIsInOut;
        final NativeType returnConv;
        final Class<?>[] paramTypes;
<commit_msg>fixed a hashCode related bug<commit_after>package com4j;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.Map;
import java.util.WeakHashMap;

/**
 *
 *
 * @author <NAME> (<EMAIL>)
 */
final class Wrapper implements InvocationHandler, Com4jObject {

    /**
     * interface pointer.
     */
    private int ptr;

    /**
     * Cached hash code. The value of IUnknown*
     */
    private int hashCode=0;

    /**
     * Cached of {@link MethodInfo} keyed by the method decl.
     *
     * TODO: revisit the cache design
     */
    private Map<Method,MethodInfo> cache = Collections.synchronizedMap(
        new WeakHashMap<Method,MethodInfo>());

    Wrapper(int ptr) {
        this.ptr = ptr;
    }

    int getPtr() {
        return ptr;
    }

    protected void finalize() throws Throwable {
        release();
    }

    private static final Object[] EMPTY_ARRAY = new Object[0];

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if(ptr==0)
            throw new IllegalStateException("COM object is already disposed");
        if(args==null)  // this makes the processing easier
            args = EMPTY_ARRAY;

        Class<?> declClazz = method.getDeclaringClass();

        if( declClazz==Com4jObject.class || declClazz==Object.class ) {
            // method declared on Com4jObject is not meant to be delegated.
            try {
                return method.invoke(this,args);
            } catch( IllegalAccessException e ) {
                throw new IllegalAccessError(e.getMessage());
            } catch( InvocationTargetException e ) {
                throw e.getTargetException();
            }
        }

        return getMethodInfo(method).invoke(ptr,args);
    }

    private MethodInfo getMethodInfo(Method method) {
        MethodInfo r = cache.get(method);
        if(r!=null)     return r;
        r = new MethodInfo(method);
        cache.put(method,r);
        return r;
    }

    public void release() {
        if(ptr!=0)
           Native.release(ptr);
        ptr=0;
        // object shouldn't change hash code.
        // so we keep the
        // hashCode=0;
    }

    public <T extends Com4jObject> boolean is( Class<T> comInterface ) {
        try {
            GUID iid = COM4J.getIID(comInterface);
            int nptr = Native.queryInterface(ptr, iid.v[0], iid.v[1] );
            Native.release(nptr);
            return true;
        } catch( ComException e ) {
            return false;
        }
    }

    public <T extends Com4jObject> T queryInterface( Class<T> comInterface ) {
        try {
            GUID iid = COM4J.getIID(comInterface);
            int nptr = Native.queryInterface(ptr, iid.v[0], iid.v[1] );
            return COM4J.wrap( comInterface, nptr );
        } catch( ComException e ) {
            return null;    // failed to cast
        }
    }

    public String toString() {
        return "ComObject:"+Integer.toHexString(ptr);
    }

    public final int hashCode() {
        if(hashCode==0) {
            if(ptr!=0) {
                hashCode = COM4J.queryInterface( ptr, COM4J.IID_IUnknown );
                Native.release(hashCode);
            } else {
                hashCode = 0;
            }
        }
        return hashCode;
    }

    public final boolean equals( Object rhs ) {
        if(!(rhs instanceof Com4jObject))   return false;
        return hashCode()==rhs.hashCode();
    }



    static class MethodInfo {
        final Method method;

        final int vtIndex;
        // list of params.code
        final int[] paramConvs;
        final NativeType[] params;
        final int returnIndex;
        final boolean returnIsInOut;
        final NativeType returnConv;
        final Class<?>[] paramTypes;

{'fraction_non_alphanumeric': 0.10302876694968952, 'fraction_numerical': 0.0060828792295019645, 'mean_word_length': 2.062475746992627, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 23, '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': '2338126', 'n_tokens_mistral': 2270, 'n_tokens_neox': 2216, 'n_words': 584}