#!/usr/bin/env python

# Copyright (c) 2016 - Digital Operatives LLC
# All rights reserved
#
# Written by Evan Sultanik, Ph.D.
# evan@sultanik.com
# 
# This source code is licensed under the GNU GENERAL PUBLIC LICENSE
# Version 2.
# 
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

def hash_it(s):
    h = 0
    for c in s:
        h = (h + (ord(c) | 0x60)) << 1
    return h

GOOD_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789_"
GOOD_CHAR_SET = set(GOOD_CHARS)

def unhash(h):
    h >>= 1;
    if h < 256:
        for c in (h,0x60,0x40,0x20):#(0x40, 0x80, 0x60, h):
            s = chr(h ^ c)
            if s in GOOD_CHAR_SET:
                yield s
    else:
        for c in map(ord, GOOD_CHARS):
            if not ((((h - (c | 0x60)) & 0x1) != 0) or ((h - (c | 0x60)) < 192)):
                for s in unhash(h - (c | 0x60)):
                    yield s + chr(c)

if __name__ == "__main__":
    import sys
    h = hash_it(sys.argv[1])
    print hex(h)
    for s in unhash(h):
        h2 = hash_it(s)
        assert h == h2
        print s + "\t" + hex(h2)
