com.amanotes.gdk 0.2.71 → 0.2.72
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +96 -88
- package/Editor/AmaGDKEditor.cs +1 -1
- package/Editor/EmbedRemoteConfigAssetInspector.cs +1 -1
- package/Editor/Extra/GDKCIBuildCommand.cs +2 -16
- package/Extra/AmaGDKInstaller.unitypackage +0 -0
- package/Extra/CheckDiskSpace.unitypackage +0 -0
- package/Extra/Consent.unitypackage +0 -0
- package/Extra/ForceUpdate.unitypackage +0 -0
- package/Extra/LegacyGDKUpdateHelper.unitypackage +0 -0
- package/Extra/PostProcessor.unitypackage +0 -0
- package/Packages/AmaGDKConfig.unitypackage +0 -0
- package/Packages/AmaGDKExample.unitypackage +0 -0
- package/Packages/AmaGDKTest.unitypackage +0 -0
- package/Packages/AppsFlyerAdapter.PurchaseConnector.unitypackage +0 -0
- package/Packages/AppsFlyerAdapter.unitypackage +0 -0
- package/Packages/FirebaseAnalyticsAdapter.unitypackage +0 -0
- package/Packages/FirebaseRemoteConfigAdapter.unitypackage +0 -0
- package/Packages/IronSourceAdapter.unitypackage +0 -0
- package/Packages/MaxAdNetworkAdapter.unitypackage +0 -0
- package/Packages/RevenueCatAdapter.unitypackage +0 -0
- package/Packages/SqliteAnalyticsAdapter.unitypackage +0 -0
- package/Runtime/Ad/AdExtension.cs +2 -1
- package/Runtime/Ad/AdLogic.cs +1 -1
- package/Runtime/Ad/AmaGDK.Ads.cs +1 -1
- package/Runtime/AmaGDK.Adapters.cs +1 -1
- package/Runtime/AmaGDK.Analytics.cs +17 -30
- package/Runtime/AmaGDK.Config.cs +1 -7
- package/Runtime/AmaGDK.Consent.cs +9 -8
- package/Runtime/AmaGDK.Context.cs +1 -1
- package/Runtime/AmaGDK.Device.cs +3 -2
- package/Runtime/AmaGDK.IAP.cs +1 -1
- package/Runtime/AmaGDK.RemoteConfig.cs +2 -2
- package/Runtime/AmaGDK.Singleton.cs +1 -1
- package/Runtime/AmaGDK.UserProfile.cs +12 -11
- package/Runtime/AmaGDK.asmdef +1 -1
- package/Runtime/AmaGDK.cs +7 -7
- package/Runtime/AnalyticQualityAsset.cs +5 -6
- package/Runtime/AudioToolkit/AmaGDK.Audio.cs +3 -2
- package/Runtime/AudioToolkit/Plugins/AudioDeviceDetector.cs +2 -2
- package/Runtime/Core/GDKDebug.cs +97 -0
- package/Runtime/Core/GDKDebug.cs.meta +3 -0
- package/Runtime/Core/GDKPool.cs +56 -337
- package/Runtime/Core/GDKRoutine.cs +3 -1
- package/Runtime/Core/GDKSemVer.cs +1 -1
- package/Runtime/Core/GDKString.cs +197 -0
- package/Runtime/Core/GDKString.cs.meta +3 -0
- package/Runtime/EmbedRemoteConfigAsset.cs +2 -1
- package/Runtime/Fps/AmaFPS.Utils.cs +1 -1
- package/Runtime/Fps/AmaFPS.cs +1 -1
- package/Runtime/Fps/AmaFPSVisualizer.cs +1 -1
- package/Runtime/Fps/FrameRecorder.cs +1 -1
- package/Runtime/GDKAudio/GDKAudio.cs +11 -8
- package/Runtime/Internal/AmaGDK.Internal.cs +22 -33
- package/Runtime/Internal/AmaGDK.Utils.cs +4 -4
- package/Runtime/Internal/AmaGDK.WebUtils.cs +1 -1
- package/Runtime/Internal/GDKGeoLocationcs.cs +2 -1
- package/Runtime/Internal/GDKServerTime.cs +2 -1
- package/Runtime/Klavar/KlavarContainer.cs +4 -4
- package/Runtime/UserProfile/Plugins/Android/AdvertisingIdFetcher.cs +1 -1
- package/Runtime/Utils/GDKUtils.cs +1 -1
- package/package.json +1 -1
package/Runtime/Core/GDKPool.cs
CHANGED
|
@@ -1,385 +1,104 @@
|
|
|
1
|
-
|
|
1
|
+
using System;
|
|
2
2
|
using System.Collections.Concurrent;
|
|
3
3
|
using System.Collections.Generic;
|
|
4
|
-
using System.Reflection;
|
|
5
4
|
using System.Text;
|
|
6
|
-
|
|
7
|
-
using
|
|
8
|
-
using UnityEngine.Assertions;
|
|
9
|
-
using UnityEngine.Profiling;
|
|
5
|
+
|
|
6
|
+
using static Amanotes.Core.GDKDebug;
|
|
10
7
|
namespace Amanotes.Core.Internal
|
|
11
8
|
{
|
|
12
|
-
|
|
9
|
+
public interface IPoolItem
|
|
13
10
|
{
|
|
14
|
-
|
|
15
|
-
{
|
|
16
|
-
if (list == null || list.Count == 0) return default;
|
|
17
|
-
|
|
18
|
-
T result = list[list.Count - 1];
|
|
19
|
-
list.RemoveAt(list.Count - 1);
|
|
20
|
-
return result;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
public static partial class GDKPool // TypeHandler
|
|
25
|
-
{
|
|
26
|
-
private const int STRING_BUILDER_DEFAULT_LEN = 64;
|
|
27
|
-
private static readonly Dictionary<Type, object> typeHandlerMap = new Dictionary<Type, object>
|
|
28
|
-
{
|
|
29
|
-
{ typeof(StringBuilder), new TypeHandler<StringBuilder>(() => new StringBuilder(), h => h.Clear()) },
|
|
30
|
-
{ typeof(HashSet<string>), new TypeHandler<HashSet<string>>(() => new HashSet<string>(), h => h.Clear()) },
|
|
31
|
-
{ typeof(Dictionary<string, object>), new TypeHandler<Dictionary<string, object>>(() => new Dictionary<string, object>(), d => d.Clear()) }
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
public static TypeHandler<T> GetTypeHandler<T>() where T : class
|
|
35
|
-
{
|
|
36
|
-
return typeHandlerMap.TryGetValue(typeof(T), out object result)
|
|
37
|
-
? UnsafeUtility.As<object, TypeHandler<T>>(ref result)
|
|
38
|
-
: null;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
public static TypeHandler<T> AddTypeHandler<T>(Func<T> newT, Action<T> resetT = null) where T : class
|
|
42
|
-
{
|
|
43
|
-
if (typeof(IPoolItem).IsAssignableFrom(typeof(T)))
|
|
44
|
-
{
|
|
45
|
-
if (resetT != null) Debug.LogWarning("Unsupported custom resetT() when T: IPoolItem!");
|
|
46
|
-
resetT = item => { (item as IPoolItem)?.Reset(); };
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
var result = new TypeHandler<T>(newT, resetT);
|
|
50
|
-
typeHandlerMap.Add(typeof(T), result);
|
|
51
|
-
return result;
|
|
52
|
-
}
|
|
53
|
-
public static TypeHandler<T> AddTypeHandler<T>(Action<T> resetT = null) where T : class, new()
|
|
54
|
-
{
|
|
55
|
-
return AddTypeHandler(() => new T(), resetT);
|
|
56
|
-
}
|
|
57
|
-
public class TypeHandler<T> where T : class
|
|
58
|
-
{
|
|
59
|
-
public readonly Func<T> newT;
|
|
60
|
-
public readonly Action<T> resetT;
|
|
61
|
-
|
|
62
|
-
public TypeHandler(Func<T> newT, Action<T> resetT)
|
|
63
|
-
{
|
|
64
|
-
this.newT = newT;
|
|
65
|
-
this.resetT = resetT;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
11
|
+
void Reset();
|
|
68
12
|
}
|
|
69
13
|
|
|
70
|
-
public static
|
|
71
|
-
{
|
|
72
|
-
public interface IPoolItem
|
|
73
|
-
{
|
|
74
|
-
void Reset();
|
|
75
|
-
}
|
|
76
|
-
public interface IPool<T> where T : class
|
|
77
|
-
{
|
|
78
|
-
int Count { get; } // Added to get the number of items currently in the pool
|
|
79
|
-
T Take();
|
|
80
|
-
void Return(T item);
|
|
81
|
-
}
|
|
82
|
-
public interface IPoolMap
|
|
83
|
-
{
|
|
84
|
-
IPool<T> GetPool<T>() where T : class;
|
|
85
|
-
IPool<T> CreatePool<T>(TypeHandler<T> handler = null) where T : class;
|
|
86
|
-
IPool<T> GetOrCreatePool<T>(TypeHandler<T> handler = null) where T : class;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
public static partial class GDKPool // POOLs
|
|
14
|
+
public static class GDKPool
|
|
90
15
|
{
|
|
91
|
-
internal
|
|
92
|
-
where T : class
|
|
93
|
-
where T1 : new()
|
|
16
|
+
internal class Pool<T> where T : new()
|
|
94
17
|
{
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
protected BasePool(TypeHandler<T> handler)
|
|
18
|
+
private readonly ConcurrentQueue<T> _pool;
|
|
19
|
+
public Pool(int initialCapacity = 4)
|
|
98
20
|
{
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
public abstract T Take();
|
|
104
|
-
public abstract void Return(T item);
|
|
105
|
-
public abstract int Count { get; }
|
|
106
|
-
}
|
|
107
|
-
internal sealed class ListPool<T> : BasePool<T, List<T>> where T : class
|
|
108
|
-
{
|
|
109
|
-
public ListPool(TypeHandler<T> handler, int capacity) : base(handler)
|
|
110
|
-
{
|
|
111
|
-
for (var i = 0; i < capacity; i++)
|
|
21
|
+
_pool = new ConcurrentQueue<T>();
|
|
22
|
+
for (var i = 0; i < initialCapacity; i++)
|
|
112
23
|
{
|
|
113
|
-
|
|
24
|
+
_pool.Enqueue(new T());
|
|
114
25
|
}
|
|
115
26
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
public override T Take()
|
|
119
|
-
{
|
|
120
|
-
if (pool.Count == 0) return handler.newT();
|
|
121
|
-
T last = pool.Pop();
|
|
122
|
-
handler.resetT?.Invoke(last); // Take from pool: Do Reset
|
|
123
|
-
return last;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
internal T TakeAt(int idx)
|
|
127
|
-
{
|
|
128
|
-
if (idx < 0 || idx >= pool.Count - 1) return Take();
|
|
129
|
-
|
|
130
|
-
// swap last item to index
|
|
131
|
-
T item = pool[idx];
|
|
132
|
-
pool[idx] = pool.Pop();
|
|
133
|
-
handler.resetT?.Invoke(item);
|
|
134
|
-
return item;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
public override void Return(T item)
|
|
138
|
-
{
|
|
139
|
-
if (item == null) return;
|
|
140
|
-
pool.Add(item);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
internal sealed class ConcurrentPool<T> : BasePool<T, ConcurrentBag<T>> where T : class
|
|
144
|
-
{
|
|
145
|
-
public ConcurrentPool(TypeHandler<T> handler, int capacity) : base(handler)
|
|
27
|
+
|
|
28
|
+
public Pool(int initialCapacity, Func<T> newT)
|
|
146
29
|
{
|
|
147
|
-
|
|
30
|
+
_pool = new ConcurrentQueue<T>();
|
|
31
|
+
for (var i = 0; i < initialCapacity; i++)
|
|
148
32
|
{
|
|
149
|
-
|
|
33
|
+
_pool.Enqueue(newT());
|
|
150
34
|
}
|
|
151
35
|
}
|
|
152
|
-
|
|
153
|
-
public
|
|
154
|
-
|
|
155
|
-
public override T Take()
|
|
156
|
-
{
|
|
157
|
-
if (!pool.TryTake(out T result)) return handler.newT();
|
|
158
|
-
handler.resetT?.Invoke(result);
|
|
159
|
-
return result;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
public override void Return(T item)
|
|
163
|
-
{
|
|
164
|
-
if (item == null) return;
|
|
165
|
-
pool.Add(item);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
public static partial class GDKPool // POOL MAP
|
|
171
|
-
{
|
|
172
|
-
internal abstract class BasePoolMap<TDict> : IPoolMap where TDict : IDictionary<Type, object>, new()
|
|
173
|
-
{
|
|
174
|
-
internal readonly TDict map = new TDict();
|
|
175
|
-
|
|
176
|
-
// IPoolMap
|
|
177
|
-
public IPool<T> GetPool<T>() where T : class
|
|
178
|
-
{
|
|
179
|
-
return map.TryGetValue(typeof(T), out object result)
|
|
180
|
-
? UnsafeUtility.As<object, IPool<T>>(ref result)
|
|
181
|
-
: null;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
public IPool<T> CreatePool<T>(TypeHandler<T> handler = null) where T : class
|
|
36
|
+
|
|
37
|
+
public T Get()
|
|
185
38
|
{
|
|
186
|
-
|
|
39
|
+
if (!_pool.TryDequeue(out var obj)) return new T();
|
|
40
|
+
if (obj is IPoolItem poolItem) poolItem.Reset();
|
|
41
|
+
return obj;
|
|
187
42
|
}
|
|
188
43
|
|
|
189
|
-
public
|
|
44
|
+
public void Return(T obj)
|
|
190
45
|
{
|
|
191
|
-
|
|
46
|
+
_pool.Enqueue(obj);
|
|
192
47
|
}
|
|
193
|
-
internal abstract IPool<T> CreatePoolInternal<T>(TypeHandler<T> handler) where T : class;
|
|
194
|
-
}
|
|
195
|
-
internal class ListPoolMap : BasePoolMap<Dictionary<Type, object>>
|
|
196
|
-
{
|
|
197
|
-
internal override IPool<T> CreatePoolInternal<T>(TypeHandler<T> handler) where T : class
|
|
198
|
-
{
|
|
199
|
-
var result = new ListPool<T>(handler, 1);
|
|
200
|
-
map.Add(typeof(T), result);
|
|
201
|
-
return result;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
internal class ConcurrentPoolMap : BasePoolMap<ConcurrentDictionary<Type, object>>
|
|
205
|
-
{
|
|
206
|
-
internal override IPool<T> CreatePoolInternal<T>(TypeHandler<T> handler) where T : class
|
|
207
|
-
{
|
|
208
|
-
var result = new ConcurrentPool<T>(handler, 1);
|
|
209
|
-
map.TryAdd(typeof(T), result);
|
|
210
|
-
return result;
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
public static partial class GDKPool
|
|
216
|
-
{
|
|
217
|
-
private static readonly ListPoolMap mainPM = new ListPoolMap();
|
|
218
|
-
private static readonly ConcurrentPoolMap threadPM = new ConcurrentPoolMap();
|
|
219
|
-
|
|
220
|
-
// HashSet<T> support
|
|
221
|
-
private static readonly ListPool<HashSet<string>> hPool; // cached reference for main-thread
|
|
222
|
-
private static readonly ListPool<StringBuilder> sbPool;
|
|
223
|
-
|
|
224
|
-
// StringBuilder support
|
|
225
|
-
private static readonly ListPool<StringBuilder> fixedSBPool;
|
|
226
|
-
|
|
227
|
-
// Dictionary support
|
|
228
|
-
private static readonly ListPool<Dictionary<string, object>> dictPool;
|
|
229
48
|
|
|
230
|
-
|
|
231
|
-
static GDKPool()
|
|
232
|
-
{
|
|
233
|
-
// Main-thread: Use fixed-length StringBuilder
|
|
234
|
-
sbPool = (ListPool<StringBuilder>) mainPM.CreatePool<StringBuilder>();
|
|
235
|
-
hPool = (ListPool<HashSet<string>>) mainPM.CreatePool<HashSet<string>>();
|
|
236
|
-
dictPool = (ListPool<Dictionary<string, object>>)mainPM.CreatePool<Dictionary<string, object>>();
|
|
237
|
-
fixedSBPool = new ListPool<StringBuilder>(new TypeHandler<StringBuilder>(null, sb => sb.Clear()), 0);
|
|
49
|
+
public int Count => _pool.Count;
|
|
238
50
|
}
|
|
51
|
+
private static readonly Pool<StringBuilder> sbPool1KB = new Pool<StringBuilder>(8, () => new StringBuilder(1024));
|
|
52
|
+
private static readonly Pool<StringBuilder> sbPool8KB = new Pool<StringBuilder>(8, () => new StringBuilder(8*1024));
|
|
53
|
+
private static readonly Pool<HashSet<string>> hashsetPool = new Pool<HashSet<string>>(4);
|
|
239
54
|
|
|
240
|
-
|
|
241
|
-
internal static void ClearAndReset()
|
|
55
|
+
public static StringBuilder GetStringBuilder(int capacityInKb = 1)
|
|
242
56
|
{
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
mainPM.map.Add(typeof(HashSet<string>), hPool);
|
|
247
|
-
mainPM.map.Add(typeof(Dictionary<string, object>), dictPool);
|
|
248
|
-
|
|
249
|
-
// other threads
|
|
250
|
-
threadPM.map.Clear();
|
|
57
|
+
StringBuilder result = capacityInKb <= 1 ? sbPool1KB.Get() : sbPool8KB.Get();
|
|
58
|
+
result.Clear();
|
|
59
|
+
return result;
|
|
251
60
|
}
|
|
252
|
-
|
|
253
|
-
public static
|
|
61
|
+
|
|
62
|
+
public static HashSet<string> GetHashSet()
|
|
254
63
|
{
|
|
255
|
-
|
|
256
|
-
|
|
64
|
+
HashSet<string> result = hashsetPool.Get();
|
|
65
|
+
result.Clear();
|
|
66
|
+
return result;
|
|
257
67
|
}
|
|
258
68
|
|
|
259
|
-
public static
|
|
69
|
+
public static string ReturnString(StringBuilder sb)
|
|
260
70
|
{
|
|
261
|
-
|
|
262
|
-
|
|
71
|
+
if (sb == null) return null;
|
|
72
|
+
var result = sb.ToString();
|
|
73
|
+
Return(sb);
|
|
74
|
+
return result;
|
|
263
75
|
}
|
|
264
76
|
|
|
265
|
-
public static void Return
|
|
77
|
+
public static void Return(StringBuilder sb)
|
|
266
78
|
{
|
|
267
|
-
if (
|
|
79
|
+
if (sb == null) return;
|
|
80
|
+
int capacity = sb.Capacity;
|
|
81
|
+
|
|
82
|
+
if (capacity == 1024)
|
|
268
83
|
{
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
{
|
|
272
|
-
fixedSBPool.Return(sb);
|
|
273
|
-
return;
|
|
274
|
-
}
|
|
84
|
+
sbPool1KB.Return(sb);
|
|
85
|
+
return;
|
|
275
86
|
}
|
|
276
87
|
|
|
277
|
-
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
public static IPool<T> GetPool<T>(bool autoCreatePool = false) where T : class, new()
|
|
281
|
-
{
|
|
282
|
-
IPool<T> result = poolMap.GetPool<T>();
|
|
283
|
-
if (result != null) return result;
|
|
284
|
-
return autoCreatePool ? CreatePool<T>() : null;
|
|
285
|
-
}
|
|
286
|
-
private static IPool<T> TryCreatePoolUsingTypeHandler<T>() where T : class
|
|
287
|
-
{
|
|
288
|
-
TypeHandler<T> handler = GetTypeHandler<T>();
|
|
289
|
-
return handler != null ? poolMap.CreatePool(handler) : null;
|
|
88
|
+
sbPool8KB.Return(sb);
|
|
290
89
|
}
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
IPool<T> result = TryCreatePoolUsingTypeHandler<T>();
|
|
294
|
-
if (result != null) return result;
|
|
295
|
-
return poolMap.CreatePool(AddTypeHandler(newT, resetT));
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
public static IPool<T> CreatePool<T>(Action<T> resetT = null) where T : class, new()
|
|
299
|
-
{
|
|
300
|
-
IPool<T> result = TryCreatePoolUsingTypeHandler<T>();
|
|
301
|
-
if (result != null) return result;
|
|
302
|
-
return poolMap.CreatePool(AddTypeHandler(() => new T(), resetT));
|
|
303
|
-
}
|
|
304
|
-
public static HashSet<T> TakeHashSet<T>()
|
|
305
|
-
{
|
|
306
|
-
var result = Take<HashSet<T>>();
|
|
307
|
-
return result ?? CreatePool<HashSet<T>>(h => h.Clear()).Take();
|
|
308
|
-
}
|
|
309
|
-
public static HashSet<string> TakeHashSet()
|
|
90
|
+
|
|
91
|
+
public static void Return(HashSet<string> hashset)
|
|
310
92
|
{
|
|
311
|
-
|
|
93
|
+
if (hashset == null) return;
|
|
94
|
+
hashsetPool.Return(hashset);
|
|
312
95
|
}
|
|
313
|
-
|
|
96
|
+
|
|
314
97
|
public static void ReturnAndNullize(ref HashSet<string> hashset)
|
|
315
98
|
{
|
|
316
99
|
if (hashset == null) return;
|
|
317
|
-
|
|
318
|
-
Return(hashset);
|
|
100
|
+
hashsetPool.Return(hashset);
|
|
319
101
|
hashset = null;
|
|
320
102
|
}
|
|
321
|
-
|
|
322
|
-
public static StringBuilder TakeStringBuilder(int fixedLength = 0)
|
|
323
|
-
{
|
|
324
|
-
if (!GDKUtils.isOnMainThread)
|
|
325
|
-
{
|
|
326
|
-
if (fixedLength != 0) Logging.LogWarningOnce("Fixed length StringBuilder only work for Main Thread!");
|
|
327
|
-
return Take<StringBuilder>();
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
if (fixedLength == 0) return Take<StringBuilder>();
|
|
331
|
-
|
|
332
|
-
if (fixedSBPool.Count == 0) return new StringBuilder(fixedLength, fixedLength);
|
|
333
|
-
List<StringBuilder> pool = fixedSBPool.pool;
|
|
334
|
-
for (var i = 0; i < pool.Count; i++)
|
|
335
|
-
{
|
|
336
|
-
if (pool[i].Capacity != fixedLength) continue;
|
|
337
|
-
return fixedSBPool.TakeAt(i);
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
return new StringBuilder(fixedLength, fixedLength);
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
private static FieldInfo sbStringValueField;
|
|
344
|
-
private static readonly Dictionary<StringBuilder, string> internalSB = new Dictionary<StringBuilder, string>();
|
|
345
|
-
public static string ReturnAndStringify(StringBuilder sb)
|
|
346
|
-
{
|
|
347
|
-
if (sb == null) return null;
|
|
348
|
-
|
|
349
|
-
// if (GDKUtils.isOnMainThread && sb.Capacity == sb.MaxCapacity)
|
|
350
|
-
// {
|
|
351
|
-
// string str;
|
|
352
|
-
// Profiler.BeginSample("GDKPool.ReturnAndStringify()");
|
|
353
|
-
// {
|
|
354
|
-
// if (!internalSB.TryGetValue(sb, out str))
|
|
355
|
-
// {
|
|
356
|
-
// sbStringValueField ??= typeof(StringBuilder)
|
|
357
|
-
// .GetField("m_StringValue", BindingFlags.NonPublic | BindingFlags.Instance);
|
|
358
|
-
//
|
|
359
|
-
// str = (string)sbStringValueField?.GetValue(sb);
|
|
360
|
-
// internalSB.Add(sb, str);
|
|
361
|
-
// }
|
|
362
|
-
//
|
|
363
|
-
// fixedSBPool.Return(sb);
|
|
364
|
-
// }
|
|
365
|
-
// Profiler.EndSample();
|
|
366
|
-
// return str;
|
|
367
|
-
// }
|
|
368
|
-
|
|
369
|
-
string result = null;
|
|
370
|
-
Profiler.BeginSample("GDKPool.ReturnAndStringify()");
|
|
371
|
-
{
|
|
372
|
-
result = sb.ToString();
|
|
373
|
-
sb.Clear();
|
|
374
|
-
Return(sb);
|
|
375
|
-
}
|
|
376
|
-
Profiler.EndSample();
|
|
377
|
-
|
|
378
|
-
return result;
|
|
379
|
-
}
|
|
380
|
-
public static Dictionary<string, object> TakeDictionary()
|
|
381
|
-
{
|
|
382
|
-
return GDKUtils.isOnMainThread ? dictPool.Take() : Take<Dictionary<string, object>>();
|
|
383
|
-
}
|
|
384
103
|
}
|
|
385
104
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
using System;
|
|
2
2
|
using System.Collections;
|
|
3
3
|
using UnityEngine;
|
|
4
|
+
using static Amanotes.Core.GDKDebug;
|
|
5
|
+
|
|
4
6
|
namespace Amanotes.Core.Internal
|
|
5
7
|
{
|
|
6
8
|
public class GDKRoutine
|
|
@@ -59,7 +61,7 @@ namespace Amanotes.Core.Internal
|
|
|
59
61
|
} catch (Exception ex)
|
|
60
62
|
{
|
|
61
63
|
status |= RoutineStatus.Stopped;
|
|
62
|
-
if (exceptionHandler == null)
|
|
64
|
+
if (exceptionHandler == null) LogError($"Exception caught in coroutine: {ex}");
|
|
63
65
|
exceptionHandler?.Invoke(ex);
|
|
64
66
|
yield break; // Stop executing the coroutine
|
|
65
67
|
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
using UnityEngine;
|
|
3
|
+
|
|
4
|
+
namespace Amanotes.Core
|
|
5
|
+
{
|
|
6
|
+
public static class GDKStringExtension
|
|
7
|
+
{
|
|
8
|
+
internal static void Log(GDKString gdkStr, LogType logType, UnityEngine.Object context, Action<string, UnityEngine.Object> logFunc)
|
|
9
|
+
{
|
|
10
|
+
StackTraceLogType type = Application.GetStackTraceLogType(logType);
|
|
11
|
+
Application.SetStackTraceLogType(logType, StackTraceLogType.None);
|
|
12
|
+
{
|
|
13
|
+
logFunc(gdkStr.ToString(), context);
|
|
14
|
+
}
|
|
15
|
+
Application.SetStackTraceLogType(logType, type);
|
|
16
|
+
gdkStr.Clear();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
public static void Log(this GDKString gdkStr, UnityEngine.Object context = null)
|
|
20
|
+
{
|
|
21
|
+
Log(gdkStr, LogType.Log, context, Debug.Log);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public static void LogWarning(this GDKString gdkStr, UnityEngine.Object context = null)
|
|
25
|
+
{
|
|
26
|
+
Log(gdkStr, LogType.Warning, context, Debug.LogWarning);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public static void LogError(this GDKString gdkStr, UnityEngine.Object context = null)
|
|
30
|
+
{
|
|
31
|
+
Log(gdkStr, LogType.Error, context, Debug.LogError);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
private static readonly char[] DigitChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
|
|
35
|
+
internal static unsafe int Write(string s, int stIndex, ulong value, bool writePrefix = false, char prefix = '-')
|
|
36
|
+
{
|
|
37
|
+
fixed (char* ptr = s)
|
|
38
|
+
{
|
|
39
|
+
var idx = 0;
|
|
40
|
+
if (writePrefix)
|
|
41
|
+
{
|
|
42
|
+
ptr[stIndex] = prefix;
|
|
43
|
+
idx++;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (value <= 9)
|
|
47
|
+
{
|
|
48
|
+
ptr[stIndex + idx] = DigitChars[value];
|
|
49
|
+
idx++;
|
|
50
|
+
return idx;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
var len = (int)Math.Ceiling(Math.Log10(value));
|
|
54
|
+
int endIdx = stIndex + len - 1 + idx;
|
|
55
|
+
do
|
|
56
|
+
{
|
|
57
|
+
ptr[endIdx] = (char)('0' + value % 10);
|
|
58
|
+
endIdx--;
|
|
59
|
+
value /= 10;
|
|
60
|
+
} while (value > 0);
|
|
61
|
+
|
|
62
|
+
idx += len;
|
|
63
|
+
return idx;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
internal static int WriteULong(this string s, int stIndex, ulong value)
|
|
68
|
+
{
|
|
69
|
+
return Write(s, stIndex, value);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
internal static int WriteLong(this string s, int stIndex, long value)
|
|
73
|
+
{
|
|
74
|
+
return Write(s, stIndex, (ulong)(value < 0 ? -value : value), value < 0, '-');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
internal static int WriteDouble(this string s, int stIndex, double value, int decimalPlaces = 4)
|
|
78
|
+
{
|
|
79
|
+
var integerPart = (ulong)value;
|
|
80
|
+
int counter = Write(s, stIndex, integerPart, value < 0);
|
|
81
|
+
if (decimalPlaces <= 0) return counter;
|
|
82
|
+
|
|
83
|
+
double fractionalPart = value - integerPart;
|
|
84
|
+
for (var i = 0; i < decimalPlaces; i++)
|
|
85
|
+
{
|
|
86
|
+
fractionalPart *= 10;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
var fractionalInt = (ulong)(fractionalPart + 0.5);
|
|
90
|
+
counter += Write(s, stIndex + counter, fractionalInt, true, '.');
|
|
91
|
+
return counter;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
public unsafe class GDKString
|
|
96
|
+
{
|
|
97
|
+
private readonly int _capacity;
|
|
98
|
+
private readonly string _str;
|
|
99
|
+
private int _length;
|
|
100
|
+
|
|
101
|
+
public GDKString(int capacity)
|
|
102
|
+
{
|
|
103
|
+
_capacity = capacity;
|
|
104
|
+
_str = new string('\0', capacity);
|
|
105
|
+
_length = 0;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
public int Length => _length;
|
|
109
|
+
|
|
110
|
+
private GDKString SetLength(int value)
|
|
111
|
+
{
|
|
112
|
+
if (value < 0 || value > _capacity)
|
|
113
|
+
{
|
|
114
|
+
throw new ArgumentOutOfRangeException(nameof(value));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
_length = value;
|
|
118
|
+
fixed (char* ptr = _str)
|
|
119
|
+
{
|
|
120
|
+
ptr[value] = '\0';
|
|
121
|
+
*(int*)((IntPtr)ptr - sizeof(int)) = _length;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return this;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
public GDKString Append(string value)
|
|
128
|
+
{
|
|
129
|
+
return string.IsNullOrEmpty(value) ? this : WriteAt(_length, value);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
public GDKString WriteAt(int stIdx, string value)
|
|
133
|
+
{
|
|
134
|
+
if (string.IsNullOrEmpty(value)) return this;
|
|
135
|
+
|
|
136
|
+
int vLength = value.Length;
|
|
137
|
+
if (stIdx + vLength >= _capacity)
|
|
138
|
+
{
|
|
139
|
+
throw new InvalidOperationException("Buffer overflow.");
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Calculate the number of bytes to copy (2 bytes per char)
|
|
143
|
+
fixed (char* srcPtr = value)
|
|
144
|
+
fixed (char* destPtr = _str)
|
|
145
|
+
{
|
|
146
|
+
// Use memcpy equivalent with pointers
|
|
147
|
+
char* destPos = destPtr + _length;
|
|
148
|
+
for (var i = 0; i < vLength; i++)
|
|
149
|
+
{
|
|
150
|
+
*(destPos + i) = *(srcPtr + i);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (stIdx + vLength > _length) SetLength(_length + vLength);
|
|
155
|
+
return this;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
public GDKString Append(int value)
|
|
159
|
+
{
|
|
160
|
+
int vLength = _str.WriteLong(Length, value);
|
|
161
|
+
return SetLength(_length + vLength);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
public GDKString Append(uint value)
|
|
165
|
+
{
|
|
166
|
+
int vLength = _str.WriteULong(Length, value);
|
|
167
|
+
return SetLength(_length + vLength);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
private const string TRUE = "True";
|
|
171
|
+
private const string FALSE = "False";
|
|
172
|
+
public GDKString Append(bool value)
|
|
173
|
+
{
|
|
174
|
+
Append(value ? TRUE : FALSE);
|
|
175
|
+
return this;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
public GDKString Append(float value)
|
|
179
|
+
{
|
|
180
|
+
int vLength = _str.WriteDouble(Length, value);
|
|
181
|
+
return SetLength(_length + vLength);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
public GDKString Append(double value)
|
|
185
|
+
{
|
|
186
|
+
int vLength = _str.WriteDouble(Length, value);
|
|
187
|
+
return SetLength(_length + vLength);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
public GDKString Clear()
|
|
191
|
+
{
|
|
192
|
+
return SetLength(0);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
public override string ToString() => _str;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
using System;
|
|
2
2
|
using System.Linq;
|
|
3
3
|
using UnityEngine;
|
|
4
|
+
using static Amanotes.Core.GDKDebug;
|
|
4
5
|
|
|
5
6
|
namespace Amanotes.Core.Internal
|
|
6
7
|
{
|
|
@@ -30,7 +31,7 @@ namespace Amanotes.Core.Internal
|
|
|
30
31
|
{
|
|
31
32
|
var config = configs?.FirstOrDefault(a => a.id == id);
|
|
32
33
|
if (config == null)
|
|
33
|
-
|
|
34
|
+
LogWarningOnce($"Not found embedded config <{id}>");
|
|
34
35
|
return config;
|
|
35
36
|
}
|
|
36
37
|
|