How to use boost::hash to get the file content hash? - c++

Is it possible to use boost:hash function to generate a file content hash with fixed length like MD5?
Is there a quick solution for this?
If not, what is the simplest way?

No, Boost doesn't implement MD5. Use a crypto/hash library for this.
CryptoC++ is nice in my experience.
OpenSSL implements all the popular digests, here's a sample that uses OpenSSL:
Live On Coliru
#include <openssl/md5.h>
#include <iostream>
#include <iomanip>
// Print the MD5 sum as hex-digits.
void print_md5_sum(unsigned char* md) {
for(unsigned i=0; i <MD5_DIGEST_LENGTH; i++) {
std::cout << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(md[i]);
}
}
#include <string>
#include <vector>
#include <fstream>
int main(int argc, char *argv[]) {
using namespace std;
vector<string> const args(argv+1, argv+argc);
for (auto& fname : args) {
MD5_CTX ctx;
MD5_Init(&ctx);
ifstream ifs(fname, std::ios::binary);
char file_buffer[4096];
while (ifs.read(file_buffer, sizeof(file_buffer)) || ifs.gcount()) {
MD5_Update(&ctx, file_buffer, ifs.gcount());
}
unsigned char digest[MD5_DIGEST_LENGTH] = {};
MD5_Final(digest, &ctx);
print_md5_sum(digest);
std::cout << "\t" << fname << "\n";
}
}

boot has such functionality. At lest now: https://www.boost.org/doc/libs/master/libs/uuid/doc/uuid.html
#include <iostream>
#include <algorithm>
#include <iterator>
#include <boost/uuid/detail/md5.hpp>
#include <boost/algorithm/hex.hpp>
using boost::uuids::detail::md5;
std::string toString(const md5::digest_type &digest)
{
const auto charDigest = reinterpret_cast<const char *>(&digest);
std::string result;
boost::algorithm::hex(charDigest, charDigest + sizeof(md5::digest_type), std::back_inserter(result));
return result;
}
int main ()
{
std::string s;
while(std::getline(std::cin, s)) {
md5 hash;
md5::digest_type digest;
hash.process_bytes(s.data(), s.size());
hash.get_digest(digest);
std::cout << "md5(" << s << ") = " << toString(digest) << '\n';
}
return 0;
}
Live Example

Related

Boost Tokenizer strange symbols at start

#include <iostream>
#include <optional>
#include <string>
#include <boost/tokenizer.hpp>
int main() {
std::string a("http://website/some-path/,file1,file2");
char *ptr = (char *)a.c_str();
boost::char_separator<char> delim(",");
std::vector<std::string> pths{};
boost::tokenizer<boost::char_separator<char>> tokens(
std::string(ptr), delim);
std::optional<std::string> pref = std::nullopt;
for (const auto& tok : tokens) {
if (!pref) {
pref = tok;
std::cerr << "prfix is set: " << tok << std::endl;
continue;
}
pths.push_back(*pref + tok);
}
for(auto &t : pths) {
std::cout << t << std::endl;
}
}
My output:
prfix is set: �site/some-path/
�site/some-path/file1
�site/some-path/file2
The question is, what is wrong with the above? If I work with std::regex, it is fine.
EDIT: the scenario with *ptr is the one I actually had: the original string was passed to a function as char *, hence the above. This is to answer the comment by #273K.
A lot can be simplified, at once removing the problems:
Live On Coliru
#include <boost/tokenizer.hpp>
#include <iostream>
#include <optional>
#include <string>
auto generate(std::string const& a) {
boost::tokenizer tokens(a, boost::char_separator<char>{","});
std::optional<std::string> prefix;
std::vector<std::string> result;
for (const auto& tok : tokens) {
if (!prefix)
prefix = tok;
else
result.push_back(*prefix + tok);
}
return result;
}
int main() {
for (auto& t : generate("http://website/some-path/,file1,file2"))
std::cout << t << std::endl;
}
Prints
http://website/some-path/file1
http://website/some-path/file2

Build incremental std::string

