<commit_before>/**
 * Clever programming language
 * Copyright (c) Clever Team
 *
 * This file is distributed under the MIT license. See LICENSE for details.
 */

#ifndef CLEVER_VALUE_H
#define CLEVER_VALUE_H

#include <cstring>

#include "core/cstring.h"
#include "types/type.h"

namespace clever {

extern Type* const g_clever_int_type;
extern Type* const g_clever_double_type;
extern Type* const g_clever_str_type;
extern Type* const g_clever_func_type;
extern Type* const g_clever_thread_type;
extern Type* const g_clever_bool_type;
extern Type* const g_clever_array_type;
extern Type* const g_clever_map_type;

#define CLEVER_INT_TYPE    g_clever_int_type
#define CLEVER_DOUBLE_TYPE g_clever_double_type
#define CLEVER_STR_TYPE    g_clever_str_type
#define CLEVER_FUNC_TYPE   g_clever_func_type
#define CLEVER_THREAD_TYPE g_clever_thread_type
#define CLEVER_BOOL_TYPE   g_clever_bool_type
#define CLEVER_ARRAY_TYPE  g_clever_array_type
#define CLEVER_MAP_TYPE    g_clever_map_type

typedef std::map     <std::string, Value*>  ValueMap;
typedef std::pair    <std::string, Value*>  ValuePair;
typedef std::vector  <Value*>               ValueVector;

class ValueObject : public RefCounted {
public:
	ValueObject()
		: RefCounted(1), m_obj(NULL), m_type(NULL) {}

	ValueObject(void* obj, const Type* type)
		: RefCounted(1), m_obj(obj), m_type(type) {}

	virtual ~ValueObject() {
		if (m_type) {
			const_cast<Type*>(m_type)->deallocData(m_obj);
		}
	}

	void* getObj() { return m_obj; }
private:
	void* m_obj;
	const Type* m_type;

	DISALLOW_COPY_AND_ASSIGN(ValueObject);
};

class Value : public RefCounted {
public:
	union DataValue {
		bool bval;
		long lval;
		double dval;
		const CString* sval;
		ValueObject* obj;

		DataValue() : lval(0) {}
		DataValue(bool value) : bval(value) {}
		DataValue(long value) : lval(value) {}
		DataValue(double value) : dval(value) {}
		DataValue(const CString* value) : sval(value) {}
	};

	Value() : m_data(), m_type(NULL), m_is_const(false) {}

	Value(bool n, bool is_const = false)
		: m_data(n), m_type(CLEVER_BOOL_TYPE), m_is_const(is_const) {}

	Value(long n, bool is_const = false)
		: m_data(n), m_type(CLEVER_INT_TYPE), m_is_const(is_const) {}

	Value(double n, bool is_const = false)
		: m_data(n), m_type(CLEVER_DOUBLE_TYPE), m_is_const(is_const) {}

	Value(const CString* value, bool is_const = false)
		: m_data(value), m_type(CLEVER_STR_TYPE), m_is_const(is_const) {}

	Value(const Type* type, bool is_const = false)
		: m_data(), m_type(type), m_is_const(is_const) {}

	~Value() {
		if (m_type && !m_type->isPrimitive()) {
			if (m_data.obj) {
				m_data.obj->delRef();
			}
		}
	}

	void setType(const Type* type) { m_type = type; }
	const Type* getType() const { return m_type; }

	void setNull() { m_type = NULL; }
	bool isNull() const { return m_type == NULL; }

	void dump() const {
		dump(std::cout);
	}

	void dump(std::ostream& out) const {
		if (m_type) {
			m_type->dump(&m_data, out);
		} else {
			out << "null";
		}
	}
	void setObj(void* ptr) {
		clever_assert_not_null(m_type);
		m_data.obj = new ValueObject(ptr, m_type);
	}
	void* getObj() const { return m_data.obj->getObj(); }

	void setInt(long n) { m_data.lval = n; m_type = CLEVER_INT_TYPE; }
	long getInt() const { return m_data.lval; }

	void setBool(bool n) { m_data.bval = n; m_type = CLEVER_BOOL_TYPE; }
	bool getBool() const { return m_data.bval; }

