# to_CSV
# Takes an array of elements, and returns one line of CSV code.
# e.g. to_CSV(['ab', 'cd', 'e,f', 'h"i']) -> 'ab,cd,"e,f","h""i"'
def to_CSV (row):
    line = ''
    for cell in row:
        cell = str(cell)
        if cell.find('"') != -1 or cell.find(',') != -1:
            cell = cell.replace('"', '""')
            cell = '"'+cell+'"'
        line = line + cell + ","
    # remove trailing comma
    if line:
        line = line[:-1]
    return line


# from_CSV
# Takes one line of CSV code, and returns an array of elements.
# e.g. from_CSV('ab,"cd","e,f","h""i"') -> ['ab', 'cd', 'e,f', 'h"i']
def from_CSV(line):
    line = line.rstrip("\n\r")
    row = []
    quotes = 0
    value = ''
    tokens = tokenise(line, ',"')
    for token in tokens:
        if token == ',':
            if quotes == 0 or quotes == 2:
                row.append(value)
                value = ''
                quotes = 0
            elif quotes == 1:
                value = value+token
        elif token == '"':
            if quotes == 0:
                if value:
                    # Quotes in an unquoted value...
                    # This is an illegal CSV line; feel free to raise an error here.
                    if value.strip() == '':
                        # Let's be nice, and strip leading spaces before a quoted string.
                        value = ''
                        quotes = 1
                    else:
                        # Let's be nice, and quietly add the rogue quote to the value.
                        value = value+token
                else:
                    quotes = 1
            elif quotes == 1:
                quotes = 2
            elif quotes == 2:
                value = value+token
                quotes = 1
        else:
            value = value+token
    if quotes == 1:
        # Quotes didn't end...
        # This is an illegal CSV line; feel free to raise and error here.
        pass
    row.append(value)
    return row


# tokenise
# Break the first string into pieces based on the chars of the second string.
# Returns a list of the words and the dividing chars.
# e.g. tokenise('Hello World', ' o') -> ['Hell', 'o', ' ', 'W', 'o', 'rld']
def tokenise(raw, chars):
    tokens = []
    while raw != '':
        firstIndex = len(raw) + 1
        for x in range(len(chars)):
            thisIndex = raw.find(chars[x])
            if 0 <= thisIndex and thisIndex < firstIndex:
                firstIndex = thisIndex
        if firstIndex > len(raw):
            tokens.append(raw)
            raw = ''
        elif firstIndex == 0:
            tokens.append(raw[0])
            raw = raw[1:]
        else:
            tokens.append(raw[:firstIndex])
            tokens.append(raw[firstIndex])
            raw = raw[firstIndex+1:]
    return tokens
