Skip to content

Commit 6df14b5

Browse files
committed
Add cross-platform storage and secure storage APIs
Introduces a unified Storage interface and implements Preferences and SecureStorage classes for key-value storage, with platform-specific backends for Linux, macOS, iOS, Android, Windows, and OHOS. Adds C and C++ example applications demonstrating usage. Provides a C API for both preferences and secure storage, and updates CMakeLists to include new examples. Platform implementations for secure storage are currently stubs except for Preferences on Linux and macOS.
1 parent 8969a98 commit 6df14b5

25 files changed

+2695
-0
lines changed

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ add_subdirectory(examples/id_allocator_example)
1414
add_subdirectory(examples/keyboard_example)
1515
add_subdirectory(examples/menu_example)
1616
add_subdirectory(examples/menu_c_example)
17+
add_subdirectory(examples/storage_example)
18+
add_subdirectory(examples/storage_c_example)
1719
add_subdirectory(examples/tray_icon_example)
1820
add_subdirectory(examples/tray_icon_c_example)
1921
add_subdirectory(examples/window_c_example)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
cmake_minimum_required(VERSION 3.10)
2+
3+
project(storage_c_example)
4+
5+
set(CMAKE_C_STANDARD 11)
6+
set(CMAKE_C_STANDARD_REQUIRED ON)
7+
8+
# Add executable
9+
add_executable(storage_c_example main.c)
10+
11+
# Link nativeapi library
12+
target_link_libraries(storage_c_example PRIVATE nativeapi)
13+
14+
# Platform-specific settings
15+
if(APPLE)
16+
target_link_libraries(storage_c_example PRIVATE "-framework Cocoa" "-framework Security")
17+
elseif(WIN32)
18+
target_link_libraries(storage_c_example PRIVATE user32 shell32 dwmapi gdiplus crypt32)
19+
elseif(UNIX)
20+
find_package(PkgConfig REQUIRED)
21+
pkg_check_modules(OPENSSL REQUIRED IMPORTED_TARGET openssl)
22+
target_link_libraries(storage_c_example PRIVATE PkgConfig::OPENSSL pthread)
23+
endif()
24+

