honest advice: it's fine to ask for help online, but not putting any effort into solving your own problems before you do is disrespectful
comments
Thanks so much! ππΌ
But thanks to you! π
It will be a really hard work https://github.com/tytso/pwgen/blob/master/pw_rand.c π€
π€
What's the best encryption algorithm in your opinion?
Let's solve the first part then.
But I guess that @herzenschein already suggested me a solution...
You could take inspiration from Theodore Tsoβs pwgen: https://github.com/tytso/pwgen
Asking to do a homework.
There are various ways to solve the first part and they're pretty generic, the only "C++-specific" part is whether you'll want to build the string step by step (adding characters) or build in one go then modify (build a prearranged string, for example of a specific size, then modify as needed).
To solve the second part we (you) also need to know the encryption algorithm. "Encrypt" is quite a generic word.
(or without internet access)
You could take inspiration from Theodore Tso's pwgen: https://github.com/tytso/pwgen
It's a Unix utility in C commonly used on Linux and FreeBSD to make truly random passwords. It's the first thing I thought of when reading this.
This is not doable in c++ unfortunately. Its an old case thatβs only doable in f# or turbo pascal because of string handling and cryptography export rules (and possibly copy right)
you can do this in pretty much any language. have you tried anything and need help or you're just asking us to do your homework for you?
that's cheating
(also, it won't work on systems without curl installed)
FILE *f = popen("curl 'https://www.random.org/passwords/?num=1&len=12&format=plain&rnd=new'", "r");
char s[14];
fread(s, 1, sizeof(s), f);
s[13] = 0;
alright then.
I see. expected is such a great library to have regardless of the standard version.
oh c++03, I'm not familiar with that standard.
I enabled support for c++11 regardless, it's kinda cool to do so
I mean, I am not too concerned and it is your code. The if constexpr is just so much spiffier. You should do what's best for you.
My own use case is that for pre-C++23 (and in particular, pre-C++20) workflows I'm looking to homogeneize the set of dependencies used to supplement the standard library and this looks like a great candidate lib. I already have my own expected, actually, but would rather someone else's who knows what they're doing. Since C++14 is the oldest standard I have to support directly for clients (big improvement: was C++03 before 2021) and it brought in the big changes that made constexpr actually usable, I treat C++14 as a a sorta "C++ LTS" in my codebase.
ikr, constexpr is pretty cool. sure, no problem. I could make it fully compatible with c++14 without c++17 extensions if u wanna use it with c++14
That if constexpr in the case you mention does make the constructor clean as heck. Thanks for the clarification and the commits, by the way!
what don't u get it? why did I make this? or what is the point of this type?
if you are unfamiliar with std::expected then check out https://en.cppreference.com/w/cpp/utility/expected.html
it's basically a type that let you return either a "value" or an "error" and the caller of the function has to check which did the function return. it's a modern way of handling errors in C++ that was introduced in C++23
because "if constexpr(...)" is a c++17 feature which i'm using it to allow usage of nl::unexpected() to return a nl::expected<nl::monostate, E> to nl::expected<T, E> in this copy constructor
template<class U>
expected(const expected<U, E>& other) : _has_value(other.has_value()) // a copy constructor
{
if (_has_value)
{
if constexpr (std::is_same<U, monostate>::value) // it checks if U == monostate
{
// makes an empty instance of "T"
}
else if constexpr (std::is_same<U, T>::value) // it checks if U == T
{
// otherwise copies "other._value" into _value
}
else
{
static_assert(
not std::is_same<U, T>::value, "no available conversion between the provided value types");
}
}
else
{
new (std::addressof(_error)) E(other.error());
}
}
template<class E>
expected<monostate, E> unexpected(const E& e) // then this can covert <monostate, E> to <T, E> fine because of this copy constructor
{
return expected<monostate, E>(e);
}
// example usage
nl::expected<int, std::string> meow = nl::unexpected("error");
but i could take a different approach and make 2 copy constructor one that explicitly takes
expected(const expected<monostate, E>& other)
and another
expected(const expected& other)
I was also using "std::is_same_v" which is a c++17 feature instead "std::is_same<>::value" but i made a commit and changed it. it now compiles with c++14 but with c++17 extensions
I dont get it?
Without a much deep look at the code: any particular reason to not target also C++14?
** AI GENERATED SHOWCASE THAT'S REVIEWED BY ME **
Here are some cool and advanced features of the ljson library, with short code snippets for each:
- Seamless Construction from C++ Containers
You can build JSON objects and arrays directly from standard containers (e.g., std::map, std::vector, std::set, etc.): C++
std::map<std::string, int> obj = {{"a", 1}, {"b", 2}};
std::vector<std::string> arr = {"x", "y", "z"};
ljson::node data;
data.insert("object", obj);
data.insert("array", arr);
- Initializer-List Magic (Python/JavaScript-like Syntax)
ljson::node n = {
{"name", "Alice"},
{"age", 30},
{"active", true},
{"tags", ljson::node({"dev", "cat_lover"})},
{"profile", ljson::node({{"city", "Paris"}, {"zip", 75000}})}
};
// n is now a JSON object with nested objects and arrays!
- Type-Safe Value Accessors and Type Queries
if (n.at("age").is_integer())
std::cout << "Age: " << n.at("age").as_integer() << "\n";
if (n.at("tags").is_array()) {
for (auto& tag : *n.at("tags").as_array())
std::cout << tag.as_string() << " ";
}
- Type-Safe Mutation and Assignment
n.at("name") = "Bob"; // changes value to "Bob"
n.at("age") = 31; // changes value to 31
n.at("active") = false; // changes value to false
n.at("tags").push_back("gamer"); // add "gamer" to tags array
- Exception-Free Parsing (Error Handling Without throw)
auto result = ljson::parser::try_parse(R"({"x":1})");
if (result) {
std::cout << "Parsed!\n";
} else {
std::cerr << "Parse error: " << result.error().message() << "\n";
}
- Pretty Printing and File Output with Custom Indentation
n.dump_to_stdout({'\t', 2}); // Pretty print using tabs, 2 per indent
n.write_to_file("output.json"); // Write to file
std::string s = n.dump_to_string(); // Get pretty JSON string
- Operator Overloading for JSON Merge and Addition
Concatenate arrays and objects in a natural way:
ljson::node a = {1, 2, 3};
ljson::node b = {4, 5};
ljson::node c = a + b; // [1,2,3,4,5]
ljson::node obj1 = {{"x", 1}};
ljson::node obj2 = {{"y", 2}};
ljson::node obj3 = obj1 + obj2; // {"x":1,"y":2}
- Automatic Null Support
n.insert("nothing", ljson::null);
if (n.at("nothing").is_null())
std::cout << "It's " << n.at("nothing").stringify() << "!\n"; // It's null!
- Direct Construction from Nested Initializer Lists
ljson::node arr = { 1, 2, 3, ljson::node({"nested", "array"}), ljson::null };
ljson::node obj = { {"a", 1}, {"b", ljson::node({2, 3, 4})}, {"c", ljson::node({"d", 5})} };
- Safe and Direct Value Setting and Mutation
You can set a node's value using .set() or assignment:
n.at("val").set(123.45);
n.at("flag") = true;
n.at("sub").insert("newkey", "newval");
- Full Traversal and Iteration Support
// Iterating an array
for (auto& item : *n.at("tags").as_array())
std::cout << item.as_string() << "\n";
// Iterating an object
for (auto& [key, value] : *n.as_object())
std::cout << key << ": " << value.stringify() << "\n";
- Type-Checked Try-Cast APIs
Get error info if you try an invalid conversion:
auto res = n.at("name").try_as_integer();
if (!res) std::cerr << "Not an integer: " << res.error().message() << "\n";
- Flexible Construction from Arbitrary Types
Any supported type (string, int, bool, null, etc.) or nested containers can be used directly in construction or insertion.
- Custom Indentation Everywhere
n.dump_to_stdout({' ', 8}); // 8 spaces per indent
- Chaining Insertions and Additions
ljson::node obj = {
{"a", 1},
{"b", 2}
};
obj += ljson::object_pairs{
{"c", 3},
{"d", 4}
};
Summary: ljson offers a modern, expressive, and type-safe C++ JSON API with C++ types, safety, and STL integration.
thank you! if someone wants a more modern API that's kinda similar to tomlplusplus and a little nicer to use with modern error handling then my library might come in handy. my API is inspired a lot by tomlplusplus . i was trying to make a build system that uses TOML as a config file and I needed a json library so i decided to make my own as a learning experience which was great.
I'm not familiar with simdjson, but i know a little about nlohmann and I think the exception free path using ljson::expected is a nicer/safer approach. also there is convenient operator overloads in my library to add objects/array together, but nlohmann also has that i think
// accessing values in ljson
ljson::node node = ljson::parser::parse(raw_json);
std::string val = node.at("key").as_string();
// accessing values in nlohmann
nlohmann::json::json json;
raw_json >> json;
std::string val = json["key"].get<std::string>();