1313
1414#include " hb_wrappers.h"
1515
16- hb_codepoint_t ParseCodepoint (const std::string& arg) {
16+ hb_codepoint_t ParseCodepoint (std::string_view arg, bool & optional) {
17+ constexpr std::string_view kOptionalPrefix = " optional:" ;
18+ if (arg.substr (0 , kOptionalPrefix .length ()) == kOptionalPrefix ) {
19+ optional = true ;
20+ arg = arg.substr (kOptionalPrefix .length ());
21+ } else {
22+ optional = false ;
23+ }
1724 uint64_t value = 0 ;
1825 // Check for \u123, u123, otherwise let strtoul work it out.
1926 if (arg[0 ] == ' u' ) {
20- value = strtoul (arg.c_str () + 1 , nullptr , 16 );
27+ value = strtoul (arg.data () + 1 , nullptr , 16 );
2128 } else if (arg[0 ] == ' \\ ' && arg[1 ] == ' u' ) {
22- value = strtoul (arg.c_str () + 2 , nullptr , 16 );
29+ value = strtoul (arg.data () + 2 , nullptr , 16 );
2330 } else {
24- value = strtoul (arg.c_str (), nullptr , 0 );
31+ value = strtoul (arg.data (), nullptr , 0 );
2532 }
2633 if (value == 0 || value > std::numeric_limits<hb_codepoint_t >::max ()) {
2734 std::cerr << " The value '" << arg << " ' (" << value
@@ -43,6 +50,10 @@ void Usage() {
4350 " and must be input as decimal numbers (123), hexadecimal "
4451 " numbers (0x7B), or unicode hexadecimal characters (\\ u7B)."
4552 << std::endl;
53+ std::cout << " Codepoints can be prefixed by the string \" optional:\" to "
54+ " specify that the codepoint can be omitted if it isn't found "
55+ " in the input font file."
56+ << std::endl;
4657 std::cout << " Input terminates with a newline." << std::endl;
4758 std::cout
4859 << " This program will de-duplicate codepoints if the same codepoint is "
@@ -113,13 +124,21 @@ int main(int argc, char** argv) {
113124 hb_face_collect_unicodes (font_face.get (), actual_codepoints.get ());
114125 std::string raw_codepoint;
115126 while (std::cin >> raw_codepoint) {
116- auto codepoint = ParseCodepoint (raw_codepoint);
127+ bool optional = false ;
128+ auto codepoint =
129+ ParseCodepoint (std::string_view (raw_codepoint), optional);
117130 if (!codepoint) {
118131 std::cerr << " Invalid codepoint for " << raw_codepoint << " ; exiting."
119132 << std::endl;
120133 return -1 ;
121134 }
135+
122136 if (!hb_set_has (actual_codepoints.get (), codepoint)) {
137+ if (optional) {
138+ // Code point is optional, so omit it.
139+ continue ;
140+ }
141+
123142 std::cerr << " Codepoint " << raw_codepoint
124143 << " not found in font, aborting." << std::endl;
125144 return -1 ;
0 commit comments