From 28f3247dbb786a42f0460a7aa88d558056a68144 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Sat, 20 Dec 2025 06:49:30 +0100 Subject: First commit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- .gitignore | 14 ++++++++++ LICENSE | 15 +++++++++++ Makefile | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++ README | 14 ++++++++++ config.mk | 8 ++++++ libcmap.h | 47 +++++++++++++++++++++++++++++++++ libcmap_block_list.c | 11 ++++++++ libcmap_find_block.c | 20 ++++++++++++++ libcmap_find_script.c | 29 ++++++++++++++++++++ libcmap_script_list.c | 11 ++++++++ mk/linux.mk | 6 +++++ mk/macos.mk | 6 +++++ mk/windows.mk | 6 +++++ 13 files changed, 260 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 README create mode 100644 config.mk create mode 100644 libcmap.h create mode 100644 libcmap_block_list.c create mode 100644 libcmap_find_block.c create mode 100644 libcmap_find_script.c create mode 100644 libcmap_script_list.c create mode 100644 mk/linux.mk create mode 100644 mk/macos.mk create mode 100644 mk/windows.mk diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a071ed4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +*\#* +*~ +*.o +*.a +*.lo +*.su +*.so +*.so.* +*.dll +*.dylib +*.gch +*.gcov +*.gcno +*.gcda diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0e6be1c --- /dev/null +++ b/LICENSE @@ -0,0 +1,15 @@ +ISC License + +© 2025 Mattias Andrée + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e189657 --- /dev/null +++ b/Makefile @@ -0,0 +1,73 @@ +.POSIX: + +CONFIGFILE = config.mk +include $(CONFIGFILE) + +OS = linux +# Linux: linux +# Mac OS: macos +# Windows: windows +include mk/$(OS).mk + + +LIB_MAJOR = 1 +LIB_MINOR = 0 +LIB_VERSION = $(LIB_MAJOR).$(LIB_MINOR) +LIB_NAME = cmap + + +OBJ =\ + libcmap_block_list.o\ + libcmap_script_list.o\ + libcmap_find_block.o\ + libcmap_find_script.o + +HDR =\ + libcmap.h + +LOBJ = $(OBJ:.o=.lo) + + +all: libcmap.a libcmap.$(LIBEXT) +$(OBJ): $(HDR) +$(LOBJ): $(HDR) + +.c.o: + $(CC) -c -o $@ $< $(CFLAGS) $(CPPFLAGS) + +.c.lo: + $(CC) -fPIC -c -o $@ $< $(CFLAGS) $(CPPFLAGS) + +libcmap.a: $(OBJ) + @rm -f -- $@ + $(AR) rc $@ $(OBJ) + $(AR) ts $@ > /dev/null + +libcmap.$(LIBEXT): $(LOBJ) + $(CC) $(LIBFLAGS) -o $@ $(LOBJ) $(LDFLAGS) + +install: libcmap.a libcmap.$(LIBEXT) + mkdir -p -- "$(DESTDIR)$(PREFIX)/lib" + mkdir -p -- "$(DESTDIR)$(PREFIX)/include" + cp -- libcmap.a "$(DESTDIR)$(PREFIX)/lib/" + cp -- libcmap.$(LIBEXT) "$(DESTDIR)$(PREFIX)/lib/libcmap.$(LIBMINOREXT)" + $(FIX_INSTALL_NAME) "$(DESTDIR)$(PREFIX)/lib/libcmap.$(LIBMINOREXT)" + ln -sf -- libcmap.$(LIBMINOREXT) "$(DESTDIR)$(PREFIX)/lib/libcmap.$(LIBMAJOREXT)" + ln -sf -- libcmap.$(LIBMAJOREXT) "$(DESTDIR)$(PREFIX)/lib/libcmap.$(LIBEXT)" + cp -- libcmap.h "$(DESTDIR)$(PREFIX)/include/" + +uninstall: + -rm -f -- "$(DESTDIR)$(PREFIX)/lib/libcmap.a" + -rm -f -- "$(DESTDIR)$(PREFIX)/lib/libcmap.$(LIBMAJOREXT)" + -rm -f -- "$(DESTDIR)$(PREFIX)/lib/libcmap.$(LIBMINOREXT)" + -rm -f -- "$(DESTDIR)$(PREFIX)/lib/libcmap.$(LIBEXT)" + -rm -f -- "$(DESTDIR)$(PREFIX)/include/libcmap.h" + +clean: + -rm -f -- *.o *.a *.lo *.su *.so *.so.* *.dll *.dylib + -rm -f -- *.gch *.gcov *.gcno *.gcda *.$(LIBEXT) + +.SUFFIXES: +.SUFFIXES: .lo .o .c + +.PHONY: all install uninstall clean diff --git a/README b/README new file mode 100644 index 0000000..9d16724 --- /dev/null +++ b/README @@ -0,0 +1,14 @@ +NAME + libcmap - Unicode character data library + +SYNOPSIS + #include + + Link with -lcmap. + +DESCRIPTION + The libcmap library provides data about characters in the + Unicode Character Set. + +SEE ALSO + libgrapheme(7) diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..f4adf12 --- /dev/null +++ b/config.mk @@ -0,0 +1,8 @@ +PREFIX = /usr +MANPREFIX = $(PREFIX)/share/man + +CC = c99 + +CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_GNU_SOURCE +CFLAGS = +LDFLAGS = diff --git a/libcmap.h b/libcmap.h new file mode 100644 index 0000000..54e60cc --- /dev/null +++ b/libcmap.h @@ -0,0 +1,47 @@ +/* See LICENSE file for copyright and license details. */ +#ifndef LIBCMAP_H +#define LIBCMAP_H + +#include +#include + +#if defined(__GNUC__) +# define LIBCMAP_PURE_ __attribute__((__pure__)) +# define LIBCMAP_CONST_ __attribute__((__const__)) +#else +# define LIBCMAP_PURE_ +# define LIBCMAP_CONST_ +#endif + + +struct libcmap_range { + uint32_t first; + uint32_t last; +}; + +struct libcmap_block { + const char *name; + struct libcmap_range range; +}; + +struct libcmap_script { + const char *name; + struct libcmap_range *ranges; + size_t nranges; +}; + + +extern const struct libcmap_block *const libcmap_block_list; +extern const size_t libcmap_block_list_size; + +extern const struct libcmap_script *const libcmap_script_list; +extern const size_t libcmap_script_list_size; + + +const struct libcmap_block *libcmap_find_block(uint32_t codepoint, size_t *offset_out); +const struct libcmap_script *libcmap_find_script(uint32_t codepoint, size_t *offset_out, size_t *subrange_out); + + +#undef LIBCMAP_PURE_ +#undef LIBCMAP_CONST_ +#endif diff --git a/libcmap_block_list.c b/libcmap_block_list.c new file mode 100644 index 0000000..e0d3b93 --- /dev/null +++ b/libcmap_block_list.c @@ -0,0 +1,11 @@ +/* See LICENSE file for copyright and license details. */ +#include "libcmap.h" + + +static const struct libcmap_block list[] = { + {"Phony block", {0, 0}} +}; + + +const struct libcmap_block *const libcmap_block_list = list; +const size_t libcmap_block_list_size = sizeof(list) / sizeof(*list); diff --git a/libcmap_find_block.c b/libcmap_find_block.c new file mode 100644 index 0000000..974297d --- /dev/null +++ b/libcmap_find_block.c @@ -0,0 +1,20 @@ +/* See LICENSE file for copyright and license details. */ +#include "libcmap.h" + + +const struct libcmap_block * +libcmap_find_block(uint32_t codepoint, size_t *offset_out) +{ + const struct libcmap_block *list = libcmap_block_list; + size_t i, n = libcmap_block_list_size; + for (i = 0; i < n; i++) { + if (list[i].range.first <= codepoint && list[i].range.last <= codepoint) { + if (offset_out) + *offset_out = (size_t)(codepoint - list[i].range.first); + return &list[i]; + } + } + if (offset_out) + *offset_out = (size_t)codepoint; + return NULL; +} diff --git a/libcmap_find_script.c b/libcmap_find_script.c new file mode 100644 index 0000000..f8787f8 --- /dev/null +++ b/libcmap_find_script.c @@ -0,0 +1,29 @@ +/* See LICENSE file for copyright and license details. */ +#include "libcmap.h" + + +const struct libcmap_script * +libcmap_find_script(uint32_t codepoint, size_t *offset_out, size_t *subrange_out) +{ + const struct libcmap_script *list = libcmap_script_list; + size_t i, j, n = libcmap_script_list_size; + size_t skipped; + for (i = 0; i < n; i++) { + skipped = 0; + for (j = 0; j < list[i].nranges; j++) { + if (list[i].ranges[j].first <= codepoint && list[i].ranges[j].last <= codepoint) { + if (offset_out) + *offset_out = skipped + (size_t)(codepoint - list[i].ranges[j].first); + if (subrange_out) + *subrange_out = j; + return &list[i]; + } + skipped += (size_t)(list[i].ranges[j].last - list[i].ranges[j].first) + 1U; + } + } + if (offset_out) + *offset_out = (size_t)codepoint; + if (subrange_out) + *subrange_out = 0; + return NULL; +} diff --git a/libcmap_script_list.c b/libcmap_script_list.c new file mode 100644 index 0000000..7464f5c --- /dev/null +++ b/libcmap_script_list.c @@ -0,0 +1,11 @@ +/* See LICENSE file for copyright and license details. */ +#include "libcmap.h" + + +static const struct libcmap_script list[] = { + {"Phony script", NULL, 0} +}; + + +const struct libcmap_script *const libcmap_script_list = list; +const size_t libcmap_script_list_size = sizeof(list) / sizeof(*list); diff --git a/mk/linux.mk b/mk/linux.mk new file mode 100644 index 0000000..ad58f69 --- /dev/null +++ b/mk/linux.mk @@ -0,0 +1,6 @@ +LIBEXT = so +LIBFLAGS = -shared -Wl,-soname,lib$(LIB_NAME).$(LIBEXT).$(LIB_MAJOR) +LIBMAJOREXT = $(LIBEXT).$(LIB_MAJOR) +LIBMINOREXT = $(LIBEXT).$(LIB_VERSION) + +FIX_INSTALL_NAME = : diff --git a/mk/macos.mk b/mk/macos.mk new file mode 100644 index 0000000..568f5eb --- /dev/null +++ b/mk/macos.mk @@ -0,0 +1,6 @@ +LIBEXT = dylib +LIBFLAGS = -dynamiclib -Wl,-compatibility_version,$(LIB_MAJOR) -Wl,-current_version,$(LIB_VERSION) +LIBMAJOREXT = $(LIB_MAJOR).$(LIBEXT) +LIBMINOREXT = $(LIB_VERSION).$(LIBEXT) + +FIX_INSTALL_NAME = install_name_tool -id "$(PREFIX)/lib/libcmap.$(LIBMAJOREXT)" diff --git a/mk/windows.mk b/mk/windows.mk new file mode 100644 index 0000000..ed5ec8d --- /dev/null +++ b/mk/windows.mk @@ -0,0 +1,6 @@ +LIBEXT = dll +LIBFLAGS = -shared +LIBMAJOREXT = $(LIB_MAJOR).$(LIBEXT) +LIBMINOREXT = $(LIB_VERSION).$(LIBEXT) + +FIX_INSTALL_NAME = : -- cgit v1.3.1