diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 00000000..82694f25
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "packages/mmkv-metal/src-native/android/MMKV"]
+ path = packages/mmkv-metal/src-native/android/MMKV
+ url = https://github.com/Tencent/MMKV.git
diff --git a/README.md b/README.md
index a608b8bc..b4d03a4b 100644
--- a/README.md
+++ b/README.md
@@ -33,6 +33,8 @@ npm start
- [@nativescript/jetpack-compose](packages/jetpack-compose/README.md)
- [@nativescript/local-notifications](packages/local-notifications/README.md)
- [@nativescript/localize](packages/localize/README.md)
+- [@nativescript/mmkv](packages/mmkv/README.md)
+- [@nativescript/mmkv-metal](packages/mmkv-metal/README.md)
- [@nativescript/pdf](packages/pdf/README.md)
- [@nativescript/picker](packages/picker/README.md)
- [@nativescript/shared-notification-delegate](packages/shared-notification-delegate/README.md)
diff --git a/apps/demo-angular/package.json b/apps/demo-angular/package.json
index 3db0fe43..cd08033b 100644
--- a/apps/demo-angular/package.json
+++ b/apps/demo-angular/package.json
@@ -37,7 +37,9 @@
"@nativescript/swift-ui": "file:../../dist/packages/swift-ui",
"@nativescript/theme-switcher": "file:../../dist/packages/theme-switcher",
"@nativescript/twitter": "file:../../dist/packages/twitter",
- "@nativescript/zip": "file:../../dist/packages/zip"
+ "@nativescript/zip": "file:../../dist/packages/zip",
+ "@nativescript/mmkv": "file:../../dist/packages/mmkv",
+ "@nativescript/mmkv-metal": "file:../../dist/packages/mmkv-metal"
},
"devDependencies": {
"@nativescript/android": "~8.4.0",
diff --git a/apps/demo-angular/src/app-routing.module.ts b/apps/demo-angular/src/app-routing.module.ts
index cefc7451..eff279e9 100644
--- a/apps/demo-angular/src/app-routing.module.ts
+++ b/apps/demo-angular/src/app-routing.module.ts
@@ -35,6 +35,8 @@ const routes: Routes = [
{ path: 'jetpack-compose', loadChildren: () => import('./plugin-demos/jetpack-compose.module').then((m) => m.JetpackComposeModule) },
{ path: 'local-notifications', loadChildren: () => import('./plugin-demos/local-notifications.module').then((m) => m.LocalNotificationsModule) },
{ path: 'localize', loadChildren: () => import('./plugin-demos/localize.module').then((m) => m.LocalizeModule) },
+ { path: 'mmkv', loadChildren: () => import('./plugin-demos/mmkv.module').then((m) => m.MmkvModule) },
+ { path: 'mmkv-metal', loadChildren: () => import('./plugin-demos/mmkv-metal.module').then((m) => m.MmkvMetalModule) },
{ path: 'pdf', loadChildren: () => import('./plugin-demos/pdf.module').then((m) => m.PdfModule) },
{ path: 'picker', loadChildren: () => import('./plugin-demos/picker.module').then((m) => m.PickerModule) },
{ path: 'shared-notification-delegate', loadChildren: () => import('./plugin-demos/shared-notification-delegate.module').then((m) => m.SharedNotificationDelegateModule) },
diff --git a/apps/demo-angular/src/home.component.ts b/apps/demo-angular/src/home.component.ts
index 863f9cb6..762c0014 100644
--- a/apps/demo-angular/src/home.component.ts
+++ b/apps/demo-angular/src/home.component.ts
@@ -90,6 +90,12 @@ export class HomeComponent {
{
name: 'localize',
},
+ {
+ name: 'mmkv',
+ },
+ {
+ name: 'mmkv-metal',
+ },
{
name: 'pdf',
},
diff --git a/apps/demo-angular/src/plugin-demos/mmkv-metal.component.html b/apps/demo-angular/src/plugin-demos/mmkv-metal.component.html
new file mode 100644
index 00000000..7e1e5bca
--- /dev/null
+++ b/apps/demo-angular/src/plugin-demos/mmkv-metal.component.html
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/apps/demo-angular/src/plugin-demos/mmkv-metal.component.ts b/apps/demo-angular/src/plugin-demos/mmkv-metal.component.ts
new file mode 100644
index 00000000..b82eb76d
--- /dev/null
+++ b/apps/demo-angular/src/plugin-demos/mmkv-metal.component.ts
@@ -0,0 +1,17 @@
+import { Component, NgZone } from '@angular/core';
+import { DemoSharedMmkvMetal } from '@demo/shared';
+import {} from '@nativescript/mmkv-metal';
+
+@Component({
+ selector: 'demo-mmkv-metal',
+ templateUrl: 'mmkv-metal.component.html',
+})
+export class MmkvMetalComponent {
+ demoShared: DemoSharedMmkvMetal;
+
+ constructor(private _ngZone: NgZone) {}
+
+ ngOnInit() {
+ this.demoShared = new DemoSharedMmkvMetal();
+ }
+}
diff --git a/apps/demo-angular/src/plugin-demos/mmkv-metal.module.ts b/apps/demo-angular/src/plugin-demos/mmkv-metal.module.ts
new file mode 100644
index 00000000..96444c4c
--- /dev/null
+++ b/apps/demo-angular/src/plugin-demos/mmkv-metal.module.ts
@@ -0,0 +1,10 @@
+import { NgModule, NO_ERRORS_SCHEMA } from '@angular/core';
+import { NativeScriptCommonModule, NativeScriptRouterModule } from '@nativescript/angular';
+import { MmkvMetalComponent } from './mmkv-metal.component';
+
+@NgModule({
+ imports: [NativeScriptCommonModule, NativeScriptRouterModule.forChild([{ path: '', component: MmkvMetalComponent }])],
+ declarations: [MmkvMetalComponent],
+ schemas: [NO_ERRORS_SCHEMA],
+})
+export class MmkvMetalModule {}
diff --git a/apps/demo-angular/src/plugin-demos/mmkv.component.html b/apps/demo-angular/src/plugin-demos/mmkv.component.html
new file mode 100644
index 00000000..ecd609f7
--- /dev/null
+++ b/apps/demo-angular/src/plugin-demos/mmkv.component.html
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/apps/demo-angular/src/plugin-demos/mmkv.component.ts b/apps/demo-angular/src/plugin-demos/mmkv.component.ts
new file mode 100644
index 00000000..246e3fc2
--- /dev/null
+++ b/apps/demo-angular/src/plugin-demos/mmkv.component.ts
@@ -0,0 +1,17 @@
+import { Component, NgZone } from '@angular/core';
+import { DemoSharedMmkv } from '@demo/shared';
+import {} from '@nativescript/mmkv';
+
+@Component({
+ selector: 'demo-mmkv',
+ templateUrl: 'mmkv.component.html',
+})
+export class MmkvComponent {
+ demoShared: DemoSharedMmkv;
+
+ constructor(private _ngZone: NgZone) {}
+
+ ngOnInit() {
+ this.demoShared = new DemoSharedMmkv();
+ }
+}
diff --git a/apps/demo-angular/src/plugin-demos/mmkv.module.ts b/apps/demo-angular/src/plugin-demos/mmkv.module.ts
new file mode 100644
index 00000000..e32dc000
--- /dev/null
+++ b/apps/demo-angular/src/plugin-demos/mmkv.module.ts
@@ -0,0 +1,10 @@
+import { NgModule, NO_ERRORS_SCHEMA } from '@angular/core';
+import { NativeScriptCommonModule, NativeScriptRouterModule } from '@nativescript/angular';
+import { MmkvComponent } from './mmkv.component';
+
+@NgModule({
+ imports: [NativeScriptCommonModule, NativeScriptRouterModule.forChild([{ path: '', component: MmkvComponent }])],
+ declarations: [MmkvComponent],
+ schemas: [NO_ERRORS_SCHEMA],
+})
+export class MmkvModule {}
diff --git a/apps/demo/nativescript.config.ts b/apps/demo/nativescript.config.ts
index e18221d6..34ed6855 100644
--- a/apps/demo/nativescript.config.ts
+++ b/apps/demo/nativescript.config.ts
@@ -1,7 +1,7 @@
import { NativeScriptConfig } from '@nativescript/core';
export default {
- id: 'org.nativescript.plugindemo',
+ id: 'io.github.triniwiz.plugindemo',
appResourcesPath: '../../tools/assets/App_Resources',
android: {
v8Flags: '--expose_gc',
@@ -9,12 +9,12 @@ export default {
},
appPath: 'src',
cli: {
- packageManager: 'npm'
+ packageManager: 'npm',
},
hooks: [
{
- type: 'before-prepare',
- script: '../../tools/scripts/before-prepare.js',
- }
- ],
+ type: 'before-prepare',
+ script: '../../tools/scripts/before-prepare.js',
+ },
+ ],
} as NativeScriptConfig;
diff --git a/apps/demo/package.json b/apps/demo/package.json
index f79cc004..49bd7f06 100644
--- a/apps/demo/package.json
+++ b/apps/demo/package.json
@@ -33,6 +33,8 @@
"@nativescript/iqkeyboardmanager": "file:../../packages/iqkeyboardmanager",
"@nativescript/local-notifications": "file:../../packages/local-notifications",
"@nativescript/localize": "file:../../dist/packages/localize",
+ "@nativescript/mmkv": "file:../../packages/mmkv",
+ "@nativescript/mmkv-metal": "file:../../packages/mmkv-metal",
"@nativescript/pdf": "file:../../packages/pdf",
"@nativescript/picker": "file:../../packages/picker",
"@nativescript/shared-notification-delegate": "file:../../packages/shared-notification-delegate",
diff --git a/apps/demo/src/app.ts b/apps/demo/src/app.ts
index 61231d5a..8e9e4af1 100644
--- a/apps/demo/src/app.ts
+++ b/apps/demo/src/app.ts
@@ -1,4 +1,5 @@
import { Application } from '@nativescript/core';
+import '@nativescript/mmkv-metal/local-storage';
// uncomment to test local notifications
// import "@nativescript/local-notifications";
diff --git a/apps/demo/src/main-page.xml b/apps/demo/src/main-page.xml
index f68418ec..7b026d59 100644
--- a/apps/demo/src/main-page.xml
+++ b/apps/demo/src/main-page.xml
@@ -41,6 +41,8 @@
+
+
diff --git a/apps/demo/src/plugin-demos/mmkv-metal.ts b/apps/demo/src/plugin-demos/mmkv-metal.ts
new file mode 100644
index 00000000..bb97bbe7
--- /dev/null
+++ b/apps/demo/src/plugin-demos/mmkv-metal.ts
@@ -0,0 +1,67 @@
+import { Observable, EventData, Page } from '@nativescript/core';
+import { DemoSharedMmkvMetal } from '@demo/shared';
+import { NSCMMKV as NSCMMKVMetal, initialize as initializeMetal } from '@nativescript/mmkv-metal';
+
+import { NSCMMKV, initialize } from '@nativescript/mmkv';
+
+export function navigatingTo(args: EventData) {
+ const page = args.object;
+ page.bindingContext = new DemoModel();
+}
+
+const key = 'k';
+const iterations = 1000;
+
+export class DemoModel extends DemoSharedMmkvMetal {
+ mmkvm: NSCMMKVMetal;
+ mmkv: NSCMMKVMetal;
+ constructor() {
+ super();
+ initializeMetal();
+ initialize();
+ console.time('NSCMMKV');
+ this.mmkv = new NSCMMKV();
+ console.timeEnd('NSCMMKV');
+
+ console.time('NSCMMKVMetal');
+ this.mmkvm = new NSCMMKVMetal();
+ console.timeEnd('NSCMMKVMetal');
+ this.mmkvm.clearAll();
+ this.mmkvm.clearMemoryCache();
+
+ this.mmkv.clearAll();
+ this.mmkv.clearMemoryCache();
+
+ this.mmkvm.set(key, 'hello');
+ this.bm(this.getFromMMKVM.bind(this));
+
+ this.mmkv.set(key, 'hello');
+ this.bm(this.getFromMMKV.bind(this));
+ this.mmkvm.close();
+ }
+
+ getFromMMKV(): string | undefined {
+ return this.mmkv.getString(key);
+ }
+
+ getFromMMKVM(): string | undefined {
+ return this.mmkvm.getString(key);
+ }
+
+ bm(func) {
+ try {
+ console.log(`Starting Benchmark...`);
+ const start = global.performance ? performance.now() : (__time() as any);
+ for (let i = 0; i < iterations; i++) {
+ func();
+ }
+ const end = global.performance ? performance.now() : (__time() as any);
+ const diff = end - start;
+ console.log(`Finished Benchmark ! Took ${diff.toFixed(4)}ms!`);
+ return diff;
+ } catch (e) {
+ console.error(`Failed Benchmark !`, e);
+ return 0;
+ }
+ }
+}
diff --git a/apps/demo/src/plugin-demos/mmkv-metal.xml b/apps/demo/src/plugin-demos/mmkv-metal.xml
new file mode 100644
index 00000000..3267f9dc
--- /dev/null
+++ b/apps/demo/src/plugin-demos/mmkv-metal.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/apps/demo/src/plugin-demos/mmkv.ts b/apps/demo/src/plugin-demos/mmkv.ts
new file mode 100644
index 00000000..73e7a8c8
--- /dev/null
+++ b/apps/demo/src/plugin-demos/mmkv.ts
@@ -0,0 +1,63 @@
+import { Observable, EventData, Page } from '@nativescript/core';
+import { DemoSharedMmkv } from '@demo/shared';
+import { NSCMMKV } from '@nativescript/mmkv';
+
+export function navigatingTo(args: EventData) {
+ const page = args.object;
+ page.bindingContext = new DemoModel();
+}
+
+const key = 'k';
+const iterations = 1000;
+
+export class DemoModel extends DemoSharedMmkv {
+ mmkv: NSCMMKV;
+ constructor() {
+ super();
+ this.mmkv = new NSCMMKV();
+ this.mmkv.clearAll();
+ this.mmkv.clearMemoryCache();
+ // this.mmkv.set('first', 'Osei');
+ // this.mmkv.set('age', 30);
+ // this.mmkv.set('metal', false);
+
+ // if (global.isAndroid) {
+ // const js = new java.lang.String('Fortune');
+ // const buf = java.nio.ByteBuffer.wrap(js.getBytes());
+ // this.mmkv.set('last', (ArrayBuffer as any).from(buf as any));
+ // } else {
+ // const data = NSString.stringWithString('Fortune').dataUsingEncoding(NSUTF8StringEncoding);
+ // this.mmkv.set('last', interop.bufferFromData(data));
+ // }
+
+ // console.log(this.mmkv.getString('first'));
+ // console.log(this.mmkv.getNumber('age'));
+ // console.log(this.mmkv.getBoolean('metal'));
+ // console.log(this.mmkv.getString('last'));
+ // console.time('test');
+ this.mmkv.set(key, 'hello');
+ this.bm(this.getFromMMKV.bind(this));
+ //this.mmkv.close();
+ }
+
+ getFromMMKV(): string | undefined {
+ return this.mmkv.getString(key);
+ }
+
+ bm(func) {
+ try {
+ console.log(`Starting Benchmark...`);
+ const start = performance.now() as any;
+ for (let i = 0; i < iterations; i++) {
+ func();
+ }
+ const end = performance.now() as any;
+ const diff = end - start;
+ console.log(`Finished Benchmark ! Took ${diff.toFixed(4)}ms!`);
+ return diff;
+ } catch (e) {
+ console.error(`Failed Benchmark !`, e);
+ return 0;
+ }
+ }
+}
diff --git a/apps/demo/src/plugin-demos/mmkv.xml b/apps/demo/src/plugin-demos/mmkv.xml
new file mode 100644
index 00000000..55216226
--- /dev/null
+++ b/apps/demo/src/plugin-demos/mmkv.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/geolocation/index.d.ts b/packages/geolocation/index.d.ts
index 40a46af0..081bb75c 100644
--- a/packages/geolocation/index.d.ts
+++ b/packages/geolocation/index.d.ts
@@ -131,14 +131,13 @@ export function getCurrentLocation(options?: Options): Promise;
*/
export function watchLocation(successCallback: successCallbackType, errorCallback: errorCallbackType, options?: Options): number;
-
/**
* Monitor for location permission change. Only on iOS!
* @param permissionCallback gets called on location permission state change
* @param errorCallback gets called on error
* @returns {number} the watch id
*/
- export function watchPermissionStatus(permissionCallback: permissionCallbackType, errorCallback: errorCallbackType): number;
+export function watchPermissionStatus(permissionCallback: permissionCallbackType, errorCallback: errorCallbackType): number;
/**
* Stop monitoring for location change. Parameter expected is the watchId returned from `watchLocation`.
diff --git a/packages/google-maps/utils/index.android.ts b/packages/google-maps/utils/index.android.ts
index e5febc3e..9854d8e5 100644
--- a/packages/google-maps/utils/index.android.ts
+++ b/packages/google-maps/utils/index.android.ts
@@ -76,7 +76,7 @@ export function intoNativeMarkerOptions(options: MarkerOptions) {
opts.icon(com.google.android.gms.maps.model.BitmapDescriptorFactory.defaultMarker(hueFromColor(color)));
}
- if(typeof options?.opacity === 'number') {
+ if (typeof options?.opacity === 'number') {
opts.alpha(options.opacity);
}
@@ -275,10 +275,7 @@ export function intoNativeGroundOverlayOptions(options: GroundOverlayOptions) {
}
if (options?.bounds) {
- opts.positionFromBounds(new com.google.android.gms.maps.model.LatLngBounds(
- new com.google.android.gms.maps.model.LatLng(options.bounds.southwest.lat, options.bounds.southwest.lng),
- new com.google.android.gms.maps.model.LatLng(options.bounds.northeast.lat, options.bounds.northeast.lng)
- ));
+ opts.positionFromBounds(new com.google.android.gms.maps.model.LatLngBounds(new com.google.android.gms.maps.model.LatLng(options.bounds.southwest.lat, options.bounds.southwest.lng), new com.google.android.gms.maps.model.LatLng(options.bounds.northeast.lat, options.bounds.northeast.lng)));
}
if (typeof options?.transparency) {
diff --git a/packages/ios-security/platforms/ios/NativeScriptIOSSecurity.xcframework/ios-arm64/NativeScriptIOSSecurity.framework/Modules/NativeScriptIOSSecurity.swiftmodule/Project/arm64-apple-ios.swiftsourceinfo b/packages/ios-security/platforms/ios/NativeScriptIOSSecurity.xcframework/ios-arm64/NativeScriptIOSSecurity.framework/Modules/NativeScriptIOSSecurity.swiftmodule/Project/arm64-apple-ios.swiftsourceinfo
index cde276cb..2d3a9e3e 100644
Binary files a/packages/ios-security/platforms/ios/NativeScriptIOSSecurity.xcframework/ios-arm64/NativeScriptIOSSecurity.framework/Modules/NativeScriptIOSSecurity.swiftmodule/Project/arm64-apple-ios.swiftsourceinfo and b/packages/ios-security/platforms/ios/NativeScriptIOSSecurity.xcframework/ios-arm64/NativeScriptIOSSecurity.framework/Modules/NativeScriptIOSSecurity.swiftmodule/Project/arm64-apple-ios.swiftsourceinfo differ
diff --git a/packages/ios-security/platforms/ios/NativeScriptIOSSecurity.xcframework/ios-arm64/dSYMs/NativeScriptIOSSecurity.framework.dSYM/Contents/Resources/DWARF/NativeScriptIOSSecurity b/packages/ios-security/platforms/ios/NativeScriptIOSSecurity.xcframework/ios-arm64/dSYMs/NativeScriptIOSSecurity.framework.dSYM/Contents/Resources/DWARF/NativeScriptIOSSecurity
index b7dba1a8..211b4e52 100644
Binary files a/packages/ios-security/platforms/ios/NativeScriptIOSSecurity.xcframework/ios-arm64/dSYMs/NativeScriptIOSSecurity.framework.dSYM/Contents/Resources/DWARF/NativeScriptIOSSecurity and b/packages/ios-security/platforms/ios/NativeScriptIOSSecurity.xcframework/ios-arm64/dSYMs/NativeScriptIOSSecurity.framework.dSYM/Contents/Resources/DWARF/NativeScriptIOSSecurity differ
diff --git a/packages/ios-security/platforms/ios/NativeScriptIOSSecurity.xcframework/ios-arm64_x86_64-simulator/NativeScriptIOSSecurity.framework/Modules/NativeScriptIOSSecurity.swiftmodule/Project/arm64-apple-ios-simulator.swiftsourceinfo b/packages/ios-security/platforms/ios/NativeScriptIOSSecurity.xcframework/ios-arm64_x86_64-simulator/NativeScriptIOSSecurity.framework/Modules/NativeScriptIOSSecurity.swiftmodule/Project/arm64-apple-ios-simulator.swiftsourceinfo
index cd03618d..c4365c7f 100644
Binary files a/packages/ios-security/platforms/ios/NativeScriptIOSSecurity.xcframework/ios-arm64_x86_64-simulator/NativeScriptIOSSecurity.framework/Modules/NativeScriptIOSSecurity.swiftmodule/Project/arm64-apple-ios-simulator.swiftsourceinfo and b/packages/ios-security/platforms/ios/NativeScriptIOSSecurity.xcframework/ios-arm64_x86_64-simulator/NativeScriptIOSSecurity.framework/Modules/NativeScriptIOSSecurity.swiftmodule/Project/arm64-apple-ios-simulator.swiftsourceinfo differ
diff --git a/packages/ios-security/platforms/ios/NativeScriptIOSSecurity.xcframework/ios-arm64_x86_64-simulator/NativeScriptIOSSecurity.framework/Modules/NativeScriptIOSSecurity.swiftmodule/Project/x86_64-apple-ios-simulator.swiftsourceinfo b/packages/ios-security/platforms/ios/NativeScriptIOSSecurity.xcframework/ios-arm64_x86_64-simulator/NativeScriptIOSSecurity.framework/Modules/NativeScriptIOSSecurity.swiftmodule/Project/x86_64-apple-ios-simulator.swiftsourceinfo
index 5dac35b1..6f6128df 100644
Binary files a/packages/ios-security/platforms/ios/NativeScriptIOSSecurity.xcframework/ios-arm64_x86_64-simulator/NativeScriptIOSSecurity.framework/Modules/NativeScriptIOSSecurity.swiftmodule/Project/x86_64-apple-ios-simulator.swiftsourceinfo and b/packages/ios-security/platforms/ios/NativeScriptIOSSecurity.xcframework/ios-arm64_x86_64-simulator/NativeScriptIOSSecurity.framework/Modules/NativeScriptIOSSecurity.swiftmodule/Project/x86_64-apple-ios-simulator.swiftsourceinfo differ
diff --git a/packages/ios-security/platforms/ios/NativeScriptIOSSecurity.xcframework/ios-arm64_x86_64-simulator/dSYMs/NativeScriptIOSSecurity.framework.dSYM/Contents/Resources/DWARF/NativeScriptIOSSecurity b/packages/ios-security/platforms/ios/NativeScriptIOSSecurity.xcframework/ios-arm64_x86_64-simulator/dSYMs/NativeScriptIOSSecurity.framework.dSYM/Contents/Resources/DWARF/NativeScriptIOSSecurity
index 791d1060..08a69d4d 100644
Binary files a/packages/ios-security/platforms/ios/NativeScriptIOSSecurity.xcframework/ios-arm64_x86_64-simulator/dSYMs/NativeScriptIOSSecurity.framework.dSYM/Contents/Resources/DWARF/NativeScriptIOSSecurity and b/packages/ios-security/platforms/ios/NativeScriptIOSSecurity.xcframework/ios-arm64_x86_64-simulator/dSYMs/NativeScriptIOSSecurity.framework.dSYM/Contents/Resources/DWARF/NativeScriptIOSSecurity differ
diff --git a/packages/ios-security/platforms/ios/NativeScriptIosSecurity.xcframework/Info.plist b/packages/ios-security/platforms/ios/NativeScriptIosSecurity.xcframework/Info.plist
index 6fb0fb41..70d3762a 100644
--- a/packages/ios-security/platforms/ios/NativeScriptIosSecurity.xcframework/Info.plist
+++ b/packages/ios-security/platforms/ios/NativeScriptIosSecurity.xcframework/Info.plist
@@ -8,32 +8,32 @@
DebugSymbolsPath
dSYMs
LibraryIdentifier
- ios-arm64
+ ios-arm64_x86_64-simulator
LibraryPath
NativeScriptIOSSecurity.framework
SupportedArchitectures
arm64
+ x86_64
SupportedPlatform
ios
+ SupportedPlatformVariant
+ simulator
DebugSymbolsPath
dSYMs
LibraryIdentifier
- ios-arm64_x86_64-simulator
+ ios-arm64
LibraryPath
NativeScriptIOSSecurity.framework
SupportedArchitectures
arm64
- x86_64
SupportedPlatform
ios
- SupportedPlatformVariant
- simulator
CFBundlePackageType
diff --git a/packages/ios-security/platforms/ios/NativeScriptIosSecurity.xcframework/ios-arm64/NativeScriptIosSecurity.framework/NativeScriptIosSecurity b/packages/ios-security/platforms/ios/NativeScriptIosSecurity.xcframework/ios-arm64/NativeScriptIosSecurity.framework/NativeScriptIosSecurity
index 206f3ecf..53142dd4 100755
Binary files a/packages/ios-security/platforms/ios/NativeScriptIosSecurity.xcframework/ios-arm64/NativeScriptIosSecurity.framework/NativeScriptIosSecurity and b/packages/ios-security/platforms/ios/NativeScriptIosSecurity.xcframework/ios-arm64/NativeScriptIosSecurity.framework/NativeScriptIosSecurity differ
diff --git a/packages/ios-security/platforms/ios/NativeScriptIosSecurity.xcframework/ios-arm64_x86_64-simulator/NativeScriptIosSecurity.framework/NativeScriptIosSecurity b/packages/ios-security/platforms/ios/NativeScriptIosSecurity.xcframework/ios-arm64_x86_64-simulator/NativeScriptIosSecurity.framework/NativeScriptIosSecurity
index 0593f519..9c7c6a6c 100755
Binary files a/packages/ios-security/platforms/ios/NativeScriptIosSecurity.xcframework/ios-arm64_x86_64-simulator/NativeScriptIosSecurity.framework/NativeScriptIosSecurity and b/packages/ios-security/platforms/ios/NativeScriptIosSecurity.xcframework/ios-arm64_x86_64-simulator/NativeScriptIosSecurity.framework/NativeScriptIosSecurity differ
diff --git a/packages/ios-security/platforms/ios/NativeScriptIosSecurity.xcframework/ios-arm64_x86_64-simulator/NativeScriptIosSecurity.framework/_CodeSignature/CodeResources b/packages/ios-security/platforms/ios/NativeScriptIosSecurity.xcframework/ios-arm64_x86_64-simulator/NativeScriptIosSecurity.framework/_CodeSignature/CodeResources
index 1a1d98e8..65f1075f 100644
--- a/packages/ios-security/platforms/ios/NativeScriptIosSecurity.xcframework/ios-arm64_x86_64-simulator/NativeScriptIosSecurity.framework/_CodeSignature/CodeResources
+++ b/packages/ios-security/platforms/ios/NativeScriptIosSecurity.xcframework/ios-arm64_x86_64-simulator/NativeScriptIosSecurity.framework/_CodeSignature/CodeResources
@@ -26,11 +26,11 @@
Modules/NativeScriptIOSSecurity.swiftmodule/Project/arm64-apple-ios-simulator.swiftsourceinfo
- LNiQaroTUMgsNSTnppuJjH+EajY=
+ JhVhOUCZPQBUV9nkMVqoZhIQNxw=
Modules/NativeScriptIOSSecurity.swiftmodule/Project/x86_64-apple-ios-simulator.swiftsourceinfo
- tWSkmHiHs3SyU8DItH1DTrGKq3c=
+ PlIJ+sZpTKaRUu8pvFU5rygAmtY=
Modules/NativeScriptIOSSecurity.swiftmodule/arm64-apple-ios-simulator.swiftdoc
@@ -42,7 +42,7 @@
Modules/NativeScriptIOSSecurity.swiftmodule/arm64-apple-ios-simulator.swiftmodule
- GVnJ/gvztohxQ3nkvPSNftZdxAE=
+ DnvR1FgNTFsKr9LqAtQiYM+ue3A=
Modules/NativeScriptIOSSecurity.swiftmodule/x86_64-apple-ios-simulator.swiftdoc
@@ -54,7 +54,7 @@
Modules/NativeScriptIOSSecurity.swiftmodule/x86_64-apple-ios-simulator.swiftmodule
- XIltSm4hmtoJ9tt53Y9/jvmGVYY=
+ h1aIusAj+W//sHbkzu3HEEUhgII=
Modules/module.modulemap
@@ -95,14 +95,14 @@
hash2
- +sDoQYqdD1fu6ixAUUnT55r+5dcIOSOoh64i8Fk2E2k=
+ o9PU04w93Cp9eEpuagYp9MugD2gnMD6GTJccgcM5Wwk=
Modules/NativeScriptIOSSecurity.swiftmodule/Project/x86_64-apple-ios-simulator.swiftsourceinfo
hash2
- b7vBwsVVJlPsIgUQiAhpIPicEXPJ2dP383OfpkWpvLg=
+ JKChWQ5qNuUu6LqzogNHL30McJ/QUzkk/MPyfFKjSfg=
Modules/NativeScriptIOSSecurity.swiftmodule/arm64-apple-ios-simulator.swiftdoc
@@ -123,7 +123,7 @@
hash2
- hFSpRo+4uhG16H4NxpCC2nUQ1uXITI4W2+zxOhBGHJs=
+ WUDuO0FIcKDihp+Ph/6zObgjXn1cA66RHfZ4d4P7H6E=
Modules/NativeScriptIOSSecurity.swiftmodule/x86_64-apple-ios-simulator.swiftdoc
@@ -144,7 +144,7 @@
hash2
- LPaXEdIQh7hQspMcyG9dBA5lODdJRCP97UUYLj3WM74=
+ LcV7I6XVBYFJjqAHZlDdwEC+ScMbZs4L567Q32wYIAY=
Modules/module.modulemap
diff --git a/packages/mmkv-metal/.eslintrc.json b/packages/mmkv-metal/.eslintrc.json
new file mode 100644
index 00000000..be41074b
--- /dev/null
+++ b/packages/mmkv-metal/.eslintrc.json
@@ -0,0 +1,18 @@
+{
+ "extends": ["../../.eslintrc.json"],
+ "ignorePatterns": ["!**/*", "node_modules/**/*"],
+ "overrides": [
+ {
+ "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
+ "rules": {}
+ },
+ {
+ "files": ["*.ts", "*.tsx"],
+ "rules": {}
+ },
+ {
+ "files": ["*.js", "*.jsx"],
+ "rules": {}
+ }
+ ]
+}
diff --git a/packages/mmkv-metal/README.md b/packages/mmkv-metal/README.md
new file mode 100644
index 00000000..32ffdc76
--- /dev/null
+++ b/packages/mmkv-metal/README.md
@@ -0,0 +1,13 @@
+# @nativescript/mmkv-metal
+
+```javascript
+ns plugin add @nativescript/mmkv-metal
+```
+
+## Usage
+
+// TODO
+
+## License
+
+Apache License Version 2.0
diff --git a/packages/mmkv-metal/common.ts b/packages/mmkv-metal/common.ts
new file mode 100644
index 00000000..25ed2c79
--- /dev/null
+++ b/packages/mmkv-metal/common.ts
@@ -0,0 +1,3 @@
+import { Observable } from '@nativescript/core';
+
+export class MmkvMetalCommon extends Observable {}
diff --git a/packages/mmkv-metal/index.android.ts b/packages/mmkv-metal/index.android.ts
new file mode 100644
index 00000000..79bc86b2
--- /dev/null
+++ b/packages/mmkv-metal/index.android.ts
@@ -0,0 +1,18 @@
+declare const __non_webpack_require__;
+import { Utils } from '@nativescript/core';
+
+// load with system before requiring which calls dlopen
+java.lang.System.loadLibrary('mmkvmetal');
+
+__non_webpack_require__('system_lib://libmmkvmetal.so');
+
+export function initialize(path) {
+ if (typeof path === 'string') {
+ NSCMMKV.initialize(path);
+ } else {
+ const root = Utils.android.getApplicationContext().getFilesDir().getAbsolutePath() + '/mmkv';
+ NSCMMKV.initialize(root);
+ }
+}
+
+export const NSCMMKV = global.NSCMMKV;
diff --git a/packages/mmkv-metal/index.d.ts b/packages/mmkv-metal/index.d.ts
new file mode 100644
index 00000000..2df8711f
--- /dev/null
+++ b/packages/mmkv-metal/index.d.ts
@@ -0,0 +1,49 @@
+export interface INSCMMKV {
+ contains(key: string): boolean;
+ set(key: string, value: boolean | string | number | ArrayBuffer);
+ key(index: number): string | null;
+ getBoolean(key: string): boolean;
+ getString(key: string): string;
+ getNumber(key: string): number;
+ getBytes(key: string): ArrayBuffer;
+ delete(key: string | string[]);
+ clearAll();
+ readonly totalSize: number;
+ readonly actualSize: number;
+ readonly keys: string[];
+
+ clearMemoryCache();
+ close();
+
+ readonly cryptKey: string | null;
+
+ recrypt(key?: string);
+}
+
+export function initialize();
+
+export class NSCMMKV implements INSCMMKV {
+ constructor(options?: { id?: string; path?: string; encryptionKey?: string; mode?: 'SINGLE' | 'MULTI' });
+
+ static readonly rootPath: string;
+
+ contains(key: string): boolean;
+ set(key: string, value: boolean | string | number | ArrayBuffer);
+ key(index: number): string | null;
+ getBoolean(key: string): boolean;
+ getString(key: string): string;
+ getNumber(key: string): number;
+ getBytes(key: string): ArrayBuffer;
+ delete(key: string | string[]);
+ clearAll();
+ readonly totalSize: number;
+ readonly actualSize: number;
+ readonly keys: string[];
+
+ clearMemoryCache();
+ close();
+
+ readonly cryptKey: string | null;
+
+ recrypt(key?: string);
+}
diff --git a/packages/mmkv-metal/index.ios.ts b/packages/mmkv-metal/index.ios.ts
new file mode 100644
index 00000000..d02c0228
--- /dev/null
+++ b/packages/mmkv-metal/index.ios.ts
@@ -0,0 +1,159 @@
+import { INSCMMKV } from '.';
+
+function intoData(value: string) {
+ return NSString.stringWithString(value).dataUsingEncoding(NSUTF8StringEncoding);
+}
+
+function intoString(value: NSData) {
+ return NSString.alloc().initWithDataEncoding(value, NSUTF8StringEncoding);
+}
+
+export class NSCMMKV implements INSCMMKV {
+ #native: MMKV;
+ constructor(options?: { id?: string; path?: string; encryptionKey?: string; mode?: 'SINGLE' | 'MULTI' }) {
+ if (!options) {
+ this.#native = MMKV.defaultMMKV();
+ } else {
+ if (options?.id && options?.encryptionKey && options?.path) {
+ this.#native = MMKV.mmkvWithIDCryptKeyRootPath(options?.id, intoData(options?.encryptionKey), options?.path);
+ } else if (options?.id && options?.encryptionKey && !options?.path && options?.mode) {
+ this.#native = MMKV.mmkvWithIDCryptKeyMode(options?.id, intoData(options?.encryptionKey), options.mode === 'MULTI' ? MMKVMode.MultiProcess : MMKVMode.SingleProcess);
+ } else if (options?.id && options?.encryptionKey && !options?.path && !options?.mode) {
+ this.#native = MMKV.mmkvWithIDCryptKey(options?.id, intoData(options?.encryptionKey));
+ } else if (options?.id && !options?.encryptionKey && options?.path && !options?.mode) {
+ this.#native = MMKV.mmkvWithIDRootPath(options?.id, options.path);
+ } else if (options?.id && options?.mode && !options?.encryptionKey && !options?.path) {
+ this.#native = MMKV.mmkvWithIDMode(options?.id, options.mode === 'MULTI' ? MMKVMode.MultiProcess : MMKVMode.SingleProcess);
+ } else if (options?.id && !options?.encryptionKey && !options?.path && !options.mode) {
+ this.#native = MMKV.mmkvWithID(options?.id);
+ } else if (options?.encryptionKey && !options?.id && !options?.path && !options.mode) {
+ const data = intoData(options?.encryptionKey);
+ this.#native = MMKV.defaultMMKVWithCryptKey(data);
+ } else {
+ // throw or return the default instance
+ this.#native = MMKV.defaultMMKV();
+ }
+ }
+ }
+
+ get native() {
+ return this.#native;
+ }
+
+ static isFileValid(id: string, path?: string): boolean {
+ if (!path) {
+ return MMKV.isFileValid(id);
+ } else {
+ return MMKV.isFileValidRootPath(id, path);
+ }
+ }
+
+ contains(key: string): boolean {
+ return this.native.containsKey(key);
+ }
+
+ key(index: number): string | null {
+ try {
+ const keys = this.native.allKeys();
+ return keys.objectAtIndex(index);
+ } catch (e) {}
+ return null;
+ }
+
+ set(key: string, value: boolean | string | number | ArrayBuffer) {
+ if (typeof value === 'boolean') {
+ this.native.setBoolForKey(value, key);
+ } else if (typeof value === 'string') {
+ this.native.setStringForKey(value, key);
+ } else if (typeof value === 'number') {
+ this.native.setDoubleForKey(value, key);
+ } else if (value instanceof ArrayBuffer) {
+ const data = NSData.dataWithData(value as any);
+ if (data) {
+ this.native.setDataForKey(data, key);
+ }
+ }
+ }
+
+ getBoolean(key: string): boolean {
+ return this.native.getBoolForKey(key);
+ }
+
+ getString(key: string): string {
+ return this.native.getStringForKey(key);
+ }
+
+ getNumber(key: string): number {
+ return this.native.getDoubleForKey(key);
+ }
+
+ getBytes(key: string) {
+ const bytes = this.native.getDataForKey(key);
+ if (!bytes) {
+ return null;
+ }
+ return interop.bufferFromData(bytes);
+ }
+
+ clearAll() {
+ this.native.clearAll();
+ }
+
+ delete(key: string | string[]) {
+ if (Array.isArray(key)) {
+ this.native.removeValuesForKeys(key);
+ } else {
+ this.native.removeValueForKey(key);
+ }
+ }
+
+ get totalSize() {
+ return this.native.totalSize();
+ }
+
+ get actualSize() {
+ return this.native.actualSize();
+ }
+
+ get keys(): string[] {
+ const keys = this.native.allKeys();
+ const count = keys.count;
+ const ret = [];
+ for (let i = 0; i < count; i++) {
+ ret.push(keys.objectAtIndex(i));
+ }
+ return ret;
+ }
+
+ clearMemoryCache() {
+ this.native.clearMemoryCache();
+ }
+
+ close() {
+ this.native.close();
+ }
+
+ get cryptKey() {
+ const key = this.native.cryptKey();
+ if (key) {
+ return intoString(key) as any;
+ }
+ return null;
+ }
+
+ static get rootPath() {
+ return MMKV.mmkvBasePath();
+ }
+
+ recrypt(key?: string) {
+ if (key) {
+ this.native.reKey(intoData(key));
+ } else {
+ this.native.reKey(null);
+ }
+ }
+}
+
+export function initialize() {
+ MMKV.initialize();
+}
diff --git a/packages/mmkv-metal/local-storage/index.ts b/packages/mmkv-metal/local-storage/index.ts
new file mode 100644
index 00000000..9152c38e
--- /dev/null
+++ b/packages/mmkv-metal/local-storage/index.ts
@@ -0,0 +1,126 @@
+import { NSCMMKV, initialize } from '@nativescript/mmkv-metal';
+
+initialize();
+
+console.log('initialize');
+
+class Storage {
+ getItem(name) {
+ return undefined;
+ }
+
+ key(id) {
+ return undefined;
+ }
+
+ setItem(name, value) {}
+
+ removeItem(name) {}
+
+ clear() {}
+
+ get length() {
+ return 0;
+ }
+}
+
+class LocalStorage extends Storage {
+ #mmkv: NSCMMKV;
+ constructor() {
+ super();
+ this.#mmkv = new NSCMMKV();
+ }
+ getItem(name) {
+ return this.#mmkv.getString(name);
+ }
+
+ key(id) {
+ return this.#mmkv.key(id);
+ }
+
+ setItem(name, value) {
+ if (value === null) {
+ this.#mmkv.set(name, 'null');
+ } else if (value === undefined) {
+ this.#mmkv.set(name, 'undefined');
+ } else {
+ this.#mmkv.set(name, value.toString());
+ }
+ }
+
+ removeItem(name) {
+ this.#mmkv.delete(name);
+ }
+
+ clear() {
+ this.#mmkv.clearAll();
+ }
+
+ get length(): number {
+ return (this.#mmkv as any).count?.() ?? 0;
+ }
+}
+
+if (!global.Storage) {
+ global.Storage = Storage;
+}
+
+if (!(global?.localStorage instanceof LocalStorage) || !global.localStorage || (module as any)?.hot) {
+ global.localStorage = new LocalStorage();
+}
+
+if (!global.sessionStorage) {
+ class SessionStorage extends Storage {
+ #data = {};
+ getItem(name) {
+ if (this.#data.hasOwnProperty(name)) {
+ return this.#data[name];
+ }
+ return null;
+ }
+
+ key(id) {
+ const keys = Object.keys(this.#data);
+ if (id >= keys.length) {
+ return null;
+ }
+ return keys[id];
+ }
+
+ setItemObject(name, value) {
+ this.#data[name] = value;
+ }
+
+ setItem(name, value) {
+ if (value === null) {
+ this.#data[name] = 'null';
+ } else if (value === undefined) {
+ this.#data[name] = 'undefined';
+ } else {
+ this.#data[name] = value.toString();
+ }
+ }
+
+ removeItem(name) {
+ if (this.#data[name]) {
+ delete this.#data[name];
+ }
+ }
+
+ clear() {
+ this.#data = {};
+ }
+ }
+
+ global.sessionStorage = new SessionStorage();
+}
+
+export default global.localStorage;
+
+if ((module as any)?.hot) {
+ const hot = (module as any)?.hot;
+ hot?.accept?.();
+ hot?.dispose?.(() => {
+ global.localStorage = undefined;
+ });
+}
diff --git a/packages/mmkv-metal/package.json b/packages/mmkv-metal/package.json
new file mode 100644
index 00000000..c470c890
--- /dev/null
+++ b/packages/mmkv-metal/package.json
@@ -0,0 +1,35 @@
+{
+ "name": "@nativescript/mmkv-metal",
+ "version": "1.0.0",
+ "description": "Add a plugin description",
+ "main": "index",
+ "typings": "index.d.ts",
+ "nativescript": {
+ "platforms": {
+ "ios": "6.0.0",
+ "android": "6.0.0"
+ }
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/NativeScript/plugins.git"
+ },
+ "keywords": [
+ "NativeScript",
+ "JavaScript",
+ "TypeScript",
+ "iOS",
+ "Android"
+ ],
+ "author": {
+ "name": "NativeScript",
+ "email": "oss@nativescript.org"
+ },
+ "bugs": {
+ "url": "https://github.com/NativeScript/plugins/issues"
+ },
+ "license": "Apache-2.0",
+ "homepage": "https://github.com/NativeScript/plugins",
+ "readmeFilename": "README.md",
+ "bootstrapper": "@nativescript/plugin-seed"
+}
diff --git a/packages/mmkv-metal/platforms/ios/Podfile b/packages/mmkv-metal/platforms/ios/Podfile
new file mode 100644
index 00000000..6292c7d2
--- /dev/null
+++ b/packages/mmkv-metal/platforms/ios/Podfile
@@ -0,0 +1 @@
+pod 'MMKV'
\ No newline at end of file
diff --git a/packages/mmkv-metal/project.json b/packages/mmkv-metal/project.json
new file mode 100644
index 00000000..86e8cd11
--- /dev/null
+++ b/packages/mmkv-metal/project.json
@@ -0,0 +1,64 @@
+{
+ "root": "packages/mmkv-metal",
+ "projectType": "library",
+ "sourceRoot": "packages/mmkv-metal",
+ "targets": {
+ "build": {
+ "executor": "@nrwl/js:tsc",
+ "options": {
+ "outputPath": "dist/packages/mmkv-metal",
+ "tsConfig": "packages/mmkv-metal/tsconfig.json",
+ "packageJson": "packages/mmkv-metal/package.json",
+ "main": "packages/mmkv-metal/index.d.ts",
+ "assets": [
+ "packages/mmkv-metal/*.md",
+ "packages/mmkv-metal/index.d.ts",
+ "LICENSE",
+ {
+ "glob": "**/*",
+ "input": "packages/mmkv-metal/platforms/",
+ "output": "./platforms/"
+ }
+ ],
+ "dependsOn": [
+ {
+ "target": "build.all",
+ "projects": "dependencies"
+ }
+ ]
+ }
+ },
+ "build.all": {
+ "executor": "@nrwl/workspace:run-commands",
+ "options": {
+ "commands": ["node tools/scripts/build-finish.ts mmkv-metal"],
+ "parallel": false
+ },
+ "outputs": ["dist/packages/mmkv-metal"],
+ "dependsOn": [
+ {
+ "target": "build.all",
+ "projects": "dependencies"
+ },
+ {
+ "target": "build",
+ "projects": "self"
+ }
+ ]
+ },
+ "focus": {
+ "executor": "@nrwl/workspace:run-commands",
+ "options": {
+ "commands": ["nx g @nativescript/plugin-tools:focus-packages mmkv-metal"],
+ "parallel": false
+ }
+ },
+ "lint": {
+ "executor": "@nrwl/linter:eslint",
+ "options": {
+ "lintFilePatterns": ["packages/mmkv-metal/**/*.ts"]
+ }
+ }
+ },
+ "tags": []
+}
diff --git a/packages/mmkv-metal/references.d.ts b/packages/mmkv-metal/references.d.ts
new file mode 100644
index 00000000..22bac92c
--- /dev/null
+++ b/packages/mmkv-metal/references.d.ts
@@ -0,0 +1 @@
+///
diff --git a/packages/mmkv-metal/src-native/android/.gitignore b/packages/mmkv-metal/src-native/android/.gitignore
new file mode 100644
index 00000000..aa724b77
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/.gitignore
@@ -0,0 +1,15 @@
+*.iml
+.gradle
+/local.properties
+/.idea/caches
+/.idea/libraries
+/.idea/modules.xml
+/.idea/workspace.xml
+/.idea/navEditor.xml
+/.idea/assetWizardSettings.xml
+.DS_Store
+/build
+/captures
+.externalNativeBuild
+.cxx
+local.properties
diff --git a/packages/mmkv-metal/src-native/android/.idea/.gitignore b/packages/mmkv-metal/src-native/android/.idea/.gitignore
new file mode 100644
index 00000000..26d33521
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/packages/mmkv-metal/src-native/android/.idea/.name b/packages/mmkv-metal/src-native/android/.idea/.name
new file mode 100644
index 00000000..cccd5273
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/.idea/.name
@@ -0,0 +1 @@
+MMKV-MetalDemo
\ No newline at end of file
diff --git a/packages/mmkv-metal/src-native/android/.idea/compiler.xml b/packages/mmkv-metal/src-native/android/.idea/compiler.xml
new file mode 100644
index 00000000..fb7f4a8a
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/mmkv-metal/src-native/android/.idea/gradle.xml b/packages/mmkv-metal/src-native/android/.idea/gradle.xml
new file mode 100644
index 00000000..8671a644
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/.idea/gradle.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/mmkv-metal/src-native/android/.idea/misc.xml b/packages/mmkv-metal/src-native/android/.idea/misc.xml
new file mode 100644
index 00000000..2a4d5b52
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/.idea/misc.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/mmkv-metal/src-native/android/.idea/vcs.xml b/packages/mmkv-metal/src-native/android/.idea/vcs.xml
new file mode 100644
index 00000000..d401d1fe
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/.idea/vcs.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/mmkv-metal/src-native/android/MMKV b/packages/mmkv-metal/src-native/android/MMKV
new file mode 160000
index 00000000..f58cf4b7
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/MMKV
@@ -0,0 +1 @@
+Subproject commit f58cf4b7e56765deda27bc30e9537cbdb3075c25
diff --git a/packages/mmkv-metal/src-native/android/app/.gitignore b/packages/mmkv-metal/src-native/android/app/.gitignore
new file mode 100644
index 00000000..42afabfd
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/app/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/packages/mmkv-metal/src-native/android/app/build.gradle b/packages/mmkv-metal/src-native/android/app/build.gradle
new file mode 100644
index 00000000..11d66b8b
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/app/build.gradle
@@ -0,0 +1,44 @@
+plugins {
+ id 'com.android.application'
+ id 'org.jetbrains.kotlin.android'
+}
+
+android {
+ compileSdk 32
+
+ defaultConfig {
+ applicationId "org.nativescript.mmkv_metaldemo"
+ minSdk 17
+ targetSdk 32
+ versionCode 1
+ versionName "1.0"
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+}
+
+dependencies {
+
+ implementation 'androidx.core:core-ktx:1.7.0'
+ implementation 'androidx.appcompat:appcompat:1.4.2'
+ implementation 'com.google.android.material:material:1.6.1'
+ implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
+ implementation project(path: ':mmkv-metal')
+ testImplementation 'junit:junit:4.13.2'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.3'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
+}
diff --git a/packages/mmkv-metal/src-native/android/app/proguard-rules.pro b/packages/mmkv-metal/src-native/android/app/proguard-rules.pro
new file mode 100644
index 00000000..481bb434
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/packages/mmkv-metal/src-native/android/app/src/androidTest/java/org/nativescript/mmkv_metaldemo/ExampleInstrumentedTest.kt b/packages/mmkv-metal/src-native/android/app/src/androidTest/java/org/nativescript/mmkv_metaldemo/ExampleInstrumentedTest.kt
new file mode 100644
index 00000000..f88f87ae
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/app/src/androidTest/java/org/nativescript/mmkv_metaldemo/ExampleInstrumentedTest.kt
@@ -0,0 +1,24 @@
+package org.nativescript.mmkv_metaldemo
+
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.ext.junit.runners.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+ @Test
+ fun useAppContext() {
+ // Context of the app under test.
+ val appContext = InstrumentationRegistry.getInstrumentation().targetContext
+ assertEquals("org.nativescript.mmkv_metaldemo", appContext.packageName)
+ }
+}
diff --git a/packages/mmkv-metal/src-native/android/app/src/main/AndroidManifest.xml b/packages/mmkv-metal/src-native/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..bde732e6
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/mmkv-metal/src-native/android/app/src/main/java/org/nativescript/mmkv_metaldemo/MainActivity.kt b/packages/mmkv-metal/src-native/android/app/src/main/java/org/nativescript/mmkv_metaldemo/MainActivity.kt
new file mode 100644
index 00000000..f259f692
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/app/src/main/java/org/nativescript/mmkv_metaldemo/MainActivity.kt
@@ -0,0 +1,11 @@
+package org.nativescript.mmkv_metaldemo
+
+import androidx.appcompat.app.AppCompatActivity
+import android.os.Bundle
+
+class MainActivity : AppCompatActivity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_main)
+ }
+}
\ No newline at end of file
diff --git a/packages/mmkv-metal/src-native/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/packages/mmkv-metal/src-native/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 00000000..7706ab9e
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/mmkv-metal/src-native/android/app/src/main/res/drawable/ic_launcher_background.xml b/packages/mmkv-metal/src-native/android/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 00000000..07d5da9c
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/mmkv-metal/src-native/android/app/src/main/res/layout/activity_main.xml b/packages/mmkv-metal/src-native/android/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 00000000..c75d0576
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
diff --git a/packages/mmkv-metal/src-native/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/packages/mmkv-metal/src-native/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 00000000..6b78462d
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/packages/mmkv-metal/src-native/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/packages/mmkv-metal/src-native/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 00000000..6b78462d
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/packages/mmkv-metal/src-native/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/packages/mmkv-metal/src-native/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp
new file mode 100644
index 00000000..c209e78e
Binary files /dev/null and b/packages/mmkv-metal/src-native/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ
diff --git a/packages/mmkv-metal/src-native/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/packages/mmkv-metal/src-native/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..b2dfe3d1
Binary files /dev/null and b/packages/mmkv-metal/src-native/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ
diff --git a/packages/mmkv-metal/src-native/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/packages/mmkv-metal/src-native/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp
new file mode 100644
index 00000000..4f0f1d64
Binary files /dev/null and b/packages/mmkv-metal/src-native/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ
diff --git a/packages/mmkv-metal/src-native/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/packages/mmkv-metal/src-native/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..62b611da
Binary files /dev/null and b/packages/mmkv-metal/src-native/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ
diff --git a/packages/mmkv-metal/src-native/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/packages/mmkv-metal/src-native/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
new file mode 100644
index 00000000..948a3070
Binary files /dev/null and b/packages/mmkv-metal/src-native/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ
diff --git a/packages/mmkv-metal/src-native/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/packages/mmkv-metal/src-native/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..1b9a6956
Binary files /dev/null and b/packages/mmkv-metal/src-native/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ
diff --git a/packages/mmkv-metal/src-native/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/packages/mmkv-metal/src-native/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
new file mode 100644
index 00000000..28d4b77f
Binary files /dev/null and b/packages/mmkv-metal/src-native/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ
diff --git a/packages/mmkv-metal/src-native/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/packages/mmkv-metal/src-native/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..9287f508
Binary files /dev/null and b/packages/mmkv-metal/src-native/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ
diff --git a/packages/mmkv-metal/src-native/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/packages/mmkv-metal/src-native/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
new file mode 100644
index 00000000..aa7d6427
Binary files /dev/null and b/packages/mmkv-metal/src-native/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ
diff --git a/packages/mmkv-metal/src-native/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/packages/mmkv-metal/src-native/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..9126ae37
Binary files /dev/null and b/packages/mmkv-metal/src-native/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ
diff --git a/packages/mmkv-metal/src-native/android/app/src/main/res/values-night/themes.xml b/packages/mmkv-metal/src-native/android/app/src/main/res/values-night/themes.xml
new file mode 100644
index 00000000..69a8f308
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/app/src/main/res/values-night/themes.xml
@@ -0,0 +1,16 @@
+
+
+
+
diff --git a/packages/mmkv-metal/src-native/android/app/src/main/res/values/colors.xml b/packages/mmkv-metal/src-native/android/app/src/main/res/values/colors.xml
new file mode 100644
index 00000000..ca1931bc
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/app/src/main/res/values/colors.xml
@@ -0,0 +1,10 @@
+
+
+ #FFBB86FC
+ #FF6200EE
+ #FF3700B3
+ #FF03DAC5
+ #FF018786
+ #FF000000
+ #FFFFFFFF
+
diff --git a/packages/mmkv-metal/src-native/android/app/src/main/res/values/strings.xml b/packages/mmkv-metal/src-native/android/app/src/main/res/values/strings.xml
new file mode 100644
index 00000000..2ec694fa
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/app/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ MMKV-MetalDemo
+
\ No newline at end of file
diff --git a/packages/mmkv-metal/src-native/android/app/src/main/res/values/themes.xml b/packages/mmkv-metal/src-native/android/app/src/main/res/values/themes.xml
new file mode 100644
index 00000000..4b11c9b0
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/app/src/main/res/values/themes.xml
@@ -0,0 +1,16 @@
+
+
+
+
diff --git a/packages/mmkv-metal/src-native/android/app/src/main/res/xml/backup_rules.xml b/packages/mmkv-metal/src-native/android/app/src/main/res/xml/backup_rules.xml
new file mode 100644
index 00000000..148c18b6
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/app/src/main/res/xml/backup_rules.xml
@@ -0,0 +1,13 @@
+
+
+
+
diff --git a/packages/mmkv-metal/src-native/android/app/src/main/res/xml/data_extraction_rules.xml b/packages/mmkv-metal/src-native/android/app/src/main/res/xml/data_extraction_rules.xml
new file mode 100644
index 00000000..0c4f95ca
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/app/src/main/res/xml/data_extraction_rules.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
diff --git a/packages/mmkv-metal/src-native/android/app/src/test/java/org/nativescript/mmkv_metaldemo/ExampleUnitTest.kt b/packages/mmkv-metal/src-native/android/app/src/test/java/org/nativescript/mmkv_metaldemo/ExampleUnitTest.kt
new file mode 100644
index 00000000..04d06f99
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/app/src/test/java/org/nativescript/mmkv_metaldemo/ExampleUnitTest.kt
@@ -0,0 +1,17 @@
+package org.nativescript.mmkv_metaldemo
+
+import org.junit.Test
+
+import org.junit.Assert.*
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+class ExampleUnitTest {
+ @Test
+ fun addition_isCorrect() {
+ assertEquals(4, 2 + 2)
+ }
+}
diff --git a/packages/mmkv-metal/src-native/android/build.gradle b/packages/mmkv-metal/src-native/android/build.gradle
new file mode 100644
index 00000000..eaf7c0c5
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/build.gradle
@@ -0,0 +1,10 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+plugins {
+ id 'com.android.application' version '7.2.2' apply false
+ id 'com.android.library' version '7.2.2' apply false
+ id 'org.jetbrains.kotlin.android' version '1.6.10' apply false
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
diff --git a/packages/mmkv-metal/src-native/android/gradle.properties b/packages/mmkv-metal/src-native/android/gradle.properties
new file mode 100644
index 00000000..3c7a8bd3
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/gradle.properties
@@ -0,0 +1,23 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app"s APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Kotlin code style for this project: "official" or "obsolete":
+kotlin.code.style=official
+# Enables namespacing of each library's R class so that its R class includes only the
+# resources declared in the library itself and none from the library's dependencies,
+# thereby reducing the size of the R class for that library
+android.nonTransitiveRClass=true
diff --git a/packages/mmkv-metal/src-native/android/gradle/wrapper/gradle-wrapper.jar b/packages/mmkv-metal/src-native/android/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000..e708b1c0
Binary files /dev/null and b/packages/mmkv-metal/src-native/android/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/packages/mmkv-metal/src-native/android/gradle/wrapper/gradle-wrapper.properties b/packages/mmkv-metal/src-native/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..ba908a26
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Fri Jun 10 02:44:45 AST 2022
+distributionBase=GRADLE_USER_HOME
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
+distributionPath=wrapper/dists
+zipStorePath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
diff --git a/packages/mmkv-metal/src-native/android/gradlew b/packages/mmkv-metal/src-native/android/gradlew
new file mode 100755
index 00000000..4f906e0c
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/gradlew
@@ -0,0 +1,185 @@
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=`expr $i + 1`
+ done
+ case $i in
+ 0) set -- ;;
+ 1) set -- "$args0" ;;
+ 2) set -- "$args0" "$args1" ;;
+ 3) set -- "$args0" "$args1" "$args2" ;;
+ 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=`save "$@"`
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+exec "$JAVACMD" "$@"
diff --git a/packages/mmkv-metal/src-native/android/gradlew.bat b/packages/mmkv-metal/src-native/android/gradlew.bat
new file mode 100644
index 00000000..ac1b06f9
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/gradlew.bat
@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/packages/mmkv-metal/src-native/android/mmkv-metal/.gitignore b/packages/mmkv-metal/src-native/android/mmkv-metal/.gitignore
new file mode 100644
index 00000000..42afabfd
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/mmkv-metal/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/packages/mmkv-metal/src-native/android/mmkv-metal/CMakeLists.txt b/packages/mmkv-metal/src-native/android/mmkv-metal/CMakeLists.txt
new file mode 100644
index 00000000..3ab36d10
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/mmkv-metal/CMakeLists.txt
@@ -0,0 +1,77 @@
+cmake_minimum_required(VERSION 3.10.0)
+
+MESSAGE("## ANDROID_NDK_ROOT: " ${ANDROID_NDK_ROOT})
+
+project(mmkvmetal)
+
+include_directories(
+ ${PROJECT_SOURCE_DIR}/src/main/cpp/include/libc++
+ ${PROJECT_SOURCE_DIR}/src/main/cpp/include
+)
+
+set(COMMON_CMAKE_ARGUMENTS "-std=c++17 -nostdinc++ -Werror -Wno-unused-result -mstackrealign -fexceptions -fno-builtin-stpcpy -fno-rtti -D_LIBCPP_ENABLE_NODISCARD -D_LIBCPP_ABI_UNSTABLE -D_LIBCPP_ABI_VERSION=Cr -DV8_31BIT_SMIS_ON_64BIT_ARCH -DV8_ENABLE_REGEXP_INTERPRETER_THREADED_DISPATCH -DV8_EMBEDDED_BUILTINS")
+
+if("${ANDROID_ABI}" MATCHES "arm64-v8a$" OR "${ANDROID_ABI}" MATCHES "x86_64$")
+ # Enable pointer compression on 64 bit platforms
+ set(COMMON_CMAKE_ARGUMENTS "${COMMON_CMAKE_ARGUMENTS} -DV8_COMPRESS_POINTERS")
+endif()
+
+
+set(CMAKE_CXX_FLAGS "${COMMON_CMAKE_ARGUMENTS}")
+
+add_subdirectory(../../MMKV/Core core)
+
+add_library(
+ mmkvmetal
+
+ SHARED
+
+ src/main/cpp/Bridge.cpp
+ src/main/cpp/Caches.cpp
+ src/main/cpp/Helpers.cpp
+ src/main/cpp/MMKVImpl.cpp
+ )
+
+set_target_properties(
+ mmkvmetal PROPERTIES
+ CXX_STANDARD 17
+ CXX_EXTENSIONS OFF
+ POSITION_INDEPENDENT_CODE ON
+ LINK_FLAGS -Wl,--allow-multiple-definition
+)
+
+
+MESSAGE("# General cmake Info")
+MESSAGE("# PROJECT_SOURCE_DIR: " ${PROJECT_SOURCE_DIR})
+MESSAGE("# CMAKE_VERSION: " ${CMAKE_VERSION})
+MESSAGE("# CMAKE_C_COMPILER_ID: " ${CMAKE_C_COMPILER_ID})
+MESSAGE("# CMAKE_CXX_COMPILER_ID: " ${CMAKE_CXX_COMPILER_ID})
+MESSAGE("# CMAKE_C_FLAGS: " ${CMAKE_C_FLAGS})
+MESSAGE("# CMAKE_CXX_FLAGS: " ${CMAKE_CXX_FLAGS})
+
+find_library(system-log log)
+find_library(system-z z)
+
+if ("${ANDROID_ABI}" MATCHES "armeabi-v7a" OR "${ANDROID_ABI}" MATCHES "x86")
+ # On API Level 19 and lower we need to link with android_support
+ # because it contains some implementation of functions such as "strtoll" and "strtoul"
+ target_link_libraries(mmkvmetal
+ ${system-log}
+ ${system-z}
+ ${PROJECT_SOURCE_DIR}/src/main/libs/${ANDROID_ABI}/libv8.a
+ ${PROJECT_SOURCE_DIR}/src/main/libs/${ANDROID_ABI}/libzip.a
+ ${ANDROID_NDK_ROOT}/sources/cxx-stl/llvm-libc++/libs/${ANDROID_ABI}/libandroid_support.a
+ core
+ android
+ )
+
+else()
+ target_link_libraries(mmkvmetal
+ ${system-log}
+ ${system-z}
+ ${PROJECT_SOURCE_DIR}/src/main/libs/${ANDROID_ABI}/libv8.a
+ ${PROJECT_SOURCE_DIR}/src/main/libs/${ANDROID_ABI}/libzip.a
+ core
+ android
+ )
+endif ()
diff --git a/packages/mmkv-metal/src-native/android/mmkv-metal/build.gradle b/packages/mmkv-metal/src-native/android/mmkv-metal/build.gradle
new file mode 100644
index 00000000..77f6e5f6
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/mmkv-metal/build.gradle
@@ -0,0 +1,87 @@
+plugins {
+ id 'com.android.library'
+ id 'org.jetbrains.kotlin.android'
+}
+
+
+def NDK_PATH = ""
+def hasNdkDirectory = project.hasProperty("ndkDirectory")
+if(!hasNdkDirectory){
+ println "No ndkDirectory set, checking environment \$ANDROID_NDK..."
+
+ NDK_PATH = "$System.env.ANDROID_NDK"
+ if (NDK_PATH == null || NDK_PATH == "null"){
+ println "No ndkDirectory set, checking environment \$ANDROID_NDK_ROOT..."
+ NDK_PATH = "$System.env.ANDROID_NDK_ROOT"
+ }
+
+ if (NDK_PATH == null || NDK_PATH == "null"){
+ println "No ndkDirectory set, checking environment \$ANDROID_NDK_HOME..."
+ NDK_PATH = "$System.env.ANDROID_NDK_HOME"
+ }
+} else {
+ NDK_PATH = ndkDirectory
+}
+println "Runtime using NDK_PATH: " + NDK_PATH
+
+
+
+
+android {
+ compileSdk 32
+ ndkVersion "20.0.5594570"
+ defaultConfig {
+ minSdk 17
+ targetSdk 32
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ consumerProguardFiles "consumer-rules.pro"
+
+ externalNativeBuild {
+ cmake {
+ arguments "-DANDROID_TOOLCHAIN=clang",
+ "-DANDROID_STL=c++_static",
+ "-DANDROID_NDK_ROOT=${System.getenv("ANDROID_NDK_ROOT")}"
+ }
+ }
+ ndk {
+ abiFilters 'x86', 'armeabi-v7a', 'arm64-v8a'
+ }
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+
+ externalNativeBuild {
+ cmake {
+ path "CMakeLists.txt"
+ }
+ }
+
+// sourceSets {
+// main {
+// jniLibs.srcDirs 'src/main/cpp/libs'
+// }
+// }
+
+}
+
+
+dependencies {
+
+ implementation 'androidx.core:core-ktx:1.6.0'
+ implementation 'androidx.appcompat:appcompat:1.4.2'
+ testImplementation 'junit:junit:4.13.2'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.3'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
+}
diff --git a/packages/mmkv-metal/src-native/android/mmkv-metal/consumer-rules.pro b/packages/mmkv-metal/src-native/android/mmkv-metal/consumer-rules.pro
new file mode 100644
index 00000000..e69de29b
diff --git a/packages/mmkv-metal/src-native/android/mmkv-metal/proguard-rules.pro b/packages/mmkv-metal/src-native/android/mmkv-metal/proguard-rules.pro
new file mode 100644
index 00000000..481bb434
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/mmkv-metal/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/packages/mmkv-metal/src-native/android/mmkv-metal/src/androidTest/java/org/nativescript/plugins/mmkv_metal/ExampleInstrumentedTest.kt b/packages/mmkv-metal/src-native/android/mmkv-metal/src/androidTest/java/org/nativescript/plugins/mmkv_metal/ExampleInstrumentedTest.kt
new file mode 100644
index 00000000..69a0369b
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/mmkv-metal/src/androidTest/java/org/nativescript/plugins/mmkv_metal/ExampleInstrumentedTest.kt
@@ -0,0 +1,24 @@
+package org.nativescript.plugins.mmkv_metal
+
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.ext.junit.runners.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+ @Test
+ fun useAppContext() {
+ // Context of the app under test.
+ val appContext = InstrumentationRegistry.getInstrumentation().targetContext
+ assertEquals("org.nativescript.plugins.mmkv_metal.test", appContext.packageName)
+ }
+}
diff --git a/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/AndroidManifest.xml b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..741e8eaf
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/AndroidManifest.xml
@@ -0,0 +1,5 @@
+
+
+
+
diff --git a/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/Bridge.cpp b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/Bridge.cpp
new file mode 100644
index 00000000..8d506210
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/Bridge.cpp
@@ -0,0 +1,23 @@
+//
+// Created by Osei Fortune on 10/06/2022.
+//
+
+#include "MMKVImpl.h"
+
+extern "C" void NSMain(const v8::FunctionCallbackInfo& args){
+ auto isolate = args.GetIsolate();
+ v8::Locker locker(isolate);
+ v8::Isolate::Scope isolate_scope(isolate);
+ v8::HandleScope handle_scope(isolate);
+
+ auto len = args.Length();
+
+ if (len != 5) {
+ auto errMsg = v8::String::NewFromUtf8(isolate, "Wrong number of arguments (expected 5)");
+ auto err = v8::Exception::Error(errMsg.ToLocalChecked());
+ isolate->ThrowException(err);
+ return;
+ }
+
+ MMKVImpl::Init(isolate);
+}
diff --git a/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/Caches.cpp b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/Caches.cpp
new file mode 100644
index 00000000..c894408a
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/Caches.cpp
@@ -0,0 +1,35 @@
+//
+// Created by Osei Fortune on 10/06/2022.
+//
+
+#include "Caches.h"
+
+std::shared_ptr >>
+Caches::perIsolateCaches_ = std::make_shared < ConcurrentMap>
+>();
+
+Caches::Caches(v8::Isolate *isolate) : isolate_(isolate) {}
+
+Caches::~Caches() {}
+
+std::shared_ptr Caches::Get(v8::Isolate *isolate) {
+ std::shared_ptr cache = Caches::perIsolateCaches_->Get(isolate);
+ if (cache == nullptr) {
+ cache = std::make_shared(isolate);
+ Caches::perIsolateCaches_->Insert(isolate, cache);
+ }
+
+ return cache;
+}
+
+void Caches::Remove(v8::Isolate *isolate) {
+ Caches::perIsolateCaches_->Remove(isolate);
+}
+
+void Caches::SetContext(v8::Local context) {
+ this->context_ = std::make_shared>(this->isolate_, context);
+}
+
+v8::Local Caches::GetContext() {
+ return this->context_->Get(this->isolate_);
+}
\ No newline at end of file
diff --git a/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/Caches.h b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/Caches.h
new file mode 100644
index 00000000..e4b8e649
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/Caches.h
@@ -0,0 +1,33 @@
+//
+// Created by Osei Fortune on 10/06/2022.
+//
+
+#pragma once
+
+#include "Common.h"
+#include "ConcurrentMap.h"
+
+class Caches {
+public:
+ Caches(v8::Isolate *isolate);
+
+ ~Caches();
+
+ static std::shared_ptr Get(v8::Isolate *isolate);
+
+ static void Remove(v8::Isolate *isolate);
+
+ void SetContext(v8::Local context);
+
+ v8::Local GetContext();
+
+
+ std::unique_ptr > MMKVTmpl = std::unique_ptr>(
+ nullptr);
+private:
+ static std::shared_ptr >>
+ perIsolateCaches_;
+ v8::Isolate *isolate_;
+ std::shared_ptr > context_;
+};
diff --git a/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/Common.h b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/Common.h
new file mode 100644
index 00000000..2de10c55
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/Common.h
@@ -0,0 +1,8 @@
+//
+// Created by Osei Fortune on 10/06/2022.
+//
+
+#pragma once
+#include
+#include "include/v8.h"
+#include
diff --git a/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/ConcurrentMap.h b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/ConcurrentMap.h
new file mode 100644
index 00000000..565b8a5d
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/ConcurrentMap.h
@@ -0,0 +1,54 @@
+//
+// Created by Osei Fortune on 10/06/2022.
+//
+
+#pragma once
+
+#include
+#include "include/robin_hood.h"
+template
+class ConcurrentMap {
+public:
+ void Insert(TKey &key, TValue value) {
+ std::lock_guard writerLock(this->containerMutex_);
+ this->container_[key] = value;
+ }
+
+ TValue Get(TKey &key) {
+ bool found;
+ return this->Get(key, found);
+ }
+
+ TValue Get(TKey &key, bool &found) {
+// std::shared_lock readerLock(this->containerMutex_);
+ std::lock_guard writerLock(this->containerMutex_);
+ auto it = this->container_.find(key);
+ found = it != this->container_.end();
+ if (found) {
+ return it->second;
+ }
+ return nullptr;
+ }
+
+ bool ContainsKey(TKey &key) {
+// std::shared_lock readerLock(this->containerMutex_);
+ std::lock_guard writerLock(this->containerMutex_);
+ auto it = this->container_.find(key);
+ return it != this->container_.end();
+ }
+
+ void Remove(TKey &key) {
+ std::lock_guard writerLock(this->containerMutex_);
+ this->container_.erase(key);
+ }
+
+ ConcurrentMap() = default;
+
+ ConcurrentMap(const ConcurrentMap &) = delete;
+
+ ConcurrentMap &operator=(const ConcurrentMap &) = delete;
+
+private:
+ std::mutex containerMutex_;
+ robin_hood::unordered_map container_;
+};
diff --git a/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/Helpers.cpp b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/Helpers.cpp
new file mode 100644
index 00000000..fd2b6048
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/Helpers.cpp
@@ -0,0 +1,99 @@
+//
+// Created by Osei Fortune on 10/06/2022.
+//
+
+#include "Helpers.h"
+
+const char *Helpers::LOG_TAG = "JS";
+int Helpers::m_maxLogcatObjectSize = 4096;
+
+
+void Helpers::sendToADBLogcat(const std::string &message, android_LogPriority logPriority) {
+ // limit the size of the message that we send to logcat using the predefined value in package.json
+ auto messageToLog = message;
+ if (messageToLog.length() > m_maxLogcatObjectSize) {
+ messageToLog = messageToLog.erase(m_maxLogcatObjectSize, std::string::npos);
+ messageToLog = messageToLog + "...";
+ }
+
+ // split strings into chunks of 4000 characters
+ // __android_log_write can't send more than 4000 to the stdout at a time
+ auto messageLength = messageToLog.length();
+ int maxStringLength = 4000;
+
+ if (messageLength < maxStringLength) {
+ __android_log_write(logPriority, Helpers::LOG_TAG, messageToLog.c_str());
+ } else {
+ for (int i = 0; i < messageLength; i += maxStringLength) {
+ auto messagePart = messageToLog.substr(i, maxStringLength);
+
+ __android_log_write(logPriority, Helpers::LOG_TAG, messagePart.c_str());
+ }
+ }
+}
+
+void Helpers::LogToConsole(const std::string &message) {
+ sendToADBLogcat(message, android_LogPriority::ANDROID_LOG_INFO);
+}
+
+void Helpers::ThrowIllegalConstructor(v8::Isolate *isolate) {
+ auto msg = ConvertToV8String(isolate, "Illegal constructor");
+ auto err = v8::Exception::TypeError(msg);
+ isolate->ThrowException(err);
+}
+
+v8::Local Helpers::ConvertToV8String(v8::Isolate *isolate, const std::string &string) {
+ return v8::String::NewFromUtf8(isolate, string.c_str()).ToLocalChecked();
+}
+
+std::string Helpers::ConvertFromV8String(v8::Isolate *isolate, const v8::Local value) {
+ if (value.IsEmpty()) {
+ return {};
+ }
+
+ if (value->IsStringObject()) {
+ v8::Local obj = value.As()->ValueOf();
+ return ConvertFromV8String(isolate, obj);
+ }
+
+ if (!value->IsString()) {
+ return {};
+ }
+
+ v8::String::Utf8Value result(isolate, value);
+
+ auto val = *result;
+ if (val == nullptr) {
+ return {};
+ }
+
+ return {val};
+}
+
+void Helpers::SetInternalClassName(v8::Isolate *isolate, v8::Local value,
+ const std::string &clazz) {
+ auto context = isolate->GetCurrentContext();
+ value->SetPrivate(context,
+ v8::Private::New(isolate, Helpers::ConvertToV8String(isolate, "class_name")),
+ Helpers::ConvertToV8String(isolate, clazz));
+}
+
+void
+Helpers::SetPrivate(v8::Isolate *isolate, v8::Local object, const std::string &property,
+ v8::Local value) {
+ auto context = isolate->GetCurrentContext();
+ auto key = v8::Private::ForApi(isolate, Helpers::ConvertToV8String(isolate, property));
+ object->SetPrivate(context, key, value);
+}
+
+v8::Local Helpers::GetPrivate(v8::Isolate *isolate, v8::Local object,
+ const std::string &property) {
+ auto context = isolate->GetCurrentContext();
+ auto key = v8::Private::ForApi(isolate, Helpers::ConvertToV8String(isolate, property));
+ auto value = object->GetPrivate(context, key);
+ if (value.IsEmpty()) {
+ return v8::Undefined(isolate);
+ } else {
+ return value.ToLocalChecked();
+ }
+}
diff --git a/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/Helpers.h b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/Helpers.h
new file mode 100644
index 00000000..8eff1444
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/Helpers.h
@@ -0,0 +1,31 @@
+//
+// Created by Osei Fortune on 10/06/2022.
+//
+
+#pragma once
+
+#include "Common.h"
+
+class Helpers {
+public:
+ static const char* LOG_TAG;
+
+ static int m_maxLogcatObjectSize;
+
+ static void sendToADBLogcat(const std::string& message, android_LogPriority logPriority);
+
+ static void LogToConsole(const std::string &message);
+
+ static void ThrowIllegalConstructor(v8::Isolate *isolate);
+
+ static v8::Local ConvertToV8String(v8::Isolate *isolate, const std::string &string);
+
+ static std::string ConvertFromV8String(v8::Isolate *isolate, const v8::Local value);
+
+ static void SetInternalClassName(v8::Isolate *isolate, v8::Local value, const std::string& clazz);
+
+ static void
+ SetPrivate(v8::Isolate *isolate, v8::Local object, const std::string& property, v8::Local value);
+
+ static v8::Local GetPrivate(v8::Isolate *isolate, v8::Local object, const std::string& property);
+};
diff --git a/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/MMKVImpl.cpp b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/MMKVImpl.cpp
new file mode 100644
index 00000000..ee0c080b
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/MMKVImpl.cpp
@@ -0,0 +1,519 @@
+//
+// Created by Osei Fortune on 10/06/2022.
+//
+
+#include "MMKVImpl.h"
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+using namespace mmkv;
+using namespace std;
+
+MMKVImpl::MMKVImpl(MMKV *mmkv) : mmkv_(mmkv) {}
+
+void MMKVImpl::Init(v8::Isolate *isolate) {
+ v8::Locker locker(isolate);
+ v8::Isolate::Scope isolate_scope(isolate);
+ v8::HandleScope handle_scope(isolate);
+ auto ctor = GetCtor(isolate);
+ auto context = isolate->GetCurrentContext();
+ auto global = context->Global();
+ auto func = ctor->GetFunction(context).ToLocalChecked();
+ auto initialize = v8::FunctionTemplate::New(isolate, &Initialize);
+ func->Set(context, Helpers::ConvertToV8String(isolate, "initialize"),
+ initialize->GetFunction(context).ToLocalChecked());
+ global->Set(context, Helpers::ConvertToV8String(isolate, "NSCMMKV"), func);
+}
+
+MMKVImpl *MMKVImpl::GetPointer(const v8::Local &object) {
+ if (object->InternalFieldCount() > 0) {
+ auto ptr = object->GetInternalField(0).As();
+ if (ptr.IsEmpty()) {
+ return nullptr;
+ }
+ return static_cast(ptr->Value());
+ }
+ return nullptr;
+}
+
+v8::Local MMKVImpl::GetCtor(v8::Isolate *isolate) {
+ auto cache = Caches::Get(isolate);
+ auto ctor = cache->MMKVTmpl.get();
+ if (ctor != nullptr) {
+ return ctor->Get(isolate);
+ }
+
+ v8::Local ctorTmpl = v8::FunctionTemplate::New(isolate, &Create);
+ ctorTmpl->SetClassName(Helpers::ConvertToV8String(isolate, "NSCMMKV"));
+ ctorTmpl->InstanceTemplate()->SetInternalFieldCount(1);
+ auto tmpl = ctorTmpl->PrototypeTemplate();
+
+ tmpl->SetAccessor(
+ Helpers::ConvertToV8String(isolate, "keys"),
+ &Keys
+ );
+
+ tmpl->SetAccessor(
+ Helpers::ConvertToV8String(isolate, "totalSize"),
+ &TotalSize
+ );
+
+ tmpl->SetAccessor(
+ Helpers::ConvertToV8String(isolate, "actualSize"),
+ &ActualSize
+ );
+
+ tmpl->Set(
+ Helpers::ConvertToV8String(isolate, "contains"),
+ v8::FunctionTemplate::New(isolate, &Contains)
+ );
+ tmpl->Set(
+ Helpers::ConvertToV8String(isolate, "count"),
+ v8::FunctionTemplate::New(isolate, &Count)
+ );
+ tmpl->Set(
+ Helpers::ConvertToV8String(isolate, "close"),
+ v8::FunctionTemplate::New(isolate, &Close)
+ );
+ tmpl->Set(
+ Helpers::ConvertToV8String(isolate, "clearAll"),
+ v8::FunctionTemplate::New(isolate, &ClearAll)
+ );
+
+ tmpl->Set(
+ Helpers::ConvertToV8String(isolate, "clearMemoryCache"),
+ v8::FunctionTemplate::New(isolate, &ClearMemoryCache)
+ );
+
+ tmpl->Set(
+ Helpers::ConvertToV8String(isolate, "set"),
+ v8::FunctionTemplate::New(isolate, &Set)
+ );
+ tmpl->Set(
+ Helpers::ConvertToV8String(isolate, "getBoolean"),
+ v8::FunctionTemplate::New(isolate, &GetBoolean)
+ );
+ tmpl->Set(
+ Helpers::ConvertToV8String(isolate, "getString"),
+ v8::FunctionTemplate::New(isolate, &GetString)
+ );
+ tmpl->Set(
+ Helpers::ConvertToV8String(isolate, "getNumber"),
+ v8::FunctionTemplate::New(isolate, &GetNumber)
+ );
+ tmpl->Set(
+ Helpers::ConvertToV8String(isolate, "getBytes"),
+ v8::FunctionTemplate::New(isolate, &GetBytes)
+ );
+ tmpl->Set(
+ Helpers::ConvertToV8String(isolate, "delete"),
+ v8::FunctionTemplate::New(isolate, &Delete)
+ );
+
+ tmpl->Set(
+ Helpers::ConvertToV8String(isolate, "key"),
+ v8::FunctionTemplate::New(isolate, &Key)
+ );
+
+ tmpl->Set(
+ Helpers::ConvertToV8String(isolate, "recrypt"),
+ v8::FunctionTemplate::New(isolate, &Recrypt)
+ );
+
+ tmpl->Set(
+ Helpers::ConvertToV8String(isolate, "getAllKeys"),
+ v8::FunctionTemplate::New(isolate, &GetAllKeys)
+ );
+ cache->MMKVTmpl =
+ std::make_unique>(isolate, ctorTmpl);
+ return ctorTmpl;
+}
+
+void MMKVImpl::Keys(v8::Local name, const v8::PropertyCallbackInfo &info) {
+ auto isolate = info.GetIsolate();
+ auto context = isolate->GetCurrentContext();
+ auto ptr = GetPointer(info.This());
+ if (ptr != nullptr) {
+ auto keys = ptr->mmkv_->allKeys();
+ auto array = v8::Array::New(isolate, keys.size());
+ for (int i = 0; i < keys.size(); i++) {
+ auto key = keys[i];
+ array->Set(context, i, Helpers::ConvertToV8String(isolate, key));
+ }
+ info.GetReturnValue().Set(array);
+ return;
+ }
+ info.GetReturnValue().Set(
+ v8::Array::New(isolate)
+ );
+}
+
+void
+MMKVImpl::TotalSize(v8::Local name, const v8::PropertyCallbackInfo &info) {
+ auto ptr = GetPointer(info.This());
+ if (ptr != nullptr) {
+ info.GetReturnValue().Set((double) ptr->mmkv_->totalSize());
+ return;
+ }
+ info.GetReturnValue().Set(0);
+}
+
+void
+MMKVImpl::ActualSize(v8::Local name, const v8::PropertyCallbackInfo &info) {
+ auto ptr = GetPointer(info.This());
+ if (ptr != nullptr) {
+ info.GetReturnValue().Set((double) ptr->mmkv_->actualSize());
+ return;
+ }
+ info.GetReturnValue().Set(0);
+}
+
+void MMKVImpl::Initialize(const v8::FunctionCallbackInfo &args) {
+ v8::Isolate *isolate = args.GetIsolate();
+ auto path = Helpers::ConvertFromV8String(isolate, args[0]);
+ MMKV::initializeMMKV(path);
+}
+
+void MMKVImpl::Create(const v8::FunctionCallbackInfo &args) {
+ v8::Isolate *isolate = args.GetIsolate();
+ auto context = isolate->GetCurrentContext();
+
+ MMKV *val = nullptr;
+ v8::Local ret = args.This();
+
+ Helpers::SetInternalClassName(isolate, ret, "NSCMMKV");
+
+ if (args.Length() == 1) {
+ auto opts = args[0];
+ if (opts->IsObject()) {
+ auto options = opts->ToObject(context).ToLocalChecked();
+ auto id = options->Get(context, Helpers::ConvertToV8String(isolate, "id"));
+ auto path = options->Get(context, Helpers::ConvertToV8String(isolate, "path"));
+ auto encryptionKey = options->Get(context,
+ Helpers::ConvertToV8String(isolate, "encryptionKey"));
+ auto mode = options->Get(context, Helpers::ConvertToV8String(isolate, "mode"));
+
+
+ if (!id.IsEmpty() && !encryptionKey.IsEmpty() && !path.IsEmpty()) {
+ auto key = Helpers::ConvertFromV8String(isolate, encryptionKey.ToLocalChecked());
+ auto localPath = Helpers::ConvertFromV8String(isolate, path.ToLocalChecked());
+ val = MMKV::mmkvWithID(
+ Helpers::ConvertFromV8String(isolate, id.ToLocalChecked()),
+ mmkv::DEFAULT_MMAP_SIZE, MMKV_SINGLE_PROCESS,
+ &key,
+ &localPath
+ );
+ } else if (!id.IsEmpty() && !encryptionKey.IsEmpty() && !mode.IsEmpty()) {
+ auto key = Helpers::ConvertFromV8String(isolate, encryptionKey.ToLocalChecked());
+ auto realMode = Helpers::ConvertFromV8String(isolate, mode.ToLocalChecked());
+ val = MMKV::mmkvWithID(
+ Helpers::ConvertFromV8String(isolate, id.ToLocalChecked()),
+ mmkv::DEFAULT_MMAP_SIZE,
+ std::strcmp(realMode.c_str(), "MULTI") ? MMKV_MULTI_PROCESS
+ : MMKV_SINGLE_PROCESS,
+ &key,
+ nullptr
+ );
+
+ } else if (!id.IsEmpty() && !encryptionKey.IsEmpty() && path.IsEmpty() &&
+ mode.IsEmpty()) {
+ auto key = Helpers::ConvertFromV8String(isolate, encryptionKey.ToLocalChecked());
+ val = MMKV::mmkvWithID(
+ Helpers::ConvertFromV8String(isolate, id.ToLocalChecked()),
+ mmkv::DEFAULT_MMAP_SIZE,
+ MMKV_SINGLE_PROCESS,
+ &key,
+ nullptr
+ );
+
+
+ } else if (!id.IsEmpty() && encryptionKey.IsEmpty() && !path.IsEmpty() &&
+ mode.IsEmpty()) {
+ auto localPath = Helpers::ConvertFromV8String(isolate, path.ToLocalChecked());
+ val = MMKV::mmkvWithID(
+ Helpers::ConvertFromV8String(isolate, id.ToLocalChecked()),
+ mmkv::DEFAULT_MMAP_SIZE, MMKV_SINGLE_PROCESS,
+ nullptr,
+ &localPath
+ );
+
+ } else if (!id.IsEmpty() && encryptionKey.IsEmpty() && !mode.IsEmpty() &&
+ path.IsEmpty()) {
+ auto realMode = Helpers::ConvertFromV8String(isolate, mode.ToLocalChecked());
+ val = MMKV::mmkvWithID(
+ Helpers::ConvertFromV8String(isolate, id.ToLocalChecked()),
+ mmkv::DEFAULT_MMAP_SIZE,
+ std::strcmp(realMode.c_str(), "MULTI") ? MMKV_MULTI_PROCESS
+ : MMKV_SINGLE_PROCESS,
+ nullptr,
+ nullptr
+ );
+
+ } else if (!id.IsEmpty() && encryptionKey.IsEmpty() && path.IsEmpty() &&
+ mode.IsEmpty()) {
+ val = MMKV::mmkvWithID(
+ Helpers::ConvertFromV8String(isolate, id.ToLocalChecked()),
+ mmkv::DEFAULT_MMAP_SIZE,
+ MMKV_SINGLE_PROCESS,
+ nullptr,
+ nullptr
+ );
+ } else if (!id.IsEmpty() && !encryptionKey.IsEmpty() && path.IsEmpty() &&
+ mode.IsEmpty()) {
+ auto key = Helpers::ConvertFromV8String(isolate, encryptionKey.ToLocalChecked());
+ val = MMKV::defaultMMKV(MMKV_SINGLE_PROCESS, &key);
+ }
+
+ }
+ }
+
+ if (val == nullptr) {
+ val = MMKV::defaultMMKV();
+ }
+
+ MMKVImpl *impl = new MMKVImpl(val);
+
+ auto ext = v8::External::New(isolate, impl);
+
+ ret->SetInternalField(0, ext);
+
+ args.GetReturnValue().Set(ret);
+}
+
+void MMKVImpl::Contains(const v8::FunctionCallbackInfo &args) {
+ auto isolate = args.GetIsolate();
+ auto ptr = GetPointer(args.This());
+ if (ptr != nullptr) {
+ auto key = Helpers::ConvertFromV8String(isolate, args[0]);
+ args.GetReturnValue().Set(ptr->mmkv_->containsKey(key));
+ return;
+ }
+ args.GetReturnValue().Set(false);
+}
+
+void MMKVImpl::Close(const v8::FunctionCallbackInfo &args) {
+ auto ptr = GetPointer(args.This());
+ if (ptr != nullptr) {
+ ptr->mmkv_->close();
+ }
+}
+
+void MMKVImpl::ClearAll(const v8::FunctionCallbackInfo &args) {
+ auto ptr = GetPointer(args.This());
+ if (ptr != nullptr) {
+ ptr->mmkv_->clearAll();
+ }
+}
+
+void MMKVImpl::ClearMemoryCache(const v8::FunctionCallbackInfo &args) {
+ auto ptr = GetPointer(args.This());
+ if (ptr != nullptr) {
+ ptr->mmkv_->clearMemoryCache();
+ }
+}
+
+void MMKVImpl::Count(const v8::FunctionCallbackInfo &args) {
+ auto ptr = GetPointer(args.This());
+ double count = 0;
+ if (ptr != nullptr) {
+ count = (double) ptr->mmkv_->count();
+ }
+ args.GetReturnValue().Set(count);
+}
+
+void MMKVImpl::Set(const v8::FunctionCallbackInfo &args) {
+ auto isolate = args.GetIsolate();
+ auto context = isolate->GetCurrentContext();
+ auto ptr = GetPointer(args.This());
+ if (ptr != nullptr && args.Length() == 2) {
+ auto key = Helpers::ConvertFromV8String(isolate, args[0]);
+ auto value = args[1];
+ if (value->IsBoolean()) {
+ ptr->mmkv_->set(value->BooleanValue(isolate), key);
+ } else if (value->IsString()) {
+ auto val = Helpers::ConvertFromV8String(isolate, value);
+ ptr->mmkv_->set(
+ val,
+ key
+ );
+ } else if (value->IsNumber()) {
+ ptr->mmkv_->set(
+ value->NumberValue(context).ToChecked(),
+ key
+ );
+ } else if (value->IsTypedArray()) {
+ auto array = value.As();
+ auto buffer = array->Buffer();
+ auto store = buffer->GetBackingStore();
+ auto data = static_cast(store->Data()) + array->ByteOffset();
+ auto len = array->Length();
+ ptr->mmkv_->set(
+ mmkv::MMBuffer(data, len),
+ key
+ );
+ }
+ }
+}
+
+void MMKVImpl::GetBoolean(const v8::FunctionCallbackInfo &args) {
+ auto isolate = args.GetIsolate();
+ auto ptr = GetPointer(args.This());
+ if (ptr != nullptr) {
+ auto key = Helpers::ConvertFromV8String(isolate, args[0]);
+ bool hasValue;
+ auto ret = ptr->mmkv_->getBool(key, false, &hasValue);
+ if (hasValue) {
+ args.GetReturnValue().Set(ret);
+ }
+ return;
+ }
+ args.GetReturnValue().SetNull();
+}
+
+void MMKVImpl::GetString(const v8::FunctionCallbackInfo &args) {
+ auto isolate = args.GetIsolate();
+ auto ptr = GetPointer(args.This());
+ if (ptr != nullptr) {
+ auto key = Helpers::ConvertFromV8String(isolate, args[0]);
+ std::string buf;
+ ptr->mmkv_->getString(key, buf);
+ args.GetReturnValue().Set(
+ Helpers::ConvertToV8String(isolate, buf)
+ );
+ return;
+ }
+ args.GetReturnValue().SetNull();
+}
+
+void MMKVImpl::GetNumber(const v8::FunctionCallbackInfo &args) {
+ auto isolate = args.GetIsolate();
+ auto ptr = GetPointer(args.This());
+ if (ptr != nullptr) {
+ auto key = Helpers::ConvertFromV8String(isolate, args[0]);
+
+ bool hasValue;
+ auto ret = ptr->mmkv_->getDouble(key, 0, &hasValue);
+
+ if (hasValue) {
+ args.GetReturnValue().Set(ret);
+ return;
+ }
+ }
+ args.GetReturnValue().SetNull();
+}
+
+void MMKVImpl::GetBytes(const v8::FunctionCallbackInfo &args) {
+ auto isolate = args.GetIsolate();
+ auto ptr = GetPointer(args.This());
+ if (ptr != nullptr) {
+ auto key = Helpers::ConvertFromV8String(isolate, args[0]);
+
+ if (ptr->mmkv_->containsKey(key)) {
+ auto ret = ptr->mmkv_->getBytes(key);
+ void *data = malloc(ret.length());
+ std::memcpy(&data, ret.getPtr(), 1);
+ auto store = v8::ArrayBuffer::NewBackingStore(data, ret.length(),
+ [](void *data, size_t length,
+ void *deleter_data) {
+ if (data != nullptr) {
+ free(data);
+ }
+ }, nullptr);
+ args.GetReturnValue().Set(
+ v8::ArrayBuffer::New(isolate, std::move(store))
+ );
+ return;
+ }
+ }
+ args.GetReturnValue().SetNull();
+}
+
+void MMKVImpl::Delete(const v8::FunctionCallbackInfo &args) {
+ auto isolate = args.GetIsolate();
+ auto context = isolate->GetCurrentContext();
+ auto ptr = GetPointer(args.This());
+ if (ptr != nullptr) {
+ auto keyValue = args[0];
+ if (keyValue->IsArray()) {
+ auto keys = keyValue.As();
+ auto size = keys->Length();
+ if (size == 0) {
+ return;
+ }
+ std::vector keysToRemove;
+ keysToRemove.reserve(size);
+ for (int i = 0; i < size; i++) {
+ auto item = keys->Get(context, i).ToLocalChecked();
+ keysToRemove.emplace_back(Helpers::ConvertFromV8String(isolate, item));
+ }
+ ptr->mmkv_->removeValuesForKeys(keysToRemove);
+ } else {
+ auto key = Helpers::ConvertFromV8String(isolate, args[0]);
+ ptr->mmkv_->removeValueForKey(key);
+ }
+ }
+}
+
+
+void MMKVImpl::Key(const v8::FunctionCallbackInfo &args) {
+ auto isolate = args.GetIsolate();
+ auto context = isolate->GetCurrentContext();
+ auto ptr = GetPointer(args.This());
+ if (ptr != nullptr) {
+ auto idVal = args[0];
+ auto id = -1;
+ if (idVal->IsNumber() || idVal->IsNumberObject()) {
+ id = idVal->IntegerValue(context).FromMaybe(-1);
+ }
+ if (id > -1) {
+ auto keys = ptr->mmkv_->allKeys();
+ if (keys.size() > id) {
+ auto keyValue = keys[id];
+ args.GetReturnValue().Set(
+ Helpers::ConvertToV8String(isolate, keyValue)
+ );
+ return;
+ }
+ }
+ }
+ args.GetReturnValue().SetUndefined();
+}
+
+void MMKVImpl::Recrypt(const v8::FunctionCallbackInfo &args) {
+ auto isolate = args.GetIsolate();
+ auto ptr = GetPointer(args.This());
+ if (ptr != nullptr) {
+ auto keyVal = args[0];
+ if (keyVal->IsNullOrUndefined()) {
+ ptr->mmkv_->reKey({});
+ } else {
+ auto key = Helpers::ConvertFromV8String(isolate, keyVal);
+ ptr->mmkv_->reKey(key);
+ }
+ }
+}
+
+
+void MMKVImpl::GetAllKeys(const v8::FunctionCallbackInfo &args) {
+ auto isolate = args.GetIsolate();
+ auto context = isolate->GetCurrentContext();
+ auto ptr = GetPointer(args.This());
+ if (ptr != nullptr) {
+ auto keys = ptr->mmkv_->allKeys();
+ auto array = v8::Array::New(isolate, keys.size());
+ for (int i = 0; i < keys.size(); i++) {
+ auto key = keys[i];
+ array->Set(context, i, Helpers::ConvertToV8String(isolate, key));
+ }
+ args.GetReturnValue().Set(array);
+ return;
+ }
+ args.GetReturnValue().Set(
+ v8::Array::New(isolate)
+ );
+}
diff --git a/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/MMKVImpl.h b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/MMKVImpl.h
new file mode 100644
index 00000000..98da3bf2
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/MMKVImpl.h
@@ -0,0 +1,67 @@
+//
+// Created by Osei Fortune on 10/06/2022.
+//
+
+#ifndef MMKV_CORE_MMKVIMPL_H
+#define MMKV_CORE_MMKVIMPL_H
+
+#include "Common.h"
+#include "Caches.h"
+#include "Helpers.h"
+#include "MMKV.h"
+
+class MMKVImpl {
+public:
+ MMKVImpl(MMKV* mmkv);
+
+ static void Init(v8::Isolate *isolate);
+
+ static MMKVImpl *GetPointer(const v8::Local& object);
+
+ static v8::Local GetCtor(v8::Isolate *isolate);
+
+ static void Initialize(const v8::FunctionCallbackInfo &args);
+
+ static void Create(const v8::FunctionCallbackInfo &args);
+
+ static void Contains(const v8::FunctionCallbackInfo &args);
+
+ static void Close(const v8::FunctionCallbackInfo &args);
+
+ static void ClearAll(const v8::FunctionCallbackInfo &args);
+
+ static void ClearMemoryCache(const v8::FunctionCallbackInfo &args);
+
+ static void Count(const v8::FunctionCallbackInfo &args);
+
+ static void Set(const v8::FunctionCallbackInfo &args);
+
+ static void GetBoolean(const v8::FunctionCallbackInfo &args);
+
+ static void GetString(const v8::FunctionCallbackInfo &args);
+
+ static void GetNumber(const v8::FunctionCallbackInfo &args);
+
+ static void GetBytes(const v8::FunctionCallbackInfo &args);
+
+ static void Delete(const v8::FunctionCallbackInfo &args);
+
+ static void Key(const v8::FunctionCallbackInfo &args);
+
+ static void Recrypt(const v8::FunctionCallbackInfo &args);
+
+ static void GetAllKeys(const v8::FunctionCallbackInfo &args);
+
+ static void Keys(v8::Local name, const v8::PropertyCallbackInfo &info);
+
+ static void TotalSize(v8::Local name, const v8::PropertyCallbackInfo &info);
+
+ static void ActualSize(v8::Local name, const v8::PropertyCallbackInfo &info);
+
+private:
+ MMKV* mmkv_;
+
+};
+
+
+#endif //MMKV_CORE_MMKVIMPL_H
diff --git a/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/include/V8NativeScriptExtension.h b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/include/V8NativeScriptExtension.h
new file mode 100644
index 00000000..d87e731a
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/include/V8NativeScriptExtension.h
@@ -0,0 +1,22 @@
+#include
+#include "v8.h"
+
+namespace v8 {
+
+ class NativeScriptExtension {
+ public:
+ static unsigned long GetAddress(const v8::Local& obj);
+
+ static v8::Local* GetClosureObjects(v8::Isolate* isolate, const v8::Local& func, int* length);
+
+ static void ReleaseClosureObjects(v8::Local* closureObjects);
+
+ static void GetAssessorPair(v8::Isolate* isolate, const v8::Local& obj, const v8::Local& propName, v8::Local& getter, v8::Local& setter);
+
+ static std::vector> GetPropertyKeys(v8::Isolate* isolate, const v8::Local& object);
+
+ static void CpuFeaturesProbe(bool cross_compile);
+ private:
+ NativeScriptExtension();
+ };
+}
diff --git a/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/include/inspector/Debugger.h b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/include/inspector/Debugger.h
new file mode 100644
index 00000000..6b8c6afe
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/include/inspector/Debugger.h
@@ -0,0 +1,58 @@
+// This file is generated by Exported_h.template.
+
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef v8_inspector_protocol_Debugger_api_h
+#define v8_inspector_protocol_Debugger_api_h
+
+#include "v8-inspector.h"
+
+namespace v8_inspector {
+namespace protocol {
+
+#ifndef v8_inspector_protocol_exported_api_h
+#define v8_inspector_protocol_exported_api_h
+class V8_EXPORT Exported {
+public:
+ virtual void AppendSerialized(std::vector* out) const = 0;
+
+ virtual ~Exported() { }
+};
+#endif // !defined(v8_inspector_protocol_exported_api_h)
+
+namespace Debugger {
+namespace API {
+
+// ------------- Enums.
+
+namespace Paused {
+namespace ReasonEnum {
+V8_EXPORT extern const char* Ambiguous;
+V8_EXPORT extern const char* Assert;
+V8_EXPORT extern const char* DebugCommand;
+V8_EXPORT extern const char* DOM;
+V8_EXPORT extern const char* EventListener;
+V8_EXPORT extern const char* Exception;
+V8_EXPORT extern const char* Instrumentation;
+V8_EXPORT extern const char* OOM;
+V8_EXPORT extern const char* Other;
+V8_EXPORT extern const char* PromiseRejection;
+V8_EXPORT extern const char* XHR;
+} // ReasonEnum
+} // Paused
+
+// ------------- Types.
+
+class V8_EXPORT SearchMatch : public Exported {
+public:
+ static std::unique_ptr fromBinary(const uint8_t* data, size_t length);
+};
+
+} // namespace API
+} // namespace Debugger
+} // namespace v8_inspector
+} // namespace protocol
+
+#endif // !defined(v8_inspector_protocol_Debugger_api_h)
diff --git a/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/include/inspector/Runtime.h b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/include/inspector/Runtime.h
new file mode 100644
index 00000000..f9d515ba
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/include/inspector/Runtime.h
@@ -0,0 +1,52 @@
+// This file is generated by Exported_h.template.
+
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef v8_inspector_protocol_Runtime_api_h
+#define v8_inspector_protocol_Runtime_api_h
+
+#include "v8-inspector.h"
+
+namespace v8_inspector {
+namespace protocol {
+
+#ifndef v8_inspector_protocol_exported_api_h
+#define v8_inspector_protocol_exported_api_h
+class V8_EXPORT Exported {
+public:
+ virtual void AppendSerialized(std::vector* out) const = 0;
+
+ virtual ~Exported() { }
+};
+#endif // !defined(v8_inspector_protocol_exported_api_h)
+
+namespace Runtime {
+namespace API {
+
+// ------------- Enums.
+
+// ------------- Types.
+
+class V8_EXPORT RemoteObject : public Exported {
+public:
+ static std::unique_ptr fromBinary(const uint8_t* data, size_t length);
+};
+
+class V8_EXPORT StackTrace : public Exported {
+public:
+ static std::unique_ptr fromBinary(const uint8_t* data, size_t length);
+};
+
+class V8_EXPORT StackTraceId : public Exported {
+public:
+ static std::unique_ptr fromBinary(const uint8_t* data, size_t length);
+};
+
+} // namespace API
+} // namespace Runtime
+} // namespace v8_inspector
+} // namespace protocol
+
+#endif // !defined(v8_inspector_protocol_Runtime_api_h)
diff --git a/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/include/inspector/Schema.h b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/include/inspector/Schema.h
new file mode 100644
index 00000000..03a76fa9
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/include/inspector/Schema.h
@@ -0,0 +1,42 @@
+// This file is generated by Exported_h.template.
+
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef v8_inspector_protocol_Schema_api_h
+#define v8_inspector_protocol_Schema_api_h
+
+#include "v8-inspector.h"
+
+namespace v8_inspector {
+namespace protocol {
+
+#ifndef v8_inspector_protocol_exported_api_h
+#define v8_inspector_protocol_exported_api_h
+class V8_EXPORT Exported {
+public:
+ virtual void AppendSerialized(std::vector* out) const = 0;
+
+ virtual ~Exported() { }
+};
+#endif // !defined(v8_inspector_protocol_exported_api_h)
+
+namespace Schema {
+namespace API {
+
+// ------------- Enums.
+
+// ------------- Types.
+
+class V8_EXPORT Domain : public Exported {
+public:
+ static std::unique_ptr fromBinary(const uint8_t* data, size_t length);
+};
+
+} // namespace API
+} // namespace Schema
+} // namespace v8_inspector
+} // namespace protocol
+
+#endif // !defined(v8_inspector_protocol_Schema_api_h)
diff --git a/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/include/libc++/CMakeLists.txt b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/include/libc++/CMakeLists.txt
new file mode 100644
index 00000000..302da8a1
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/include/libc++/CMakeLists.txt
@@ -0,0 +1,274 @@
+set(files
+ __bit_reference
+ __bsd_locale_defaults.h
+ __bsd_locale_fallbacks.h
+ __errc
+ __debug
+ __functional_03
+ __functional_base
+ __functional_base_03
+ __hash_table
+ __libcpp_version
+ __locale
+ __mutex_base
+ __node_handle
+ __nullptr
+ __split_buffer
+ __sso_allocator
+ __std_stream
+ __string
+ __threading_support
+ __tree
+ __tuple
+ __undef_macros
+ algorithm
+ any
+ array
+ atomic
+ bit
+ bitset
+ cassert
+ ccomplex
+ cctype
+ cerrno
+ cfenv
+ cfloat
+ charconv
+ chrono
+ cinttypes
+ ciso646
+ climits
+ clocale
+ cmath
+ codecvt
+ compare
+ complex
+ complex.h
+ condition_variable
+ csetjmp
+ csignal
+ cstdarg
+ cstdbool
+ cstddef
+ cstdint
+ cstdio
+ cstdlib
+ cstring
+ ctgmath
+ ctime
+ ctype.h
+ cwchar
+ cwctype
+ deque
+ errno.h
+ exception
+ execution
+ experimental/__config
+ experimental/__memory
+ experimental/algorithm
+ experimental/coroutine
+ experimental/deque
+ experimental/filesystem
+ experimental/forward_list
+ experimental/functional
+ experimental/iterator
+ experimental/list
+ experimental/map
+ experimental/memory_resource
+ experimental/propagate_const
+ experimental/regex
+ experimental/set
+ experimental/simd
+ experimental/string
+ experimental/type_traits
+ experimental/unordered_map
+ experimental/unordered_set
+ experimental/utility
+ experimental/vector
+ ext/__hash
+ ext/hash_map
+ ext/hash_set
+ fenv.h
+ filesystem
+ float.h
+ forward_list
+ fstream
+ functional
+ future
+ initializer_list
+ inttypes.h
+ iomanip
+ ios
+ iosfwd
+ iostream
+ istream
+ iterator
+ limits
+ limits.h
+ list
+ locale
+ locale.h
+ map
+ math.h
+ memory
+ module.modulemap
+ mutex
+ new
+ numeric
+ optional
+ ostream
+ queue
+ random
+ ratio
+ regex
+ scoped_allocator
+ set
+ setjmp.h
+ shared_mutex
+ span
+ sstream
+ stack
+ stdbool.h
+ stddef.h
+ stdexcept
+ stdint.h
+ stdio.h
+ stdlib.h
+ streambuf
+ string
+ string.h
+ string_view
+ strstream
+ system_error
+ tgmath.h
+ thread
+ tuple
+ type_traits
+ typeindex
+ typeinfo
+ unordered_map
+ unordered_set
+ utility
+ valarray
+ variant
+ vector
+ version
+ wchar.h
+ wctype.h
+ )
+
+if(LIBCXX_INSTALL_SUPPORT_HEADERS)
+ set(files
+ ${files}
+ support/android/locale_bionic.h
+ support/fuchsia/xlocale.h
+ support/ibm/limits.h
+ support/ibm/locale_mgmt_aix.h
+ support/ibm/support.h
+ support/ibm/xlocale.h
+ support/musl/xlocale.h
+ support/newlib/xlocale.h
+ support/solaris/floatingpoint.h
+ support/solaris/wchar.h
+ support/solaris/xlocale.h
+ support/win32/limits_msvc_win32.h
+ support/win32/locale_win32.h
+ support/xlocale/__nop_locale_mgmt.h
+ support/xlocale/__posix_l_fallback.h
+ support/xlocale/__strtonum_fallback.h
+ )
+endif()
+
+if (LIBCXX_NEEDS_SITE_CONFIG)
+ # Generate a custom __config header. The new header is created
+ # by prepending __config_site to the current __config header.
+ add_custom_command(OUTPUT ${LIBCXX_BINARY_DIR}/__generated_config
+ COMMAND ${PYTHON_EXECUTABLE} ${LIBCXX_SOURCE_DIR}/utils/cat_files.py
+ ${LIBCXX_BINARY_DIR}/__config_site
+ ${LIBCXX_SOURCE_DIR}/include/__config
+ -o ${LIBCXX_BINARY_DIR}/__generated_config
+ DEPENDS ${LIBCXX_SOURCE_DIR}/include/__config
+ ${LIBCXX_BINARY_DIR}/__config_site
+ )
+ # Add a target that executes the generation commands.
+ add_custom_target(cxx-generated-config ALL
+ DEPENDS ${LIBCXX_BINARY_DIR}/__generated_config)
+ set(generated_config_deps cxx-generated-config)
+else()
+ set(files
+ ${files}
+ __config
+ )
+endif()
+
+# In some build configurations (like bootstrapping clang), we need to be able to
+# install the libcxx headers before the CMake configuration for libcxx runs. Making
+# the name of this target configurable allows LLVM/runtimes/CMakeLists.txt to
+# add this subdirectory to the LLVM build to put libcxx's headers in place
+# before libcxx's build configuration is run.
+if (NOT CXX_HEADER_TARGET)
+ set(CXX_HEADER_TARGET cxx-headers)
+endif()
+if(NOT LIBCXX_USING_INSTALLED_LLVM AND LIBCXX_HEADER_DIR)
+ set(output_dir ${LIBCXX_HEADER_DIR}/include/c++/v1)
+
+ set(out_files)
+ foreach(f ${files})
+ set(src ${CMAKE_CURRENT_SOURCE_DIR}/${f})
+ set(dst ${output_dir}/${f})
+ add_custom_command(OUTPUT ${dst}
+ DEPENDS ${src}
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src} ${dst}
+ COMMENT "Copying CXX header ${f}")
+ list(APPEND out_files ${dst})
+ endforeach()
+
+ if (LIBCXX_NEEDS_SITE_CONFIG)
+ # Copy the generated header as __config into build directory.
+ set(src ${LIBCXX_BINARY_DIR}/__generated_config)
+ set(dst ${output_dir}/__config)
+ add_custom_command(OUTPUT ${dst}
+ DEPENDS ${src} ${generated_config_deps}
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src} ${dst}
+ COMMENT "Copying CXX __config")
+ list(APPEND out_files ${dst})
+ endif()
+
+ add_custom_target(${CXX_HEADER_TARGET} ALL DEPENDS ${out_files} ${LIBCXX_CXX_ABI_HEADER_TARGET})
+else()
+ add_custom_target(${CXX_HEADER_TARGET})
+endif()
+set_target_properties(${CXX_HEADER_TARGET} PROPERTIES FOLDER "Misc")
+
+if (LIBCXX_INSTALL_HEADERS)
+ foreach(file ${files})
+ get_filename_component(dir ${file} DIRECTORY)
+ install(FILES ${file}
+ DESTINATION ${LIBCXX_INSTALL_HEADER_PREFIX}include/c++/v1/${dir}
+ COMPONENT ${CXX_HEADER_TARGET}
+ PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
+ )
+ endforeach()
+
+ if (LIBCXX_NEEDS_SITE_CONFIG)
+ # Install the generated header as __config.
+ install(FILES ${LIBCXX_BINARY_DIR}/__generated_config
+ DESTINATION ${LIBCXX_INSTALL_HEADER_PREFIX}include/c++/v1
+ PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
+ RENAME __config
+ COMPONENT ${CXX_HEADER_TARGET})
+ endif()
+
+ if (NOT CMAKE_CONFIGURATION_TYPES)
+ add_custom_target(install-${CXX_HEADER_TARGET}
+ DEPENDS ${CXX_HEADER_TARGET} ${generated_config_deps}
+ COMMAND "${CMAKE_COMMAND}"
+ -DCMAKE_INSTALL_COMPONENT=${CXX_HEADER_TARGET}
+ -P "${CMAKE_BINARY_DIR}/cmake_install.cmake")
+ # Stripping is a no-op for headers
+ add_custom_target(install-${CXX_HEADER_TARGET}-stripped DEPENDS install-${CXX_HEADER_TARGET})
+
+ add_custom_target(install-libcxx-headers DEPENDS install-${CXX_HEADER_TARGET})
+ add_custom_target(install-libcxx-headers-stripped DEPENDS install-${CXX_HEADER_TARGET}-stripped)
+ endif()
+endif()
diff --git a/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/include/libc++/__bit_reference b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/include/libc++/__bit_reference
new file mode 100644
index 00000000..cce74fb5
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/include/libc++/__bit_reference
@@ -0,0 +1,1280 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___BIT_REFERENCE
+#define _LIBCPP___BIT_REFERENCE
+
+#include <__config>
+#include
+#include
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+template class __bit_iterator;
+template class __bit_const_reference;
+
+template
+struct __has_storage_type
+{
+ static const bool value = false;
+};
+
+template ::value>
+class __bit_reference
+{
+ typedef typename _Cp::__storage_type __storage_type;
+ typedef typename _Cp::__storage_pointer __storage_pointer;
+
+ __storage_pointer __seg_;
+ __storage_type __mask_;
+
+ friend typename _Cp::__self;
+
+ friend class __bit_const_reference<_Cp>;
+ friend class __bit_iterator<_Cp, false>;
+public:
+ _LIBCPP_INLINE_VISIBILITY operator bool() const _NOEXCEPT
+ {return static_cast(*__seg_ & __mask_);}
+ _LIBCPP_INLINE_VISIBILITY bool operator ~() const _NOEXCEPT
+ {return !static_cast(*this);}
+
+ _LIBCPP_INLINE_VISIBILITY
+ __bit_reference& operator=(bool __x) _NOEXCEPT
+ {
+ if (__x)
+ *__seg_ |= __mask_;
+ else
+ *__seg_ &= ~__mask_;
+ return *this;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ __bit_reference& operator=(const __bit_reference& __x) _NOEXCEPT
+ {return operator=(static_cast(__x));}
+
+ _LIBCPP_INLINE_VISIBILITY void flip() _NOEXCEPT {*__seg_ ^= __mask_;}
+ _LIBCPP_INLINE_VISIBILITY __bit_iterator<_Cp, false> operator&() const _NOEXCEPT
+ {return __bit_iterator<_Cp, false>(__seg_, static_cast(__libcpp_ctz(__mask_)));}
+private:
+ _LIBCPP_INLINE_VISIBILITY
+ __bit_reference(__storage_pointer __s, __storage_type __m) _NOEXCEPT
+ : __seg_(__s), __mask_(__m) {}
+};
+
+template
+class __bit_reference<_Cp, false>
+{
+};
+
+template
+inline _LIBCPP_INLINE_VISIBILITY
+void
+swap(__bit_reference<_Cp> __x, __bit_reference<_Cp> __y) _NOEXCEPT
+{
+ bool __t = __x;
+ __x = __y;
+ __y = __t;
+}
+
+template
+inline _LIBCPP_INLINE_VISIBILITY
+void
+swap(__bit_reference<_Cp> __x, __bit_reference<_Dp> __y) _NOEXCEPT
+{
+ bool __t = __x;
+ __x = __y;
+ __y = __t;
+}
+
+template
+inline _LIBCPP_INLINE_VISIBILITY
+void
+swap(__bit_reference<_Cp> __x, bool& __y) _NOEXCEPT
+{
+ bool __t = __x;
+ __x = __y;
+ __y = __t;
+}
+
+template
+inline _LIBCPP_INLINE_VISIBILITY
+void
+swap(bool& __x, __bit_reference<_Cp> __y) _NOEXCEPT
+{
+ bool __t = __x;
+ __x = __y;
+ __y = __t;
+}
+
+template
+class __bit_const_reference
+{
+ typedef typename _Cp::__storage_type __storage_type;
+ typedef typename _Cp::__const_storage_pointer __storage_pointer;
+
+ __storage_pointer __seg_;
+ __storage_type __mask_;
+
+ friend typename _Cp::__self;
+ friend class __bit_iterator<_Cp, true>;
+public:
+ _LIBCPP_INLINE_VISIBILITY
+ __bit_const_reference(const __bit_reference<_Cp>& __x) _NOEXCEPT
+ : __seg_(__x.__seg_), __mask_(__x.__mask_) {}
+
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR operator bool() const _NOEXCEPT
+ {return static_cast(*__seg_ & __mask_);}
+
+ _LIBCPP_INLINE_VISIBILITY __bit_iterator<_Cp, true> operator&() const _NOEXCEPT
+ {return __bit_iterator<_Cp, true>(__seg_, static_cast(__libcpp_ctz(__mask_)));}
+private:
+ _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_CONSTEXPR
+ __bit_const_reference(__storage_pointer __s, __storage_type __m) _NOEXCEPT
+ : __seg_(__s), __mask_(__m) {}
+
+ __bit_const_reference& operator=(const __bit_const_reference& __x);
+};
+
+// find
+
+template
+__bit_iterator<_Cp, _IsConst>
+__find_bool_true(__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_type __n)
+{
+ typedef __bit_iterator<_Cp, _IsConst> _It;
+ typedef typename _It::__storage_type __storage_type;
+ static const int __bits_per_word = _It::__bits_per_word;
+ // do first partial word
+ if (__first.__ctz_ != 0)
+ {
+ __storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_);
+ __storage_type __dn = _VSTD::min(__clz_f, __n);
+ __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn));
+ __storage_type __b = *__first.__seg_ & __m;
+ if (__b)
+ return _It(__first.__seg_, static_cast(_VSTD::__libcpp_ctz(__b)));
+ if (__n == __dn)
+ return __first + __n;
+ __n -= __dn;
+ ++__first.__seg_;
+ }
+ // do middle whole words
+ for (; __n >= __bits_per_word; ++__first.__seg_, __n -= __bits_per_word)
+ if (*__first.__seg_)
+ return _It(__first.__seg_, static_cast(_VSTD::__libcpp_ctz(*__first.__seg_)));
+ // do last partial word
+ if (__n > 0)
+ {
+ __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
+ __storage_type __b = *__first.__seg_ & __m;
+ if (__b)
+ return _It(__first.__seg_, static_cast(_VSTD::__libcpp_ctz(__b)));
+ }
+ return _It(__first.__seg_, static_cast(__n));
+}
+
+template
+__bit_iterator<_Cp, _IsConst>
+__find_bool_false(__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_type __n)
+{
+ typedef __bit_iterator<_Cp, _IsConst> _It;
+ typedef typename _It::__storage_type __storage_type;
+ const int __bits_per_word = _It::__bits_per_word;
+ // do first partial word
+ if (__first.__ctz_ != 0)
+ {
+ __storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_);
+ __storage_type __dn = _VSTD::min(__clz_f, __n);
+ __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn));
+ __storage_type __b = ~*__first.__seg_ & __m;
+ if (__b)
+ return _It(__first.__seg_, static_cast(_VSTD::__libcpp_ctz(__b)));
+ if (__n == __dn)
+ return __first + __n;
+ __n -= __dn;
+ ++__first.__seg_;
+ }
+ // do middle whole words
+ for (; __n >= __bits_per_word; ++__first.__seg_, __n -= __bits_per_word)
+ {
+ __storage_type __b = ~*__first.__seg_;
+ if (__b)
+ return _It(__first.__seg_, static_cast(_VSTD::__libcpp_ctz(__b)));
+ }
+ // do last partial word
+ if (__n > 0)
+ {
+ __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
+ __storage_type __b = ~*__first.__seg_ & __m;
+ if (__b)
+ return _It(__first.__seg_, static_cast(_VSTD::__libcpp_ctz(__b)));
+ }
+ return _It(__first.__seg_, static_cast(__n));
+}
+
+template
+inline _LIBCPP_INLINE_VISIBILITY
+__bit_iterator<_Cp, _IsConst>
+find(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, const _Tp& __value_)
+{
+ if (static_cast(__value_))
+ return __find_bool_true(__first, static_cast(__last - __first));
+ return __find_bool_false(__first, static_cast(__last - __first));
+}
+
+// count
+
+template
+typename __bit_iterator<_Cp, _IsConst>::difference_type
+__count_bool_true(__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_type __n)
+{
+ typedef __bit_iterator<_Cp, _IsConst> _It;
+ typedef typename _It::__storage_type __storage_type;
+ typedef typename _It::difference_type difference_type;
+ const int __bits_per_word = _It::__bits_per_word;
+ difference_type __r = 0;
+ // do first partial word
+ if (__first.__ctz_ != 0)
+ {
+ __storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_);
+ __storage_type __dn = _VSTD::min(__clz_f, __n);
+ __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn));
+ __r = _VSTD::__libcpp_popcount(*__first.__seg_ & __m);
+ __n -= __dn;
+ ++__first.__seg_;
+ }
+ // do middle whole words
+ for (; __n >= __bits_per_word; ++__first.__seg_, __n -= __bits_per_word)
+ __r += _VSTD::__libcpp_popcount(*__first.__seg_);
+ // do last partial word
+ if (__n > 0)
+ {
+ __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
+ __r += _VSTD::__libcpp_popcount(*__first.__seg_ & __m);
+ }
+ return __r;
+}
+
+template
+typename __bit_iterator<_Cp, _IsConst>::difference_type
+__count_bool_false(__bit_iterator<_Cp, _IsConst> __first, typename _Cp::size_type __n)
+{
+ typedef __bit_iterator<_Cp, _IsConst> _It;
+ typedef typename _It::__storage_type __storage_type;
+ typedef typename _It::difference_type difference_type;
+ const int __bits_per_word = _It::__bits_per_word;
+ difference_type __r = 0;
+ // do first partial word
+ if (__first.__ctz_ != 0)
+ {
+ __storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_);
+ __storage_type __dn = _VSTD::min(__clz_f, __n);
+ __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn));
+ __r = _VSTD::__libcpp_popcount(~*__first.__seg_ & __m);
+ __n -= __dn;
+ ++__first.__seg_;
+ }
+ // do middle whole words
+ for (; __n >= __bits_per_word; ++__first.__seg_, __n -= __bits_per_word)
+ __r += _VSTD::__libcpp_popcount(~*__first.__seg_);
+ // do last partial word
+ if (__n > 0)
+ {
+ __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
+ __r += _VSTD::__libcpp_popcount(~*__first.__seg_ & __m);
+ }
+ return __r;
+}
+
+template
+inline _LIBCPP_INLINE_VISIBILITY
+typename __bit_iterator<_Cp, _IsConst>::difference_type
+count(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, const _Tp& __value_)
+{
+ if (static_cast(__value_))
+ return __count_bool_true(__first, static_cast(__last - __first));
+ return __count_bool_false(__first, static_cast(__last - __first));
+}
+
+// fill_n
+
+template
+void
+__fill_n_false(__bit_iterator<_Cp, false> __first, typename _Cp::size_type __n)
+{
+ typedef __bit_iterator<_Cp, false> _It;
+ typedef typename _It::__storage_type __storage_type;
+ const int __bits_per_word = _It::__bits_per_word;
+ // do first partial word
+ if (__first.__ctz_ != 0)
+ {
+ __storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_);
+ __storage_type __dn = _VSTD::min(__clz_f, __n);
+ __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn));
+ *__first.__seg_ &= ~__m;
+ __n -= __dn;
+ ++__first.__seg_;
+ }
+ // do middle whole words
+ __storage_type __nw = __n / __bits_per_word;
+ _VSTD::memset(_VSTD::__to_raw_pointer(__first.__seg_), 0, __nw * sizeof(__storage_type));
+ __n -= __nw * __bits_per_word;
+ // do last partial word
+ if (__n > 0)
+ {
+ __first.__seg_ += __nw;
+ __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
+ *__first.__seg_ &= ~__m;
+ }
+}
+
+template
+void
+__fill_n_true(__bit_iterator<_Cp, false> __first, typename _Cp::size_type __n)
+{
+ typedef __bit_iterator<_Cp, false> _It;
+ typedef typename _It::__storage_type __storage_type;
+ const int __bits_per_word = _It::__bits_per_word;
+ // do first partial word
+ if (__first.__ctz_ != 0)
+ {
+ __storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_);
+ __storage_type __dn = _VSTD::min(__clz_f, __n);
+ __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn));
+ *__first.__seg_ |= __m;
+ __n -= __dn;
+ ++__first.__seg_;
+ }
+ // do middle whole words
+ __storage_type __nw = __n / __bits_per_word;
+ _VSTD::memset(_VSTD::__to_raw_pointer(__first.__seg_), -1, __nw * sizeof(__storage_type));
+ __n -= __nw * __bits_per_word;
+ // do last partial word
+ if (__n > 0)
+ {
+ __first.__seg_ += __nw;
+ __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
+ *__first.__seg_ |= __m;
+ }
+}
+
+template
+inline _LIBCPP_INLINE_VISIBILITY
+void
+fill_n(__bit_iterator<_Cp, false> __first, typename _Cp::size_type __n, bool __value_)
+{
+ if (__n > 0)
+ {
+ if (__value_)
+ __fill_n_true(__first, __n);
+ else
+ __fill_n_false(__first, __n);
+ }
+}
+
+// fill
+
+template
+inline _LIBCPP_INLINE_VISIBILITY
+void
+fill(__bit_iterator<_Cp, false> __first, __bit_iterator<_Cp, false> __last, bool __value_)
+{
+ _VSTD::fill_n(__first, static_cast(__last - __first), __value_);
+}
+
+// copy
+
+template
+__bit_iterator<_Cp, false>
+__copy_aligned(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last,
+ __bit_iterator<_Cp, false> __result)
+{
+ typedef __bit_iterator<_Cp, _IsConst> _In;
+ typedef typename _In::difference_type difference_type;
+ typedef typename _In::__storage_type __storage_type;
+ const int __bits_per_word = _In::__bits_per_word;
+ difference_type __n = __last - __first;
+ if (__n > 0)
+ {
+ // do first word
+ if (__first.__ctz_ != 0)
+ {
+ unsigned __clz = __bits_per_word - __first.__ctz_;
+ difference_type __dn = _VSTD::min(static_cast(__clz), __n);
+ __n -= __dn;
+ __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz - __dn));
+ __storage_type __b = *__first.__seg_ & __m;
+ *__result.__seg_ &= ~__m;
+ *__result.__seg_ |= __b;
+ __result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word;
+ __result.__ctz_ = static_cast((__dn + __result.__ctz_) % __bits_per_word);
+ ++__first.__seg_;
+ // __first.__ctz_ = 0;
+ }
+ // __first.__ctz_ == 0;
+ // do middle words
+ __storage_type __nw = __n / __bits_per_word;
+ _VSTD::memmove(_VSTD::__to_raw_pointer(__result.__seg_),
+ _VSTD::__to_raw_pointer(__first.__seg_),
+ __nw * sizeof(__storage_type));
+ __n -= __nw * __bits_per_word;
+ __result.__seg_ += __nw;
+ // do last word
+ if (__n > 0)
+ {
+ __first.__seg_ += __nw;
+ __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
+ __storage_type __b = *__first.__seg_ & __m;
+ *__result.__seg_ &= ~__m;
+ *__result.__seg_ |= __b;
+ __result.__ctz_ = static_cast(__n);
+ }
+ }
+ return __result;
+}
+
+template
+__bit_iterator<_Cp, false>
+__copy_unaligned(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last,
+ __bit_iterator<_Cp, false> __result)
+{
+ typedef __bit_iterator<_Cp, _IsConst> _In;
+ typedef typename _In::difference_type difference_type;
+ typedef typename _In::__storage_type __storage_type;
+ static const int __bits_per_word = _In::__bits_per_word;
+ difference_type __n = __last - __first;
+ if (__n > 0)
+ {
+ // do first word
+ if (__first.__ctz_ != 0)
+ {
+ unsigned __clz_f = __bits_per_word - __first.__ctz_;
+ difference_type __dn = _VSTD::min(static_cast(__clz_f), __n);
+ __n -= __dn;
+ __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn));
+ __storage_type __b = *__first.__seg_ & __m;
+ unsigned __clz_r = __bits_per_word - __result.__ctz_;
+ __storage_type __ddn = _VSTD::min<__storage_type>(__dn, __clz_r);
+ __m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __ddn));
+ *__result.__seg_ &= ~__m;
+ if (__result.__ctz_ > __first.__ctz_)
+ *__result.__seg_ |= __b << (__result.__ctz_ - __first.__ctz_);
+ else
+ *__result.__seg_ |= __b >> (__first.__ctz_ - __result.__ctz_);
+ __result.__seg_ += (__ddn + __result.__ctz_) / __bits_per_word;
+ __result.__ctz_ = static_cast((__ddn + __result.__ctz_) % __bits_per_word);
+ __dn -= __ddn;
+ if (__dn > 0)
+ {
+ __m = ~__storage_type(0) >> (__bits_per_word - __dn);
+ *__result.__seg_ &= ~__m;
+ *__result.__seg_ |= __b >> (__first.__ctz_ + __ddn);
+ __result.__ctz_ = static_cast(__dn);
+ }
+ ++__first.__seg_;
+ // __first.__ctz_ = 0;
+ }
+ // __first.__ctz_ == 0;
+ // do middle words
+ unsigned __clz_r = __bits_per_word - __result.__ctz_;
+ __storage_type __m = ~__storage_type(0) << __result.__ctz_;
+ for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_)
+ {
+ __storage_type __b = *__first.__seg_;
+ *__result.__seg_ &= ~__m;
+ *__result.__seg_ |= __b << __result.__ctz_;
+ ++__result.__seg_;
+ *__result.__seg_ &= __m;
+ *__result.__seg_ |= __b >> __clz_r;
+ }
+ // do last word
+ if (__n > 0)
+ {
+ __m = ~__storage_type(0) >> (__bits_per_word - __n);
+ __storage_type __b = *__first.__seg_ & __m;
+ __storage_type __dn = _VSTD::min(__n, static_cast(__clz_r));
+ __m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __dn));
+ *__result.__seg_ &= ~__m;
+ *__result.__seg_ |= __b << __result.__ctz_;
+ __result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word;
+ __result.__ctz_ = static_cast((__dn + __result.__ctz_) % __bits_per_word);
+ __n -= __dn;
+ if (__n > 0)
+ {
+ __m = ~__storage_type(0) >> (__bits_per_word - __n);
+ *__result.__seg_ &= ~__m;
+ *__result.__seg_ |= __b >> __dn;
+ __result.__ctz_ = static_cast(__n);
+ }
+ }
+ }
+ return __result;
+}
+
+template
+inline _LIBCPP_INLINE_VISIBILITY
+__bit_iterator<_Cp, false>
+copy(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result)
+{
+ if (__first.__ctz_ == __result.__ctz_)
+ return __copy_aligned(__first, __last, __result);
+ return __copy_unaligned(__first, __last, __result);
+}
+
+// copy_backward
+
+template
+__bit_iterator<_Cp, false>
+__copy_backward_aligned(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last,
+ __bit_iterator<_Cp, false> __result)
+{
+ typedef __bit_iterator<_Cp, _IsConst> _In;
+ typedef typename _In::difference_type difference_type;
+ typedef typename _In::__storage_type __storage_type;
+ const int __bits_per_word = _In::__bits_per_word;
+ difference_type __n = __last - __first;
+ if (__n > 0)
+ {
+ // do first word
+ if (__last.__ctz_ != 0)
+ {
+ difference_type __dn = _VSTD::min(static_cast(__last.__ctz_), __n);
+ __n -= __dn;
+ unsigned __clz = __bits_per_word - __last.__ctz_;
+ __storage_type __m = (~__storage_type(0) << (__last.__ctz_ - __dn)) & (~__storage_type(0) >> __clz);
+ __storage_type __b = *__last.__seg_ & __m;
+ *__result.__seg_ &= ~__m;
+ *__result.__seg_ |= __b;
+ __result.__ctz_ = static_cast(((-__dn & (__bits_per_word - 1)) +
+ __result.__ctz_) % __bits_per_word);
+ // __last.__ctz_ = 0
+ }
+ // __last.__ctz_ == 0 || __n == 0
+ // __result.__ctz_ == 0 || __n == 0
+ // do middle words
+ __storage_type __nw = __n / __bits_per_word;
+ __result.__seg_ -= __nw;
+ __last.__seg_ -= __nw;
+ _VSTD::memmove(_VSTD::__to_raw_pointer(__result.__seg_),
+ _VSTD::__to_raw_pointer(__last.__seg_),
+ __nw * sizeof(__storage_type));
+ __n -= __nw * __bits_per_word;
+ // do last word
+ if (__n > 0)
+ {
+ __storage_type __m = ~__storage_type(0) << (__bits_per_word - __n);
+ __storage_type __b = *--__last.__seg_ & __m;
+ *--__result.__seg_ &= ~__m;
+ *__result.__seg_ |= __b;
+ __result.__ctz_ = static_cast(-__n & (__bits_per_word - 1));
+ }
+ }
+ return __result;
+}
+
+template
+__bit_iterator<_Cp, false>
+__copy_backward_unaligned(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last,
+ __bit_iterator<_Cp, false> __result)
+{
+ typedef __bit_iterator<_Cp, _IsConst> _In;
+ typedef typename _In::difference_type difference_type;
+ typedef typename _In::__storage_type __storage_type;
+ const int __bits_per_word = _In::__bits_per_word;
+ difference_type __n = __last - __first;
+ if (__n > 0)
+ {
+ // do first word
+ if (__last.__ctz_ != 0)
+ {
+ difference_type __dn = _VSTD::min(static_cast(__last.__ctz_), __n);
+ __n -= __dn;
+ unsigned __clz_l = __bits_per_word - __last.__ctz_;
+ __storage_type __m = (~__storage_type(0) << (__last.__ctz_ - __dn)) & (~__storage_type(0) >> __clz_l);
+ __storage_type __b = *__last.__seg_ & __m;
+ unsigned __clz_r = __bits_per_word - __result.__ctz_;
+ __storage_type __ddn = _VSTD::min(__dn, static_cast(__result.__ctz_));
+ if (__ddn > 0)
+ {
+ __m = (~__storage_type(0) << (__result.__ctz_ - __ddn)) & (~__storage_type(0) >> __clz_r);
+ *__result.__seg_ &= ~__m;
+ if (__result.__ctz_ > __last.__ctz_)
+ *__result.__seg_ |= __b << (__result.__ctz_ - __last.__ctz_);
+ else
+ *__result.__seg_ |= __b >> (__last.__ctz_ - __result.__ctz_);
+ __result.__ctz_ = static_cast(((-__ddn & (__bits_per_word - 1)) +
+ __result.__ctz_) % __bits_per_word);
+ __dn -= __ddn;
+ }
+ if (__dn > 0)
+ {
+ // __result.__ctz_ == 0
+ --__result.__seg_;
+ __result.__ctz_ = static_cast(-__dn & (__bits_per_word - 1));
+ __m = ~__storage_type(0) << __result.__ctz_;
+ *__result.__seg_ &= ~__m;
+ __last.__ctz_ -= __dn + __ddn;
+ *__result.__seg_ |= __b << (__result.__ctz_ - __last.__ctz_);
+ }
+ // __last.__ctz_ = 0
+ }
+ // __last.__ctz_ == 0 || __n == 0
+ // __result.__ctz_ != 0 || __n == 0
+ // do middle words
+ unsigned __clz_r = __bits_per_word - __result.__ctz_;
+ __storage_type __m = ~__storage_type(0) >> __clz_r;
+ for (; __n >= __bits_per_word; __n -= __bits_per_word)
+ {
+ __storage_type __b = *--__last.__seg_;
+ *__result.__seg_ &= ~__m;
+ *__result.__seg_ |= __b >> __clz_r;
+ *--__result.__seg_ &= __m;
+ *__result.__seg_ |= __b << __result.__ctz_;
+ }
+ // do last word
+ if (__n > 0)
+ {
+ __m = ~__storage_type(0) << (__bits_per_word - __n);
+ __storage_type __b = *--__last.__seg_ & __m;
+ __clz_r = __bits_per_word - __result.__ctz_;
+ __storage_type __dn = _VSTD::min(__n, static_cast(__result.__ctz_));
+ __m = (~__storage_type(0) << (__result.__ctz_ - __dn)) & (~__storage_type(0) >> __clz_r);
+ *__result.__seg_ &= ~__m;
+ *__result.__seg_ |= __b >> (__bits_per_word - __result.__ctz_);
+ __result.__ctz_ = static_cast(((-__dn & (__bits_per_word - 1)) +
+ __result.__ctz_) % __bits_per_word);
+ __n -= __dn;
+ if (__n > 0)
+ {
+ // __result.__ctz_ == 0
+ --__result.__seg_;
+ __result.__ctz_ = static_cast(-__n & (__bits_per_word - 1));
+ __m = ~__storage_type(0) << __result.__ctz_;
+ *__result.__seg_ &= ~__m;
+ *__result.__seg_ |= __b << (__result.__ctz_ - (__bits_per_word - __n - __dn));
+ }
+ }
+ }
+ return __result;
+}
+
+template
+inline _LIBCPP_INLINE_VISIBILITY
+__bit_iterator<_Cp, false>
+copy_backward(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result)
+{
+ if (__last.__ctz_ == __result.__ctz_)
+ return __copy_backward_aligned(__first, __last, __result);
+ return __copy_backward_unaligned(__first, __last, __result);
+}
+
+// move
+
+template
+inline _LIBCPP_INLINE_VISIBILITY
+__bit_iterator<_Cp, false>
+move(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result)
+{
+ return _VSTD::copy(__first, __last, __result);
+}
+
+// move_backward
+
+template
+inline _LIBCPP_INLINE_VISIBILITY
+__bit_iterator<_Cp, false>
+move_backward(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result)
+{
+ return _VSTD::copy_backward(__first, __last, __result);
+}
+
+// swap_ranges
+
+template
+__bit_iterator<__C2, false>
+__swap_ranges_aligned(__bit_iterator<__C1, false> __first, __bit_iterator<__C1, false> __last,
+ __bit_iterator<__C2, false> __result)
+{
+ typedef __bit_iterator<__C1, false> _I1;
+ typedef typename _I1::difference_type difference_type;
+ typedef typename _I1::__storage_type __storage_type;
+ const int __bits_per_word = _I1::__bits_per_word;
+ difference_type __n = __last - __first;
+ if (__n > 0)
+ {
+ // do first word
+ if (__first.__ctz_ != 0)
+ {
+ unsigned __clz = __bits_per_word - __first.__ctz_;
+ difference_type __dn = _VSTD::min(static_cast(__clz), __n);
+ __n -= __dn;
+ __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz - __dn));
+ __storage_type __b1 = *__first.__seg_ & __m;
+ *__first.__seg_ &= ~__m;
+ __storage_type __b2 = *__result.__seg_ & __m;
+ *__result.__seg_ &= ~__m;
+ *__result.__seg_ |= __b1;
+ *__first.__seg_ |= __b2;
+ __result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word;
+ __result.__ctz_ = static_cast((__dn + __result.__ctz_) % __bits_per_word);
+ ++__first.__seg_;
+ // __first.__ctz_ = 0;
+ }
+ // __first.__ctz_ == 0;
+ // do middle words
+ for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_, ++__result.__seg_)
+ swap(*__first.__seg_, *__result.__seg_);
+ // do last word
+ if (__n > 0)
+ {
+ __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
+ __storage_type __b1 = *__first.__seg_ & __m;
+ *__first.__seg_ &= ~__m;
+ __storage_type __b2 = *__result.__seg_ & __m;
+ *__result.__seg_ &= ~__m;
+ *__result.__seg_ |= __b1;
+ *__first.__seg_ |= __b2;
+ __result.__ctz_ = static_cast(__n);
+ }
+ }
+ return __result;
+}
+
+template
+__bit_iterator<__C2, false>
+__swap_ranges_unaligned(__bit_iterator<__C1, false> __first, __bit_iterator<__C1, false> __last,
+ __bit_iterator<__C2, false> __result)
+{
+ typedef __bit_iterator<__C1, false> _I1;
+ typedef typename _I1::difference_type difference_type;
+ typedef typename _I1::__storage_type __storage_type;
+ const int __bits_per_word = _I1::__bits_per_word;
+ difference_type __n = __last - __first;
+ if (__n > 0)
+ {
+ // do first word
+ if (__first.__ctz_ != 0)
+ {
+ unsigned __clz_f = __bits_per_word - __first.__ctz_;
+ difference_type __dn = _VSTD::min(static_cast(__clz_f), __n);
+ __n -= __dn;
+ __storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn));
+ __storage_type __b1 = *__first.__seg_ & __m;
+ *__first.__seg_ &= ~__m;
+ unsigned __clz_r = __bits_per_word - __result.__ctz_;
+ __storage_type __ddn = _VSTD::min<__storage_type>(__dn, __clz_r);
+ __m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __ddn));
+ __storage_type __b2 = *__result.__seg_ & __m;
+ *__result.__seg_ &= ~__m;
+ if (__result.__ctz_ > __first.__ctz_)
+ {
+ unsigned __s = __result.__ctz_ - __first.__ctz_;
+ *__result.__seg_ |= __b1 << __s;
+ *__first.__seg_ |= __b2 >> __s;
+ }
+ else
+ {
+ unsigned __s = __first.__ctz_ - __result.__ctz_;
+ *__result.__seg_ |= __b1 >> __s;
+ *__first.__seg_ |= __b2 << __s;
+ }
+ __result.__seg_ += (__ddn + __result.__ctz_) / __bits_per_word;
+ __result.__ctz_ = static_cast((__ddn + __result.__ctz_) % __bits_per_word);
+ __dn -= __ddn;
+ if (__dn > 0)
+ {
+ __m = ~__storage_type(0) >> (__bits_per_word - __dn);
+ __b2 = *__result.__seg_ & __m;
+ *__result.__seg_ &= ~__m;
+ unsigned __s = __first.__ctz_ + __ddn;
+ *__result.__seg_ |= __b1 >> __s;
+ *__first.__seg_ |= __b2 << __s;
+ __result.__ctz_ = static_cast(__dn);
+ }
+ ++__first.__seg_;
+ // __first.__ctz_ = 0;
+ }
+ // __first.__ctz_ == 0;
+ // do middle words
+ __storage_type __m = ~__storage_type(0) << __result.__ctz_;
+ unsigned __clz_r = __bits_per_word - __result.__ctz_;
+ for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_)
+ {
+ __storage_type __b1 = *__first.__seg_;
+ __storage_type __b2 = *__result.__seg_ & __m;
+ *__result.__seg_ &= ~__m;
+ *__result.__seg_ |= __b1 << __result.__ctz_;
+ *__first.__seg_ = __b2 >> __result.__ctz_;
+ ++__result.__seg_;
+ __b2 = *__result.__seg_ & ~__m;
+ *__result.__seg_ &= __m;
+ *__result.__seg_ |= __b1 >> __clz_r;
+ *__first.__seg_ |= __b2 << __clz_r;
+ }
+ // do last word
+ if (__n > 0)
+ {
+ __m = ~__storage_type(0) >> (__bits_per_word - __n);
+ __storage_type __b1 = *__first.__seg_ & __m;
+ *__first.__seg_ &= ~__m;
+ __storage_type __dn = _VSTD::min<__storage_type>(__n, __clz_r);
+ __m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __dn));
+ __storage_type __b2 = *__result.__seg_ & __m;
+ *__result.__seg_ &= ~__m;
+ *__result.__seg_ |= __b1 << __result.__ctz_;
+ *__first.__seg_ |= __b2 >> __result.__ctz_;
+ __result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word;
+ __result.__ctz_ = static_cast((__dn + __result.__ctz_) % __bits_per_word);
+ __n -= __dn;
+ if (__n > 0)
+ {
+ __m = ~__storage_type(0) >> (__bits_per_word - __n);
+ __b2 = *__result.__seg_ & __m;
+ *__result.__seg_ &= ~__m;
+ *__result.__seg_ |= __b1 >> __dn;
+ *__first.__seg_ |= __b2 << __dn;
+ __result.__ctz_ = static_cast(__n);
+ }
+ }
+ }
+ return __result;
+}
+
+template
+inline _LIBCPP_INLINE_VISIBILITY
+__bit_iterator<__C2, false>
+swap_ranges(__bit_iterator<__C1, false> __first1, __bit_iterator<__C1, false> __last1,
+ __bit_iterator<__C2, false> __first2)
+{
+ if (__first1.__ctz_ == __first2.__ctz_)
+ return __swap_ranges_aligned(__first1, __last1, __first2);
+ return __swap_ranges_unaligned(__first1, __last1, __first2);
+}
+
+// rotate
+
+template
+struct __bit_array
+{
+ typedef typename _Cp::difference_type difference_type;
+ typedef typename _Cp::__storage_type __storage_type;
+ typedef typename _Cp::__storage_pointer __storage_pointer;
+ typedef typename _Cp::iterator iterator;
+ static const unsigned __bits_per_word = _Cp::__bits_per_word;
+ static const unsigned _Np = 4;
+
+ difference_type __size_;
+ __storage_type __word_[_Np];
+
+ _LIBCPP_INLINE_VISIBILITY static difference_type capacity()
+ {return static_cast(_Np * __bits_per_word);}
+ _LIBCPP_INLINE_VISIBILITY explicit __bit_array(difference_type __s) : __size_(__s) {}
+ _LIBCPP_INLINE_VISIBILITY iterator begin()
+ {
+ return iterator(pointer_traits<__storage_pointer>::pointer_to(__word_[0]), 0);
+ }
+ _LIBCPP_INLINE_VISIBILITY iterator end()
+ {
+ return iterator(pointer_traits<__storage_pointer>::pointer_to(__word_[0]) + __size_ / __bits_per_word,
+ static_cast(__size_ % __bits_per_word));
+ }
+};
+
+template
+__bit_iterator<_Cp, false>
+rotate(__bit_iterator<_Cp, false> __first, __bit_iterator<_Cp, false> __middle, __bit_iterator<_Cp, false> __last)
+{
+ typedef __bit_iterator<_Cp, false> _I1;
+ typedef typename _I1::difference_type difference_type;
+ difference_type __d1 = __middle - __first;
+ difference_type __d2 = __last - __middle;
+ _I1 __r = __first + __d2;
+ while (__d1 != 0 && __d2 != 0)
+ {
+ if (__d1 <= __d2)
+ {
+ if (__d1 <= __bit_array<_Cp>::capacity())
+ {
+ __bit_array<_Cp> __b(__d1);
+ _VSTD::copy(__first, __middle, __b.begin());
+ _VSTD::copy(__b.begin(), __b.end(), _VSTD::copy(__middle, __last, __first));
+ break;
+ }
+ else
+ {
+ __bit_iterator<_Cp, false> __mp = _VSTD::swap_ranges(__first, __middle, __middle);
+ __first = __middle;
+ __middle = __mp;
+ __d2 -= __d1;
+ }
+ }
+ else
+ {
+ if (__d2 <= __bit_array<_Cp>::capacity())
+ {
+ __bit_array<_Cp> __b(__d2);
+ _VSTD::copy(__middle, __last, __b.begin());
+ _VSTD::copy_backward(__b.begin(), __b.end(), _VSTD::copy_backward(__first, __middle, __last));
+ break;
+ }
+ else
+ {
+ __bit_iterator<_Cp, false> __mp = __first + __d2;
+ _VSTD::swap_ranges(__first, __mp, __middle);
+ __first = __mp;
+ __d1 -= __d2;
+ }
+ }
+ }
+ return __r;
+}
+
+// equal
+
+template
+bool
+__equal_unaligned(__bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> __last1,
+ __bit_iterator<_Cp, _IC2> __first2)
+{
+ typedef __bit_iterator<_Cp, _IC1> _It;
+ typedef typename _It::difference_type difference_type;
+ typedef typename _It::__storage_type __storage_type;
+ static const int __bits_per_word = _It::__bits_per_word;
+ difference_type __n = __last1 - __first1;
+ if (__n > 0)
+ {
+ // do first word
+ if (__first1.__ctz_ != 0)
+ {
+ unsigned __clz_f = __bits_per_word - __first1.__ctz_;
+ difference_type __dn = _VSTD::min(static_cast(__clz_f), __n);
+ __n -= __dn;
+ __storage_type __m = (~__storage_type(0) << __first1.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn));
+ __storage_type __b = *__first1.__seg_ & __m;
+ unsigned __clz_r = __bits_per_word - __first2.__ctz_;
+ __storage_type __ddn = _VSTD::min<__storage_type>(__dn, __clz_r);
+ __m = (~__storage_type(0) << __first2.__ctz_) & (~__storage_type(0) >> (__clz_r - __ddn));
+ if (__first2.__ctz_ > __first1.__ctz_)
+ {
+ if ((*__first2.__seg_ & __m) != (__b << (__first2.__ctz_ - __first1.__ctz_)))
+ return false;
+ }
+ else
+ {
+ if ((*__first2.__seg_ & __m) != (__b >> (__first1.__ctz_ - __first2.__ctz_)))
+ return false;
+ }
+ __first2.__seg_ += (__ddn + __first2.__ctz_) / __bits_per_word;
+ __first2.__ctz_ = static_cast((__ddn + __first2.__ctz_) % __bits_per_word);
+ __dn -= __ddn;
+ if (__dn > 0)
+ {
+ __m = ~__storage_type(0) >> (__bits_per_word - __dn);
+ if ((*__first2.__seg_ & __m) != (__b >> (__first1.__ctz_ + __ddn)))
+ return false;
+ __first2.__ctz_ = static_cast(__dn);
+ }
+ ++__first1.__seg_;
+ // __first1.__ctz_ = 0;
+ }
+ // __first1.__ctz_ == 0;
+ // do middle words
+ unsigned __clz_r = __bits_per_word - __first2.__ctz_;
+ __storage_type __m = ~__storage_type(0) << __first2.__ctz_;
+ for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first1.__seg_)
+ {
+ __storage_type __b = *__first1.__seg_;
+ if ((*__first2.__seg_ & __m) != (__b << __first2.__ctz_))
+ return false;
+ ++__first2.__seg_;
+ if ((*__first2.__seg_ & ~__m) != (__b >> __clz_r))
+ return false;
+ }
+ // do last word
+ if (__n > 0)
+ {
+ __m = ~__storage_type(0) >> (__bits_per_word - __n);
+ __storage_type __b = *__first1.__seg_ & __m;
+ __storage_type __dn = _VSTD::min(__n, static_cast(__clz_r));
+ __m = (~__storage_type(0) << __first2.__ctz_) & (~__storage_type(0) >> (__clz_r - __dn));
+ if ((*__first2.__seg_ & __m) != (__b << __first2.__ctz_))
+ return false;
+ __first2.__seg_ += (__dn + __first2.__ctz_) / __bits_per_word;
+ __first2.__ctz_ = static_cast((__dn + __first2.__ctz_) % __bits_per_word);
+ __n -= __dn;
+ if (__n > 0)
+ {
+ __m = ~__storage_type(0) >> (__bits_per_word - __n);
+ if ((*__first2.__seg_ & __m) != (__b >> __dn))
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+template
+bool
+__equal_aligned(__bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> __last1,
+ __bit_iterator<_Cp, _IC2> __first2)
+{
+ typedef __bit_iterator<_Cp, _IC1> _It;
+ typedef typename _It::difference_type difference_type;
+ typedef typename _It::__storage_type __storage_type;
+ static const int __bits_per_word = _It::__bits_per_word;
+ difference_type __n = __last1 - __first1;
+ if (__n > 0)
+ {
+ // do first word
+ if (__first1.__ctz_ != 0)
+ {
+ unsigned __clz = __bits_per_word - __first1.__ctz_;
+ difference_type __dn = _VSTD::min(static_cast(__clz), __n);
+ __n -= __dn;
+ __storage_type __m = (~__storage_type(0) << __first1.__ctz_) & (~__storage_type(0) >> (__clz - __dn));
+ if ((*__first2.__seg_ & __m) != (*__first1.__seg_ & __m))
+ return false;
+ ++__first2.__seg_;
+ ++__first1.__seg_;
+ // __first1.__ctz_ = 0;
+ // __first2.__ctz_ = 0;
+ }
+ // __first1.__ctz_ == 0;
+ // __first2.__ctz_ == 0;
+ // do middle words
+ for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first1.__seg_, ++__first2.__seg_)
+ if (*__first2.__seg_ != *__first1.__seg_)
+ return false;
+ // do last word
+ if (__n > 0)
+ {
+ __storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
+ if ((*__first2.__seg_ & __m) != (*__first1.__seg_ & __m))
+ return false;
+ }
+ }
+ return true;
+}
+
+template
+inline _LIBCPP_INLINE_VISIBILITY
+bool
+equal(__bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> __last1, __bit_iterator<_Cp, _IC2> __first2)
+{
+ if (__first1.__ctz_ == __first2.__ctz_)
+ return __equal_aligned(__first1, __last1, __first2);
+ return __equal_unaligned(__first1, __last1, __first2);
+}
+
+template
+class __bit_iterator
+{
+public:
+ typedef typename _Cp::difference_type difference_type;
+ typedef bool value_type;
+ typedef __bit_iterator pointer;
+ typedef typename conditional<_IsConst, __bit_const_reference<_Cp>, __bit_reference<_Cp> >::type reference;
+ typedef random_access_iterator_tag iterator_category;
+
+private:
+ typedef typename _Cp::__storage_type __storage_type;
+ typedef typename conditional<_IsConst, typename _Cp::__const_storage_pointer,
+ typename _Cp::__storage_pointer>::type __storage_pointer;
+ static const unsigned __bits_per_word = _Cp::__bits_per_word;
+
+ __storage_pointer __seg_;
+ unsigned __ctz_;
+
+public:
+ _LIBCPP_INLINE_VISIBILITY __bit_iterator() _NOEXCEPT
+#if _LIBCPP_STD_VER > 11
+ : __seg_(nullptr), __ctz_(0)
+#endif
+ {}
+
+ _LIBCPP_INLINE_VISIBILITY
+ __bit_iterator(const __bit_iterator<_Cp, false>& __it) _NOEXCEPT
+ : __seg_(__it.__seg_), __ctz_(__it.__ctz_) {}
+
+ _LIBCPP_INLINE_VISIBILITY reference operator*() const _NOEXCEPT
+ {return reference(__seg_, __storage_type(1) << __ctz_);}
+
+ _LIBCPP_INLINE_VISIBILITY __bit_iterator& operator++()
+ {
+ if (__ctz_ != __bits_per_word-1)
+ ++__ctz_;
+ else
+ {
+ __ctz_ = 0;
+ ++__seg_;
+ }
+ return *this;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY __bit_iterator operator++(int)
+ {
+ __bit_iterator __tmp = *this;
+ ++(*this);
+ return __tmp;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY __bit_iterator& operator--()
+ {
+ if (__ctz_ != 0)
+ --__ctz_;
+ else
+ {
+ __ctz_ = __bits_per_word - 1;
+ --__seg_;
+ }
+ return *this;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY __bit_iterator operator--(int)
+ {
+ __bit_iterator __tmp = *this;
+ --(*this);
+ return __tmp;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY __bit_iterator& operator+=(difference_type __n)
+ {
+ if (__n >= 0)
+ __seg_ += (__n + __ctz_) / __bits_per_word;
+ else
+ __seg_ += static_cast(__n - __bits_per_word + __ctz_ + 1)
+ / static_cast(__bits_per_word);
+ __n &= (__bits_per_word - 1);
+ __ctz_ = static_cast((__n + __ctz_) % __bits_per_word);
+ return *this;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY __bit_iterator& operator-=(difference_type __n)
+ {
+ return *this += -__n;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY __bit_iterator operator+(difference_type __n) const
+ {
+ __bit_iterator __t(*this);
+ __t += __n;
+ return __t;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY __bit_iterator operator-(difference_type __n) const
+ {
+ __bit_iterator __t(*this);
+ __t -= __n;
+ return __t;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ friend __bit_iterator operator+(difference_type __n, const __bit_iterator& __it) {return __it + __n;}
+
+ _LIBCPP_INLINE_VISIBILITY
+ friend difference_type operator-(const __bit_iterator& __x, const __bit_iterator& __y)
+ {return (__x.__seg_ - __y.__seg_) * __bits_per_word + __x.__ctz_ - __y.__ctz_;}
+
+ _LIBCPP_INLINE_VISIBILITY reference operator[](difference_type __n) const {return *(*this + __n);}
+
+ _LIBCPP_INLINE_VISIBILITY friend bool operator==(const __bit_iterator& __x, const __bit_iterator& __y)
+ {return __x.__seg_ == __y.__seg_ && __x.__ctz_ == __y.__ctz_;}
+
+ _LIBCPP_INLINE_VISIBILITY friend bool operator!=(const __bit_iterator& __x, const __bit_iterator& __y)
+ {return !(__x == __y);}
+
+ _LIBCPP_INLINE_VISIBILITY friend bool operator<(const __bit_iterator& __x, const __bit_iterator& __y)
+ {return __x.__seg_ < __y.__seg_ || (__x.__seg_ == __y.__seg_ && __x.__ctz_ < __y.__ctz_);}
+
+ _LIBCPP_INLINE_VISIBILITY friend bool operator>(const __bit_iterator& __x, const __bit_iterator& __y)
+ {return __y < __x;}
+
+ _LIBCPP_INLINE_VISIBILITY friend bool operator<=(const __bit_iterator& __x, const __bit_iterator& __y)
+ {return !(__y < __x);}
+
+ _LIBCPP_INLINE_VISIBILITY friend bool operator>=(const __bit_iterator& __x, const __bit_iterator& __y)
+ {return !(__x < __y);}
+
+private:
+ _LIBCPP_INLINE_VISIBILITY
+ __bit_iterator(__storage_pointer __s, unsigned __ctz) _NOEXCEPT
+ : __seg_(__s), __ctz_(__ctz) {}
+
+ friend typename _Cp::__self;
+
+ friend class __bit_reference<_Cp>;
+ friend class __bit_const_reference<_Cp>;
+ friend class __bit_iterator<_Cp, true>;
+ template friend struct __bit_array;
+ template friend void __fill_n_false(__bit_iterator<_Dp, false> __first, typename _Dp::size_type __n);
+ template friend void __fill_n_true(__bit_iterator<_Dp, false> __first, typename _Dp::size_type __n);
+ template friend __bit_iterator<_Dp, false> __copy_aligned(__bit_iterator<_Dp, _IC> __first,
+ __bit_iterator<_Dp, _IC> __last,
+ __bit_iterator<_Dp, false> __result);
+ template friend __bit_iterator<_Dp, false> __copy_unaligned(__bit_iterator<_Dp, _IC> __first,
+ __bit_iterator<_Dp, _IC> __last,
+ __bit_iterator<_Dp, false> __result);
+ template friend __bit_iterator<_Dp, false> copy(__bit_iterator<_Dp, _IC> __first,
+ __bit_iterator<_Dp, _IC> __last,
+ __bit_iterator<_Dp, false> __result);
+ template friend __bit_iterator<_Dp, false> __copy_backward_aligned(__bit_iterator<_Dp, _IC> __first,
+ __bit_iterator<_Dp, _IC> __last,
+ __bit_iterator<_Dp, false> __result);
+ template friend __bit_iterator<_Dp, false> __copy_backward_unaligned(__bit_iterator<_Dp, _IC> __first,
+ __bit_iterator<_Dp, _IC> __last,
+ __bit_iterator<_Dp, false> __result);
+ template friend __bit_iterator<_Dp, false> copy_backward(__bit_iterator<_Dp, _IC> __first,
+ __bit_iterator<_Dp, _IC> __last,
+ __bit_iterator<_Dp, false> __result);
+ template friend __bit_iterator<__C2, false> __swap_ranges_aligned(__bit_iterator<__C1, false>,
+ __bit_iterator<__C1, false>,
+ __bit_iterator<__C2, false>);
+ template friend __bit_iterator<__C2, false> __swap_ranges_unaligned(__bit_iterator<__C1, false>,
+ __bit_iterator<__C1, false>,
+ __bit_iterator<__C2, false>);
+ template friend __bit_iterator<__C2, false> swap_ranges(__bit_iterator<__C1, false>,
+ __bit_iterator<__C1, false>,
+ __bit_iterator<__C2, false>);
+ template friend __bit_iterator<_Dp, false> rotate(__bit_iterator<_Dp, false>,
+ __bit_iterator<_Dp, false>,
+ __bit_iterator<_Dp, false>);
+ template friend bool __equal_aligned(__bit_iterator<_Dp, _IC1>,
+ __bit_iterator<_Dp, _IC1>,
+ __bit_iterator<_Dp, _IC2>);
+ template friend bool __equal_unaligned(__bit_iterator<_Dp, _IC1>,
+ __bit_iterator<_Dp, _IC1>,
+ __bit_iterator<_Dp, _IC2>);
+ template friend bool equal(__bit_iterator<_Dp, _IC1>,
+ __bit_iterator<_Dp, _IC1>,
+ __bit_iterator<_Dp, _IC2>);
+ template friend __bit_iterator<_Dp, _IC> __find_bool_true(__bit_iterator<_Dp, _IC>,
+ typename _Dp::size_type);
+ template friend __bit_iterator<_Dp, _IC> __find_bool_false(__bit_iterator<_Dp, _IC>,
+ typename _Dp::size_type);
+ template friend typename __bit_iterator<_Dp, _IC>::difference_type
+ __count_bool_true(__bit_iterator<_Dp, _IC>, typename _Dp::size_type);
+ template friend typename __bit_iterator<_Dp, _IC>::difference_type
+ __count_bool_false(__bit_iterator<_Dp, _IC>, typename _Dp::size_type);
+};
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___BIT_REFERENCE
diff --git a/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/include/libc++/__bsd_locale_defaults.h b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/include/libc++/__bsd_locale_defaults.h
new file mode 100644
index 00000000..2ace2a21
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/include/libc++/__bsd_locale_defaults.h
@@ -0,0 +1,36 @@
+// -*- C++ -*-
+//===---------------------- __bsd_locale_defaults.h -----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// The BSDs have lots of *_l functions. We don't want to define those symbols
+// on other platforms though, for fear of conflicts with user code. So here,
+// we will define the mapping from an internal macro to the real BSD symbol.
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP_BSD_LOCALE_DEFAULTS_H
+#define _LIBCPP_BSD_LOCALE_DEFAULTS_H
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#pragma GCC system_header
+#endif
+
+#define __libcpp_mb_cur_max_l(loc) MB_CUR_MAX_L(loc)
+#define __libcpp_btowc_l(ch, loc) btowc_l(ch, loc)
+#define __libcpp_wctob_l(wch, loc) wctob_l(wch, loc)
+#define __libcpp_wcsnrtombs_l(dst, src, nwc, len, ps, loc) wcsnrtombs_l(dst, src, nwc, len, ps, loc)
+#define __libcpp_wcrtomb_l(src, wc, ps, loc) wcrtomb_l(src, wc, ps, loc)
+#define __libcpp_mbsnrtowcs_l(dst, src, nms, len, ps, loc) mbsnrtowcs_l(dst, src, nms, len, ps, loc)
+#define __libcpp_mbrtowc_l(pwc, s, n, ps, l) mbrtowc_l(pwc, s, n, ps, l)
+#define __libcpp_mbtowc_l(pwc, pmb, max, l) mbtowc_l(pwc, pmb, max, l)
+#define __libcpp_mbrlen_l(s, n, ps, l) mbrlen_l(s, n, ps, l)
+#define __libcpp_localeconv_l(l) localeconv_l(l)
+#define __libcpp_mbsrtowcs_l(dest, src, len, ps, l) mbsrtowcs_l(dest, src, len, ps, l)
+#define __libcpp_snprintf_l(...) snprintf_l(__VA_ARGS__)
+#define __libcpp_asprintf_l(...) asprintf_l(__VA_ARGS__)
+#define __libcpp_sscanf_l(...) sscanf_l(__VA_ARGS__)
+
+#endif // _LIBCPP_BSD_LOCALE_DEFAULTS_H
diff --git a/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/include/libc++/__bsd_locale_fallbacks.h b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/include/libc++/__bsd_locale_fallbacks.h
new file mode 100644
index 00000000..a807fe03
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/include/libc++/__bsd_locale_fallbacks.h
@@ -0,0 +1,139 @@
+// -*- C++ -*-
+//===---------------------- __bsd_locale_fallbacks.h ----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// The BSDs have lots of *_l functions. This file provides reimplementations
+// of those functions for non-BSD platforms.
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP_BSD_LOCALE_FALLBACKS_DEFAULTS_H
+#define _LIBCPP_BSD_LOCALE_FALLBACKS_DEFAULTS_H
+
+#include
+#include
+#include
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+inline _LIBCPP_INLINE_VISIBILITY
+decltype(MB_CUR_MAX) __libcpp_mb_cur_max_l(locale_t __l)
+{
+ __libcpp_locale_guard __current(__l);
+ return MB_CUR_MAX;
+}
+
+inline _LIBCPP_INLINE_VISIBILITY
+wint_t __libcpp_btowc_l(int __c, locale_t __l)
+{
+ __libcpp_locale_guard __current(__l);
+ return btowc(__c);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY
+int __libcpp_wctob_l(wint_t __c, locale_t __l)
+{
+ __libcpp_locale_guard __current(__l);
+ return wctob(__c);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY
+size_t __libcpp_wcsnrtombs_l(char *__dest, const wchar_t **__src, size_t __nwc,
+ size_t __len, mbstate_t *__ps, locale_t __l)
+{
+ __libcpp_locale_guard __current(__l);
+ return wcsnrtombs(__dest, __src, __nwc, __len, __ps);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY
+size_t __libcpp_wcrtomb_l(char *__s, wchar_t __wc, mbstate_t *__ps, locale_t __l)
+{
+ __libcpp_locale_guard __current(__l);
+ return wcrtomb(__s, __wc, __ps);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY
+size_t __libcpp_mbsnrtowcs_l(wchar_t * __dest, const char **__src, size_t __nms,
+ size_t __len, mbstate_t *__ps, locale_t __l)
+{
+ __libcpp_locale_guard __current(__l);
+ return mbsnrtowcs(__dest, __src, __nms, __len, __ps);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY
+size_t __libcpp_mbrtowc_l(wchar_t *__pwc, const char *__s, size_t __n,
+ mbstate_t *__ps, locale_t __l)
+{
+ __libcpp_locale_guard __current(__l);
+ return mbrtowc(__pwc, __s, __n, __ps);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY
+int __libcpp_mbtowc_l(wchar_t *__pwc, const char *__pmb, size_t __max, locale_t __l)
+{
+ __libcpp_locale_guard __current(__l);
+ return mbtowc(__pwc, __pmb, __max);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY
+size_t __libcpp_mbrlen_l(const char *__s, size_t __n, mbstate_t *__ps, locale_t __l)
+{
+ __libcpp_locale_guard __current(__l);
+ return mbrlen(__s, __n, __ps);
+}
+
+inline _LIBCPP_INLINE_VISIBILITY
+lconv *__libcpp_localeconv_l(locale_t __l)
+{
+ __libcpp_locale_guard __current(__l);
+ return localeconv();
+}
+
+inline _LIBCPP_INLINE_VISIBILITY
+size_t __libcpp_mbsrtowcs_l(wchar_t *__dest, const char **__src, size_t __len,
+ mbstate_t *__ps, locale_t __l)
+{
+ __libcpp_locale_guard __current(__l);
+ return mbsrtowcs(__dest, __src, __len, __ps);
+}
+
+inline
+int __libcpp_snprintf_l(char *__s, size_t __n, locale_t __l, const char *__format, ...) {
+ va_list __va;
+ va_start(__va, __format);
+ __libcpp_locale_guard __current(__l);
+ int __res = vsnprintf(__s, __n, __format, __va);
+ va_end(__va);
+ return __res;
+}
+
+inline
+int __libcpp_asprintf_l(char **__s, locale_t __l, const char *__format, ...) {
+ va_list __va;
+ va_start(__va, __format);
+ __libcpp_locale_guard __current(__l);
+ int __res = vasprintf(__s, __format, __va);
+ va_end(__va);
+ return __res;
+}
+
+inline
+int __libcpp_sscanf_l(const char *__s, locale_t __l, const char *__format, ...) {
+ va_list __va;
+ va_start(__va, __format);
+ __libcpp_locale_guard __current(__l);
+ int __res = vsscanf(__s, __format, __va);
+ va_end(__va);
+ return __res;
+}
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP_BSD_LOCALE_FALLBACKS_DEFAULTS_H
diff --git a/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/include/libc++/__config b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/include/libc++/__config
new file mode 100644
index 00000000..044cd0ce
--- /dev/null
+++ b/packages/mmkv-metal/src-native/android/mmkv-metal/src/main/cpp/include/libc++/__config
@@ -0,0 +1,1483 @@
+// -*- C++ -*-
+//===--------------------------- __config ---------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP_CONFIG
+#define _LIBCPP_CONFIG
+
+#if defined(_MSC_VER) && !defined(__clang__)
+# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# define _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
+# endif
+#endif
+
+#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
+#pragma GCC system_header
+#endif
+
+#ifdef __cplusplus
+
+#ifdef __GNUC__
+# define _GNUC_VER (__GNUC__ * 100 + __GNUC_MINOR__)
+// The _GNUC_VER_NEW macro better represents the new GCC versioning scheme
+// introduced in GCC 5.0.
+# define _GNUC_VER_NEW (_GNUC_VER * 10 + __GNUC_PATCHLEVEL__)
+#else
+# define _GNUC_VER 0
+# define _GNUC_VER_NEW 0
+#endif
+
+#define _LIBCPP_VERSION 10000
+
+#ifndef _LIBCPP_ABI_VERSION
+# define _LIBCPP_ABI_VERSION 1
+#endif
+
+#ifndef __STDC_HOSTED__
+# define _LIBCPP_FREESTANDING
+#endif
+
+#ifndef _LIBCPP_STD_VER
+# if __cplusplus <= 201103L
+# define _LIBCPP_STD_VER 11
+# elif __cplusplus <= 201402L
+# define _LIBCPP_STD_VER 14
+# elif __cplusplus <= 201703L
+# define _LIBCPP_STD_VER 17
+# else
+# define _LIBCPP_STD_VER 18 // current year, or date of c++2a ratification
+# endif
+#endif // _LIBCPP_STD_VER
+
+#if defined(__ELF__)
+# define _LIBCPP_OBJECT_FORMAT_ELF 1
+#elif defined(__MACH__)
+# define _LIBCPP_OBJECT_FORMAT_MACHO 1
+#elif defined(_WIN32)
+# define _LIBCPP_OBJECT_FORMAT_COFF 1
+#elif defined(__wasm__)
+# define _LIBCPP_OBJECT_FORMAT_WASM 1
+#else
+# error Unknown object file format
+#endif
+
+#if defined(_LIBCPP_ABI_UNSTABLE) || _LIBCPP_ABI_VERSION >= 2
+// Change short string representation so that string data starts at offset 0,
+// improving its alignment in some cases.
+# define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
+// Fix deque iterator type in order to support incomplete types.
+# define _LIBCPP_ABI_INCOMPLETE_TYPES_IN_DEQUE
+// Fix undefined behavior in how std::list stores its linked nodes.
+# define _LIBCPP_ABI_LIST_REMOVE_NODE_POINTER_UB
+// Fix undefined behavior in how __tree stores its end and parent nodes.
+# define _LIBCPP_ABI_TREE_REMOVE_NODE_POINTER_UB
+// Fix undefined behavior in how __hash_table stores its pointer types.
+# define _LIBCPP_ABI_FIX_UNORDERED_NODE_POINTER_UB
+# define _LIBCPP_ABI_FORWARD_LIST_REMOVE_NODE_POINTER_UB
+# define _LIBCPP_ABI_FIX_UNORDERED_CONTAINER_SIZE_TYPE
+// Don't use a nullptr_t simulation type in C++03 instead using C++11 nullptr
+// provided under the alternate keyword __nullptr, which changes the mangling
+// of nullptr_t. This option is ABI incompatible with GCC in C++03 mode.
+# define _LIBCPP_ABI_ALWAYS_USE_CXX11_NULLPTR
+// Define the `pointer_safety` enum as a C++11 strongly typed enumeration
+// instead of as a class simulating an enum. If this option is enabled
+// `pointer_safety` and `get_pointer_safety()` will no longer be available
+// in C++03.
+# define _LIBCPP_ABI_POINTER_SAFETY_ENUM_TYPE
+// Define a key function for `bad_function_call` in the library, to centralize
+// its vtable and typeinfo to libc++ rather than having all other libraries
+// using that class define their own copies.
+# define _LIBCPP_ABI_BAD_FUNCTION_CALL_KEY_FUNCTION
+// Enable optimized version of __do_get_(un)signed which avoids redundant copies.
+# define _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET
+// Use the smallest possible integer type to represent the index of the variant.
+// Previously libc++ used "unsigned int" exclusively.
+# define _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION
+// Unstable attempt to provide a more optimized std::function
+# define _LIBCPP_ABI_OPTIMIZED_FUNCTION
+// All the regex constants must be distinct and nonzero.
+# define _LIBCPP_ABI_REGEX_CONSTANTS_NONZERO
+#elif _LIBCPP_ABI_VERSION == 1
+# if !defined(_LIBCPP_OBJECT_FORMAT_COFF)
+// Enable compiling copies of now inline methods into the dylib to support
+// applications compiled against older libraries. This is unnecessary with
+// COFF dllexport semantics, since dllexport forces a non-inline definition
+// of inline functions to be emitted anyway. Our own non-inline copy would
+// conflict with the dllexport-emitted copy, so we disable it.
+# define _LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS
+# endif
+// Feature macros for disabling pre ABI v1 features. All of these options
+// are deprecated.
+# if defined(__FreeBSD__)
+# define _LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR
+# endif
+#endif
+
+#ifdef _LIBCPP_TRIVIAL_PAIR_COPY_CTOR
+#error "_LIBCPP_TRIVIAL_PAIR_COPY_CTOR" is no longer supported. \
+ use _LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR instead
+#endif
+
+#define _LIBCPP_CONCAT1(_LIBCPP_X,_LIBCPP_Y) _LIBCPP_X##_LIBCPP_Y
+#define _LIBCPP_CONCAT(_LIBCPP_X,_LIBCPP_Y) _LIBCPP_CONCAT1(_LIBCPP_X,_LIBCPP_Y)
+
+#ifndef _LIBCPP_ABI_NAMESPACE
+# define _LIBCPP_ABI_NAMESPACE _LIBCPP_CONCAT(__,_LIBCPP_ABI_VERSION)
+#endif
+
+#if __cplusplus < 201103L
+#define _LIBCPP_CXX03_LANG
+#endif
+
+#ifndef __has_attribute
+#define __has_attribute(__x) 0
+#endif
+
+#ifndef __has_builtin
+#define __has_builtin(__x) 0
+#endif
+
+#ifndef __has_extension
+#define __has_extension(__x) 0
+#endif
+
+#ifndef __has_feature
+#define __has_feature(__x) 0
+#endif
+
+#ifndef __has_cpp_attribute
+#define __has_cpp_attribute(__x) 0
+#endif
+
+// '__is_identifier' returns '0' if '__x' is a reserved identifier provided by
+// the compiler and '1' otherwise.
+#ifndef __is_identifier
+#define __is_identifier(__x) 1
+#endif
+
+#ifndef __has_declspec_attribute
+#define __has_declspec_attribute(__x) 0
+#endif
+
+#define __has_keyword(__x) !(__is_identifier(__x))
+
+#ifndef __has_include
+#define __has_include(...) 0
+#endif
+
+#if defined(__clang__)
+# define _LIBCPP_COMPILER_CLANG
+# ifndef __apple_build_version__
+# define _LIBCPP_CLANG_VER (__clang_major__ * 100 + __clang_minor__)
+# endif
+#elif defined(__GNUC__)
+# define _LIBCPP_COMPILER_GCC
+#elif defined(_MSC_VER)
+# define _LIBCPP_COMPILER_MSVC
+#elif defined(__IBMCPP__)
+# define _LIBCPP_COMPILER_IBM
+#endif
+
+#if defined(_LIBCPP_COMPILER_GCC) && __cplusplus < 201103L
+#error "libc++ does not support using GCC with C++03. Please enable C++11"
+#endif
+
+// FIXME: ABI detection should be done via compiler builtin macros. This
+// is just a placeholder until Clang implements such macros. For now assume
+// that Windows compilers pretending to be MSVC++ target the Microsoft ABI,
+// and allow the user to explicitly specify the ABI to handle cases where this
+// heuristic falls short.
+#if defined(_LIBCPP_ABI_FORCE_ITANIUM) && defined(_LIBCPP_ABI_FORCE_MICROSOFT)
+# error "Only one of _LIBCPP_ABI_FORCE_ITANIUM and _LIBCPP_ABI_FORCE_MICROSOFT can be defined"
+#elif defined(_LIBCPP_ABI_FORCE_ITANIUM)
+# define _LIBCPP_ABI_ITANIUM
+#elif defined(_LIBCPP_ABI_FORCE_MICROSOFT)
+# define _LIBCPP_ABI_MICROSOFT
+#else
+# if defined(_WIN32) && defined(_MSC_VER)
+# define _LIBCPP_ABI_MICROSOFT
+# else
+# define _LIBCPP_ABI_ITANIUM
+# endif
+#endif
+
+#if defined(_LIBCPP_ABI_MICROSOFT) && !defined(_LIBCPP_NO_VCRUNTIME)
+# define _LIBCPP_ABI_VCRUNTIME
+#endif
+
+// Need to detect which libc we're using if we're on Linux.
+#if defined(__linux__)
+# include
+# if defined(__GLIBC_PREREQ)
+# define _LIBCPP_GLIBC_PREREQ(a, b) __GLIBC_PREREQ(a, b)
+# else
+# define _LIBCPP_GLIBC_PREREQ(a, b) 0
+# endif // defined(__GLIBC_PREREQ)
+#endif // defined(__linux__)
+
+#ifdef __LITTLE_ENDIAN__
+# if __LITTLE_ENDIAN__
+# define _LIBCPP_LITTLE_ENDIAN
+# endif // __LITTLE_ENDIAN__
+#endif // __LITTLE_ENDIAN__
+
+#ifdef __BIG_ENDIAN__
+# if __BIG_ENDIAN__
+# define _LIBCPP_BIG_ENDIAN
+# endif // __BIG_ENDIAN__
+#endif // __BIG_ENDIAN__
+
+#ifdef __BYTE_ORDER__
+# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+# define _LIBCPP_LITTLE_ENDIAN
+# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+# define _LIBCPP_BIG_ENDIAN
+# endif // __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#endif // __BYTE_ORDER__
+
+#ifdef __FreeBSD__
+# include
+# include
+# if _BYTE_ORDER == _LITTLE_ENDIAN
+# define _LIBCPP_LITTLE_ENDIAN
+# else // _BYTE_ORDER == _LITTLE_ENDIAN
+# define _LIBCPP_BIG_ENDIAN
+# endif // _BYTE_ORDER == _LITTLE_ENDIAN
+# ifndef __LONG_LONG_SUPPORTED
+# define _LIBCPP_HAS_NO_LONG_LONG
+# endif // __LONG_LONG_SUPPORTED
+#endif // __FreeBSD__
+
+#ifdef __NetBSD__
+# include
+# if _BYTE_ORDER == _LITTLE_ENDIAN
+# define _LIBCPP_LITTLE_ENDIAN
+# else // _BYTE_ORDER == _LITTLE_ENDIAN
+# define _LIBCPP_BIG_ENDIAN
+# endif // _BYTE_ORDER == _LITTLE_ENDIAN
+# define _LIBCPP_HAS_QUICK_EXIT
+#endif // __NetBSD__
+
+#if defined(_WIN32)
+# define _LIBCPP_WIN32API
+# define _LIBCPP_LITTLE_ENDIAN
+# define _LIBCPP_SHORT_WCHAR 1
+// Both MinGW and native MSVC provide a "MSVC"-like environment
+# define _LIBCPP_MSVCRT_LIKE
+// If mingw not explicitly detected, assume using MS C runtime only if
+// a MS compatibility version is specified.
+# if defined(_MSC_VER) && !defined(__MINGW32__)
+# define _LIBCPP_MSVCRT // Using Microsoft's C Runtime library
+# endif
+# if (defined(_M_AMD64) || defined(__x86_64__)) || (defined(_M_ARM) || defined(__arm__))
+# define _LIBCPP_HAS_BITSCAN64
+# endif
+# define _LIBCPP_HAS_OPEN_WITH_WCHAR
+# if defined(_LIBCPP_MSVCRT)
+# define _LIBCPP_HAS_QUICK_EXIT
+# endif
+
+// Some CRT APIs are unavailable to store apps
+# if defined(WINAPI_FAMILY)
+# include