<commit_before>
//
//  Interface wrapper around JNI
//

#include <jni.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>


#define SUCCESS 1
#define FAILURE 0


#define TYPE_BYTE		0
#define TYPE_SHORT	1
#define TYPE_INT		2
#define TYPE_LONG		3
#define TYPE_FLOAT	4
#define TYPE_DOUBLE	5
#define TYPE_BOOLEAN	6
#define TYPE_CHAR		7
#define TYPE_STRING	8
#define TYPE_VOID		9


#define ERROR_NONE				-1
#define ERROR_COULD_NOT_CREATE_VM		0
#define ERROR_VM_ALREADY_EXISTS		1
#define ERROR_VM_NOT_CREATED			2
#define ERROR_COULD_NOT_ALLOCATE_MEMORY	3
#define ERROR_CLASS_NOT_FOUND			4
#define ERROR_METHOD_NOT_FOUND		5
#define ERROR_INVALID_CLASS			6
#define ERROR_INVALID_OBJECT			7


JavaVM *jvm = NULL;
JNIEnv *env = NULL;
int last_error = ERROR_NONE;


/// Creates the Java virtual machine.
/// Returns 1 on success and 0 on failure.
int create_jvm(char *classpath) {
	if (jvm == NULL) {
		JavaVMOption options[1];
		JavaVMInitArgs vm_args;

		char destination[200];
		strcpy(destination, "-Djava.class.path=");
		strcat(destination, classpath);
		options[0].optionString = destination;

		vm_args.version = JNI_VERSION_1_2;
		vm_args.nOptions = 1;
		vm_args.options = options;
		long status = JNI_CreateJavaVM(&jvm, (void **) &env, &vm_args);

		if (status != JNI_OK) {
			last_error = ERROR_COULD_NOT_CREATE_VM;
			return FAILURE;
		}

		return SUCCESS;
	}

}


/// Destroys the Java VM once its finished being used.
void destroy_jvm(void) {
	(*jvm)->DestroyJavaVM(jvm);
}


/// Returns the error code for the latest function called.
int get_error(void) {
	return last_error;
}


/// Returns the class from the class name.
/// Returns NULL on failure.
void * class_from_name(char *name) {
	last_error = ERROR_NONE;

	// Check the VM exists
	if (jvm == NULL || env == NULL) {
		last_error = ERROR_VM_NOT_CREATED;
		return NULL;
	}

	// Find the class
	jclass java_class = (*env)->FindClass(env, name);
	if (java_class == NULL) {
		last_error = ERROR_CLASS_NOT_FOUND;
		return NULL;
	}

	return (void *) java_class;
}


/// Converts a void pointer and type into a JNI value.
/// PRIVATE
jvalue value_to_jni_value(int type, void *content) {
	jvalue result;

	if (type == TYPE_BYTE) {
		result.b = *((jbyte *) content);
	} else if (type == TYPE_SHORT) {
		result.s = *((jshort *) content);
	} else if (type == TYPE_INT) {
		result.i = *((jint *) content);
	} else if (type == TYPE_LONG) {
		result.j = *((jlong *) content);
	} else if (type == TYPE_FLOAT) {
		result.f = *((jfloat *) content);
	} else if (type == TYPE_DOUBLE) {
		result.d = *((jdouble *) content);
	} else if (type == TYPE_BOOLEAN) {
		result.z = *((jboolean *) content);
	} else if (type == TYPE_CHAR) {
		result.c = *((jchar *) content);
	} else if (type == TYPE_STRING) {
		result.l = (*env)->NewStringUTF(env, (char *) content);
	}

	return result;
}


/// Convert a list of arguments into an array of JNI values.
/// Note: Return value must be freed!
/// PRIVATE
jvalue * args_to_jni_args(int count, int *types, void **values) {
	jvalue *args = malloc(sizeof(jvalue) * count);
	if (args == NULL) {
		return NULL;
	}

	for (int i = 0; i < count; i++) {
		int type = types[i];
		void *value = values[i];
		if (value != NULL && type != TYPE_VOID) {
			args[i] = value_to_jni_value(type, value);
		}

		free(value);
	}

	return args;
}