	void setDouble(double n) { m_data.dval = n; m_type = CLEVER_DOUBLE_TYPE; }
	double getDouble() const { return m_data.dval; }

	const DataValue* getData() const { return &m_data; }

	void setStr(const CString* str) { m_data.sval = str; m_type = CLEVER_STR_TYPE; }
	const CString* getStr() const { return m_data.sval; }

	void copy(const Value* value) {
		m_type = value->getType();
		memcpy(&m_data, value->getData(), sizeof(DataValue));

		if (m_type && !m_type->isPrimitive()) {
			if (m_data.obj) {
				m_data.obj->addRef();
			}
		}
	}

	Value* clone() const {
		Value* val = new Value;
		val->copy(this);
		return val;
	}

	bool asBool() const {
		if (isNull()) {
			return false;
		} else if (m_type == CLEVER_BOOL_TYPE) {
			return m_data.bval;
		}
		return true;
	}

	// @TODO(muriloadriano): This is a workout to allow the assign on a const
	// variable declaration. If the current data is null and it is const, the
	// assign must be performed (first assign), if it is not null and const,
	// we cannot assign because it is trying to change its value. If it this
	// value isn't const it is assignable too. Maybe this could be done in a
	// clever way.
	bool isAssignable() const {
		return isNull() || !isConst();
	}

	bool isConst() const {
		return m_is_const;
	}

	void setConst(bool constness = true) {
		m_is_const = constness;
	}
private:
	DataValue m_data;
	const Type* m_type;
	bool m_is_const;

	DISALLOW_COPY_AND_ASSIGN(Value);
};

} // clever

#endif // CLEVER_VALUE_H<commit_msg>safety while mod.std.concurrent is loaded<commit_after>/**
 * Clever programming language
 * Copyright (c) Clever Team
 *
 * This file is distributed under the MIT license. See LICENSE for details.
 */

#ifndef CLEVER_VALUE_H
#define CLEVER_VALUE_H

#include <cstring>

#include "core/cstring.h"
#include "types/type.h"

namespace clever {

extern Type* const g_clever_int_type;
extern Type* const g_clever_double_type;
extern Type* const g_clever_str_type;
extern Type* const g_clever_func_type;
extern Type* const g_clever_thread_type;
extern Type* const g_clever_bool_type;
extern Type* const g_clever_array_type;
extern Type* const g_clever_map_type;

#define CLEVER_INT_TYPE    g_clever_int_type
#define CLEVER_DOUBLE_TYPE g_clever_double_type
#define CLEVER_STR_TYPE    g_clever_str_type
#define CLEVER_FUNC_TYPE   g_clever_func_type
#define CLEVER_THREAD_TYPE g_clever_thread_type
#define CLEVER_BOOL_TYPE   g_clever_bool_type
#define CLEVER_ARRAY_TYPE  g_clever_array_type
#define CLEVER_MAP_TYPE    g_clever_map_type

#ifdef MOD_STD_CONCURRENT
# define SAFETY_CTOR() pthread_mutex_init(&m_mutex, NULL)
# define SAFETY_DTOR() pthread_mutex_destroy(&m_mutex)
#else
# define SAFETY_CTOR()
# define SAFETY_DTOR()
#endif

typedef std::map     <std::string, Value*>  ValueMap;
typedef std::pair    <std::string, Value*>  ValuePair;
typedef std::vector  <Value*>               ValueVector;

class ValueObject : public RefCounted {
public:
	ValueObject()
		: RefCounted(1), m_obj(NULL), m_type(NULL) {}

	ValueObject(void* obj, const Type* type)
		: RefCounted(1), m_obj(obj), m_type(type) {}

	virtual ~ValueObject() {
		if (m_type) {
			const_cast<Type*>(m_type)->deallocData(m_obj);
		}
	}

	void* getObj() { return m_obj; }
private:
	void* m_obj;
	const Type* m_type;

	DISALLOW_COPY_AND_ASSIGN(ValueObject);
};

class Value : public RefCounted {
public:
	union DataValue {
		bool bval;
		long lval;
		double dval;
		const CString* sval;
		ValueObject* obj;

