<commit_before>#include <Python.h>
#include <structseq.h>
#ifdef PLATFORM_BSD
#include <xlocale.h>
#else
#include <locale.h>
#endif
#include "localeconv.h"

#ifndef PLATFORM_BSD
#include <string.h>
const char *querylocale(int mask, locale_t loc)
{
	int type = ffs(mask) - 1;
	/*TODO: return locale name */
	return ("C");
}
#endif

static PyObject *LanguageError;
static PyTypeObject LocaleType;

static PyMethodDef LanguageMethods[] = {
	{NULL, NULL, 0, NULL},
};


typedef struct {
	PyObject_HEAD
	locale_t locale;
} Locale;


static Locale* create_locale(PyTypeObject* type, locale_t loc) {
	Locale *self;
	if ((self=(Locale*)type->tp_alloc(type, 0))!=NULL)
		self->locale=loc;
	return self;
}


static PyObject* Locale_new(PyTypeObject* type, PyObject* args, PyObject* kwargs) {
	return (PyObject*)create_locale(type, LC_GLOBAL_LOCALE);
}


static void Locale_dealloc(Locale* self) {
	if (self->locale!=LC_GLOBAL_LOCALE)
		freelocale(self->locale);
	self->ob_type->tp_free((PyObject*)self);
}


static int Locale_init(Locale* self, PyObject* args, PyObject* kwargs) {
	static char *keywords[] = {"mask", "locale", "base", NULL}; 
	int mask = LC_ALL_MASK;
	const char* locale = NULL;
	PyObject* base = NULL;

	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|izO!", keywords,
				&mask, &locale, &LocaleType, &base))
		return 0;

	locale_t loc = newlocale(mask, locale,
			base!=NULL ? ((Locale*)base)->locale : NULL);
	if (loc==NULL)
		PyErr_SetString(PyExc_RuntimeError, "Error creating new Locale.");
	else {
		if (self->locale!=LC_GLOBAL_LOCALE)
			freelocale(self->locale);
		self->locale=loc;
	}
	return 0;
}


static PyObject* Locale_current_locale(PyObject* cls) {
	locale_t loc = uselocale(NULL);
	if (loc==NULL) {
		PyErr_SetString(PyExc_RuntimeError, "Error getting current locale.");
		return NULL;
	}
	PyObject* result = (PyObject*)create_locale(&LocaleType, loc);
	if (result==NULL)
		freelocale(loc);
	return result;
}


static PyObject* Locale_use(Locale* self) {
	locale_t previous = uselocale(self->locale);
	PyObject* result = (PyObject*)create_locale(&LocaleType, previous);
	if (result==NULL)
		freelocale(previous);
	return result;
}

static PyObject* Locale_name(Locale* self, PyObject* mask) {
	if (!PyInt_Check(mask)) {
		PyErr_SetString(PyExc_ValueError, "Mask must be an integer.");
		return NULL;
	}

	int m = (int)PyInt_AsSsize_t(mask);
	if (!m) {
		PyErr_SetString(PyExc_ValueError, "Mask may not be zero.");
		return NULL;
	}
	const char* name = querylocale(m, self->locale);
	if (name==NULL) {
		Py_RETURN_NONE;
	} else 
		return PyString_FromString(name);
}

#include "localeconv.c"


static PyMethodDef Locale_methods[] = {
	{"current_locale", (PyCFunction)Locale_current_locale,
		METH_NOARGS|METH_CLASS,
		"Get the currently active locale."},
	{"name", (PyCFunction)Locale_name, METH_O,
		"Get locale name for a specified category."},
	{"use", (PyCFunction)Locale_use, METH_NOARGS,
	 	"Switch the current thread to this locale."},
	{"lconv", (PyCFunction)Locale_localeconv, METH_NOARGS,
		"Return locale conventions"},
	{NULL},
};<commit_msg>Explicitly handle OS without querylocale()<commit_after>#include <Python.h>
#include <structseq.h>
#ifdef PLATFORM_BSD
#include <xlocale.h>
#else
#include <locale.h>
#endif
#include "localeconv.h"