examples/storage_c_example/main.c

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
#include <nativeapi.h>
2+
#include <stdio.h>
3+
#include <stdlib.h>
4+
5+
void demo_preferences() {
6+
printf("=== Preferences C API Demo ===\n");
7+
8+
// Create preferences with custom scope
9+
native_preferences_t prefs = native_preferences_create_with_scope("my_c_app");
10+
if (!prefs) {
11+
printf("Failed to create preferences\n");
12+
return;
13+
}
14+
15+
// Store some values
16+
native_preferences_set(prefs, "username", "alice");
17+
native_preferences_set(prefs, "theme", "light");
18+
native_preferences_set(prefs, "font_size", "12");
19+
20+
// Retrieve values
21+
char* username = native_preferences_get(prefs, "username", "");
22+
char* theme = native_preferences_get(prefs, "theme", "");
23+
char* font_size = native_preferences_get(prefs, "font_size", "");
24+
25+
printf("Username: %s\n", username);
26+
printf("Theme: %s\n", theme);
27+
printf("Font size: %s\n", font_size);
28+
29+
native_preferences_free_string(username);
30+
native_preferences_free_string(theme);
31+
native_preferences_free_string(font_size);
32+
33+
// Check if key exists
34+
if (native_preferences_contains(prefs, "language")) {
35+
char* language = native_preferences_get(prefs, "language", "");
36+
printf("Language: %s\n", language);
37+
native_preferences_free_string(language);
38+
} else {
39+
char* default_lang = native_preferences_get(prefs, "language", "en");
40+
printf("Language not set, using default: %s\n", default_lang);
41+
native_preferences_free_string(default_lang);
42+
}
43+
44+
// Get all keys
45+
char** keys = NULL;
46+
size_t count = 0;
47+
if (native_preferences_get_keys(prefs, &keys, &count)) {
48+
printf("\nAll keys (%zu):\n", count);
49+
for (size_t i = 0; i < count; i++) {
50+
char* value = native_preferences_get(prefs, keys[i], "");
51+
printf(" - %s: %s\n", keys[i], value);
52+
native_preferences_free_string(value);
53+
}
54+
native_preferences_free_string_array(keys, count);
55+
}
56+
57+
// Get size
58+
size_t size = native_preferences_get_size(prefs);
59+
printf("Total items: %zu\n", size);
60+
61+
// Remove a key
62+
printf("\nRemoving 'font_size'...\n");
63+
native_preferences_remove(prefs, "font_size");
64+
printf("Size after removal: %zu\n", native_preferences_get_size(prefs));
65+
66+
// Get scope
67+
char* scope = native_preferences_get_scope(prefs);
68+
printf("Scope: %s\n", scope);
69+
native_preferences_free_string(scope);
70+
71+
// Clean up
72+
native_preferences_destroy(prefs);
73+
74+
printf("\n");
75+
}
76+
77+
void demo_secure_storage() {
78+
printf("=== Secure Storage C API Demo ===\n");
79+
80+
// Check if secure storage is available
81+
if (!native_secure_storage_is_available()) {
82+
printf("Secure storage is not available on this platform\n");
83+
return;
84+
}
85+
86+
// Create secure storage with custom scope
87+
native_secure_storage_t storage = native_secure_storage_create_with_scope("my_c_app_secure");
88+
if (!storage) {
89+
printf("Failed to create secure storage\n");
90+
return;
91+
}
92+
93+
// Store sensitive data
94+
native_secure_storage_set(storage, "api_key", "sk-c-api-1234567890");
95+
native_secure_storage_set(storage, "secret", "my_secret_value");
96+
native_secure_storage_set(storage, "token", "bearer_token_xyz");
97+
98+
// Retrieve sensitive data
99+
char* api_key = native_secure_storage_get(storage, "api_key", "");
100+
char* secret = native_secure_storage_get(storage, "secret", "");
101+
102+
printf("API Key: %s\n", api_key);
103+
printf("Secret: %s\n", secret);
104+
105+
native_secure_storage_free_string(api_key);
106+
native_secure_storage_free_string(secret);
107+
108+
// Get all keys
109+
char** keys = NULL;
110+
size_t count = 0;
111+
if (native_secure_storage_get_keys(storage, &keys, &count)) {
112+
printf("\nStored secure items (%zu):\n", count);
113+
for (size_t i = 0; i < count; i++) {
114+
printf(" - %s: [encrypted]\n", keys[i]);
115+
}
116+
native_secure_storage_free_string_array(keys, count);
117+
}
118+
119+
// Check existence
120+
if (native_secure_storage_contains(storage, "api_key")) {
121+
printf("\nAPI key is securely stored\n");
122+
}
123+
124+
// Get size
125+
size_t size = native_secure_storage_get_size(storage);
126+
printf("Total secure items: %zu\n", size);
127+
128+
// Remove sensitive data
129+
printf("\nRemoving 'token'...\n");
130+
native_secure_storage_remove(storage, "token");
131+
printf("Size after removal: %zu\n", native_secure_storage_get_size(storage));
132+
133+
// Get scope
134+
char* storage_scope = native_secure_storage_get_scope(storage);
135+
printf("Scope: %s\n", storage_scope);
136+
native_secure_storage_free_string(storage_scope);
137+
138+
// Clean up (optional: clear all for this demo)
139+
// native_secure_storage_clear(storage);
140+
141+
native_secure_storage_destroy(storage);
142+
143+
printf("\n");
144+
}
145+
146+
int main() {
147+
printf("Storage C API Example\n");
148+
printf("=====================\n\n");
149+
150+
// Demo Preferences (plain text storage)
151+
demo_preferences();
152+
153+
// Demo SecureStorage (encrypted storage)
154+
demo_secure_storage();
155+
156+
printf("Done! Check your system's storage locations:\n");
157+
printf(" - macOS: NSUserDefaults & Keychain\n");
158+
printf(" - Windows: Registry & DPAPI\n");
159+
printf(" - Linux: ~/.config/nativeapi & ~/.local/share/nativeapi\n");
160+
161+
return 0;
162+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
cmake_minimum_required(VERSION 3.10)
2+
3+
project(storage_example)
4+
5+
set(CMAKE_CXX_STANDARD 17)
6+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
7+
8+
# Add executable
9+
add_executable(storage_example main.cpp)
10+
11+
# Link nativeapi library
12+
target_link_libraries(storage_example PRIVATE nativeapi)
13+
14+
# Platform-specific settings
15+
if(APPLE)
16+
target_link_libraries(storage_example PRIVATE "-framework Cocoa" "-framework Security")
17+
elseif(WIN32)
18+
target_link_libraries(storage_example PRIVATE user32 shell32 dwmapi gdiplus crypt32)
19+
elseif(UNIX)
20+
find_package(PkgConfig REQUIRED)
21+
pkg_check_modules(OPENSSL REQUIRED IMPORTED_TARGET openssl)
22+
target_link_libraries(storage_example PRIVATE PkgConfig::OPENSSL pthread)
23+
endif()
24+

examples/storage_example/main.cpp

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
#include <nativeapi.h>
2+
#include <iostream>
3+
4+
using namespace nativeapi;
5+
6+
void DemoPreferences() {
7+
std::cout << "=== Preferences Demo ===" << std::endl;
8+
9+
// Create preferences with custom scope
10+
Preferences prefs("my_app");
11+
12+
// Store some values
13+
prefs.Set("username", "john_doe");
14+
prefs.Set("theme", "dark");
15+
prefs.Set("font_size", "14");
16+
17+
// Retrieve values
18+
std::cout << "Username: " << prefs.Get("username") << std::endl;
19+
std::cout << "Theme: " << prefs.Get("theme") << std::endl;
20+
std::cout << "Font size: " << prefs.Get("font_size") << std::endl;
21+
22+
// Check if key exists
23+
if (prefs.Contains("language")) {
24+
std::cout << "Language: " << prefs.Get("language") << std::endl;
25+
} else {
26+
std::cout << "Language not set, using default: " << prefs.Get("language", "en") << std::endl;
27+
}
28+
29+
// Get all keys
30+
auto keys = prefs.GetKeys();
31+
std::cout << "\nAll keys (" << prefs.GetSize() << "):" << std::endl;
32+
for (const auto& key : keys) {
33+
std::cout << " - " << key << ": " << prefs.Get(key) << std::endl;
34+
}
35+
36+
// Remove a key
37+
std::cout << "\nRemoving 'font_size'..." << std::endl;
38+
prefs.Remove("font_size");
39+
std::cout << "Size after removal: " << prefs.GetSize() << std::endl;
40+
41+
std::cout << std::endl;
42+
}
43+
44+
void DemoSecureStorage() {
45+
std::cout << "=== Secure Storage Demo ===" << std::endl;
46+
47+
// Check if secure storage is available
48+
if (!SecureStorage::IsAvailable()) {
49+
std::cout << "Secure storage is not available on this platform" << std::endl;
50+
return;
51+
}
52+
53+
// Create secure storage with custom scope
54+
SecureStorage storage("my_app_secure");
55+
56+
// Store sensitive data
57+
storage.Set("api_token", "sk-1234567890abcdef");
58+
storage.Set("encryption_key", "very_secret_key_12345");
59+
storage.Set("password", "super_secret_password");
60+
61+
// Retrieve sensitive data
62+
std::cout << "API Token: " << storage.Get("api_token") << std::endl;
63+
std::cout << "Password: " << storage.Get("password") << std::endl;
64+
65+
// Get all keys (values are encrypted at rest)
66+
auto keys = storage.GetKeys();
67+
std::cout << "\nStored secure items (" << storage.GetSize() << "):" << std::endl;
68+
for (const auto& key : keys) {
69+
std::cout << " - " << key << ": [encrypted]" << std::endl;
70+
}
71+
72+
// Check existence
73+
if (storage.Contains("api_token")) {
74+
std::cout << "\nAPI token is securely stored" << std::endl;
75+
}
76+
77+
// Remove sensitive data
78+
std::cout << "\nRemoving 'password'..." << std::endl;
79+
storage.Remove("password");
80+
std::cout << "Size after removal: " << storage.GetSize() << std::endl;
81+
82+
// Clear all (for cleanup in this demo)
83+
// storage.Clear();
84+
85+
std::cout << std::endl;
86+
}
87+
88+
void DemoStorageInterface() {
89+
std::cout << "=== Storage Interface Demo ===" << std::endl;
90+
91+
// Use Storage interface polymorphically
92+
Storage* storage = new Preferences("polymorphic_test");
93+
94+
storage->Set("test_key", "test_value");
95+
std::cout << "Stored via Storage interface: " << storage->Get("test_key") << std::endl;
96+
97+
delete storage;
98+
99+
std::cout << std::endl;
100+
}
101+
102+
int main() {
103+
std::cout << "Storage Example - Web Storage-like API for C++" << std::endl;
104+
std::cout << "================================================" << std::endl;
105+
std::cout << std::endl;
106+
107+
try {
108+
// Demo Preferences (plain text storage)
109+
DemoPreferences();
110+
111+
// Demo SecureStorage (encrypted storage)
112+
DemoSecureStorage();
113+
114+
// Demo polymorphic usage
115+
DemoStorageInterface();
116+
117+
std::cout << "Done! Check your system's storage locations:" << std::endl;
118+
std::cout << " - macOS: NSUserDefaults & Keychain" << std::endl;
119+
std::cout << " - Windows: Registry & DPAPI" << std::endl;
120+
std::cout << " - Linux: ~/.config/nativeapi & ~/.local/share/nativeapi" << std::endl;
121+
122+
} catch (const std::exception& e) {
123+
std::cerr << "Error: " << e.what() << std::endl;
124+
return 1;
125+
}
126+
127+
return 0;
128+
}

include/nativeapi.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,13 @@
1212
#include "../src/foundation/event_emitter.h"
1313
#include "../src/foundation/geometry.h"
1414
#include "../src/foundation/id_allocator.h"
15+
#include "../src/foundation/storage.h"
1516
#include "../src/image.h"
1617
#include "../src/keyboard_event.h"
1718
#include "../src/keyboard_monitor.h"
1819
#include "../src/menu.h"
20+
#include "../src/preferences.h"
21+
#include "../src/secure_storage.h"
1922
#include "../src/tray_icon.h"
2023
#include "../src/tray_icon_event.h"
2124
#include "../src/tray_manager.h"
@@ -34,6 +37,7 @@
3437
#include "../src/capi/keyboard_monitor_c.h"
3538
#include "../src/capi/menu_c.h"
3639
#include "../src/capi/run_example_app_c.h"
40+
#include "../src/capi/storage_c.h"
3741
#include "../src/capi/string_utils_c.h"
3842
#include "../src/capi/tray_icon_c.h"
3943
#include "../src/capi/tray_manager_c.h"

0 commit comments

Comments
 (0)