		DataValue() : lval(0) {}
		DataValue(bool value) : bval(value) {}
		DataValue(long value) : lval(value) {}
		DataValue(double value) : dval(value) {}
		DataValue(const CString* value) : sval(value) {}
	};

	Value() : m_data(), m_type(NULL), m_is_const(false) {SAFETY_CTOR();}

	Value(bool n, bool is_const = false)
		: m_data(n), m_type(CLEVER_BOOL_TYPE), m_is_const(is_const) {SAFETY_CTOR();}

	Value(long n, bool is_const = false)
		: m_data(n), m_type(CLEVER_INT_TYPE), m_is_const(is_const) {SAFETY_CTOR();}

	Value(double n, bool is_const = false)
		: m_data(n), m_type(CLEVER_DOUBLE_TYPE), m_is_const(is_const) {SAFETY_CTOR();}

	Value(const CString* value, bool is_const = false)
		: m_data(value), m_type(CLEVER_STR_TYPE), m_is_const(is_const) {SAFETY_CTOR();}

	Value(const Type* type, bool is_const = false)
		: m_data(), m_type(type), m_is_const(is_const) {SAFETY_CTOR();}

	~Value() {
		if (m_type && !m_type->isPrimitive()) {
			if (m_data.obj) {
				m_data.obj->delRef();
			}
		}
		SAFETY_DTOR();
	}

	void setType(const Type* type) { m_type = type; }
	const Type* getType() const { return m_type; }

	void setNull() { m_type = NULL; }
	bool isNull() const { return m_type == NULL; }

	void dump() const {
		dump(std::cout);
	}

	void dump(std::ostream& out) const {
		if (m_type) {
			m_type->dump(&m_data, out);
		} else {
			out << "null";
		}
	}
	void setObj(void* ptr) {
		clever_assert_not_null(m_type);
		m_data.obj = new ValueObject(ptr, m_type);
	}
	void* getObj() const { return m_data.obj->getObj(); }

	void setInt(long n) { m_data.lval = n; m_type = CLEVER_INT_TYPE; }
	long getInt() const { return m_data.lval; }

	void setBool(bool n) { m_data.bval = n; m_type = CLEVER_BOOL_TYPE; }
	bool getBool() const { return m_data.bval; }

	void setDouble(double n) { m_data.dval = n; m_type = CLEVER_DOUBLE_TYPE; }
	double getDouble() const { return m_data.dval; }

	const DataValue* getData() const { return &m_data; }

	void setStr(const CString* str) { m_data.sval = str; m_type = CLEVER_STR_TYPE; }
	const CString* getStr() const { return m_data.sval; }

	void copy(const Value* value) {
		m_type = value->getType();
		memcpy(&m_data, value->getData(), sizeof(DataValue));

		if (m_type && !m_type->isPrimitive()) {
			if (m_data.obj) {
				m_data.obj->addRef();
			}
		}
	}

	Value* clone() const {
		Value* val = new Value;
		val->copy(this);
		return val;
	}

	bool asBool() const {
		if (isNull()) {
			return false;
		} else if (m_type == CLEVER_BOOL_TYPE) {
			return m_data.bval;
		}
		return true;
	}

	// @TODO(muriloadriano): This is a workout to allow the assign on a const
	// variable declaration. If the current data is null and it is const, the
	// assign must be performed (first assign), if it is not null and const,
	// we cannot assign because it is trying to change its value. If it this
	// value isn't const it is assignable too. Maybe this could be done in a
	// clever way.
	bool isAssignable() const {
		return isNull() || !isConst();
	}

	bool isConst() const {
		return m_is_const;
	}

	void setConst(bool constness = true) {
		m_is_const = constness;
	}

private:
	DataValue m_data;
	const Type* m_type;
	bool m_is_const;
#ifdef MOD_STD_CONCURRENT
	pthread_mutex_t m_mutex;
#endif
	DISALLOW_COPY_AND_ASSIGN(Value);
};

} // clever

#endif // CLEVER_VALUE_H
{'fraction_non_alphanumeric': 0.1251845290817833, 'fraction_numerical': 0.000590493061706525, 'mean_word_length': 4.411075612353567, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 33, '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': '3456149', 'n_tokens_mistral': 4118, 'n_tokens_neox': 3865, 'n_words': 960}