Skip to content

Instantly share code, notes, and snippets.

@JamesMcNellis
Last active December 11, 2015 08:58
Show Gist options
  • Save JamesMcNellis/4576590 to your computer and use it in GitHub Desktop.
Save JamesMcNellis/4576590 to your computer and use it in GitHub Desktop.
// Copyright James P. McNellis 2013. //
// Distributed under the Boost Software License, Version 1.0. //
// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) //
#include <algorithm>
#include <cctype>
#include <cstdio>
#include <map>
#include <memory>
#include <string>
#include <vector>
#include <windows.h>
struct close_handle_deleter
{
typedef HANDLE pointer;
void operator()(HANDLE h) { if (h != INVALID_HANDLE_VALUE && h != nullptr) { CloseHandle(h); } }
};
struct unmap_file_view_deleter
{
void operator()(void* p) { if (p != nullptr) { UnmapViewOfFile(p); } }
};
typedef std::unique_ptr<HANDLE, close_handle_deleter> raii_handle;
typedef std::unique_ptr<void, unmap_file_view_deleter> raii_file_view;
typedef std::map<std::string, unsigned long long> count_map_type;
int main(int argc, char** argv)
{
if (argc <= 1)
return std::puts("no files to process\n"), 0;
count_map_type word_counts;
unsigned const files_processed(std::count_if(argv + 1, argv + argc, [&](char const* file_name) -> bool
{
raii_handle const file(CreateFile(file_name, GENERIC_READ, FILE_SHARE_READ, nullptr,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr));
if (file.get() == INVALID_HANDLE_VALUE)
return std::printf("failed to open file %s\n", file_name), false;
raii_handle const mapping(CreateFileMapping(file.get(), nullptr, PAGE_READONLY, 0, 0, nullptr));
if (mapping.get() == nullptr)
return std::printf("failed to map file %s\n", file_name), false;
raii_file_view const view(MapViewOfFile(mapping.get(), FILE_MAP_READ, 0, 0, 0));
if (view.get() == nullptr)
return std::printf("failed to map view of file %s\n", file_name), false;
LARGE_INTEGER file_size = { };
if (GetFileSizeEx(file.get(), &file_size) == FALSE)
return std::printf("failed to compute size of file %s\n", file_name), false;
char const* const file_first(reinterpret_cast<char const*>(view.get()));
char const* const file_last(file_first + file_size.QuadPart);
char const* word_first(nullptr);
for (char const* it(file_first); it != file_last; ++it)
{
if (*it < 0 || (!std::isalnum(*it) && *it != '_'))
{
if (word_first != nullptr)
++word_counts[std::string(word_first, it)];
word_first = nullptr;
}
else if (word_first == nullptr)
{
word_first = it;
}
}
if (word_first != nullptr)
++word_counts[std::string(word_first, file_last)];
return true;
}));
std::printf("%u word(s) in %u file(s)\n", static_cast<unsigned>(word_counts.size()), files_processed);
std::for_each(begin(word_counts), end(word_counts), [&](count_map_type::const_reference e)
{
std::printf("%s: %llu\n", e.first.c_str(), e.second);
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment