Last active
December 11, 2015 08:58
-
-
Save JamesMcNellis/4576590 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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