package cc.blynk.utils; import java.util.regex.Pattern; /** * The Blynk Project. * Created by Dmitriy Dumanskiy. * Created on 2/18/2015. */ public class StringUtils { public static final char BODY_SEPARATOR = '\0'; public static final String BODY_SEPARATOR_STRING = String.valueOf(BODY_SEPARATOR); public static final char DEVICE_SEPARATOR = '-'; public static final Pattern PIN_PATTERN = Pattern.compile("/pin/", Pattern.LITERAL); public static final Pattern PIN_PATTERN_0 = Pattern.compile("/pin[0]/", Pattern.LITERAL); public static final Pattern PIN_PATTERN_1 = Pattern.compile("/pin[1]/", Pattern.LITERAL); public static final Pattern PIN_PATTERN_2 = Pattern.compile("/pin[2]/", Pattern.LITERAL); public static final Pattern PIN_PATTERN_3 = Pattern.compile("/pin[3]/", Pattern.LITERAL); public static final Pattern PIN_PATTERN_4 = Pattern.compile("/pin[4]/", Pattern.LITERAL); public static final Pattern PIN_PATTERN_5 = Pattern.compile("/pin[5]/", Pattern.LITERAL); public static final Pattern DATETIME_PATTERN = Pattern.compile("/datetime_iso/", Pattern.LITERAL); /** * Parses string similar to this : "xw 1 xxxx" * Every hard message has at least 3 starting chars we don't need. */ private static final int START_INDEX = 3; /** * Efficient split method (instead of String.split). * * Returns pin from hardware body. For instance * * "aw 11 32" - is body. Where 11 is pin Number. * * @throws java.lang.NumberFormatException in case parsed pin not a Number. * */ public static String fetchPin(String body) { int i = START_INDEX; while (i < body.length()) { if (body.charAt(i) == BODY_SEPARATOR) { return body.substring(START_INDEX, i); } i++; } return body.substring(START_INDEX, i); } /** * Optimized method for splitting. It is uses knowledge of Blynk message structure. So it is 2-3 times faster * and produces less garbage. * * Does same as String.split(BODY_SEPARATOR_STRING, 3); * * See StringUtilPerfTest * Benchmark Mode Cnt Score Error Units StringUtilPerfTest.customSplit3_aw_100_900 avgt 5 46.806 ± 6.927 ns/op StringUtilPerfTest.customSplit3_aw_10_long_text avgt 5 52.334 ± 9.231 ns/op StringUtilPerfTest.customSplit3_aw_1_2 avgt 5 48.483 ± 14.347 ns/op StringUtilPerfTest.customSplit3_vw_1 avgt 5 34.943 ± 9.918 ns/op StringUtilPerfTest.customSplit3_vw_99_22222 avgt 5 46.511 ± 15.401 ns/op StringUtilPerfTest.customSplit3_vw_99_900 avgt 5 48.025 ± 18.951 ns/op StringUtilPerfTest.split3_aw_100_900 avgt 5 113.358 ± 26.606 ns/op StringUtilPerfTest.split3_aw_10_long_text avgt 5 117.831 ± 39.682 ns/op StringUtilPerfTest.split3_aw_1_2 avgt 5 106.119 ± 1.289 ns/op StringUtilPerfTest.split3_vw_1 avgt 5 87.868 ± 11.709 ns/op StringUtilPerfTest.split3_vw_99_22222 avgt 5 115.280 ± 8.697 ns/op StringUtilPerfTest.split3_vw_99_900 avgt 5 123.085 ± 20.625 ns/op * * */ public static String[] split3(String body) { final int i1 = body.indexOf(BODY_SEPARATOR, 1); if (i1 == -1) { return new String[] {body}; } final int i2 = body.indexOf(BODY_SEPARATOR, i1 + 1); if (i2 == -1) { return new String[] {body.substring(0, i1), body.substring(i1 + 1, body.length())}; } return new String[] {body.substring(0, i1), body.substring(i1 + 1, i2), body.substring(i2 + 1, body.length())}; } public static String[] split2Device(String body) { return split2(DEVICE_SEPARATOR, body); } private static String[] split2(char separator, String body) { final int i1 = body.indexOf(separator, 1); if (i1 == -1) { return new String[] {body}; } return new String[] {body.substring(0, i1), body.substring(i1 + 1, body.length())}; } public static String[] split2(String body) { return split2(BODY_SEPARATOR, body); } public static String prependDashIdAndDeviceId(int dashId, int deviceId, String body) { //todo this is back compatibility code. remove in future versions if (deviceId == 0) { return "" + dashId + BODY_SEPARATOR + body; } return "" + dashId + DEVICE_SEPARATOR + deviceId + BODY_SEPARATOR+ body; } }