static PyObject *LanguageError;
static PyTypeObject LocaleType;

static PyMethodDef LanguageMethods[] = {
	{NULL, NULL, 0, NULL},
};


typedef struct {
	PyObject_HEAD
	locale_t locale;
} Locale;


static Locale* create_locale(PyTypeObject* type, locale_t loc) {
	Locale *self;
	if ((self=(Locale*)type->tp_alloc(type, 0))!=NULL)
		self->locale=loc;
	return self;
}


static PyObject* Locale_new(PyTypeObject* type, PyObject* args, PyObject* kwargs) {
	return (PyObject*)create_locale(type, LC_GLOBAL_LOCALE);
}


static void Locale_dealloc(Locale* self) {
	if (self->locale!=LC_GLOBAL_LOCALE)
		freelocale(self->locale);
	self->ob_type->tp_free((PyObject*)self);
}


static int Locale_init(Locale* self, PyObject* args, PyObject* kwargs) {
	static char *keywords[] = {"mask", "locale", "base", NULL}; 
	int mask = LC_ALL_MASK;
	const char* locale = NULL;
	PyObject* base = NULL;

	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|izO!", keywords,
				&mask, &locale, &LocaleType, &base))
		return 0;

	locale_t loc = newlocale(mask, locale,
			base!=NULL ? ((Locale*)base)->locale : NULL);
	if (loc==NULL)
		PyErr_SetString(PyExc_RuntimeError, "Error creating new Locale.");
	else {
		if (self->locale!=LC_GLOBAL_LOCALE)
			freelocale(self->locale);
		self->locale=loc;
	}
	return 0;
}


static PyObject* Locale_current_locale(PyObject* cls) {
	locale_t loc = uselocale(NULL);
	if (loc==NULL) {
		PyErr_SetString(PyExc_RuntimeError, "Error getting current locale.");
		return NULL;
	}
	PyObject* result = (PyObject*)create_locale(&LocaleType, loc);
	if (result==NULL)
		freelocale(loc);
	return result;
}


static PyObject* Locale_use(Locale* self) {
	locale_t previous = uselocale(self->locale);
	PyObject* result = (PyObject*)create_locale(&LocaleType, previous);
	if (result==NULL)
		freelocale(previous);
	return result;
}

static PyObject* Locale_name(Locale* self, PyObject* mask) {
#ifdef PLATFORM_BSD
	if (!PyInt_Check(mask)) {
		PyErr_SetString(PyExc_ValueError, "Mask must be an integer.");
		return NULL;
	}

	int m = (int)PyInt_AsSsize_t(mask);
	if (!m) {
		PyErr_SetString(PyExc_ValueError, "Mask may not be zero.");
		return NULL;
	}
	const char* name = querylocale(m, self->locale);
	if (name==NULL) {
		Py_RETURN_NONE;
	} else 
		return PyString_FromString(name);
#else
	PyErr_SetString(PyExc_RuntimeError, "This OS does not support querylocalae()");
	return NULL;
#endif
}

#include "localeconv.c"


static PyMethodDef Locale_methods[] = {
	{"current_locale", (PyCFunction)Locale_current_locale,
		METH_NOARGS|METH_CLASS,
		"Get the currently active locale."},
	{"name", (PyCFunction)Locale_name, METH_O,
		"Get locale name for a specified category."},
	{"use", (PyCFunction)Locale_use, METH_NOARGS,
	 	"Switch the current thread to this locale."},
	{"lconv", (PyCFunction)Locale_localeconv, METH_NOARGS,
		"Return locale conventions"},
	{NULL},
};
{'fraction_non_alphanumeric': 0.14146182646915187, 'fraction_numerical': 0.001465082207390526, 'mean_word_length': 5.678260869565217, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 36, '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': '2293233', 'n_tokens_mistral': 2295, 'n_tokens_neox': 2242, 'n_words': 526}