/// Calls a static method on a class.
/// Returns NULL on failure.
void * call_static_method(void *java_class, char *name, char *signature, int return_type,
		int arg_count, int *arg_types, void **arg_values) {
	last_error = ERROR_NONE;

	// Check the VM exists
	if (jvm == NULL || env == NULL) {
		last_error = ERROR_VM_NOT_CREATED;
		return NULL;
	}

	// Validate class
	jclass cast_class = (jclass) java_class;
	if (cast_class == NULL) {
		last_error = ERROR_INVALID_CLASS;
		return NULL;
	}

	// Get method ID
	jmethodID method_id = (*env)->GetStaticMethodID(env, cast_class, name, signature);
	if (method_id == NULL) {
		last_error = ERROR_METHOD_NOT_FOUND;
		return NULL;
	}

	jvalue *args = args_to_jni_args(arg_count, arg_types, arg_values);
	if (args == NULL) {
		last_error = ERROR_COULD_NOT_ALLOCATE_MEMORY;
		return NULL;
	}

	void *result = NULL;
	if (return_type != TYPE_VOID && return_type != TYPE_STRING) {
		result = malloc(sizeof(jvalue));
		if (result == NULL) {
			last_error = ERROR_COULD_NOT_ALLOCATE_MEMORY;
			return NULL;
		}

		// Call the method
		if (return_type == TYPE_BYTE) {
			((jvalue *) result)->b =
				(*env)->CallStaticByteMethodA(env, cast_class, method_id, args);
		} else if (return_type == TYPE_SHORT) {
			((jvalue *) result)->s =
				(*env)->CallStaticShortMethodA(env, cast_class, method_id, args);
		} else if (return_type == TYPE_INT) {
			((jvalue *) result)->i =
				(*env)->CallStaticIntMethodA(env, cast_class, method_id, args);
		} else if (return_type == TYPE_LONG) {
			((jvalue *) result)->j =
				(*env)->CallStaticLongMethodA(env, cast_class, method_id, args);
		} else if (return_type == TYPE_FLOAT) {
			((jvalue *) result)->f =
				(*env)->CallStaticFloatMethodA(env, cast_class, method_id, args);
		} else if (return_type == TYPE_DOUBLE) {
			((jvalue *) result)->d =
				(*env)->CallStaticDoubleMethodA(env, cast_class, method_id, args);
		} else if (return_type == TYPE_BOOLEAN) {
			((jvalue *) result)->z =
				(*env)->CallStaticBooleanMethodA(env, cast_class, method_id, args);
		} else if (return_type == TYPE_CHAR) {
			((jvalue *) result)->c =
				(*env)->CallStaticCharMethodA(env, cast_class, method_id, args);
		}
	} else if (return_type == TYPE_STRING) {
		jstring value = (*env)->CallStaticObjectMethodA(env, cast_class, method_id, args);

		// Allocate the results buffer
		int size = (*env)->GetStringUTFLength(env, value);
		result = malloc(sizeof(char) * (size + 1));

		// Get the string and copy it into the results buffer
		const char *str = (*env)->GetStringUTFChars(env, value, NULL);
		if (str == NULL) {
			last_error = ERROR_COULD_NOT_ALLOCATE_MEMORY;
			return NULL;
		}

		memcpy(result, str, size + 1);

		// Free the Java string
		(*env)->ReleaseStringUTFChars(env, value, str);
	} else {
		(*env)->CallStaticVoidMethodA(env, cast_class, method_id, args);
	}

	free(args);
	return result;
}


/// Creates a new instance of a class.
/// The arguments relate to the arguments passed to the constructor.
void * create_object(void *java_class, char *signature, int arg_count, int *arg_types,
		void **arg_values) {
	last_error = ERROR_NONE;

	// Check the VM exists
	if (jvm == NULL || env == NULL) {
		last_error = ERROR_VM_NOT_CREATED;
		return NULL;
	}

	// Validate class
	jclass cast_class = (jclass) java_class;
	if (cast_class == NULL) {
		last_error = ERROR_INVALID_CLASS;
		return NULL;
	}

	// Get constructor method ID
	jmethodID constructor_id = (*env)->GetMethodID(env, cast_class, "<init>", signature);
	if (constructor_id == NULL) {
		last_error = ERROR_METHOD_NOT_FOUND;
		return NULL;
	}

	jvalue *args = args_to_jni_args(arg_count, arg_types, arg_values);
	if (args == NULL) {
		last_error = ERROR_COULD_NOT_ALLOCATE_MEMORY;
		return NULL;
	}

	jobject instance = (*env)->NewObjectA(env, cast_class, constructor_id, args);

	free(args);
	return (void *) instance;
}


