<commit_before>/**
  * Touhou Community Reliant Automatic Patcher
  * Cheap command-line patch stack configuration tool
  */

#include <thcrap.h>
#include <thcrap_update/src/update.h>
#include "configure.h"
#include "search.h"

json_t *dep_to_sel(const char *dep_str)
{
	if(dep_str) {
		const char *slash = strrchr(dep_str, '/');
		if(slash) {
			return json_pack("[s#s]", dep_str, slash - dep_str, slash + 1);
		} else {
			return json_pack("[ns]", dep_str);
		}
	}
	return NULL;
}

// Returns 1 if the patch [sel] is in [sel_stack]. [sel]'s repository ID can
// be a JSON NULL object to ignore the repository.
int IsSelected(json_t *sel_stack, const json_t *sel)
{
	json_t *sel_repo = json_array_get(sel, 0);
	json_t *sel_patch = json_array_get(sel, 1);
	json_t *cmp;
	size_t i;

	json_array_foreach(sel_stack, i, cmp) {
		json_t *cmp_repo = json_array_get(cmp, 0);
		json_t *cmp_patch = json_array_get(cmp, 1);
		if(
			(json_is_string(sel_repo) ? json_equal(cmp_repo, sel_repo) : 1)
			&& json_equal(cmp_patch, sel_patch)
		) {
			return 1;
		}
	}
	return 0;
}

// Locates a repository for [sel] in [repo_list], starting from [orig_repo_id].
const char* SearchPatch(json_t *repo_list, const char *orig_repo_id, const json_t *sel)
{
	const char *repo_id = json_array_get_string(sel, 0);
	const char *patch_id = json_array_get_string(sel, 1);
	const json_t *orig_repo = json_object_get(repo_list, orig_repo_id);
	const json_t *patches = json_object_get(orig_repo, "patches");
	const json_t *remote_repo;
	const char *key;

	// Absolute dependency
	// In fact, just a check to see whether [sel] is available.
	if(repo_id) {
		remote_repo = json_object_get(repo_list, repo_id);
		patches = json_object_get(remote_repo, "patches");
		return json_object_get(patches, patch_id) ? repo_id : NULL;
	}

	// Relative dependency
	if(json_object_get(patches, patch_id)) {
		return orig_repo_id;
	}

	json_object_foreach(repo_list, key, remote_repo) {<commit_msg>thcrap_configure: Refactor selector matching into its own function.<commit_after>/**
  * Touhou Community Reliant Automatic Patcher
  * Cheap command-line patch stack configuration tool
  */

#include <thcrap.h>
#include <thcrap_update/src/update.h>
#include "configure.h"
#include "search.h"

json_t *dep_to_sel(const char *dep_str)
{
	if(dep_str) {
		const char *slash = strrchr(dep_str, '/');
		if(slash) {
			return json_pack("[s#s]", dep_str, slash - dep_str, slash + 1);
		} else {
			return json_pack("[ns]", dep_str);
		}
	}
	return NULL;
}

// Returns 1 if the selectors [a] and [b] refer to the same patch.
// The repository IDs can be JSON NULLs to ignore them.
int sel_match(const json_t *a, const json_t *b)
{
	json_t *a_r = json_array_get(a, 0);
	json_t *a_p = json_array_get(a, 1);
	json_t *b_r = json_array_get(b, 0);
	json_t *b_p = json_array_get(b, 1);
	int absolute = json_is_string(a_r) && json_is_string(b_r);
	return (absolute ? json_equal(a_r, b_r) : 1) && json_equal(a_p, b_p);
}

int IsSelected(json_t *sel_stack, const json_t *sel)
{
	json_t *cmp;
	size_t i;
	json_array_foreach(sel_stack, i, cmp) {
		if(sel_match(sel, cmp)) {
			return 1;
		}
	}
	return 0;
}

// Locates a repository for [sel] in [repo_list], starting from [orig_repo_id].
const char* SearchPatch(json_t *repo_list, const char *orig_repo_id, const json_t *sel)
{
	const char *repo_id = json_array_get_string(sel, 0);
	const char *patch_id = json_array_get_string(sel, 1);
	const json_t *orig_repo = json_object_get(repo_list, orig_repo_id);
	const json_t *patches = json_object_get(orig_repo, "patches");
	const json_t *remote_repo;
	const char *key;

	// Absolute dependency
	// In fact, just a check to see whether [sel] is available.
	if(repo_id) {
		remote_repo = json_object_get(repo_list, repo_id);
		patches = json_object_get(remote_repo, "patches");
		return json_object_get(patches, patch_id) ? repo_id : NULL;
	}

	// Relative dependency
	if(json_object_get(patches, patch_id)) {
		return orig_repo_id;
	}

	json_object_foreach(repo_list, key, remote_repo) {
{'fraction_non_alphanumeric': 0.125, 'fraction_numerical': 0.005478087649402391, 'mean_word_length': 4.771551724137931, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, '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': '5805978', 'n_tokens_mistral': 1646, 'n_tokens_neox': 1565, 'n_words': 391}