[–] 1 point 1 year ago* (3 children)

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.

  • source
  • [–] 0 points 1 year ago

    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)

  • source
  • [–] 2 points 1 year ago (1 child)

    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.

  • source
  • parent
  • context
  • [–] [S] 1 point 1 year ago

    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

  • source
  • parent
  • context
  • [–] [S] 2 points 1 year ago* (last edited 1 year ago) (4 children)

    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

  • source
  • parent
  • context
  • [–] [S] 1 point 1 year ago* (last edited 1 year ago)

    ** 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:

    1. 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);
    
    1. 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!
    
    1. 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() << " ";
    }
    
    1. 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
    
    1. 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";
    }
    
    1. 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
    
    1. 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}
    
    1. 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!
    
    1. 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})} };
    
    1. 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");
    
    1. 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";
    
    1. 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";
    
    1. Flexible Construction from Arbitrary Types

    Any supported type (string, int, bool, null, etc.) or nested containers can be used directly in construction or insertion.

    1. Custom Indentation Everywhere
    n.dump_to_stdout({' ', 8}); // 8 spaces per indent
    
    1. 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.

  • source
  • [–] [S] 2 points 1 year ago* (last edited 1 year ago)

    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>();
    
    
  • source
  • parent
  • context
  • view more: β€Ή prev next β€Ί