/// Calls a method on a class.
void * call_method(void *java_object, char *name, char *signature, int return_type,
		int arg_count, int *arg_types, void **arg_values) {
	last_error = ERROR_NONE;

	// Check the VM exists
	if (jvm == NULL || env == NULL) {
		last_error = ERROR_VM_NOT_CREATED;
		return NULL;
	}

	// Validate object
	jobject cast_object = (jobject) java_object;
	if (cast_object == NULL) {
		last_error = ERROR_INVALID_OBJECT;
		return NULL;
	}

	// Get class
	jclass object_class = (*env)->GetObjectClass(env, cast_object);
	if (object_class == NULL) {
		last_error = ERROR_INVALID_CLASS;
		return NULL;
	}

	// Get method ID
	jmethodID method_id = (*env)->GetMethodID(env, object_class, name, signature);
	if (method_id == NULL) {
		last_error = ERROR_METHOD_NOT_FOUND;
		return NULL;
	}

	jvalue *args = args_to_jni_args(arg_count, arg_types, arg_values);
	if (args == NULL) {
		last_error = ERROR_COULD_NOT_ALLOCATE_MEMORY;
		return NULL;
	}

	void *result = NULL;
	if (return_type != TYPE_VOID) {
		result = malloc(sizeof(jvalue));
		if (result == NULL) {
			last_error = ERROR_COULD_NOT_ALLOCATE_MEMORY;
			return NULL;
		}

		// Call the method
		if (return_type == TYPE_BYTE) {
			((jvalue *)result)->b =
				(*env)->CallByteMethodA(env, cast_object, method_id, args);
		} else if (return_type == TYPE_SHORT) {
			((jvalue *)result)->s =
				(*env)->CallShortMethodA(env, cast_object, method_id, args);
		} else if (return_type == TYPE_INT) {
			((jvalue *)result)->i =
				(*env)->CallIntMethodA(env, cast_object, method_id, args);
		} else if (return_type == TYPE_LONG) {
			((jvalue *)result)->j =
				(*env)->CallLongMethodA(env, cast_object, method_id, args);
		} else if (return_type == TYPE_FLOAT) {
			((jvalue *)result)->f =
				(*env)->CallFloatMethodA(env, cast_object, method_id, args);
		} else if (return_type == TYPE_DOUBLE) {
			((jvalue *)result)->d =
				(*env)->CallDoubleMethodA(env, cast_object, method_id, args);
		} else if (return_type == TYPE_BOOLEAN) {
			((jvalue *)result)->z =
				(*env)->CallBooleanMethodA(env, cast_object, method_id, args);
		} else if (return_type == TYPE_CHAR) {
			((jvalue *)result)->c =
				(*env)->CallCharMethodA(env, cast_object, method_id, args);
		}
	} else if (return_type == TYPE_STRING) {
		jstring value = (*env)->CallObjectMethodA(env, cast_object, method_id, args);

		// Allocate the results buffer
		int size = (*env)->GetStringUTFLength(env, value);
		result = malloc(sizeof(char) * (size + 1));

		// Get the string and copy it into the results buffer
		const char *str = (*env)->GetStringUTFChars(env, value, NULL);
		if (str == NULL) {
			last_error = ERROR_COULD_NOT_ALLOCATE_MEMORY;
			return NULL;
		}

		memcpy(result, str, size + 1);

		// Free the Java string
		(*env)->ReleaseStringUTFChars(env, value, str);
	} else {
		(*env)->CallVoidMethodA(env, cast_object, method_id, args);
	}

	free(args);
	return result;
}
<commit_msg>Added check to confirm JVM isn't null<commit_after>
//
//  Interface wrapper around JNI
//

#include <jni.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>


#define SUCCESS 1
#define FAILURE 0