I try to build an std::string in the form of "start:Pdc1;Pdc2;Pdc3;"
With following code I can build the repeated "Pdc" and the incremental string "123" but I'm unable to combine the two strings.
#include <string>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <iterator>
#include <numeric>
int main()
{
std::ostringstream ss;
std::string hdr("start:");
std::fill_n(std::ostream_iterator<std::string>(ss), 3, "Pdc;");
hdr.append(ss.str());
std::string v("abc");
std::iota(v.begin(), v.end(), '1');
std::cout << hdr << std::endl;
std::cout << v << std::endl;
std::cout << "Expected output: start:Pdc1;Pdc2;Pdc3;" << std::endl;
return 0;
}
How can I build this string? Preferable without a while or for loop.
The expected output is: start:Pdc1;Pdc2;Pdc3;
std::strings can be concatenated via their operator+ (or +=) and integers can be converted via std::to_string:
std::string res("start:");
for (int i=0;i<3;++i){
res += "Pdc" + std::to_string(i+1) + ";";
}
std::cout << res << "\n";
If you like you can use an algorithm instead of the handwritten loop, but it will still be a loop (your code has 2 loops, but only 1 is needed).
Code to generate your expected string, though with a small for loop.
#include <iostream>
#include <string>
#include <sstream>
std::string cmd(const std::size_t N)
{
std::ostringstream os;
os << "start:";
for(std::size_t n = 1; n <= N; ++n) os << "Pdc" << n << ";";
return os.str();
}
int main()
{
std::cout << cmd(3ul);
return 0;
}

Skip integers while reading text from file into array

I am trying to create a program where I could read string data from a file and store it into an array, but I want to skip any integers or non-letters and not read them into the array. Any ideas on how to do that?
This is my code:
#include <iostream>
#include <stream>
#include <iomanip>
#include <cstdlib>
#include <algorithm>
#include <cctype>
#include <string>
using namespace std;
void loadData();
int main()
{
loadData();
return 0;
}
void loadData()
{
const int SIZE = 100;
string fileName;
std::string wordArray[SIZE];
cout << "Please enter the name of the text file you want to process followed by '.txt': " << endl;
cin >> fileName;
ifstream dataFile;
dataFile.open(fileName, ios::in);
if (dataFile.fail())
{
cerr << fileName << " could not be opened." << endl; //error message if file opening fails
exit(-1);
}
while (!dataFile.eof())
{
for (int i = 0; i < SIZE; i++)
{
dataFile >> wordArray[i];
for (std::string& s : wordArray) //this for loop transforms all the words in the text file into lowercase
std::transform(s.begin(), s.end(), s.begin(),
[](unsigned char c) { return std::tolower(c); });
cout << wordArray[i] << endl;
}
}
}
Use copy_if:
for (std::string& s : wordArray)
std::copy_if(s.begin(), s.end(), s.begin(),
[](char& c) { c = std::tolower(c); return std::isalpha(c); });
Note that this may not be the most efficient code.
This is a scenario where regexes can come in handy.
They do require forward iterators though, so you need to read in the whole file at once before extracting words.
#include <iostream>
#include <iterator>
#include <fstream>
#include <regex>
std::string read_whole_file(const std::string& file_name) {
std::ifstream file(file_name);
return {std::istreambuf_iterator<char>(file),
std::istreambuf_iterator<char>()};
}
int main()
{
// ...
auto file_data = read_whole_file(filename);
std::regex word_regex("(\\w+)");
auto words_begin =
std::sregex_iterator(file_data.begin(), file_data.end(), word_regex);
auto words_end = std::sregex_iterator();
for (auto i = words_begin; i != words_end; ++i) {
std::cout << "found word" << i->str() << '\n';
}
}

snprintf c++ alternative

