Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / third_party / pigweed / repo / pw_tokenizer / java / dev / pigweed / tokenizer / Detokenizer.java
1 // Copyright 2020 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14
15 /**
16  * This is a Java Native Interface (JNI) wrapper for the Detokenizer class.
17  *
18  * <p>This classes uses the Android Base64 library instead of the standard Java Base64, which is not
19  * yet available on Android. To use this class outside of Android, replace android.util.Base64 with
20  * java.util.Base64.
21  */
22 package dev.pigweed.tokenizer;
23
24 import android.util.Base64;
25 import java.util.regex.Matcher;
26 import java.util.regex.Pattern;
27
28 /** This class provides the Java interface for the C++ Detokenizer class. */
29 public class Detokenizer {
30   // Android's Base64 library doesn't seem to check if the Base64-encoded data is valid. This
31   // regular expression checks that it is. Does not match URL-safe or unpadded Base64.
32   private static final Pattern TOKENIZED_STRING =
33       Pattern.compile("\\$([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)?");
34
35   static {
36     System.loadLibrary("detokenizer");
37   }
38
39   // The handle to the C++ detokenizer instance.
40   private final long handle;
41
42   public Detokenizer() {
43     this(new byte[0]);
44   }
45
46   public Detokenizer(byte[] tokenDatabase) {
47     handle = newNativeDetokenizer(tokenDatabase);
48   }
49
50   /**
51    * Detokenizes and replaces all recognized tokenized messages ($ followed by Base64) in the
52    * provided string. Unrecognized tokenized strings are left unchanged.
53    */
54   public String detokenize(String message) {
55     Matcher matcher = TOKENIZED_STRING.matcher(message);
56     StringBuilder result = new StringBuilder();
57     int lastIndex = 0;
58
59     while (matcher.find()) {
60       result.append(message, lastIndex, matcher.start());
61
62       String decoded =
63           detokenizeNative(handle, Base64.decode(matcher.group().substring(1), Base64.DEFAULT));
64       result.append(decoded != null ? decoded : matcher.group());
65
66       lastIndex = matcher.end();
67     }
68
69     result.append(message, lastIndex, message.length());
70     return result.toString();
71   }
72
73   /** Deletes memory allocated in C++ when this class is garbage collected. */
74   @Override
75   protected void finalize() {
76     deleteNativeDetokenizer(handle);
77   }
78
79   /** Creates a new detokenizer using the provided data as the database. */
80   private static native long newNativeDetokenizer(byte[] data);
81
82   /** Deletes the detokenizer object with the provided handle, which MUST be valid. */
83   private static native void deleteNativeDetokenizer(long handle);
84
85   /**
86    * Returns the detokenized version of the provided data. This is non-static so this object has a
87    * reference held while the function is running, which prevents finalize from running before
88    * detokenizeNative finishes.
89    */
90   private native String detokenizeNative(long handle, byte[] data);
91 }