#define TYPE_BYTE		0
#define TYPE_SHORT	1
#define TYPE_INT		2
#define TYPE_LONG		3
#define TYPE_FLOAT	4
#define TYPE_DOUBLE	5
#define TYPE_BOOLEAN	6
#define TYPE_CHAR		7
#define TYPE_STRING	8
#define TYPE_VOID		9


#define ERROR_NONE				-1
#define ERROR_COULD_NOT_CREATE_VM		0
#define ERROR_VM_ALREADY_EXISTS		1
#define ERROR_VM_NOT_CREATED			2
#define ERROR_COULD_NOT_ALLOCATE_MEMORY	3
#define ERROR_CLASS_NOT_FOUND			4
#define ERROR_METHOD_NOT_FOUND		5
#define ERROR_INVALID_CLASS			6
#define ERROR_INVALID_OBJECT			7


JavaVM *jvm = NULL;
JNIEnv *env = NULL;
int last_error = ERROR_NONE;


/// Creates the Java virtual machine.
/// Returns 1 on success and 0 on failure.
int create_jvm(char *classpath) {
	if (jvm == NULL) {
		JavaVMOption options[1];
		JavaVMInitArgs vm_args;

		char destination[200];
		strcpy(destination, "-Djava.class.path=");
		strcat(destination, classpath);
		options[0].optionString = destination;

		vm_args.version = JNI_VERSION_1_2;
		vm_args.nOptions = 1;
		vm_args.options = options;
		long status = JNI_CreateJavaVM(&jvm, (void **) &env, &vm_args);

		if (status != JNI_OK) {
			last_error = ERROR_COULD_NOT_CREATE_VM;
			return FAILURE;
		}

		return SUCCESS;
	}

	return FAILURE;
}


/// Destroys the Java VM once its finished being used.
void destroy_jvm(void) {
	if (jvm != NULL) {
		(*jvm)->DestroyJavaVM(jvm);
	}
}


/// Returns the error code for the latest function called.
int get_error(void) {
	return last_error;
}


/// Returns the class from the class name.
/// Returns NULL on failure.
void * class_from_name(char *name) {
	last_error = ERROR_NONE;

	// Check the VM exists
	if (jvm == NULL || env == NULL) {
		last_error = ERROR_VM_NOT_CREATED;
		return NULL;
	}

	// Find the class
	jclass java_class = (*env)->FindClass(env, name);
	if (java_class == NULL) {
		last_error = ERROR_CLASS_NOT_FOUND;
		return NULL;
	}

	return (void *) java_class;
}


/// Converts a void pointer and type into a JNI value.
/// PRIVATE
jvalue value_to_jni_value(int type, void *content) {
	jvalue result;

	if (type == TYPE_BYTE) {
		result.b = *((jbyte *) content);
	} else if (type == TYPE_SHORT) {
		result.s = *((jshort *) content);
	} else if (type == TYPE_INT) {
		result.i = *((jint *) content);
	} else if (type == TYPE_LONG) {
		result.j = *((jlong *) content);
	} else if (type == TYPE_FLOAT) {
		result.f = *((jfloat *) content);
	} else if (type == TYPE_DOUBLE) {
		result.d = *((jdouble *) content);
	} else if (type == TYPE_BOOLEAN) {
		result.z = *((jboolean *) content);
	} else if (type == TYPE_CHAR) {
		result.c = *((jchar *) content);
	} else if (type == TYPE_STRING) {
		result.l = (*env)->NewStringUTF(env, (char *) content);
	}

	return result;
}


/// Convert a list of arguments into an array of JNI values.
/// Note: Return value must be freed!
/// PRIVATE
jvalue * args_to_jni_args(int count, int *types, void **values) {
	jvalue *args = malloc(sizeof(jvalue) * count);
	if (args == NULL) {
		return NULL;
	}

	for (int i = 0; i < count; i++) {
		int type = types[i];
		void *value = values[i];
		if (value != NULL && type != TYPE_VOID) {
			args[i] = value_to_jni_value(type, value);
		}

		free(value);
	}

	return args;
}


