001package gudusoft.gsqlparser.dlineage.graph.utils; 002 003import java.io.IOException; 004import java.io.StringWriter; 005import java.io.Writer; 006import java.util.Locale; 007 008public abstract class StringTranslator { 009 010 protected static final char[] HEX_DIGITS = "0123456789ABCDEF".toCharArray(); 011 012 public StringTranslator() { 013 } 014 015 public abstract int translate(CharSequence input, int index, Writer out) throws IOException; 016 017 public final String translate(CharSequence input) { 018 if (input == null) { 019 return null; 020 } 021 try (StringWriter writer = new StringWriter(input.length() * 2)) { 022 translate(input, writer); 023 return writer.toString(); 024 } catch (IOException e) { 025 throw new RuntimeException(e); 026 } 027 } 028 029 public final void translate(CharSequence input, Writer out) throws IOException { 030 if (out == null) { 031 throw new IllegalArgumentException("The Writer must not be null"); 032 } 033 if (input == null) return; 034 035 int currentPos = 0; 036 final int inputLength = input.length(); 037 038 while (currentPos < inputLength) { 039 int consumedChars = translate(input, currentPos, out); 040 041 if (consumedChars == 0) { 042 char currentChar = input.charAt(currentPos++); 043 out.write(currentChar); 044 045 // 处理高/低代理对 046 if (Character.isHighSurrogate(currentChar) && currentPos < inputLength) { 047 char nextChar = input.charAt(currentPos); 048 if (Character.isLowSurrogate(nextChar)) { 049 out.write(nextChar); 050 currentPos++; 051 } 052 } 053 } else { 054 for (int i = 0; i < consumedChars; i++) { 055 currentPos += Character.charCount(Character.codePointAt(input, currentPos)); 056 } 057 } 058 } 059 } 060 061 public final StringTranslator with(StringTranslator... translators) { 062 StringTranslator[] combined = new StringTranslator[translators.length + 1]; 063 combined[0] = this; 064 System.arraycopy(translators, 0, combined, 1, translators.length); 065 return new Translators(combined); 066 } 067 068 public static String hex(int codepoint) { 069 return Integer.toHexString(codepoint).toUpperCase(Locale.ENGLISH); 070 } 071}