aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore14
-rw-r--r--LICENSE15
-rw-r--r--Makefile73
-rw-r--r--README14
-rw-r--r--config.mk8
-rw-r--r--libcmap.h47
-rw-r--r--libcmap_block_list.c11
-rw-r--r--libcmap_find_block.c20
-rw-r--r--libcmap_find_script.c29
-rw-r--r--libcmap_script_list.c11
-rw-r--r--mk/linux.mk6
-rw-r--r--mk/macos.mk6
-rw-r--r--mk/windows.mk6
13 files changed, 260 insertions, 0 deletions
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 <m@maandree.se>
+
+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 <libcmap.h>
+
+ 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 <stddef.h>
+#include <stdint.h>
+
+#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 = :