/// Calls a static method on a class.
/// Returns NULL on failure.
void * call_static_method(void *java_class, char *name, char *signature, int return_type,
		int arg_count, int *arg_types, void **arg_values) {
	last_error = ERROR_NONE;

	// Check the VM exists
	if (jvm == NULL || env == NULL) {
		last_error = ERROR_VM_NOT_CREATED;
		return NULL;
	}

	// Validate class
	jclass cast_class = (jclass) java_class;
	if (cast_class == NULL) {
		last_error = ERROR_INVALID_CLASS;
		return NULL;
	}

	// Get method ID
	jmethodID method_id = (*env)->GetStaticMethodID(env, cast_class, name, signature);
	if (method_id == NULL) {
		last_error = ERROR_METHOD_NOT_FOUND;
		return NULL;
	}

	jvalue *args = args_to_jni_args(arg_count, arg_types, arg_values);
	if (args == NULL) {
		last_error = ERROR_COULD_NOT_ALLOCATE_MEMORY;
		return NULL;
	}

	void *result = NULL;
	if (return_type != TYPE_VOID && return_type != TYPE_STRING) {
		result = malloc(sizeof(jvalue));
		if (result == NULL) {
			last_error = ERROR_COULD_NOT_ALLOCATE_MEMORY;
			return NULL;
		}

		// Call the method
		if (return_type == TYPE_BYTE) {
			((jvalue *) result)->b =
				(*env)->CallStaticByteMethodA(env, cast_class, method_id, args);
		} else if (return_type == TYPE_SHORT) {
			((jvalue *) result)->s =
				(*env)->CallStaticShortMethodA(env, cast_class, method_id, args);
		} else if (return_type == TYPE_INT) {
			((jvalue *) result)->i =
				(*env)->CallStaticIntMethodA(env, cast_class, method_id, args);
		} else if (return_type == TYPE_LONG) {
			((jvalue *) result)->j =
				(*env)->CallStaticLongMethodA(env, cast_class, method_id, args);
		} else if (return_type == TYPE_FLOAT) {
			((jvalue *) result)->f =
				(*env)->CallStaticFloatMethodA(env, cast_class, method_id, args);
		} else if (return_type == TYPE_DOUBLE) {
			((jvalue *) result)->d =
				(*env)->CallStaticDoubleMethodA(env, cast_class, method_id, args);
		} else if (return_type == TYPE_BOOLEAN) {
			((jvalue *) result)->z =
				(*env)->CallStaticBooleanMethodA(env, cast_class, method_id, args);
		} else if (return_type == TYPE_CHAR) {
			((jvalue *) result)->c =
				(*env)->CallStaticCharMethodA(env, cast_class, method_id, args);
		}
	} else if (return_type == TYPE_STRING) {
		jstring value = (*env)->CallStaticObjectMethodA(env, cast_class, method_id, args);

		// Allocate the results buffer
		int size = (*env)->GetStringUTFLength(env, value);
		result = malloc(sizeof(char) * (size + 1));

		// Get the string and copy it into the results buffer
		const char *str = (*env)->GetStringUTFChars(env, value, NULL);
		if (str == NULL) {
			last_error = ERROR_COULD_NOT_ALLOCATE_MEMORY;
			return NULL;
		}

		memcpy(result, str, size + 1);

		// Free the Java string
		(*env)->ReleaseStringUTFChars(env, value, str);
	} else {
		(*env)->CallStaticVoidMethodA(env, cast_class, method_id, args);
	}

	free(args);
	return result;
}


/// Creates a new instance of a class.
/// The arguments relate to the arguments passed to the constructor.
void * create_object(void *java_class, char *signature, int arg_count, int *arg_types,
		void **arg_values) {
	last_error = ERROR_NONE;

	// Check the VM exists
	if (jvm == NULL || env == NULL) {
		last_error = ERROR_VM_NOT_CREATED;
		return NULL;
	}

	// Validate class
	jclass cast_class = (jclass) java_class;
	if (cast_class == NULL) {
		last_error = ERROR_INVALID_CLASS;
		return NULL;
	}

	// Get constructor method ID
	jmethodID constructor_id = (*env)->GetMethodID(env, cast_class, "<init>", signature);
	if (constructor_id == NULL) {
		last_error = ERROR_METHOD_NOT_FOUND;
		return NULL;
	}

	jvalue *args = args_to_jni_args(arg_count, arg_types, arg_values);
	if (args == NULL) {
		last_error = ERROR_COULD_NOT_ALLOCATE_MEMORY;
		return NULL;
	}

	jobject instance = (*env)->NewObjectA(env, cast_class, constructor_id, args);

	free(args);
	return (void *) instance;
}


