dataTypes = ["CPUndefinedDataType", "CPIntegerDataType", "CPUnsignedIntegerDataType", "CPFloatingPointDataType", "CPComplexFloatingPointDataType", "CPDecimalDataType"]

types = { "CPUndefinedDataType" : [],
        "CPIntegerDataType" : ["int8_t", "int16_t", "int32_t", "int64_t"],
        "CPUnsignedIntegerDataType" : ["uint8_t", "uint16_t", "uint32_t", "uint64_t"],
        "CPFloatingPointDataType" : ["float", "double"],
        "CPComplexFloatingPointDataType" : ["float complex", "double complex"],
        "CPDecimalDataType" : ["NSDecimal"] }

nsnumber_factory = { "int8_t" : "Char",
					"int16_t" : "Short",
					"int32_t" : "Long",
					"int64_t" : "LongLong",
					"uint8_t" : "UnsignedChar",
				   "uint16_t" : "UnsignedShort",
				   "uint32_t" : "UnsignedLong",
				   "uint64_t" : "UnsignedLongLong",
					  "float" : "Float",
					 "double" : "Double",
			  "float complex" : "Float",
			 "double complex" : "Double",
				  "NSDecimal" : "Decimal"
}

nsnumber_methods = { "int8_t" : "char",
					"int16_t" : "short",
					"int32_t" : "long",
					"int64_t" : "longLong",
					"uint8_t" : "unsignedChar",
				   "uint16_t" : "unsignedShort",
				   "uint32_t" : "unsignedLong",
				   "uint64_t" : "unsignedLongLong",
					  "float" : "float",
					 "double" : "double",
			  "float complex" : "float",
			 "double complex" : "double",
				  "NSDecimal" : "decimal"
}

null_values = { "int8_t" : "0",
			   "int16_t" : "0",
			   "int32_t" : "0",
			   "int64_t" : "0",
			   "uint8_t" : "0",
			  "uint16_t" : "0",
			  "uint32_t" : "0",
			  "uint64_t" : "0",
				 "float" : "NAN",
				"double" : "NAN",
		 "float complex" : "NAN",
		"double complex" : "NAN",
			 "NSDecimal" : "CPDecimalNaN()"
}

print "[CPNumericData sampleValue:]"
print ""
print "switch ( self.dataTypeFormat ) {"
for dt in dataTypes:
    print "\tcase %s:" % dt
    if ( len(types[dt]) == 0 ):
        print '\t\t[NSException raise:NSInvalidArgumentException format:@"Unsupported data type (%s)"];' % (dt)
    else:
        print "\t\tswitch ( self.sampleBytes ) {"
        for t in types[dt]:
            print "\t\t\tcase sizeof(%s):" % t
            if ( t == "NSDecimal" ):
                number_class = "NSDecimalNumber"
                number_method = "decimalNumber"
            else:
                number_class = "NSNumber"
                number_method = "number"
            print "\t\t\t\tresult = [%s %sWith%s:*(%s *)[self samplePointer:sample]];" % (number_class, number_method, nsnumber_factory[t], t)
            print "\t\t\t\tbreak;"
        print "\t\t}"
    print "\t\tbreak;"
print "}"

print "\n\n"
print "---------------"
print "\n\n"

print "[CPNumericData dataFromArray:dataType:]"
print ""
print "switch ( newDataType.dataTypeFormat ) {"
for dt in dataTypes:
    print "\tcase %s:" % dt
    if ( len(types[dt]) == 0 ):
        print "\t\t// Unsupported"
    else:
        print "\t\tswitch ( newDataType.sampleBytes ) {"
        for t in types[dt]:
            print "\t\t\tcase sizeof(%s): {" % t
            print "\t\t\t\t%s *toBytes = (%s *)sampleData.mutableBytes;" % (t, t)
            print "\t\t\t\tfor ( id sample in newData ) {"
            print "\t\t\t\t\tif ( [sample respondsToSelector:@selector(%sValue)] ) {" % nsnumber_methods[t]
            print "\t\t\t\t\t\t*toBytes++ = (%s)[(NSNumber *)sample %sValue];" % (t, nsnumber_methods[t])
            print "\t\t\t\t\t}"
            print "\t\t\t\t\telse {"
            print "\t\t\t\t\t\t*toBytes++ = %s;" % null_values[t]
            print "\t\t\t\t\t}"
            print "\t\t\t\t}"
            print "\t\t\t}"
            print "\t\t\t\tbreak;"
        print "\t\t}"
    print "\t\tbreak;"
print "}"

print "\n\n"
print "---------------"
print "\n\n"

print "[CPNumericData convertData:dataType:toData:dataType:]"
print ""
print "switch ( sourceDataType->dataTypeFormat ) {"
for dt in dataTypes:
    print "\tcase %s:" % dt
    if ( len(types[dt]) > 0 ):
        print "\t\tswitch ( sourceDataType->sampleBytes ) {"
        for t in types[dt]:
            print "\t\t\tcase sizeof(%s):" % t
            print "\t\t\t\tswitch ( destDataType->dataTypeFormat ) {"
            for ndt in dataTypes:
                print "\t\t\t\t\tcase %s:" % ndt
                if ( len(types[ndt]) > 0 ):
                    print "\t\t\t\t\t\tswitch ( destDataType->sampleBytes ) {"
                    for nt in types[ndt]:
                        print "\t\t\t\t\t\t\tcase sizeof(%s): { // %s -> %s" % (nt, t, nt)
                        if ( t == nt ):
                            print "\t\t\t\t\t\t\t\t\tmemcpy(destData.mutableBytes, sourceData.bytes, sampleCount * sizeof(%s));" % t
                        else:
                            print "\t\t\t\t\t\t\t\t\tconst %s *fromBytes = (%s *)sourceData.bytes;" % (t, t)
                            print "\t\t\t\t\t\t\t\t\tconst %s *lastSample = fromBytes + sampleCount;" % t
                            print "\t\t\t\t\t\t\t\t\t%s *toBytes = (%s *)destData.mutableBytes;" % (nt, nt)
                            if ( t == "NSDecimal" ):
                                print "\t\t\t\t\t\t\t\t\twhile ( fromBytes < lastSample ) *toBytes++ = CPDecimal%sValue(*fromBytes++);" % nsnumber_factory[nt]
                            elif ( nt == "NSDecimal" ):
                                print "\t\t\t\t\t\t\t\t\twhile ( fromBytes < lastSample ) *toBytes++ = CPDecimalFrom%s(*fromBytes++);" % nsnumber_factory[t]
                            else:
                                print "\t\t\t\t\t\t\t\t\twhile ( fromBytes < lastSample ) *toBytes++ = (%s)*fromBytes++;" % nt
                        print "\t\t\t\t\t\t\t\t}"
                        print "\t\t\t\t\t\t\t\tbreak;"
                    print "\t\t\t\t\t\t}"
                print "\t\t\t\t\t\tbreak;"
            print "\t\t\t\t}"
            print "\t\t\t\tbreak;"
        print "\t\t}"
    print "\t\tbreak;"
print "}"
