import argparse import os import csv parser = argparse.ArgumentParser(description="Convert CSV to .h defines") parser.add_argument("--csv", required=True, help="Path to CSV file") parser.add_argument("--output", required=True, help="Path to output .h file") parser.add_argument("--variable", required=True, help="Name of generated array variable") parser.add_argument('--index-include-path', required=False, default='', help="Include path for index defines") parser.add_argument('--index-prefix', required=False, default='', help="Prefix for index defines") parser.add_argument('--index-column', required=True, help="Column name for index values") parser.add_argument('--data-column', required=True, help="Column name for data values") args = parser.parse_args() # Start Header outHeader = "#pragma once\n" outHeader += "#include \"dusk.h\"\n" if args.index_include_path: outHeader += f'#include "{args.index_include_path}"\n' outHeader += "\n" # Read CSV file with open(args.csv, newline='') as csvfile: reader = csv.reader(csvfile) headers = next(reader) # Ensure both index and data columns exist. if args.index_column not in headers: raise ValueError(f"Index column '{args.index_column}' not found in CSV headers") if args.data_column not in headers: raise ValueError(f"Data column '{args.data_column}' not found in CSV headers") # Create key-value pairs from CSV rows. index_col_idx = headers.index(args.index_column) data_col_idx = headers.index(args.data_column) keyValuePairs = {} for row in reader: key = row[index_col_idx] value = row[data_col_idx] # Don't allow duplicate keys. if key in keyValuePairs: raise ValueError(f"Duplicate key '{key}' found in CSV") keyValuePairs[key] = value # Determine type. Can be float, int, bool, or string. isFloat = False isInt = False isBool = False isString = False # If there's no entries, assume string type. if len(keyValuePairs) == 0: isString = True else: allInts = True allFloats = True # Check if ALL values can be parsed as int or float. for value in keyValuePairs.values(): if allInts: try: int(value) except: allInts = False if allFloats: try: float(value) except: allFloats = False if not allInts and not allFloats: break if allInts: isInt = True elif allFloats: isFloat = True else: # Not all floats/ints, probably string or bool, check first entry firstValue = next(iter(keyValuePairs.values())) if firstValue.lower() in ['true', 'false']: isBool = True else: isString = True typeString = "" if isFloat: typeString = "float" elif isInt: typeString = "int" elif isBool: typeString = "bool" elif isString: typeString = "char*" # Now begin generating header. outHeader += f"static const {typeString} {args.variable}[] = {{\n" for key in keyValuePairs: outHeader += f" [{args.index_prefix}{key}] = " value = keyValuePairs[key] if isFloat: outHeader += str(float(value)) elif isInt: outHeader += str(int(value)) elif isBool: asBool = 'true' if value.lower() == 'true' else 'false' outHeader += asBool elif isString: escaped = value.replace('\\', '\\\\').replace('"', '\\"') outHeader += f'"{escaped}"' outHeader += ",\n" outHeader += "};\n\n" # Write to output file with open(args.output, 'w') as outFile: outFile.write(outHeader)