Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

provide a sample handler calculating a SHA1 hash for a document #124

Closed
Kosta-Github opened this issue Aug 30, 2014 · 3 comments
Closed
Labels

Comments

@Kosta-Github
Copy link
Contributor

I was playing a bit with rapidjson and came up with this simple Handler for calculating a SHA1 hash value for a Document (with a little bit of a help from boost::uuids::detail::sha1):

#include <boost/uuid/sha1.hpp>

struct HashCalculator {
  using namespace rapidjson;

  boost::uuids::detail::sha1 sha1;

  template<typename T>
  inline bool add_to_hash(T&& t) { return add_to_hash(&t, sizeof(t)); }
  inline bool add_to_hash(const void* str, size_t len) { sha1.process_bytes(str, len); return true; }

  inline std::string get_hash() {
    unsigned int digest[] = { 0, 0, 0, 0, 0 };
    sha1.get_digest(digest);
    return base64_encode( // use a base64 encoding lib at your liking...
      reinterpret_cast<const unsigned char*>(digest), sizeof(digest)
    );
  }

  inline bool Null()                                         { return add_to_hash('N'); }
  inline bool Bool(bool b)                                   { return add_to_hash(b ? 'T' : 'F'); }
  inline bool Int(int i)                                     { return add_to_hash(i); }
  inline bool Uint(unsigned u)                               { return add_to_hash(u); }
  inline bool Int64(int64_t i)                               { return add_to_hash(i); }
  inline bool Uint64(uint64_t u)                             { return add_to_hash(u); }
  inline bool Double(double d)                               { return add_to_hash(d); }
  inline bool String(const char* str, SizeType length, bool) { return add_to_hash(str, length); }
  inline bool StartObject()                                  { return add_to_hash('O'); }
  inline bool Key(const char* str, SizeType length, bool)    { return add_to_hash(str, length); }
  inline bool EndObject(SizeType memberCount)                { return add_to_hash(memberCount); }
  inline bool StartArray()                                   { return add_to_hash('A'); }
  inline bool EndArray(SizeType elementCount)                { return add_to_hash(elementCount); }
};

std::string calculate_hash(rapidjson::Document const& doc_) {
  HashCalculator hasher;
  doc_.Accept(hasher);
  return hasher.get_hash();
}

Maybe you find that useful and want to provide as an additional example?

@miloyip
Copy link
Collaborator

miloyip commented Aug 30, 2014

Thank you for your contribution.

Besides, you can also use Reader, if you only need to compute hash for a JSON but not do anything more on it. Then there will be no overhead of creating a DOM.

A good thing is that, without any modification, your code can do that perfectly.

HashCalculator hasher;
Reader reader;
StringStream ss(json);
reader.Parse(ss,hasher);
std::string hash = hasher.get_hash();

Besides, I think your calculate_hash() function should be a static or global function.

@Kosta-Github
Copy link
Contributor Author

calculate_hash() is in global scope outside of the HashCalculator...

@Kosta-Github
Copy link
Contributor Author

BTW, your example of the CapitalizeFilter could be shortened if you inherit the template parameter OutputHandler like this:

template<typename OutputHandler>
struct CapitalizeFilter : public OutputHandler {

    template<typename... ARGS>
    inline CapitalizeFilter(ARGS&&... args) : OutputHandler(std::forward<ARGS>(args)...) { }

    inline bool String(const char* str, rapidjson::SizeType len, bool) {
        buffer_.assign(str, str + len);
        std::transform(buffer_.begin(), buffer_.end(), buffer_.begin(), [](char c) { return std::toupper(c); });
        return OutputHandler::String(buffer_.data(), len, true); // true = output handler need to copy the string
    }

    std::string buffer_;
};

std::string calculate_hash(document const& doc_) {
    CapitalizeFilter<HashCalculator> cap_hasher;
    doc_.Accept(cap_hasher);
    return cap_hasher.get_hash();
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants