Updated Library Documentation (markdown)
@@ -1 +1,613 @@
|
||||
## libhelper library
|
||||
It provides functions, classes and macros that will make your work easier when writing your string program, such as the name `libhelper`.
|
||||
|
||||
---
|
||||
|
||||
### Helpful macros and variables
|
||||
`libhelper` provides some macros and variables to make your work easier.
|
||||
|
||||
```c++
|
||||
// File/directory modes
|
||||
constexpr mode_t DEFAULT_FILE_PERMS = 0644;
|
||||
constexpr mode_t DEFAULT_EXTENDED_FILE_PERMS = 0755;
|
||||
constexpr mode_t DEFAULT_DIR_PERMS = 0755;
|
||||
|
||||
// Boolean alternatives (is there anyone who will actually use it???)
|
||||
constexpr int YES = 1; // YES = true
|
||||
constexpr int NO = 0; // NO = false
|
||||
|
||||
// Macros that can be useful for size conversions
|
||||
#define KB(x) (x * 1024) // KB(8) = 8192 (8 * 1024)
|
||||
#define MB(x) (KB(x) * 1024) // MB(4) = 4194304 (KB(4) * 1024)
|
||||
#define GB(x) (MB(x) * 1024) // GB(1) = 1073741824 (MB(1) * 1024)
|
||||
|
||||
// Conversion from bytes to other units
|
||||
#define TO_KB(x) (x / 1024) // TO_KB(1024) = 1
|
||||
#define TO_MB(x) (TO_KB(x) / 1024) // TO_MB(2048) (2048 / 1024)
|
||||
#define TO_GB(x) (TO_MB(x) / 1024) // TO_GB(1048576) (TO_MB(1048576) / 1024)
|
||||
|
||||
// Macros to use for text decoration
|
||||
#define STYLE_RESET "\033[0m"
|
||||
#define BOLD "\033[1m"
|
||||
#define FAINT "\033[2m"
|
||||
#define ITALIC "\033[3m"
|
||||
#define UNDERLINE "\033[4m"
|
||||
#define BLINC "\033[5m"
|
||||
#define FAST_BLINC "\033[6m"
|
||||
#define STRIKE_THROUGHT "\033[9m"
|
||||
#define NO_UNDERLINE "\033[24m"
|
||||
#define NO_BLINC "\033[25m"
|
||||
#define RED "\033[31m"
|
||||
#define GREEN "\033[32m"
|
||||
#define YELLOW "\033[33m"
|
||||
|
||||
// If NO_C_TYPE_HANDLERS is defined, these macros are can't defined.
|
||||
#ifndef NO_C_TYPE_HANDLERS
|
||||
// ABORT(message), ex: ABORT("memory error!\n")
|
||||
#define ABORT(msg) \
|
||||
do { \
|
||||
fprintf(stderr, "%s%sCRITICAL ERROR%s: %s\nAborting...\n", BOLD, RED, \
|
||||
STYLE_RESET, msg); \
|
||||
abort(); \
|
||||
} while (0)
|
||||
|
||||
// ERROR(message, exit), ex: ERROR("an error occured.\n", 1)
|
||||
#define ERROR(msg, code) \
|
||||
do { \
|
||||
fprintf(stderr, "%s%sERROR%s: %s", BOLD, RED, STYLE_RESET, msg); \
|
||||
exit(code); \
|
||||
} while (0)
|
||||
|
||||
// WARNING(message), ex: WARNING("using default setting.\n")
|
||||
#define WARNING(msg) \
|
||||
fprintf(stderr, "%s%sWARNING%s: %s", BOLD, YELLOW, STYLE_RESET, msg);
|
||||
|
||||
// INFO(message), ex: INFO("operation ended.\n")
|
||||
#define INFO(msg) \
|
||||
fprintf(stdout, "%s%sINFO%s: %s", BOLD, GREEN, STYLE_RESET, msg);
|
||||
#endif // #ifndef NO_C_TYPE_HANDLERS
|
||||
|
||||
// Common version string creator.
|
||||
// Don't forget to define the BUILD*** macros.
|
||||
#define MKVERSION(name) \
|
||||
char vinfo[512]; \
|
||||
sprintf(vinfo, \
|
||||
"%s %s [%s %s]\nBuildType: %s\nCMakeVersion: %s\nCompilerVersion: " \
|
||||
"%s\nBuildFlags: %s", \
|
||||
name, BUILD_VERSION, BUILD_DATE, BUILD_TIME, BUILD_TYPE, \
|
||||
BUILD_CMAKE_VERSION, BUILD_COMPILER_VERSION, BUILD_FLAGS); \
|
||||
return std::string(vinfo)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Classes
|
||||
`libhelper` provides three classes in total. One is for logging (used with macros), one is an error class created with `std::exception`, and the third is a garbage collector.
|
||||
|
||||
---
|
||||
|
||||
#### Logging Class
|
||||
A total of four logging levels are provided: information, warning, error, and abort (critical error).
|
||||
|
||||
```c++
|
||||
enum LogLevels {
|
||||
INFO = static_cast<int>('I'),
|
||||
WARNING = static_cast<int>('W'),
|
||||
ERROR = static_cast<int>('E'),
|
||||
ABORT = static_cast<int>('A')
|
||||
};
|
||||
|
||||
// It actually seemed more logical to use the numerical equivalents of logical letters instead of numbers like 1-2.
|
||||
```
|
||||
|
||||
A class called `Logging` handles everything. However, logging directly using the class isn't practical. There are some macros for this:
|
||||
|
||||
```c++
|
||||
#define LOG(level) \
|
||||
Helper::Logger(level, __func__, Helper::LoggingProperties::FILE.data(), \
|
||||
Helper::LoggingProperties::NAME.data(), __FILE__, __LINE__)
|
||||
#define LOGN(name, level) \
|
||||
Helper::Logger(level, __func__, Helper::LoggingProperties::FILE.data(), \
|
||||
name, __FILE__, __LINE__)
|
||||
#define LOGNF(name, file, level) \
|
||||
Helper::Logger(level, file, name, __FILE__, __LINE__)
|
||||
|
||||
#define LOG_IF(level, condition) \
|
||||
if (condition) \
|
||||
Helper::Logger(level, __func__, Helper::LoggingProperties::FILE.data(), \
|
||||
Helper::LoggingProperties::NAME.data(), __FILE__, __LINE__)
|
||||
#define LOGN_IF(name, level, condition) \
|
||||
if (condition) \
|
||||
Helper::Logger(level, __func__, Helper::LoggingProperties::FILE.data(), \
|
||||
name, __FILE__, __LINE__)
|
||||
#define LOGNF_IF(name, file, level, condition) \
|
||||
if (condition) Helper::Logger(level, __func__, file, name, __FILE__, __LINE__)
|
||||
```
|
||||
|
||||
There are some settings available for logging. These are stored in the `Helper::LoggingProperties` namespace. These are: `FILE` (`std::string_view`), `NAME` (`std::string_view`), `PRINT` (`bool`), `DISABLE` (`bool`). The default values are:
|
||||
|
||||
```c++
|
||||
// Utilities.cpp
|
||||
|
||||
namespace Helper {
|
||||
namespace LoggingProperties {
|
||||
std::string_view FILE = "last_logs.log", NAME = "main";
|
||||
bool PRINT = NO, DISABLE = NO;
|
||||
} // namespace LoggingProperties
|
||||
} // namespace Helper
|
||||
```
|
||||
|
||||
- `PRINT` specifies whether the log will be printed to the screen. This can be useful for things like verbose logging. The default is `NO` (`false`).
|
||||
- You can control logging with `DISABLE`. The default is `NO` (`false`). Setting it to true stops logging. No writing to the file.
|
||||
- `FILE` is the file where the log content will be saved. By default, it's `last_logs.log`. It's created in your current directory.
|
||||
- `NAME` is the name of the program that prints the log that will appear in the log. By default, it is `main`.
|
||||
|
||||
You can change these settings directly or use the provided functions.
|
||||
|
||||
```c++
|
||||
namespace Helper {
|
||||
namespace LoggingProperties {
|
||||
void set(std::string_view name, std::string_view file);
|
||||
void setProgramName(std::string_view name);
|
||||
void setLogFile(std::string_view file);
|
||||
void setPrinting(int state);
|
||||
void setLoggingState(int state); // Disable/enable logging
|
||||
|
||||
void reset();
|
||||
} // namespace LoggingProperties
|
||||
} // namespae Helper
|
||||
```
|
||||
|
||||
It's pretty clear what the functions named `set***` do. But I'd still like to mention `reset()`. It restores default settings.
|
||||
Now we can reinforce it with use cases. That would be good.
|
||||
|
||||
```c++
|
||||
#include <libhelper/lib.hpp>
|
||||
#include <iostream>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
Helper::LoggingProperties::set("pmt", "/storage/emulated/0/Dccuments/last_pmt_logs.log");
|
||||
|
||||
LOG(INFO) << "Hello World!" << std::endl;
|
||||
LOG_IF(WARNING, argc < 2) << "No argument speficed!" << std::endl;
|
||||
LOGN(argv[0], INFO) << "Hello World from " << argv[0] << " program!" << std::endl;
|
||||
LOGNF(argv[0], "last_logs_test.log", INFO) << "LOGNF() test!!!" << std::endl;
|
||||
LOGN_IF(argv[0], WARNING, argc < 2) << "No argument speficed! (test 2)" << std::endl;
|
||||
LOGNF_IF(argv[0], "last_logs_test.log", ERROR, argc > 3) << "Too many argument!" << std::endl;
|
||||
|
||||
std::cout << "Program complete!" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### Error Class
|
||||
It is a throwable error class derived from `std::exception`. Thrown errors are also recorded in the logs.
|
||||
|
||||
```c++
|
||||
#include <libhelper/lib.hpp>
|
||||
#include <iostream>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
try {
|
||||
if (argc < 2)
|
||||
throw Helper::Error("No enoght argument!");
|
||||
} catch (Helper::Error &e) {
|
||||
std::cerr << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### Garbage Collector Class
|
||||
The garbage collector is there to free allocated memory (certain types) and close file pointers. In other words, it handles your work for you. It also has additional auxiliary functions.
|
||||
|
||||
```c++
|
||||
namespace Helper {
|
||||
class garbageCollector {
|
||||
// Other definations...
|
||||
|
||||
public:
|
||||
~garbageCollector();
|
||||
|
||||
void delAfterProgress(char *&_ptr); // Delete allocated char variables after function
|
||||
void delAfterProgress(uint8_t *&_ptr); // Delete allocated uint8_t variables after funtion
|
||||
void delFileAfterProgress(const std::string &path); // Delete input file after function
|
||||
void closeAfterProgress(FILE *&_fp); // Close input file pointers after function
|
||||
void closeAfterProgress(DIR *&_dp); // Close input directory pointers after function
|
||||
void closeAfterProgress(int _fd); // Close input file descriptor after function
|
||||
|
||||
// You can add whatever you want by using it multiple times
|
||||
};
|
||||
|
||||
// Open input path with flags and add to integrity list. And return file descriptor. open() is emulated
|
||||
[[nodiscard]] int openAndAddToCloseList(const std::string_view &path,
|
||||
garbageCollector &collector, int flags,
|
||||
mode_t mode = 0000);
|
||||
// fopen() is emulated.
|
||||
[[nodiscard]] FILE *openAndAddToCloseList(const std::string_view &path,
|
||||
garbageCollector &collector,
|
||||
const char *mode);
|
||||
[[nodiscard]] DIR *openAndAddToCloseList(const std::string_view &path,
|
||||
garbageCollector &collector);
|
||||
|
||||
// You can need use returned values!!! Because these functions marked as nodiscard
|
||||
} // namespace Helper
|
||||
```
|
||||
|
||||
Usage example...
|
||||
```c++
|
||||
#include <libhelper/lib.hpp>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <iostream>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
Helper::garbageCollector collector;
|
||||
|
||||
int fd1 = open("file.txt", O_TRUNC | O_CREAT, 0644);
|
||||
collector.closeAfterProgress(fd1); // no need close() anymore
|
||||
// You can do the same with FILE or DIR
|
||||
// Do your file progresses...
|
||||
|
||||
// Delete file.txt automaticly after program
|
||||
collector.delFileAfterProgess("file.txt");
|
||||
|
||||
int fd2 = Helper::openAndAddToCloseList("file2.txt", collector, O_TRUNC, DEFAULT_FILE_PERMS);
|
||||
// Do your file progresses...
|
||||
// WARNING: It does not check whether the file is opened or not.
|
||||
|
||||
DIR *dp = Helper::openAndAddToCloseList("dir1", collector);
|
||||
// Do your directory progresses...
|
||||
// WARNING: It does not check whether the directory is opened or not.
|
||||
|
||||
auto *buffer = new char[4096]; // Allocate memory
|
||||
collector.delAfterProgrss(buffer);
|
||||
// You can do the same with uint8_t
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### Functions
|
||||
`libhelper` provides many helper functions. Some of these throw `Helper::Error`. We'll cover each one with code examples.
|
||||
|
||||
```c++
|
||||
#include <libhelper/lib.hpp>
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
/**
|
||||
Checker functions - don't throw Helper::Error
|
||||
|
||||
bool hasSuperUser();
|
||||
// Returns true if user id equals AID_ROOT.
|
||||
// See srclib/libhelper/include/private/android_filesystem_config.h
|
||||
|
||||
bool hasAdbPermissions();
|
||||
// Returns true if user id equals AID_SHELL.
|
||||
// See srclib/libhelper/include/private/android_filesystem_config.h
|
||||
|
||||
bool isExists(std::string_view entry);
|
||||
// Returns true if entry exists (file or directory).
|
||||
|
||||
bool fileIsExists(std::string_view file);
|
||||
// Returns true if given file exists.
|
||||
|
||||
bool directoryIsExists(std::string_view directory);
|
||||
// Returns true if given directory exists.
|
||||
|
||||
bool linkIsExists(std::string_view entry);
|
||||
// Returns true if entry is symbolic or hard link.
|
||||
|
||||
bool isLink(std::string_view entry);
|
||||
// Returns true if entry is a symbolic link.
|
||||
|
||||
bool isSymbolicLink(std::string_view entry);
|
||||
// Alias of isLink().
|
||||
|
||||
bool isHardLink(std::string_view entry);
|
||||
// Returns true if entry is a hard link.
|
||||
|
||||
bool areLinked(std::string_view entry1, std::string_view entry2);
|
||||
// Returns true if entry1 links to entry2 (symbolic link).
|
||||
*/
|
||||
|
||||
if (!Helper::hasSuperUser())
|
||||
std::cout << "Super user privileges not given." << std::endl;
|
||||
|
||||
if (Helper::hasAdbPermissions())
|
||||
std::cout << "You have ADB shell privileges." << std::endl;
|
||||
|
||||
if (Helper::isExists("myentry"))
|
||||
std::cout << "myentry exists." << std::endl;
|
||||
|
||||
if (Helper::fileIsExists("file.txt"))
|
||||
std::cout << "file.txt exists." << std::endl;
|
||||
|
||||
if (Helper::directoryIsExists("mydir"))
|
||||
std::cout << "mydir exists." << std::endl;
|
||||
|
||||
if (Helper::linkIsExists("mylinked_entry"))
|
||||
std::cout << "mylinked_entry is symbolic or hard link." << std::endl;
|
||||
|
||||
if (Helper::isLink("mylinked_entry"))
|
||||
std::cout << "mylinked_entry is symbolic link." << std::endl;
|
||||
|
||||
if (Helper::isHardLink("myhardlinked_entry"))
|
||||
std::cout << "myhardlinked_entry is hard link." << std::endl;
|
||||
|
||||
if (Helper::areLinked("mylinked_entry", "myentry"))
|
||||
std::cout << "mylinked_entry links to myentry." << std::endl;
|
||||
|
||||
|
||||
/**
|
||||
File I/O - don't throw Helper::Error
|
||||
|
||||
bool writeFile(std::string_view file, std::string_view text);
|
||||
// Writes given text into file.
|
||||
// If file does not exist, it is automatically created.
|
||||
// Returns true on success.
|
||||
|
||||
std::optional<std::string> readFile(std::string_view file);
|
||||
// Reads file content into string.
|
||||
// On success returns file content.
|
||||
// On error returns std::nullopt.
|
||||
*/
|
||||
|
||||
if (Helper::writeFile("file.txt", "hello world"))
|
||||
std::cout << "file.txt written." << std::endl;
|
||||
|
||||
auto result = Helper::readFile("file.txt");
|
||||
if (!result)
|
||||
std::cerr << "Cannot read file.txt." << std::endl;
|
||||
else
|
||||
std::cout << "file.txt: " << *result << std::endl;
|
||||
|
||||
|
||||
/**
|
||||
Creators - don't throw Helper::Error
|
||||
|
||||
bool makeDirectory(std::string_view path);
|
||||
// Creates a directory at given path.
|
||||
// Returns true on success.
|
||||
|
||||
bool makeRecursiveDirectory(std::string_view paths);
|
||||
// Creates all directories in given path recursively.
|
||||
// Returns true on success.
|
||||
|
||||
bool createFile(std::string_view path);
|
||||
// Creates an empty file at given path.
|
||||
// Returns true on success.
|
||||
|
||||
bool createSymlink(std::string_view entry1, std::string_view entry2);
|
||||
// Creates a symbolic link entry2 pointing to entry1.
|
||||
// Returns true on success.
|
||||
*/
|
||||
|
||||
if (Helper::makeDirectory("dir"))
|
||||
std::cout << "dir created." << std::endl;
|
||||
|
||||
if (Helper::makeRecursiveDirectory("dir1/dir2/dir3"))
|
||||
std::cout << "dir1/dir2/dir3 created." << std::endl;
|
||||
|
||||
if (Helper::createFile("newfile.txt"))
|
||||
std::cout << "newfile.txt created." << std::endl;
|
||||
|
||||
if (Helper::createSymlink("newfile.txt", "newfile_symlink.txt"))
|
||||
std::cout << "newfile.txt symlinked to newfile_symlink.txt." << std::endl;
|
||||
|
||||
|
||||
/**
|
||||
Removers - don't throw Helper::Error
|
||||
|
||||
bool eraseEntry(std::string_view entry);
|
||||
// Removes file or empty directory.
|
||||
// Returns true on success.
|
||||
|
||||
bool eraseDirectoryRecursive(std::string_view directory);
|
||||
// Removes directory and all its contents recursively.
|
||||
// Returns true on success.
|
||||
*/
|
||||
|
||||
if (Helper::eraseEntry("file.txt"))
|
||||
std::cout << "file.txt erased." << std::endl;
|
||||
|
||||
if (Helper::eraseDirectoryRecursive("dir1/dir2/dir3"))
|
||||
std::cout << "dir1/dir2/dir3 erased." << std::endl;
|
||||
|
||||
|
||||
/**
|
||||
Getters - don't throw Helper::Error
|
||||
|
||||
int64_T fileSize(std::string_view file);
|
||||
// Returns file size in bytes.
|
||||
// On error returns -1.
|
||||
|
||||
std::string readSymlink(std::string_view entry);
|
||||
// Reads the target of symbolic link.
|
||||
// Returns empty string on error.
|
||||
*/
|
||||
|
||||
if (size_t size = Helper::fileSize("newfile.txt"); size == -1)
|
||||
std::cout << "Cannot get size of newfile.txt" << std::endl;
|
||||
else
|
||||
std::cout << "Size of newfile.txt: " << size << std::endl;
|
||||
|
||||
if (std::string s = Helper::readSymlink("newfile_symlink.txt"); s.empty())
|
||||
std::cout << "Cannot read symlink: newfile_symlink.txt" << std::endl;
|
||||
else
|
||||
std::cout << "newfile_symlink.txt points to " << s << std::endl;
|
||||
|
||||
/**
|
||||
SHA-256 helpers
|
||||
|
||||
bool sha256Compare(std::string_view file1, std::string_view file2);
|
||||
// Compares the SHA-256 hash of two files.
|
||||
// Returns true if hashes are equal, false otherwise.
|
||||
// Uses sha256Of() internally.
|
||||
// Does not throw Helper::Error.
|
||||
|
||||
std::optional<std::string> sha256Of(std::string_view path);
|
||||
// Calculates SHA-256 of a file at given path.
|
||||
// Returns hex string of hash on success.
|
||||
// On error, throws Helper::Error.
|
||||
*/
|
||||
|
||||
if (Helper::sha256Compare("file1.bin", "file2.bin"))
|
||||
std::cout << "file1.bin and file2.bin are identical (SHA-256)" << std::endl;
|
||||
else
|
||||
std::cout << "Files differ (SHA-256)" << std::endl;
|
||||
|
||||
if (auto hash = Helper::sha256Of("file1.bin"))
|
||||
std::cout << "SHA-256 of file1.bin: " << *hash << std::endl;
|
||||
else
|
||||
std::cout << "Failed to calculate SHA-256 of file1.bin" << std::endl;
|
||||
|
||||
/**
|
||||
Utilities - don't throw Helper::Error
|
||||
|
||||
bool copyFile(std::string_view file, std::string_view dest);
|
||||
// Copies file to dest.
|
||||
// Returns true on success.
|
||||
|
||||
bool runCommand(std::string_view cmd);
|
||||
// Runs a system command without capturing output.
|
||||
// Returns true if exit status == 0.
|
||||
|
||||
bool confirmPropt(std::string_view message);
|
||||
// Shows message and asks for y/N from user.
|
||||
// Returns true if user selects "Yes", false otherwise.
|
||||
|
||||
bool changeMode(std::string_view file, mode_t mode);
|
||||
// Changes file permissions.
|
||||
// Returns true on success.
|
||||
|
||||
bool changeOwner(std::string_view file, uid_t uid, gid_t gid);
|
||||
// Changes file owner and group.
|
||||
// Returns true on success.
|
||||
|
||||
std::string currentWorkingDirectory();
|
||||
// Returns current working directory as string.
|
||||
|
||||
std::string currentDate();
|
||||
// Returns current date as string (format: YYYY-MM-DD).
|
||||
|
||||
std::string currentTime();
|
||||
// Returns current time as string (format: HH:MM:SS).
|
||||
|
||||
std::string runCommandWithOutput(std::string_view cmd);
|
||||
// Runs system command and returns its stdout as string.
|
||||
|
||||
std::string pathJoin(std::string base, std::string relative);
|
||||
// Joins base path with relative path and returns result.
|
||||
|
||||
std::string pathBasename(std::string_view entry);
|
||||
// Returns the filename part of given path.
|
||||
|
||||
std::string pathDirname(std::string_view entry);
|
||||
// Returns the directory part of given path.
|
||||
|
||||
uint64_t getRandomOffset(uint64_t size, uint64_t bufferSize);
|
||||
// Returns random offset depending on size and bufferSize.
|
||||
*/
|
||||
|
||||
if (Helper::copyFile("file.txt", "backup.txt"))
|
||||
std::cout << "file.txt copied to backup.txt" << std::endl;
|
||||
|
||||
if (Helper::runCommand("ls -l"))
|
||||
std::cout << "Command executed successfully" << std::endl;
|
||||
|
||||
if (Helper::confirmPropt("Do you want to continue?"))
|
||||
std::cout << "User confirmed YES" << std::endl;
|
||||
else
|
||||
std::cout << "User selected NO" << std::endl;
|
||||
|
||||
if (Helper::changeMode("file.txt", 0644))
|
||||
std::cout << "file.txt mode changed to 644" << std::endl;
|
||||
|
||||
if (Helper::changeOwner("file.txt", 1000, 1000))
|
||||
std::cout << "file.txt owner changed to uid=1000 gid=1000" << std::endl;
|
||||
|
||||
std::cout << "CWD: " << Helper::currentWorkingDirectory() << std::endl;
|
||||
std::cout << "Today: " << Helper::currentDate() << std::endl;
|
||||
std::cout << "Now: " << Helper::currentTime() << std::endl;
|
||||
|
||||
std::string output = Helper::runCommandWithOutput("echo Hello");
|
||||
std::cout << "Output: " << output << std::endl;
|
||||
|
||||
std::cout << "Joined path: " << Helper::pathJoin("/home/user", "docs/file.txt") << std::endl;
|
||||
std::cout << "Basename: " << Helper::pathBasename("/home/user/docs/file.txt") << std::endl;
|
||||
std::cout << "Dirname: " << Helper::pathDirname("/home/user/docs/file.txt") << std::endl;
|
||||
|
||||
uint64_t offset = Helper::getRandomOffset(10240, 512);
|
||||
std::cout << "Random offset: " << offset << std::endl;
|
||||
|
||||
/**
|
||||
Android - don't throw Helper::Error
|
||||
WARNING: IF AN ANDROID-SPECIFIED SYSROOT IS NOT USED, IT WILL NOT BE
|
||||
ADDED AUTOMATICALLY BECAUSE THERE IS NO __ANDROID__ DECLARATION.
|
||||
|
||||
std::string getProperty(std::string_view prop);
|
||||
// Reads a system property.
|
||||
// Returns property value as string.
|
||||
// Returns empty string if property not found.
|
||||
|
||||
bool reboot(std::string_view arg);
|
||||
// Reboots the system with given argument.
|
||||
// Example args: "reboot", "recovery", "bootloader".
|
||||
// Returns true on success.
|
||||
*/
|
||||
|
||||
std::string model = Helper::getProperty("ro.product.model");
|
||||
if (model.empty())
|
||||
std::cout << "Cannot read property ro.product.model" << std::endl;
|
||||
else
|
||||
std::cout << "Device model: " << model << std::endl;
|
||||
|
||||
if (Helper::reboot("recovery"))
|
||||
std::cout << "Rebooting into recovery..." << std::endl;
|
||||
else
|
||||
std::cerr << "Failed to reboot" << std::endl;
|
||||
|
||||
/**
|
||||
Library-specific - don't throw Helper::Error
|
||||
|
||||
std::string getLibVersion();
|
||||
// Returns library version string.
|
||||
*/
|
||||
|
||||
std::cout << "Helper library version: " << Helper::getLibVersion() << std::endl;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### Compling and linking
|
||||
If you're using CMake in your project, you can include it directly with `add_subdirectory`. Both the static and shared libraries will be compiled.
|
||||
|
||||
```cmake
|
||||
# Include libhelper library
|
||||
add_subdirectory(srclib/libhelper)
|
||||
|
||||
# Usage example
|
||||
add_executable(main main.cpp)
|
||||
target_link_libraries(main PRIVATE helper_shared) # use helper_static if you want link static library
|
||||
```
|
||||
|
||||
If you're going to use it prebuilt, you can find it in the PMT releases. Or you can compile it separately... WARNING: PMT releases only include builds for ARM.
|
||||
|
||||
---
|
||||
|
||||
## libpartition_map library
|
||||
soon!
|
||||
Reference in New Issue
Block a user