1b7d1787dSŁukasz Kosmaty // Copyright © 2021-present 650 Industries, Inc. (aka Expo)
2b7d1787dSŁukasz Kosmaty 
3b7d1787dSŁukasz Kosmaty #pragma once
4b7d1787dSŁukasz Kosmaty 
5b7d1787dSŁukasz Kosmaty #include <fbjni/fbjni.h>
6b7d1787dSŁukasz Kosmaty 
7b7d1787dSŁukasz Kosmaty #include <memory>
8b7d1787dSŁukasz Kosmaty #include <unordered_map>
9b7d1787dSŁukasz Kosmaty 
10b7d1787dSŁukasz Kosmaty namespace jni = facebook::jni;
11b7d1787dSŁukasz Kosmaty 
12b7d1787dSŁukasz Kosmaty namespace expo {
13*75c7ead1SKudo Chien 
14*75c7ead1SKudo Chien template <typename T>
hash_combine(std::size_t & seed,const T & v)15*75c7ead1SKudo Chien inline void hash_combine(std::size_t& seed, const T& v)
16*75c7ead1SKudo Chien {
17*75c7ead1SKudo Chien   std::hash<T> hasher;
18*75c7ead1SKudo Chien   // Reference from: https://github.com/boostorg/container_hash/blob/boost-1.76.0/include/boost/container_hash/hash.hpp
19*75c7ead1SKudo Chien   seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
20*75c7ead1SKudo Chien }
21*75c7ead1SKudo Chien 
22*75c7ead1SKudo Chien struct pairhash {
23*75c7ead1SKudo Chien   template <typename A, typename B>
operatorpairhash24*75c7ead1SKudo Chien   std::size_t operator()(const std::pair<A, B>& v) const {
25*75c7ead1SKudo Chien     std::size_t seed = 0;
26*75c7ead1SKudo Chien     hash_combine(seed, v.first);
27*75c7ead1SKudo Chien     hash_combine(seed, v.second);
28*75c7ead1SKudo Chien     return seed;
29*75c7ead1SKudo Chien   }
30*75c7ead1SKudo Chien };
31*75c7ead1SKudo Chien 
32*75c7ead1SKudo Chien using MethodHashMap = std::unordered_map<std::pair<std::string, std::string>, jmethodID, pairhash>;
33b7d1787dSŁukasz Kosmaty 
34b7d1787dSŁukasz Kosmaty /**
35b7d1787dSŁukasz Kosmaty  * Singleton registry used to store references to often used Java classes.
36b7d1787dSŁukasz Kosmaty  */
37b7d1787dSŁukasz Kosmaty class JavaReferencesCache {
38b7d1787dSŁukasz Kosmaty public:
39b7d1787dSŁukasz Kosmaty   /**
40b7d1787dSŁukasz Kosmaty    * An entry in the Java class registry.
41b7d1787dSŁukasz Kosmaty    */
42b7d1787dSŁukasz Kosmaty   class CachedJClass {
43b7d1787dSŁukasz Kosmaty   public:
44b7d1787dSŁukasz Kosmaty     CachedJClass(jclass clazz, MethodHashMap methods);
45b7d1787dSŁukasz Kosmaty 
46b7d1787dSŁukasz Kosmaty     /**
47b7d1787dSŁukasz Kosmaty      * A bare reference to the class object.
48b7d1787dSŁukasz Kosmaty      */
49b7d1787dSŁukasz Kosmaty     jclass clazz;
50b7d1787dSŁukasz Kosmaty 
51b7d1787dSŁukasz Kosmaty     /**
52b7d1787dSŁukasz Kosmaty      * Returns a cached method id for provided method name and signature.
53b7d1787dSŁukasz Kosmaty      */
54b7d1787dSŁukasz Kosmaty     jmethodID getMethod(const std::string &name, const std::string &signature);
55b7d1787dSŁukasz Kosmaty 
56b7d1787dSŁukasz Kosmaty   private:
57b7d1787dSŁukasz Kosmaty     MethodHashMap methods;
58b7d1787dSŁukasz Kosmaty   };
59b7d1787dSŁukasz Kosmaty 
60b7d1787dSŁukasz Kosmaty   JavaReferencesCache(JavaReferencesCache const &) = delete;
61b7d1787dSŁukasz Kosmaty 
62b7d1787dSŁukasz Kosmaty   JavaReferencesCache &operator=(JavaReferencesCache const &) = delete;
63b7d1787dSŁukasz Kosmaty 
64b7d1787dSŁukasz Kosmaty   /**
65b7d1787dSŁukasz Kosmaty    * Gets a singleton instance
66b7d1787dSŁukasz Kosmaty    */
67b7d1787dSŁukasz Kosmaty   static std::shared_ptr<JavaReferencesCache> instance();
68b7d1787dSŁukasz Kosmaty 
69b7d1787dSŁukasz Kosmaty   /**
70b7d1787dSŁukasz Kosmaty    * Gets a cached Java class entry.
71b7d1787dSŁukasz Kosmaty    */
72b7d1787dSŁukasz Kosmaty   CachedJClass &getJClass(const std::string &className);
73b7d1787dSŁukasz Kosmaty 
74b7d1787dSŁukasz Kosmaty   /**
758d89495bSŁukasz Kosmaty    * Gets a cached Java class entry or loads it to the registry.
768d89495bSŁukasz Kosmaty    */
778d89495bSŁukasz Kosmaty   CachedJClass &getOrLoadJClass(JNIEnv *env, const std::string &className);
788d89495bSŁukasz Kosmaty 
798d89495bSŁukasz Kosmaty   /**
80b7d1787dSŁukasz Kosmaty    * Loads predefined set of Java classes and stores them
81b7d1787dSŁukasz Kosmaty    */
82b7d1787dSŁukasz Kosmaty   void loadJClasses(JNIEnv *env);
83b7d1787dSŁukasz Kosmaty 
84b7d1787dSŁukasz Kosmaty private:
85b7d1787dSŁukasz Kosmaty   JavaReferencesCache() = default;
86b7d1787dSŁukasz Kosmaty 
87b7d1787dSŁukasz Kosmaty   std::unordered_map<std::string, CachedJClass> jClassRegistry;
88b7d1787dSŁukasz Kosmaty 
89b7d1787dSŁukasz Kosmaty   void loadJClass(
90b7d1787dSŁukasz Kosmaty     JNIEnv *env,
91b7d1787dSŁukasz Kosmaty     const std::string &name,
92b7d1787dSŁukasz Kosmaty     const std::vector<std::pair<std::string, std::string>> &methods
93b7d1787dSŁukasz Kosmaty   );
94b7d1787dSŁukasz Kosmaty };
95b7d1787dSŁukasz Kosmaty } // namespace expo
96