How can I convert this code from C into C++ ?
char out[61]; //null terminator
for (i = 0; i < 20; i++) {
snprintf(out+i*3, 4, "%02x ", obuf[i])
}
I can't find any alternative for snprintf.
Use stringstream class from <sstream>.
E.g.:
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
using namespace std;
int main()
{
stringstream ss;
for (int i = 0; i < 20; i++) {
ss << setw(3) << i;
}
cout << "Resulting string: " << endl;
cout << ss.str() << endl;
printf("Resulting char*: \n%s\n", ss.str().c_str() );
return 0;
}
This code is valid C++11, if you have #include <cstdio> and type std::snprintf (or using namespace std;).
No need to "fix" what isn't broken.
You can use Boost.Format.
#include <boost/format.hpp>
#include <string>
std::string out;
for (size_t i=0; i<20; ++i)
out += (boost::format("%02x") % int(obuf[i])).str();
You can convert this code from C to C++ easily with standard library's std::stringstream and iomanip I/O stream manipulators:
#include <sstream>
#include <iomanip>
...
std::ostringstream stream;
stream << std::setfill('0') << std::hex;
for (const auto byte : obuf)
stream << std::setw(2) << byte;
const auto out = stream.str();

How to convert Byte Array to Hexadecimal String in C++?

I am looking for a fastest way to convert a byte array of arbitrary length to a hexadecimal string. This question has been fully answered here at StackOverflow for C#. Some solutions in C++ can be found here.
Are there any "turnkey" or "ready-made" solutions to a problem? C-style solutions are welcome.
#include <vector>
#include <iostream>
#include <algorithm>
#include <string>
#include <iterator>
#include <sstream>
#include <iomanip>
int main()
{
std::vector<unsigned char> v;
v.push_back( 1 );
v.push_back( 2 );
v.push_back( 3 );
v.push_back( 4 );
std::ostringstream ss;
ss << std::hex << std::uppercase << std::setfill( '0' );
std::for_each( v.cbegin(), v.cend(), [&]( int c ) { ss << std::setw( 2 ) << c; } );
std::string result = ss.str();
std::cout << result << std::endl;
return 0;
}
Or, if you've got a compiler that supports uniform initialization syntax and range based for loops you can save a few lines.
#include <vector>
#include <sstream>
#include <string>
#include <iostream>
#include <iomanip>
int main()
{
std::vector<unsigned char> v { 1, 2, 3, 4 };
std::ostringstream ss;
ss << std::hex << std::uppercase << std::setfill( '0' );
for( int c : v ) {
ss << std::setw( 2 ) << c;
}
std::string result = ss.str();
std::cout << result << std::endl;
}
Use boost::alogorithm::hex
std::vector<unsigned char> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
std::string res;
boost::algorithm::hex(v.begin(), v.end(), back_inserter(res));
You can use the C++ Standard Library and or you can use boost::lexical_cast
#include <iostream>
#include <string>
#include <array>
#include <vector>
#include <sstream>
#include <iomanip>
#include <algorithm>
using namespace std;
// use this macro for c++11 feature
#define USE_CPP11
int main(int argc, char* argv[])
{
array<unsigned char, 3> hexArr = {0x01, 0xff, 0x55};
const char separator = ' '; // separator between two numbers
ostringstream os;
os << hex << setfill('0'); // set the stream to hex with 0 fill
#ifdef USE_CPP11
std::for_each(std::begin(hexArr), std::end(hexArr), [&os, &separator] (int i)
{
os << setw(2) << i << separator;
});
#else // c++03
typedef array<unsigned char, 3>::const_iterator const_iterator;
for (const_iterator it = hexArr.begin(); it != hexArr.end(); ++it)
{
os << setw(2) << int(*it) << separator;
}
#endif
os << dec << setfill(' '); // reset the stream to "original"
// print the string
cout << "the string array is: " << os.str() << endl;
return EXIT_SUCCESS;
}
One of the fastest way I know in C++ 11:
template <size_t byteCount>
string BytesArrayToHexString( const std::array<byte, byteCount>& src )
{
static const char table[] = "0123456789ABCDEF";
std::array<char, 2 * byteCount + 1> dst;
const byte* srcPtr = &src[0];
char* dstPtr = &dst[0];
for (auto count = byteCount; count > 0; --count)
{
unsigned char c = *srcPtr++;
*dstPtr++ = table[c >> 4];
*dstPtr++ = table[c & 0x0f];
}
*dstPtr = 0;
return &dst[0];
}
A good compiler should not have any problem to apply SSE optimization on this....