<commit_before>/*
 *The MIT License (MIT)
 *
 * Copyright (c) <2014> <<NAME>>
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

#include "cjet_io.h"
#include "compiler.h"
#include "hashtable.h"
#include "jet_string.h"
#include "json/cJSON.h"
#include "list.h"
#include "peer.h"
#include "response.h"
#include "router.h"
#include "state.h"
#include "table.h"
#include "uuid.h"

static struct state_or_method *alloc_state(const char *path, const cJSON *value_object,
				 struct peer *p, double timeout, int flags)
{
	struct state_or_method *s = calloc(1, sizeof(*s));
	if (unlikely(s == NULL)) {
		log_peer_err(p, "Could not allocate memory for %s object!\n",
			     "state");
		return NULL;
	}
	s->flags = flags;
	s->timeout = timeout;
	s->fetch_table_size = CONFIG_INITIAL_FETCH_TABLE_SIZE;
	s->fetcher_table = calloc(s->fetch_table_size, sizeof(struct fetch *));
	if (s->fetcher_table == NULL) {
		log_peer_err(p, "Could not allocate memory for fetch table!\n");
		goto alloc_fetch_table_failed;
	}

	s->path = duplicate_string(path);
	if (unlikely(s->path == NULL)) {
		log_peer_err(p, "Could not allocate memory for %s object!\n",
			     "path");
		goto alloc_path_failed;
	}
	if (value_object != NULL) {
		cJSON *value_copy = cJSON_Duplicate(value_object, 1);
		if (unlikely(value_copy == NULL)) {
			log_peer_err(p, "Could not copy value object!\n");
			goto value_copy_failed;
		}
		s->value = value_copy;
	}
	INIT_LIST_HEAD(&s->state_list);
	s->peer = p;

	return s;

value_copy_failed:
	free(s->path);
alloc_path_failed:
	free(s->fetcher_table);
alloc_fetch_table_failed:
	free(s);
	return NULL;
}

static void free_state_or_method(struct state_or_method *s)
{
	if (s->value != NULL) {
		cJSON_Delete(s->value);
	}
	free(s->path);
	free(s->fetcher_table);
	free(s);
}

bool state_is_fetch_only(struct state_or_method *s)
{
	if ((s->flags & FETCH_ONLY_FLAG) == FETCH_ONLY_FLAG) {
		return true;
	} else {
		return false;
	}
}

cJSON *change_state(struct peer *p, const char *path, const cJSON *value)
{
	struct state_or_method *s = state_table_get(path);
	if (unlikely(s == NULL)) {
		cJSON *error =
		    create_invalid_params_error(p, "not exists", path);
		return error;
	}
	if (unlikely(s->peer != p)) {
		cJSON *error =
		    create_invalid_params_error(p, "not owner of state", path);
		return error;
	}
	if (unlikely(s->value == NULL)) {
		cJSON *error =
		    create_invalid_params_error(p, "change on method not possible", path);
		return error;
	}
	cJSON *value_copy = cJSON_Duplicate(value, 1);
	if (value_copy == NULL) {
		cJSON *error =
		    create_internal_error(p, "reason", "not enough memory");
		return error;
	}
	cJSON_Delete(s->value);
	s->value = value_copy;
	if (unlikely(notify_fetchers(s, "change") != 0)) {
		cJSON *error = create_internal_error(
		    p, "reason", "Can't notify fetching peer");
		return error;
	}
	return NULL;
}

cJSON *set_or_call(struct peer *p, const char *path, const cJSON *value,
		 const cJSON *json_rpc, enum type what)
{
	cJSON *error;
	struct state_or_method *s = state_table_get(path);
	if (unlikely(s == NULL)) {
		error = create_invalid_params_error(p, "not exists", path);
		return error;
	}

	if (unlikely(s->peer == p)) {
		error = create_invalid_params_error(
			p, "owner of method shall not set/call a state/method via jet", path);
		return error;
	}

	if (unlikely(((what == STATE) && (s->value == NULL)) ||<commit_msg>Reject set if state is fetchOnly.<commit_after>/*
 *The MIT License (MIT)
 *
 * Copyright (c) <2014> <<NAME>>
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

#include "cjet_io.h"
#include "compiler.h"
#include "hashtable.h"
#include "jet_string.h"
#include "json/cJSON.h"
#include "list.h"
#include "peer.h"
#include "response.h"
#include "router.h"
#include "state.h"
#include "table.h"
#include "uuid.h"

static struct state_or_method *alloc_state(const char *path, const cJSON *value_object,
				 struct peer *p, double timeout, int flags)
{
	struct state_or_method *s = calloc(1, sizeof(*s));
	if (unlikely(s == NULL)) {
		log_peer_err(p, "Could not allocate memory for %s object!\n",
			     "state");
		return NULL;
	}
	s->flags = flags;
	s->timeout = timeout;
	s->fetch_table_size = CONFIG_INITIAL_FETCH_TABLE_SIZE;
	s->fetcher_table = calloc(s->fetch_table_size, sizeof(struct fetch *));
	if (s->fetcher_table == NULL) {
		log_peer_err(p, "Could not allocate memory for fetch table!\n");
		goto alloc_fetch_table_failed;
	}

	s->path = duplicate_string(path);
	if (unlikely(s->path == NULL)) {
		log_peer_err(p, "Could not allocate memory for %s object!\n",
			     "path");
		goto alloc_path_failed;
	}
	if (value_object != NULL) {
		cJSON *value_copy = cJSON_Duplicate(value_object, 1);
		if (unlikely(value_copy == NULL)) {
			log_peer_err(p, "Could not copy value object!\n");
			goto value_copy_failed;
		}
		s->value = value_copy;
	}
	INIT_LIST_HEAD(&s->state_list);
	s->peer = p;

	return s;

value_copy_failed:
	free(s->path);
alloc_path_failed:
	free(s->fetcher_table);
alloc_fetch_table_failed:
	free(s);
	return NULL;
}

static void free_state_or_method(struct state_or_method *s)
{
	if (s->value != NULL) {
		cJSON_Delete(s->value);
	}
	free(s->path);
	free(s->fetcher_table);
	free(s);
}

bool state_is_fetch_only(struct state_or_method *s)
{
	if ((s->flags & FETCH_ONLY_FLAG) == FETCH_ONLY_FLAG) {
		return true;
	} else {
		return false;
	}
}

cJSON *change_state(struct peer *p, const char *path, const cJSON *value)
{
	struct state_or_method *s = state_table_get(path);
	if (unlikely(s == NULL)) {
		cJSON *error =
		    create_invalid_params_error(p, "not exists", path);
		return error;
	}
	if (unlikely(s->peer != p)) {
		cJSON *error =
		    create_invalid_params_error(p, "not owner of state", path);
		return error;
	}
	if (unlikely(s->value == NULL)) {
		cJSON *error =
		    create_invalid_params_error(p, "change on method not possible", path);
		return error;
	}
	cJSON *value_copy = cJSON_Duplicate(value, 1);
	if (value_copy == NULL) {
		cJSON *error =
		    create_internal_error(p, "reason", "not enough memory");
		return error;
	}
	cJSON_Delete(s->value);
	s->value = value_copy;
	if (unlikely(notify_fetchers(s, "change") != 0)) {
		cJSON *error = create_internal_error(
		    p, "reason", "Can't notify fetching peer");
		return error;
	}
	return NULL;
}

cJSON *set_or_call(struct peer *p, const char *path, const cJSON *value,
		 const cJSON *json_rpc, enum type what)
{
	cJSON *error;
	struct state_or_method *s = state_table_get(path);
	if (unlikely(s == NULL)) {
		error = create_invalid_params_error(p, "not exists", path);
		return error;
	}

	if (unlikely(s->peer == p)) {
		error = create_invalid_params_error(
			p, "owner of method shall not set/call a state/method via jet", path);
		return error;
	}

	if (unlikely(state_is_fetch_only(s))) {
		error = create_invalid_params_error(
			p, "fetchOnly", path);
		return error;
	}

	if (unlikely(((what == STATE) && (s->value == NULL)) ||
{'fraction_non_alphanumeric': 0.12593079281646954, 'fraction_numerical': 0.0017520805957074025, 'mean_word_length': 4.3818503241013556, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 63, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5232092', 'n_tokens_mistral': 3274, 'n_tokens_neox': 3119, 'n_words': 968}