/// Calls a method on a class.
void * call_method(void *java_object, char *name, char *signature, int return_type,
		int arg_count, int *arg_types, void **arg_values) {
	last_error = ERROR_NONE;

	// Check the VM exists
	if (jvm == NULL || env == NULL) {
		last_error = ERROR_VM_NOT_CREATED;
		return NULL;
	}

	// Validate object
	jobject cast_object = (jobject) java_object;
	if (cast_object == NULL) {
		last_error = ERROR_INVALID_OBJECT;
		return NULL;
	}

	// Get class
	jclass object_class = (*env)->GetObjectClass(env, cast_object);
	if (object_class == NULL) {
		last_error = ERROR_INVALID_CLASS;
		return NULL;
	}

	// Get method ID
	jmethodID method_id = (*env)->GetMethodID(env, object_class, name, signature);
	if (method_id == NULL) {
		last_error = ERROR_METHOD_NOT_FOUND;
		return NULL;
	}

	jvalue *args = args_to_jni_args(arg_count, arg_types, arg_values);
	if (args == NULL) {
		last_error = ERROR_COULD_NOT_ALLOCATE_MEMORY;
		return NULL;
	}

	void *result = NULL;
	if (return_type != TYPE_VOID) {
		result = malloc(sizeof(jvalue));
		if (result == NULL) {
			last_error = ERROR_COULD_NOT_ALLOCATE_MEMORY;
			return NULL;
		}

		// Call the method
		if (return_type == TYPE_BYTE) {
			((jvalue *)result)->b =
				(*env)->CallByteMethodA(env, cast_object, method_id, args);
		} else if (return_type == TYPE_SHORT) {
			((jvalue *)result)->s =
				(*env)->CallShortMethodA(env, cast_object, method_id, args);
		} else if (return_type == TYPE_INT) {
			((jvalue *)result)->i =
				(*env)->CallIntMethodA(env, cast_object, method_id, args);
		} else if (return_type == TYPE_LONG) {
			((jvalue *)result)->j =
				(*env)->CallLongMethodA(env, cast_object, method_id, args);
		} else if (return_type == TYPE_FLOAT) {
			((jvalue *)result)->f =
				(*env)->CallFloatMethodA(env, cast_object, method_id, args);
		} else if (return_type == TYPE_DOUBLE) {
			((jvalue *)result)->d =
				(*env)->CallDoubleMethodA(env, cast_object, method_id, args);
		} else if (return_type == TYPE_BOOLEAN) {
			((jvalue *)result)->z =
				(*env)->CallBooleanMethodA(env, cast_object, method_id, args);
		} else if (return_type == TYPE_CHAR) {
			((jvalue *)result)->c =
				(*env)->CallCharMethodA(env, cast_object, method_id, args);
		}
	} else if (return_type == TYPE_STRING) {
		jstring value = (*env)->CallObjectMethodA(env, cast_object, method_id, args);

		// Allocate the results buffer
		int size = (*env)->GetStringUTFLength(env, value);
		result = malloc(sizeof(char) * (size + 1));

		// Get the string and copy it into the results buffer
		const char *str = (*env)->GetStringUTFChars(env, value, NULL);
		if (str == NULL) {
			last_error = ERROR_COULD_NOT_ALLOCATE_MEMORY;
			return NULL;
		}

		memcpy(result, str, size + 1);

		// Free the Java string
		(*env)->ReleaseStringUTFChars(env, value, str);
	} else {
		(*env)->CallVoidMethodA(env, cast_object, method_id, args);
	}

	free(args);
	return result;
}

{'fraction_non_alphanumeric': 0.1404856903600808, 'fraction_numerical': 0.0035466233190483225, 'mean_word_length': 3.9992612656981037, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 113, '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': '2830569', 'n_tokens_mistral': 7889, 'n_tokens_neox': 7286, 'n_words': 1891}