18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Module for handling utf8 just like any other charset.
38c2ecf20Sopenharmony_ci * By Urban Widmark 2000
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#include <linux/module.h>
78c2ecf20Sopenharmony_ci#include <linux/kernel.h>
88c2ecf20Sopenharmony_ci#include <linux/string.h>
98c2ecf20Sopenharmony_ci#include <linux/nls.h>
108c2ecf20Sopenharmony_ci#include <linux/errno.h>
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_cistatic unsigned char identity[256];
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_cistatic int uni2char(wchar_t uni, unsigned char *out, int boundlen)
158c2ecf20Sopenharmony_ci{
168c2ecf20Sopenharmony_ci	int n;
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci	if (boundlen <= 0)
198c2ecf20Sopenharmony_ci		return -ENAMETOOLONG;
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci	n = utf32_to_utf8(uni, out, boundlen);
228c2ecf20Sopenharmony_ci	if (n < 0) {
238c2ecf20Sopenharmony_ci		*out = '?';
248c2ecf20Sopenharmony_ci		return -EINVAL;
258c2ecf20Sopenharmony_ci	}
268c2ecf20Sopenharmony_ci	return n;
278c2ecf20Sopenharmony_ci}
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_cistatic int char2uni(const unsigned char *rawstring, int boundlen, wchar_t *uni)
308c2ecf20Sopenharmony_ci{
318c2ecf20Sopenharmony_ci	int n;
328c2ecf20Sopenharmony_ci	unicode_t u;
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci	n = utf8_to_utf32(rawstring, boundlen, &u);
358c2ecf20Sopenharmony_ci	if (n < 0 || u > MAX_WCHAR_T) {
368c2ecf20Sopenharmony_ci		*uni = 0x003f;	/* ? */
378c2ecf20Sopenharmony_ci		return -EINVAL;
388c2ecf20Sopenharmony_ci	}
398c2ecf20Sopenharmony_ci	*uni = (wchar_t) u;
408c2ecf20Sopenharmony_ci	return n;
418c2ecf20Sopenharmony_ci}
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_cistatic struct nls_table table = {
448c2ecf20Sopenharmony_ci	.charset	= "utf8",
458c2ecf20Sopenharmony_ci	.uni2char	= uni2char,
468c2ecf20Sopenharmony_ci	.char2uni	= char2uni,
478c2ecf20Sopenharmony_ci	.charset2lower	= identity,	/* no conversion */
488c2ecf20Sopenharmony_ci	.charset2upper	= identity,
498c2ecf20Sopenharmony_ci};
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_cistatic int __init init_nls_utf8(void)
528c2ecf20Sopenharmony_ci{
538c2ecf20Sopenharmony_ci	int i;
548c2ecf20Sopenharmony_ci	for (i=0; i<256; i++)
558c2ecf20Sopenharmony_ci		identity[i] = i;
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci        return register_nls(&table);
588c2ecf20Sopenharmony_ci}
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_cistatic void __exit exit_nls_utf8(void)
618c2ecf20Sopenharmony_ci{
628c2ecf20Sopenharmony_ci        unregister_nls(&table);
638c2ecf20Sopenharmony_ci}
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_cimodule_init(init_nls_utf8)
668c2ecf20Sopenharmony_cimodule_exit(exit_nls_utf8)
678c2ecf20Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL");
68