summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib
diff options
context:
space:
mode:
author Nathan Woods <npwoods@mess.org>2016-07-23 12:49:33 -0400
committer Nathan Woods <npwoods@mess.org>2016-07-23 12:49:33 -0400
commit4aa0ab1724e8fe19775d6be982ec312604a2a6b3 (patch)
tree14f54f2739422cb8640c7b51ffd2af8bc7271114 /src/lib
parent4423c242a693c37fbb4edc50f17c02cdf98abd88 (diff)
Moved src/emu/hash.[cpp|h] into src/lib/util, and namespaced that code (and hashing.[cpp|h]) into util::
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/util/chd.cpp100
-rw-r--r--src/lib/util/chd.h36
-rw-r--r--src/lib/util/hash.cpp423
-rw-r--r--src/lib/util/hash.h122
-rw-r--r--src/lib/util/hashing.cpp3
-rw-r--r--src/lib/util/hashing.h3
6 files changed, 619 insertions, 68 deletions
diff --git a/src/lib/util/chd.cpp b/src/lib/util/chd.cpp
index 55bc313102a..fd6f1c5ad1a 100644
--- a/src/lib/util/chd.cpp
+++ b/src/lib/util/chd.cpp
@@ -115,7 +115,7 @@ struct chd_file::metadata_entry
struct chd_file::metadata_hash
{
UINT8 tag[4]; // tag of the metadata in big-endian
- sha1_t sha1; // hash data
+ util::sha1_t sha1; // hash data
};
@@ -159,9 +159,9 @@ inline void chd_file::be_write(UINT8 *base, UINT64 value, int numbytes)
// stream in bigendian order
//-------------------------------------------------
-inline sha1_t chd_file::be_read_sha1(const UINT8 *base)
+inline util::sha1_t chd_file::be_read_sha1(const UINT8 *base)
{
- sha1_t result;
+ util::sha1_t result;
memcpy(&result.m_raw[0], base, sizeof(result.m_raw));
return result;
}
@@ -172,7 +172,7 @@ inline sha1_t chd_file::be_read_sha1(const UINT8 *base)
// stream in bigendian order
//-------------------------------------------------
-inline void chd_file::be_write_sha1(UINT8 *base, sha1_t value)
+inline void chd_file::be_write_sha1(UINT8 *base, util::sha1_t value)
{
memcpy(base, &value.m_raw[0], sizeof(value.m_raw));
}
@@ -311,7 +311,7 @@ chd_file::~chd_file()
}
/**
- * @fn sha1_t chd_file::sha1()
+ * @fn util::sha1_t chd_file::sha1()
*
* @brief -------------------------------------------------
* sha1 - return our SHA1 value
@@ -320,24 +320,24 @@ chd_file::~chd_file()
* @return A sha1_t.
*/
-sha1_t chd_file::sha1()
+util::sha1_t chd_file::sha1()
{
try
{
// read the big-endian version
- UINT8 rawbuf[sizeof(sha1_t)];
+ UINT8 rawbuf[sizeof(util::sha1_t)];
file_read(m_sha1_offset, rawbuf, sizeof(rawbuf));
return be_read_sha1(rawbuf);
}
catch (chd_error &)
{
// on failure, return nullptr
- return sha1_t::null;
+ return util::sha1_t::null;
}
}
/**
- * @fn sha1_t chd_file::raw_sha1()
+ * @fn util::sha1_t chd_file::raw_sha1()
*
* @brief -------------------------------------------------
* raw_sha1 - return our raw SHA1 value
@@ -349,7 +349,7 @@ sha1_t chd_file::sha1()
* @return A sha1_t.
*/
-sha1_t chd_file::raw_sha1()
+util::sha1_t chd_file::raw_sha1()
{
try
{
@@ -358,19 +358,19 @@ sha1_t chd_file::raw_sha1()
throw CHDERR_UNSUPPORTED_VERSION;
// read the big-endian version
- UINT8 rawbuf[sizeof(sha1_t)];
+ UINT8 rawbuf[sizeof(util::sha1_t)];
file_read(m_rawsha1_offset, rawbuf, sizeof(rawbuf));
return be_read_sha1(rawbuf);
}
catch (chd_error &)
{
// on failure, return nullptr
- return sha1_t::null;
+ return util::sha1_t::null;
}
}
/**
- * @fn sha1_t chd_file::parent_sha1()
+ * @fn util::sha1_t chd_file::parent_sha1()
*
* @brief -------------------------------------------------
* parent_sha1 - return our parent's SHA1 value
@@ -382,7 +382,7 @@ sha1_t chd_file::raw_sha1()
* @return A sha1_t.
*/
-sha1_t chd_file::parent_sha1()
+util::sha1_t chd_file::parent_sha1()
{
try
{
@@ -391,14 +391,14 @@ sha1_t chd_file::parent_sha1()
throw CHDERR_UNSUPPORTED_VERSION;
// read the big-endian version
- UINT8 rawbuf[sizeof(sha1_t)];
+ UINT8 rawbuf[sizeof(util::sha1_t)];
file_read(m_parentsha1_offset, rawbuf, sizeof(rawbuf));
return be_read_sha1(rawbuf);
}
catch (chd_error &)
{
// on failure, return nullptr
- return sha1_t::null;
+ return util::sha1_t::null;
}
}
@@ -523,10 +523,10 @@ chd_error chd_file::hunk_info(UINT32 hunknum, chd_codec_type &compressor, UINT32
* @param rawdata The rawdata.
*/
-void chd_file::set_raw_sha1(sha1_t rawdata)
+void chd_file::set_raw_sha1(util::sha1_t rawdata)
{
// create a big-endian version
- UINT8 rawbuf[sizeof(sha1_t)];
+ UINT8 rawbuf[sizeof(util::sha1_t)];
be_write_sha1(rawbuf, rawdata);
// write to the header
@@ -551,14 +551,14 @@ void chd_file::set_raw_sha1(sha1_t rawdata)
* @param parent The parent.
*/
-void chd_file::set_parent_sha1(sha1_t parent)
+void chd_file::set_parent_sha1(util::sha1_t parent)
{
// if no file, fail
if (m_file == nullptr)
throw CHDERR_INVALID_FILE;
// create a big-endian version
- UINT8 rawbuf[sizeof(sha1_t)];
+ UINT8 rawbuf[sizeof(util::sha1_t)];
be_write_sha1(rawbuf, parent);
// write to the header
@@ -902,13 +902,13 @@ chd_error chd_file::read_hunk(UINT32 hunknum, void *buffer)
blocklen = be_read(&rawmap[12], 2) + (rawmap[14] << 16);
file_read(blockoffs, &m_compressed[0], blocklen);
m_decompressor[0]->decompress(&m_compressed[0], blocklen, dest, m_hunkbytes);
- if (!(rawmap[15] & V34_MAP_ENTRY_FLAG_NO_CRC) && dest != nullptr && crc32_creator::simple(dest, m_hunkbytes) != blockcrc)
+ if (!(rawmap[15] & V34_MAP_ENTRY_FLAG_NO_CRC) && dest != nullptr && util::crc32_creator::simple(dest, m_hunkbytes) != blockcrc)
throw CHDERR_DECOMPRESSION_ERROR;
return CHDERR_NONE;
case V34_MAP_ENTRY_TYPE_UNCOMPRESSED:
file_read(blockoffs, dest, m_hunkbytes);
- if (!(rawmap[15] & V34_MAP_ENTRY_FLAG_NO_CRC) && crc32_creator::simple(dest, m_hunkbytes) != blockcrc)
+ if (!(rawmap[15] & V34_MAP_ENTRY_FLAG_NO_CRC) && util::crc32_creator::simple(dest, m_hunkbytes) != blockcrc)
throw CHDERR_DECOMPRESSION_ERROR;
return CHDERR_NONE;
@@ -916,7 +916,7 @@ chd_error chd_file::read_hunk(UINT32 hunknum, void *buffer)
be_write(dest, blockoffs, 8);
for (UINT32 bytes = 8; bytes < m_hunkbytes; bytes++)
dest[bytes] = dest[bytes - 8];
- if (!(rawmap[15] & V34_MAP_ENTRY_FLAG_NO_CRC) && crc32_creator::simple(dest, m_hunkbytes) != blockcrc)
+ if (!(rawmap[15] & V34_MAP_ENTRY_FLAG_NO_CRC) && util::crc32_creator::simple(dest, m_hunkbytes) != blockcrc)
throw CHDERR_DECOMPRESSION_ERROR;
return CHDERR_NONE;
@@ -961,15 +961,15 @@ chd_error chd_file::read_hunk(UINT32 hunknum, void *buffer)
case COMPRESSION_TYPE_3:
file_read(blockoffs, &m_compressed[0], blocklen);
m_decompressor[rawmap[0]]->decompress(&m_compressed[0], blocklen, dest, m_hunkbytes);
- if (!m_decompressor[rawmap[0]]->lossy() && dest != nullptr && crc16_creator::simple(dest, m_hunkbytes) != blockcrc)
+ if (!m_decompressor[rawmap[0]]->lossy() && dest != nullptr && util::crc16_creator::simple(dest, m_hunkbytes) != blockcrc)
throw CHDERR_DECOMPRESSION_ERROR;
- if (m_decompressor[rawmap[0]]->lossy() && crc16_creator::simple(&m_compressed[0], blocklen) != blockcrc)
+ if (m_decompressor[rawmap[0]]->lossy() && util::crc16_creator::simple(&m_compressed[0], blocklen) != blockcrc)
throw CHDERR_DECOMPRESSION_ERROR;
return CHDERR_NONE;
case COMPRESSION_NONE:
file_read(blockoffs, dest, m_hunkbytes);
- if (crc16_creator::simple(dest, m_hunkbytes) != blockcrc)
+ if (util::crc16_creator::simple(dest, m_hunkbytes) != blockcrc)
throw CHDERR_DECOMPRESSION_ERROR;
return CHDERR_NONE;
@@ -1558,7 +1558,7 @@ chd_error chd_file::clone_all_metadata(chd_file &source)
}
/**
- * @fn sha1_t chd_file::compute_overall_sha1(sha1_t rawsha1)
+ * @fn util::sha1_t chd_file::compute_overall_sha1(sha1_t rawsha1)
*
* @brief -------------------------------------------------
* compute_overall_sha1 - iterate through the metadata and compute the overall hash of
@@ -1570,7 +1570,7 @@ chd_error chd_file::clone_all_metadata(chd_file &source)
* @return The calculated overall sha 1.
*/
-sha1_t chd_file::compute_overall_sha1(sha1_t rawsha1)
+util::sha1_t chd_file::compute_overall_sha1(util::sha1_t rawsha1)
{
// only works for v4 and above
if (m_version < 4)
@@ -1593,7 +1593,7 @@ sha1_t chd_file::compute_overall_sha1(sha1_t rawsha1)
// create an entry for this metadata and add it
metadata_hash hashentry;
be_write(hashentry.tag, metaentry.metatag, 4);
- hashentry.sha1 = sha1_creator::simple(&filedata[0], metaentry.length);
+ hashentry.sha1 = util::sha1_creator::simple(&filedata[0], metaentry.length);
hasharray.push_back(hashentry);
}
@@ -1602,7 +1602,7 @@ sha1_t chd_file::compute_overall_sha1(sha1_t rawsha1)
qsort(&hasharray[0], hasharray.size(), sizeof(hasharray[0]), metadata_hash_compare);
// read the raw data hash from our header and start a new SHA1 with that data
- sha1_creator overall_sha1;
+ util::sha1_creator overall_sha1;
overall_sha1.append(&rawsha1, sizeof(rawsha1));
if (!hasharray.empty())
overall_sha1.append(&hasharray[0], hasharray.size() * sizeof(hasharray[0]));
@@ -1750,7 +1750,7 @@ UINT32 chd_file::guess_unitbytes()
* @param [in,out] parentsha1 The first parentsha.
*/
-void chd_file::parse_v3_header(UINT8 *rawheader, sha1_t &parentsha1)
+void chd_file::parse_v3_header(UINT8 *rawheader, util::sha1_t &parentsha1)
{
// verify header length
if (be_read(&rawheader[8], 4) != V3_HEADER_SIZE)
@@ -1813,7 +1813,7 @@ void chd_file::parse_v3_header(UINT8 *rawheader, sha1_t &parentsha1)
* @param [in,out] parentsha1 The first parentsha.
*/
-void chd_file::parse_v4_header(UINT8 *rawheader, sha1_t &parentsha1)
+void chd_file::parse_v4_header(UINT8 *rawheader, util::sha1_t &parentsha1)
{
// verify header length
if (be_read(&rawheader[8], 4) != V4_HEADER_SIZE)
@@ -1873,7 +1873,7 @@ void chd_file::parse_v4_header(UINT8 *rawheader, sha1_t &parentsha1)
* @param [in,out] parentsha1 The first parentsha.
*/
-void chd_file::parse_v5_header(UINT8 *rawheader, sha1_t &parentsha1)
+void chd_file::parse_v5_header(UINT8 *rawheader, util::sha1_t &parentsha1)
{
// verify header length
if (be_read(&rawheader[8], 4) != V5_HEADER_SIZE)
@@ -1928,7 +1928,7 @@ chd_error chd_file::compress_v5_map()
try
{
// first get a CRC-16 of the original rawmap
- crc16_t mapcrc = crc16_creator::simple(&m_rawmap[0], m_hunkcount * 12);
+ util::crc16_t mapcrc = util::crc16_creator::simple(&m_rawmap[0], m_hunkcount * 12);
// create a buffer to hold the RLE data
dynamic_buffer compression_rle(m_hunkcount);
@@ -2244,7 +2244,7 @@ void chd_file::decompress_v5_map()
}
// verify the final CRC
- if (crc16_creator::simple(&m_rawmap[0], m_hunkcount * 12) != mapcrc)
+ if (util::crc16_creator::simple(&m_rawmap[0], m_hunkcount * 12) != mapcrc)
throw CHDERR_DECOMPRESSION_ERROR;
}
@@ -2310,15 +2310,15 @@ chd_error chd_file::create_common()
be_write(&rawheader[48], m_metaoffset, 8);
be_write(&rawheader[56], m_hunkbytes, 4);
be_write(&rawheader[60], m_unitbytes, 4);
- be_write_sha1(&rawheader[64], sha1_t::null);
- be_write_sha1(&rawheader[84], sha1_t::null);
- be_write_sha1(&rawheader[104], (m_parent != nullptr) ? m_parent->sha1() : sha1_t::null);
+ be_write_sha1(&rawheader[64], util::sha1_t::null);
+ be_write_sha1(&rawheader[84], util::sha1_t::null);
+ be_write_sha1(&rawheader[104], (m_parent != nullptr) ? m_parent->sha1() : util::sha1_t::null);
// write the resulting header
file_write(0, rawheader, sizeof(rawheader));
// parse it back out to set up fields appropriately
- sha1_t parentsha1;
+ util::sha1_t parentsha1;
parse_v5_header(rawheader, parentsha1);
// writes are obviously permitted; reads only if uncompressed
@@ -2403,7 +2403,7 @@ chd_error chd_file::open_common(bool writeable)
throw CHDERR_UNSUPPORTED_VERSION;
// read the header if we support it
- sha1_t parentsha1 = sha1_t::null;
+ util::sha1_t parentsha1 = util::sha1_t::null;
switch (m_version)
{
case 3: parse_v3_header(rawheader, parentsha1); break;
@@ -2416,7 +2416,7 @@ chd_error chd_file::open_common(bool writeable)
throw CHDERR_FILE_NOT_WRITEABLE;
// make sure we have a parent if we need one (and don't if we don't)
- if (parentsha1 != sha1_t::null)
+ if (parentsha1 != util::sha1_t::null)
{
if (m_parent == nullptr)
m_parent_missing = true;
@@ -2535,7 +2535,7 @@ void chd_file::verify_proper_compression_append(UINT32 hunknum)
* @param crc16 The CRC 16.
*/
-void chd_file::hunk_write_compressed(UINT32 hunknum, INT8 compression, const UINT8 *compressed, UINT32 complength, crc16_t crc16)
+void chd_file::hunk_write_compressed(UINT32 hunknum, INT8 compression, const UINT8 *compressed, UINT32 complength, util::crc16_t crc16)
{
// verify that we are appending properly to a compressed file
verify_proper_compression_append(hunknum);
@@ -2711,10 +2711,10 @@ void chd_file::metadata_update_hash()
return;
// compute the new overall hash
- sha1_t fullsha1 = compute_overall_sha1(raw_sha1());
+ util::sha1_t fullsha1 = compute_overall_sha1(raw_sha1());
// create a big-endian version
- UINT8 rawbuf[sizeof(sha1_t)];
+ UINT8 rawbuf[sizeof(util::sha1_t)];
be_write_sha1(&rawbuf[0], fullsha1);
// write to the header
@@ -3033,8 +3033,8 @@ void chd_file_compressor::async_walk_parent(work_item &item)
units = 1;
for (UINT32 unit = 0; unit < units; unit++)
{
- item.m_hash[unit].m_crc16 = crc16_creator::simple(item.m_data + unit * unit_bytes(), hunk_bytes());
- item.m_hash[unit].m_sha1 = sha1_creator::simple(item.m_data + unit * unit_bytes(), hunk_bytes());
+ item.m_hash[unit].m_crc16 = util::crc16_creator::simple(item.m_data + unit * unit_bytes(), hunk_bytes());
+ item.m_hash[unit].m_sha1 = util::sha1_creator::simple(item.m_data + unit * unit_bytes(), hunk_bytes());
}
item.m_status = WS_COMPLETE;
}
@@ -3075,8 +3075,8 @@ void chd_file_compressor::async_compress_hunk(work_item &item, int threadid)
item.m_codecs = m_codecs[threadid];
// compute CRC-16 and SHA-1 hashes
- item.m_hash[0].m_crc16 = crc16_creator::simple(item.m_data, hunk_bytes());
- item.m_hash[0].m_sha1 = sha1_creator::simple(item.m_data, hunk_bytes());
+ item.m_hash[0].m_crc16 = util::crc16_creator::simple(item.m_data, hunk_bytes());
+ item.m_hash[0].m_sha1 = util::sha1_creator::simple(item.m_data, hunk_bytes());
// find the best compression scheme, unless we already have a self or parent match
// (note we may miss a self match from blocks not yet added, but this just results in extra work)
@@ -3254,7 +3254,7 @@ void chd_file_compressor::hashmap::reset()
* @return An UINT64.
*/
-UINT64 chd_file_compressor::hashmap::find(crc16_t crc16, sha1_t sha1)
+UINT64 chd_file_compressor::hashmap::find(util::crc16_t crc16, util::sha1_t sha1)
{
// look up the entry in the map
for (entry_t *entry = m_map[crc16]; entry != nullptr; entry = entry->m_next)
@@ -3275,7 +3275,7 @@ UINT64 chd_file_compressor::hashmap::find(crc16_t crc16, sha1_t sha1)
* @param sha1 The first sha.
*/
-void chd_file_compressor::hashmap::add(UINT64 itemnum, crc16_t crc16, sha1_t sha1)
+void chd_file_compressor::hashmap::add(UINT64 itemnum, util::crc16_t crc16, util::sha1_t sha1)
{
// add to the appropriate map
if (m_block_list->m_nextalloc == ARRAY_LENGTH(m_block_list->m_array))
diff --git a/src/lib/util/chd.h b/src/lib/util/chd.h
index a3b0e0c7304..b0eb4143374 100644
--- a/src/lib/util/chd.h
+++ b/src/lib/util/chd.h
@@ -317,14 +317,14 @@ public:
bool compressed() const { return (m_compression[0] != CHD_CODEC_NONE); }
chd_codec_type compression(int index) const { return m_compression[index]; }
chd_file *parent() const { return m_parent; }
- sha1_t sha1();
- sha1_t raw_sha1();
- sha1_t parent_sha1();
+ util::sha1_t sha1();
+ util::sha1_t raw_sha1();
+ util::sha1_t parent_sha1();
chd_error hunk_info(UINT32 hunknum, chd_codec_type &compressor, UINT32 &compbytes);
// setters
- void set_raw_sha1(sha1_t rawdata);
- void set_parent_sha1(sha1_t parent);
+ void set_raw_sha1(util::sha1_t rawdata);
+ void set_parent_sha1(util::sha1_t parent);
// file create
chd_error create(const char *filename, UINT64 logicalbytes, UINT32 hunkbytes, UINT32 unitbytes, chd_codec_type compression[4]);
@@ -359,7 +359,7 @@ public:
chd_error clone_all_metadata(chd_file &source);
// hashing helper
- sha1_t compute_overall_sha1(sha1_t rawsha1);
+ util::sha1_t compute_overall_sha1(util::sha1_t rawsha1);
// codec interfaces
chd_error codec_configure(chd_codec_type codec, int param, void *config);
@@ -374,8 +374,8 @@ private:
// inline helpers
UINT64 be_read(const UINT8 *base, int numbytes);
void be_write(UINT8 *base, UINT64 value, int numbytes);
- sha1_t be_read_sha1(const UINT8 *base);
- void be_write_sha1(UINT8 *base, sha1_t value);
+ util::sha1_t be_read_sha1(const UINT8 *base);
+ void be_write_sha1(UINT8 *base, util::sha1_t value);
void file_read(UINT64 offset, void *dest, UINT32 length);
void file_write(UINT64 offset, const void *source, UINT32 length);
UINT64 file_append(const void *source, UINT32 length, UINT32 alignment = 0);
@@ -383,16 +383,16 @@ private:
// internal helpers
UINT32 guess_unitbytes();
- void parse_v3_header(UINT8 *rawheader, sha1_t &parentsha1);
- void parse_v4_header(UINT8 *rawheader, sha1_t &parentsha1);
- void parse_v5_header(UINT8 *rawheader, sha1_t &parentsha1);
+ void parse_v3_header(UINT8 *rawheader, util::sha1_t &parentsha1);
+ void parse_v4_header(UINT8 *rawheader, util::sha1_t &parentsha1);
+ void parse_v5_header(UINT8 *rawheader, util::sha1_t &parentsha1);
chd_error compress_v5_map();
void decompress_v5_map();
chd_error create_common();
chd_error open_common(bool writeable);
void create_open_common();
void verify_proper_compression_append(UINT32 hunknum);
- void hunk_write_compressed(UINT32 hunknum, INT8 compression, const UINT8 *compressed, UINT32 complength, crc16_t crc16);
+ void hunk_write_compressed(UINT32 hunknum, INT8 compression, const UINT8 *compressed, UINT32 complength, util::crc16_t crc16);
void hunk_copy_from_self(UINT32 hunknum, UINT32 otherhunk);
void hunk_copy_from_parent(UINT32 hunknum, UINT64 parentunit);
bool metadata_find(chd_metadata_tag metatag, INT32 metaindex, metadata_entry &metaentry, bool resume = false);
@@ -469,8 +469,8 @@ private:
// operations
void reset();
- UINT64 find(crc16_t crc16, sha1_t sha1);
- void add(UINT64 itemnum, crc16_t crc16, sha1_t sha1);
+ UINT64 find(util::crc16_t crc16, util::sha1_t sha1);
+ void add(UINT64 itemnum, util::crc16_t crc16, util::sha1_t sha1);
// constants
static const UINT64 NOT_FOUND = ~UINT64(0);
@@ -480,7 +480,7 @@ private:
{
entry_t * m_next; // next entry in list
UINT64 m_itemnum; // item number
- sha1_t m_sha1; // SHA-1 of the block
+ util::sha1_t m_sha1; // SHA-1 of the block
};
// block of entries
@@ -511,8 +511,8 @@ private:
// a CRC-16/SHA-1 pair
struct hash_pair
{
- crc16_t m_crc16; // calculated CRC-16
- sha1_t m_sha1; // calculated SHA-1
+ util::crc16_t m_crc16; // calculated CRC-16
+ util::sha1_t m_sha1; // calculated SHA-1
};
// a single work item
@@ -556,7 +556,7 @@ private:
bool m_walking_parent; // are we building the parent map?
UINT64 m_total_in; // total bytes in
UINT64 m_total_out; // total bytes out
- sha1_creator m_compsha1; // running SHA-1 on raw data
+ util::sha1_creator m_compsha1; // running SHA-1 on raw data
// hash lookup maps
hashmap m_parent_map; // hash map for parent
diff --git a/src/lib/util/hash.cpp b/src/lib/util/hash.cpp
new file mode 100644
index 00000000000..6d7ac9319e3
--- /dev/null
+++ b/src/lib/util/hash.cpp
@@ -0,0 +1,423 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles
+/***************************************************************************
+
+ hash.cpp
+
+ Function to handle hash functions (checksums)
+
+ Based on original idea by Farfetch'd
+
+***************************************************************************/
+
+#include "hash.h"
+#include "hashing.h"
+#include <ctype.h>
+
+
+namespace util {
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+const char hash_collection::HASH_CRC;
+const char hash_collection::HASH_SHA1;
+
+const char *hash_collection::HASH_TYPES_CRC = "R";
+const char *hash_collection::HASH_TYPES_CRC_SHA1 = "RS";
+const char *hash_collection::HASH_TYPES_ALL = "RS";
+
+const char hash_collection::FLAG_NO_DUMP;
+const char hash_collection::FLAG_BAD_DUMP;
+
+
+
+//**************************************************************************
+// HASH COLLECTION
+//**************************************************************************
+
+//-------------------------------------------------
+// hash_collection - constructor
+//-------------------------------------------------
+
+hash_collection::hash_collection()
+ : m_has_crc32(false),
+ m_has_sha1(false),
+ m_creator(nullptr)
+{
+}
+
+
+hash_collection::hash_collection(const char *string)
+ : m_has_crc32(false),
+ m_has_sha1(false),
+ m_creator(nullptr)
+{
+ from_internal_string(string);
+}
+
+
+hash_collection::hash_collection(const hash_collection &src)
+ : m_has_crc32(false),
+ m_has_sha1(false),
+ m_creator(nullptr)
+{
+ copyfrom(src);
+}
+
+
+//-------------------------------------------------
+// ~hash_collection - destructor
+//-------------------------------------------------
+
+hash_collection::~hash_collection()
+{
+ delete m_creator;
+}
+
+
+//-------------------------------------------------
+// operator= - assignment operator
+//-------------------------------------------------
+
+hash_collection &hash_collection::operator=(const hash_collection &src)
+{
+ // ignore self-assignment
+ if (this != &src)
+ copyfrom(src);
+ return *this;
+}
+
+
+//-------------------------------------------------
+// operator== - test for equality
+//-------------------------------------------------
+
+bool hash_collection::operator==(const hash_collection &rhs) const
+{
+ // match CRCs
+ int matches = 0;
+ if (m_has_crc32 && rhs.m_has_crc32)
+ {
+ if (m_crc32 != rhs.m_crc32)
+ return false;
+ matches++;
+ }
+
+ // match SHA1s
+ if (m_has_sha1 && rhs.m_has_sha1)
+ {
+ if (m_sha1 != rhs.m_sha1)
+ return false;
+ matches++;
+ }
+
+ // if all shared hashes match, return true
+ return (matches > 0);
+}
+
+
+//-------------------------------------------------
+// hash_types - return a list of hash types as
+// a string
+//-------------------------------------------------
+
+std::string hash_collection::hash_types() const
+{
+ std::string buffer;
+ if (m_has_crc32)
+ buffer.push_back(HASH_CRC);
+ if (m_has_sha1)
+ buffer.push_back(HASH_SHA1);
+ return buffer;
+}
+
+
+//-------------------------------------------------
+// reset - reset the hash collection to an empty
+// set of hashes and flags
+//-------------------------------------------------
+
+void hash_collection::reset()
+{
+ m_flags.clear();
+ m_has_crc32 = m_has_sha1 = false;
+ delete m_creator;
+ m_creator = nullptr;
+}
+
+
+//-------------------------------------------------
+// add_from_string - add a new hash, importing
+// from a string
+//-------------------------------------------------
+
+bool hash_collection::add_from_string(char type, const char *buffer, int length)
+{
+ // handle CRCs
+ if (type == HASH_CRC)
+ return m_has_crc32 = m_crc32.from_string(buffer, length);
+
+ // handle SHA1s
+ else if (type == HASH_SHA1)
+ return m_has_sha1 = m_sha1.from_string(buffer, length);
+
+ return false;
+}
+
+
+//-------------------------------------------------
+// remove - remove a hash of the given type
+//-------------------------------------------------
+
+bool hash_collection::remove(char type)
+{
+ bool result = false;
+
+ // handle CRCs
+ if (type == HASH_CRC)
+ {
+ result = m_has_crc32;
+ m_has_crc32 = false;
+ }
+
+ // handle SHA1s
+ else if (type == HASH_SHA1)
+ {
+ result = m_has_sha1;
+ m_has_sha1 = false;
+ }
+ return result;
+}
+
+
+//-------------------------------------------------
+// internal_string - convert set of hashes and
+// flags to a string in our internal compact
+// format
+//-------------------------------------------------
+
+std::string hash_collection::internal_string() const
+{
+ std::string buffer;
+
+ // handle CRCs
+ if (m_has_crc32) {
+ buffer.push_back(HASH_CRC);
+ buffer.append(m_crc32.as_string());
+ }
+ // handle SHA1s
+ if (m_has_sha1) {
+ buffer.push_back(HASH_SHA1);
+ buffer.append(m_sha1.as_string());
+ }
+
+ // append flags
+ buffer.append(m_flags);
+ return buffer;
+}
+
+
+//-------------------------------------------------
+// macro_string - convert set of hashes and
+// flags to a string in the macroized format
+//-------------------------------------------------
+
+std::string hash_collection::macro_string() const
+{
+ std::string buffer;
+
+ // handle CRCs
+ if (m_has_crc32)
+ buffer.append("CRC(").append(m_crc32.as_string()).append(") ");
+
+ // handle SHA1s
+ if (m_has_sha1)
+ buffer.append("SHA1(").append(m_sha1.as_string()).append(") ");
+
+ // append flags
+ if (flag(FLAG_NO_DUMP))
+ buffer.append("NO_DUMP ");
+ if (flag(FLAG_BAD_DUMP))
+ buffer.append("BAD_DUMP ");
+ strtrimspace(buffer);
+ return buffer;
+}
+
+
+//-------------------------------------------------
+// attribute_string - convert set of hashes and
+// flags to a string in XML attribute format
+//-------------------------------------------------
+
+std::string hash_collection::attribute_string() const
+{
+ std::string buffer;
+
+ // handle CRCs
+ if (m_has_crc32)
+ buffer.append("crc=\"").append(m_crc32.as_string()).append("\" ");
+
+ // handle SHA1s
+ if (m_has_sha1)
+ buffer.append("sha1=\"").append(m_sha1.as_string()).append("\" ");
+
+ // append flags
+ if (flag(FLAG_NO_DUMP))
+ buffer.append("status=\"nodump\"");
+ if (flag(FLAG_BAD_DUMP))
+ buffer.append("status=\"baddump\"");
+ strtrimspace(buffer);
+ return buffer;
+}
+
+
+//-------------------------------------------------
+// from_internal_string - convert an internal
+// compact string to set of hashes and flags
+//-------------------------------------------------
+
+bool hash_collection::from_internal_string(const char *string)
+{
+ // start fresh
+ reset();
+
+ // determine the end of the string
+ const char *stringend = string + strlen(string);
+ const char *ptr = string;
+
+ // loop until we hit it
+ bool errors = false;
+ int skip_digits = 0;
+ while (ptr < stringend)
+ {
+ char c = *ptr++;
+ char uc = toupper(c);
+
+ // non-hex alpha values specify a hash type
+ if (uc >= 'G' && uc <= 'Z')
+ {
+ skip_digits = 0;
+ if (uc == HASH_CRC)
+ {
+ m_has_crc32 = true;
+ errors = !m_crc32.from_string(ptr, stringend - ptr);
+ skip_digits = 2 * sizeof(crc32_t);
+ }
+ else if (uc == HASH_SHA1)
+ {
+ m_has_sha1 = true;
+ errors = !m_sha1.from_string(ptr, stringend - ptr);
+ skip_digits = 2 * sizeof(sha1_t);
+ }
+ else
+ errors = true;
+ }
+
+ // hex values are ignored, though unexpected
+ else if ((uc >= '0' && uc <= '9') || (uc >= 'A' && uc <= 'F'))
+ {
+ if (skip_digits != 0)
+ skip_digits--;
+ else
+ errors = true;
+ }
+
+ // anything else is a flag
+ else if (skip_digits != 0)
+ errors = true;
+ else
+ m_flags.push_back(c);
+ }
+ return !errors;
+}
+
+
+//-------------------------------------------------
+// begin - begin hashing
+//-------------------------------------------------
+
+void hash_collection::begin(const char *types)
+{
+ // nuke previous creator and make a new one
+ delete m_creator;
+ m_creator = new hash_creator;
+
+ // by default use all types
+ if (types == nullptr)
+ m_creator->m_doing_crc32 = m_creator->m_doing_sha1 = true;
+
+ // otherwise, just allocate the ones that are specified
+ else
+ {
+ m_creator->m_doing_crc32 = (strchr(types, HASH_CRC) != nullptr);
+ m_creator->m_doing_sha1 = (strchr(types, HASH_SHA1) != nullptr);
+ }
+}
+
+
+//-------------------------------------------------
+// buffer - add the given buffer to the hash
+//-------------------------------------------------
+
+void hash_collection::buffer(const UINT8 *data, UINT32 length)
+{
+ assert(m_creator != nullptr);
+
+ // append to each active hash
+ if (m_creator->m_doing_crc32)
+ m_creator->m_crc32_creator.append(data, length);
+ if (m_creator->m_doing_sha1)
+ m_creator->m_sha1_creator.append(data, length);
+}
+
+
+//-------------------------------------------------
+// end - stop hashing
+//-------------------------------------------------
+
+void hash_collection::end()
+{
+ assert(m_creator != nullptr);
+
+ // finish up the CRC32
+ if (m_creator->m_doing_crc32)
+ {
+ m_has_crc32 = true;
+ m_crc32 = m_creator->m_crc32_creator.finish();
+ }
+
+ // finish up the SHA1
+ if (m_creator->m_doing_sha1)
+ {
+ m_has_sha1 = true;
+ m_sha1 = m_creator->m_sha1_creator.finish();
+ }
+
+ // nuke the creator
+ delete m_creator;
+ m_creator = nullptr;
+}
+
+
+//-------------------------------------------------
+// copyfrom - copy everything from another
+// collection
+//-------------------------------------------------
+
+void hash_collection::copyfrom(const hash_collection &src)
+{
+ // copy flags directly
+ m_flags = src.m_flags;
+
+ // copy hashes
+ m_has_crc32 = src.m_has_crc32;
+ m_crc32 = src.m_crc32;
+ m_has_sha1 = src.m_has_sha1;
+ m_sha1 = src.m_sha1;
+
+ // don't copy creators
+ m_creator = nullptr;
+}
+
+} // namespace util
diff --git a/src/lib/util/hash.h b/src/lib/util/hash.h
new file mode 100644
index 00000000000..ec628a949f2
--- /dev/null
+++ b/src/lib/util/hash.h
@@ -0,0 +1,122 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles
+/***************************************************************************
+
+ hash.h
+
+ Function to handle hash functions (checksums)
+
+ Based on original idea by Farfetch'd
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __HASH_H__
+#define __HASH_H__
+
+#include "hashing.h"
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+// use these to define compile-time internal-format hash strings
+#define CRC(x) "R" #x
+#define SHA1(x) "S" #x
+#define NO_DUMP "!"
+#define BAD_DUMP "^"
+
+
+namespace util {
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+
+// ======================> hash_collection
+
+// a collection of the various supported hashes and flags
+class hash_collection
+{
+public:
+ // hash types are identified by non-hex alpha values (G-Z)
+ static constexpr char HASH_CRC = 'R';
+ static constexpr char HASH_SHA1 = 'S';
+
+ // common combinations for requests
+ static const char *HASH_TYPES_CRC;
+ static const char *HASH_TYPES_CRC_SHA1;
+ static const char *HASH_TYPES_ALL;
+
+ // flags are identified by punctuation marks
+ static constexpr char FLAG_NO_DUMP = '!';
+ static constexpr char FLAG_BAD_DUMP = '^';
+
+ // construction/destruction
+ hash_collection();
+ hash_collection(const char *string);
+ hash_collection(const hash_collection &src);
+ ~hash_collection();
+
+ // operators
+ hash_collection &operator=(const hash_collection &src);
+ bool operator==(const hash_collection &rhs) const;
+ bool operator!=(const hash_collection &rhs) const { return !(*this == rhs); }
+
+ // getters
+ bool flag(char flag) const { return (m_flags.find_first_of(flag) != std::string::npos); }
+ std::string hash_types() const;
+
+ // hash manipulators
+ void reset();
+ bool add_from_string(char type, const char *buffer, int length = -1);
+ bool remove(char type);
+
+ // CRC-specific helpers
+ bool crc(UINT32 &result) const { result = m_crc32; return m_has_crc32; }
+ void add_crc(UINT32 crc) { m_crc32 = crc; m_has_crc32 = true; }
+
+ // SHA1-specific helpers
+ bool sha1(sha1_t &result) const { result = m_sha1; return m_has_sha1; }
+ void add_sha1(sha1_t sha1) { m_has_sha1 = true; m_sha1 = sha1; }
+
+ // string conversion
+ std::string internal_string() const;
+ std::string macro_string() const;
+ std::string attribute_string() const;
+ bool from_internal_string(const char *string);
+
+ // creation
+ void begin(const char *types = nullptr);
+ void buffer(const UINT8 *data, UINT32 length);
+ void end();
+ void compute(const UINT8 *data, UINT32 length, const char *types = nullptr) { begin(types); buffer(data, length); end(); }
+
+private:
+ // internal helpers
+ void copyfrom(const hash_collection &src);
+
+ // internal state
+ std::string m_flags;
+ bool m_has_crc32;
+ crc32_t m_crc32;
+ bool m_has_sha1;
+ sha1_t m_sha1;
+
+ // creators
+ struct hash_creator
+ {
+ bool m_doing_crc32;
+ crc32_creator m_crc32_creator;
+ bool m_doing_sha1;
+ sha1_creator m_sha1_creator;
+ };
+ hash_creator * m_creator;
+};
+
+
+} // namespace util
+
+#endif /* __HASH_H__ */
diff --git a/src/lib/util/hashing.cpp b/src/lib/util/hashing.cpp
index 240e64af9ad..dd6b9847f15 100644
--- a/src/lib/util/hashing.cpp
+++ b/src/lib/util/hashing.cpp
@@ -14,6 +14,7 @@
#include <sstream>
+namespace util {
//**************************************************************************
// CONSTANTS
//**************************************************************************
@@ -291,3 +292,5 @@ void crc16_creator::append(const void *data, UINT32 length)
crc = (crc << 8) ^ s_table[(crc >> 8) ^ *src++];
m_accum.m_raw = crc;
}
+
+} // namespace util
diff --git a/src/lib/util/hashing.h b/src/lib/util/hashing.h
index 51a7da7c694..8b58d3afc8b 100644
--- a/src/lib/util/hashing.h
+++ b/src/lib/util/hashing.h
@@ -20,6 +20,7 @@
#include "sha1.h"
+namespace util {
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
@@ -217,4 +218,6 @@ protected:
};
+} // namespace util
+
#endif // __HASHING_H__