1 /* 2 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package build.tools.generateemojidata; 27 28 import java.io.IOException; 29 import java.nio.file.Files; 30 import java.nio.file.Paths; 31 import java.nio.file.StandardOpenOption; 32 import java.util.ArrayList; 33 import java.util.List; 34 import java.util.function.Predicate; 35 import java.util.stream.Collectors; 36 import java.util.stream.Stream; 37 38 /** 39 * Generate EmojiData.java 40 * args[0]: Full path string to the template file 41 * args[1]: Full path string to the directory that contains "emoji-data.txt" 42 * args[2]: Full path string to the generated .java file 43 */ 44 public class GenerateEmojiData { 45 public static void main(String[] args) { 46 try { 47 final Range[] last = new Range[1]; // last extended pictographic range 48 last[0] = new Range(0, 0); 49 50 List<Range> extPictRanges = Files.lines(Paths.get(args[1], "emoji-data.txt")) 51 .filter(Predicate.not(l -> l.startsWith("#") || l.isBlank())) 52 .filter(l -> l.contains("; Extended_Pictograph")) 53 .map(l -> new Range(l.replaceFirst(" .*", ""))) 54 .sorted() 55 .collect(ArrayList<Range>::new, 56 (list, r) -> { 57 // collapsing consecutive pictographic ranges 58 int lastIndex = list.size() - 1; 59 if (lastIndex >= 0) { 60 Range lastRange = list.get(lastIndex); 61 if (lastRange.last + 1 == r.start) { 62 list.set(lastIndex, new Range(lastRange.start, r.last)); 63 return; 64 } 65 } 66 list.add(r); 67 }, 68 ArrayList<Range>::addAll); 69 70 // make the code point conditions 71 String extPictCodePoints = extPictRanges.stream() 72 .map(r -> { 73 if (r.start == r.last) { 74 return (" ".repeat(12) + "cp == 0x" + toHexString(r.start)); 75 } else if (r.start == r.last - 1) { 76 return " ".repeat(12) + "cp == 0x" + toHexString(r.start) + " ||\n" + 77 " ".repeat(12) + "cp == 0x" + toHexString(r.last); 78 } else { 79 return " ".repeat(11) + "(cp >= 0x" + toHexString(r.start) + 80 " && cp <= 0x" + toHexString(r.last) + ")"; 81 } 82 }) 83 .collect(Collectors.joining(" ||\n")) + ";\n"; 84 85 // Generate EmojiData.java file 86 Files.write(Paths.get(args[2]), 87 Files.lines(Paths.get(args[0])) 88 .flatMap(l -> { 89 if (l.equals("%%%EXTPICT%%%")) { 90 return Stream.of(extPictCodePoints); 91 } else { 92 return Stream.of(l); 93 } 94 }) 95 .collect(Collectors.toList()), 96 StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING); 97 } catch (IOException e) { 98 e.printStackTrace(); 99 } 100 } 101 102 static int toInt(String hexStr) { 103 return Integer.parseUnsignedInt(hexStr, 16); 104 } 105 106 static String toHexString(int cp) { 107 String ret = Integer.toUnsignedString(cp, 16).toUpperCase(); 108 if (ret.length() < 4) { 109 ret = "0".repeat(4 - ret.length()) + ret; 110 } 111 return ret; 112 } 113 114 static class Range implements Comparable<Range> { 115 int start; 116 int last; 117 118 Range (int start, int last) { 119 this.start = start; 120 this.last = last; 121 } 122 123 Range (String input) { 124 input = input.replaceFirst("\\s#.*", ""); 125 start = toInt(input.replaceFirst("[\\s\\.].*", "")); 126 last = input.contains("..") ? 127 toInt(input.replaceFirst(".*\\.\\.", "") 128 .replaceFirst(";.*", "").trim()) 129 : start; 130 } 131 132 @Override 133 public String toString() { 134 return "Start: " + toHexString(start) + ", Last: " + toHexString(last); 135 } 136 137 @Override 138 public int compareTo(Range other) { 139 return Integer.compare(start, other.start); 140 } 141 } 142 }