summaryrefslogtreecommitdiff
path: root/src/Emoji.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/Emoji.zig')
-rw-r--r--src/Emoji.zig130
1 files changed, 44 insertions, 86 deletions
diff --git a/src/Emoji.zig b/src/Emoji.zig
index 75b44c2..13f675b 100644
--- a/src/Emoji.zig
+++ b/src/Emoji.zig
@@ -1,17 +1,17 @@
1const std = @import("std"); 1//! Emoji module
2const builtin = @import("builtin");
3const mem = std.mem;
4const Allocator = mem.Allocator;
5const compress = std.compress;
6const unicode = std.unicode;
7
8const CodePoint = @import("code_point").CodePoint;
9const CodePointIterator = @import("code_point").Iterator;
10 2
11s1: []u16 = undefined, 3const Data = struct {
12s2: []u6 = undefined, 4 s1: []const u16 = undefined,
5 s2: []const u6 = undefined,
6};
13 7
14const Emoji = @This(); 8const emoji = emoji: {
9 const data = @import("emoji");
10 break :emoji Data{
11 .s1 = &data.s1,
12 .s2 = &data.s2,
13 };
14};
15 15
16// This must be an exact match of `Emoji` from `codegen/emoji.zig`. 16// This must be an exact match of `Emoji` from `codegen/emoji.zig`.
17pub const Properties = packed struct { 17pub const Properties = packed struct {
@@ -23,110 +23,68 @@ pub const Properties = packed struct {
23 Extended_Pictographic: bool = false, 23 Extended_Pictographic: bool = false,
24}; 24};
25 25
26pub fn init(allocator: Allocator) Allocator.Error!Emoji {
27 var emoji = Emoji{};
28 try emoji.setup(allocator);
29 return emoji;
30}
31
32pub fn setup(emoji: *Emoji, allocator: Allocator) Allocator.Error!void {
33 const decompressor = compress.flate.inflate.decompressor;
34 const in_bytes = @embedFile("emoji");
35 var in_fbs = std.io.fixedBufferStream(in_bytes);
36 var in_decomp = decompressor(.raw, in_fbs.reader());
37 var reader = in_decomp.reader();
38
39 const endian = builtin.cpu.arch.endian();
40
41 const s1_len: u16 = reader.readInt(u16, endian) catch unreachable;
42 emoji.s1 = try allocator.alloc(u16, s1_len);
43 errdefer allocator.free(emoji.s1);
44 for (0..s1_len) |i| emoji.s1[i] = reader.readInt(u16, endian) catch unreachable;
45
46 const s2_len: u16 = reader.readInt(u16, endian) catch unreachable;
47 emoji.s2 = try allocator.alloc(u6, s2_len);
48 errdefer allocator.free(emoji.s2);
49 for (0..s2_len) |i| emoji.s2[i] = @intCast(reader.readInt(u8, endian) catch unreachable);
50}
51
52pub fn deinit(emoji: *const Emoji, allocator: Allocator) void {
53 allocator.free(emoji.s1);
54 allocator.free(emoji.s2);
55}
56
57/// Lookup the emoji properties for a code point. 26/// Lookup the emoji properties for a code point.
58fn properties(emoji: Emoji, cp: u21) Properties { 27fn properties(cp: u21) Properties {
59 return @bitCast(emoji.s2[emoji.s1[cp >> 8] + (cp & 0xff)]); 28 return @bitCast(emoji.s2[emoji.s1[cp >> 8] + (cp & 0xff)]);
60} 29}
61 30
62pub fn isEmoji(emoji: Emoji, cp: u21) bool { 31pub fn isEmoji(cp: u21) bool {
63 return properties(emoji, cp).Emoji; 32 return properties(cp).Emoji;
64} 33}
65 34
66pub fn isEmojiPresentation(emoji: Emoji, cp: u21) bool { 35pub fn isEmojiPresentation(cp: u21) bool {
67 return properties(emoji, cp).Emoji_Presentation; 36 return properties(cp).Emoji_Presentation;
68} 37}
69 38
70pub fn isEmojiModifier(emoji: Emoji, cp: u21) bool { 39pub fn isEmojiModifier(cp: u21) bool {
71 return properties(emoji, cp).Emoji_Modifier; 40 return properties(cp).Emoji_Modifier;
72} 41}
73 42
74pub fn isEmojiModifierBase(emoji: Emoji, cp: u21) bool { 43pub fn isEmojiModifierBase(cp: u21) bool {
75 return properties(emoji, cp).Emoji_Modifier_Base; 44 return properties(cp).Emoji_Modifier_Base;
76} 45}
77 46
78pub fn isEmojiComponent(emoji: Emoji, cp: u21) bool { 47pub fn isEmojiComponent(cp: u21) bool {
79 return properties(emoji, cp).Emoji_Component; 48 return properties(cp).Emoji_Component;
80} 49}
81 50
82pub fn isExtendedPictographic(emoji: Emoji, cp: u21) bool { 51pub fn isExtendedPictographic(cp: u21) bool {
83 return properties(emoji, cp).Extended_Pictographic; 52 return properties(cp).Extended_Pictographic;
84} 53}
85 54
86test "isEmoji" { 55test "isEmoji" {
87 const emoji = try Emoji.init(std.testing.allocator); 56 try std.testing.expect(isEmoji(0x1F415)); // 🐕
88 defer emoji.deinit(std.testing.allocator); 57 try std.testing.expect(!isEmoji(0x3042)); // あ
89
90 try std.testing.expect(emoji.isEmoji(0x1F415)); // 🐕
91 try std.testing.expect(!emoji.isEmoji(0x3042)); // あ
92} 58}
93 59
94test "isEmojiPresentation" { 60test "isEmojiPresentation" {
95 const emoji = try Emoji.init(std.testing.allocator); 61 try std.testing.expect(isEmojiPresentation(0x1F408)); // 🐈
96 defer emoji.deinit(std.testing.allocator); 62 try std.testing.expect(!isEmojiPresentation(0x267E)); // ♾
97
98 try std.testing.expect(emoji.isEmojiPresentation(0x1F408)); // 🐈
99 try std.testing.expect(!emoji.isEmojiPresentation(0x267E)); // ♾
100} 63}
101 64
102test "isEmojiModifier" { 65test "isEmojiModifier" {
103 const emoji = try Emoji.init(std.testing.allocator); 66 try std.testing.expect(isEmojiModifier(0x1F3FF)); //
104 defer emoji.deinit(std.testing.allocator); 67 try std.testing.expect(!isEmojiModifier(0x1F385)); // 🎅
105
106 try std.testing.expect(emoji.isEmojiModifier(0x1F3FF)); // 🏿
107 try std.testing.expect(!emoji.isEmojiModifier(0x1F385)); // 🎅
108} 68}
109 69
110test "isEmojiModifierBase" { 70test "isEmojiModifierBase" {
111 const emoji = try Emoji.init(std.testing.allocator); 71 try std.testing.expect(isEmojiModifierBase(0x1F977)); // 🥷
112 defer emoji.deinit(std.testing.allocator); 72 try std.testing.expect(!isEmojiModifierBase(0x1F4F8)); // 📸
113
114 try std.testing.expect(emoji.isEmojiModifierBase(0x1F977)); // 🥷
115 try std.testing.expect(!emoji.isEmojiModifierBase(0x1F4F8)); // 📸
116} 73}
117 74
118test "isEmojiComponent" { 75test "isEmojiComponent" {
119 const emoji = try Emoji.init(std.testing.allocator); 76 try std.testing.expect(isEmojiComponent(0x1F9B0)); // 🦰
120 defer emoji.deinit(std.testing.allocator); 77 try std.testing.expect(!isEmojiComponent(0x1F9B5)); // 🦵
121
122 try std.testing.expect(emoji.isEmojiComponent(0x1F9B0)); // 🦰
123 try std.testing.expect(!emoji.isEmojiComponent(0x1F9B5)); // 🦵
124} 78}
125 79
126test "isExtendedPictographic" { 80test "isExtendedPictographic" {
127 const emoji = try Emoji.init(std.testing.allocator); 81 try std.testing.expect(isExtendedPictographic(0x1F005)); // 🀅
128 defer emoji.deinit(std.testing.allocator); 82 try std.testing.expect(!isExtendedPictographic(0x2A)); // *
129
130 try std.testing.expect(emoji.isExtendedPictographic(0x1F005)); // 🀅
131 try std.testing.expect(!emoji.isExtendedPictographic(0x2A)); // *
132} 83}
84
85const std = @import("std");
86const builtin = @import("builtin");
87const unicode = std.unicode;
88
89const CodePoint = @import("code_point").CodePoint;
90const CodePointIterator = @import("code_point").Iterator;