@@ -1297,6 +1297,7 @@ func generateCFunctionDeclaration(op introspection.Operation) string {
1297
1297
// generateCFunctionImplementation generates C implementations for vips operations
1298
1298
func generateCFunctionImplementation (op introspection.Operation ) string {
1299
1299
var result strings.Builder
1300
+
1300
1301
// Handle basic function (no options)
1301
1302
if len (op .Arguments ) == 0 {
1302
1303
result .WriteString (fmt .Sprintf ("int vipsgen_%s() {\n " , op .Name ))
@@ -1359,89 +1360,147 @@ func generateCFunctionImplementation(op introspection.Operation) string {
1359
1360
result .WriteString (fmt .Sprintf (" VipsOperation *operation = vips_operation_new(\" %s\" );\n " , op .Name ))
1360
1361
result .WriteString (" if (!operation) return 1;\n " )
1361
1362
1362
- // Handle required arguments first
1363
+ // Create VipsArray objects for array inputs
1364
+ for _ , opt := range op .OptionalInputs {
1365
+ if strings .HasPrefix (opt .GoType , "[]" ) {
1366
+ arrayType := getArrayType (opt .GoType )
1367
+ if arrayType == "double" {
1368
+ result .WriteString (fmt .Sprintf (" VipsArrayDouble *%s_array = NULL;\n " , opt .Name ))
1369
+ result .WriteString (fmt .Sprintf (" if (%s != NULL && %s_n > 0) { %s_array = vips_array_double_new(%s, %s_n); }\n " , opt .Name , opt .Name , opt .Name , opt .Name , opt .Name ))
1370
+ } else if arrayType == "int" {
1371
+ result .WriteString (fmt .Sprintf (" VipsArrayInt *%s_array = NULL;\n " , opt .Name ))
1372
+ result .WriteString (fmt .Sprintf (" if (%s != NULL && %s_n > 0) { %s_array = vips_array_int_new(%s, %s_n); }\n " , opt .Name , opt .Name , opt .Name , opt .Name , opt .Name ))
1373
+ } else if arrayType == "image" {
1374
+ result .WriteString (fmt .Sprintf (" VipsArrayImage *%s_array = NULL;\n " , opt .Name ))
1375
+ result .WriteString (fmt .Sprintf (" if (%s != NULL && %s_n > 0) { %s_array = vips_array_image_new(%s, %s_n); }\n " , opt .Name , opt .Name , opt .Name , opt .Name , opt .Name ))
1376
+ }
1377
+ }
1378
+ }
1379
+
1380
+ // Combine required and optional parameters in a single condition
1381
+ var allParamsList []string
1382
+
1383
+ // Add required parameters first
1363
1384
for _ , arg := range op .Arguments {
1364
1385
if arg .IsOutput {
1365
1386
continue // Skip output arguments, they'll be handled after build
1366
1387
}
1367
1388
1368
1389
// Special handling for different types of arguments
1369
1390
if arg .IsSource {
1370
- result .WriteString (fmt .Sprintf (" if (vips_object_set(VIPS_OBJECT(operation), \" %s\" , (VipsSource*)%s, NULL)) { g_object_unref(operation); return 1; }\n " , arg .Name , arg .Name ))
1391
+ allParamsList = append (allParamsList ,
1392
+ fmt .Sprintf ("vips_object_set(VIPS_OBJECT(operation), \" %s\" , (VipsSource*)%s, NULL)" , arg .Name , arg .Name ))
1371
1393
} else if arg .Name == "buf" || arg .Name == "buffer" {
1372
- // Handle buffer and its length together
1373
- result .WriteString (fmt .Sprintf (" if (vips_object_set(VIPS_OBJECT(operation), \" %s\" , %s, NULL)) { g_object_unref(operation); return 1; }\n " , arg .Name , arg .Name ))
1374
- for _ , lenArg := range op .Arguments {
1375
- if lenArg .Name == "len" {
1376
- result .WriteString (fmt .Sprintf (" if (vips_object_set(VIPS_OBJECT(operation), \" %s\" , %s, NULL)) { g_object_unref(operation); return 1; }\n " , lenArg .Name , lenArg .Name ))
1394
+ // Handle buffer parameter
1395
+ allParamsList = append (allParamsList ,
1396
+ fmt .Sprintf ("vips_object_set(VIPS_OBJECT(operation), \" %s\" , %s, NULL)" , arg .Name , arg .Name ))
1397
+ } else if arg .Name == "len" {
1398
+ // Handle len parameter (check if associated with buffer)
1399
+ var isBufferLen bool
1400
+ for _ , bArg := range op .Arguments {
1401
+ if bArg .Name == "buf" || bArg .Name == "buffer" {
1402
+ isBufferLen = true
1377
1403
break
1378
1404
}
1379
1405
}
1380
- } else if arg .Name != "len" { // Skip "len" as it's handled with buffer
1381
- result .WriteString (fmt .Sprintf (" if (vips_object_set(VIPS_OBJECT(operation), \" %s\" , %s, NULL)) { g_object_unref(operation); return 1; }\n " , arg .Name , arg .Name ))
1406
+ if isBufferLen {
1407
+ allParamsList = append (allParamsList ,
1408
+ fmt .Sprintf ("vips_object_set(VIPS_OBJECT(operation), \" %s\" , %s, NULL)" , arg .Name , arg .Name ))
1409
+ }
1410
+ } else if arg .GoType == "string" {
1411
+ // String parameter
1412
+ allParamsList = append (allParamsList ,
1413
+ fmt .Sprintf ("vips_object_set(VIPS_OBJECT(operation), \" %s\" , %s, NULL)" , arg .Name , arg .Name ))
1414
+ } else if arg .GoType == "*C.VipsImage" {
1415
+ // Image parameter
1416
+ allParamsList = append (allParamsList ,
1417
+ fmt .Sprintf ("vips_object_set(VIPS_OBJECT(operation), \" %s\" , %s, NULL)" , arg .Name , arg .Name ))
1382
1418
} else {
1383
- continue // Skip len parameter, already handled
1419
+ // Other scalar parameters
1420
+ allParamsList = append (allParamsList ,
1421
+ fmt .Sprintf ("vips_object_set(VIPS_OBJECT(operation), \" %s\" , %s, NULL)" , arg .Name , arg .Name ))
1384
1422
}
1385
1423
}
1386
1424
1387
- // Create VipsArray objects for array inputs
1425
+ // Add optional parameters using type-specific setter functions
1388
1426
for _ , opt := range op .OptionalInputs {
1389
1427
if strings .HasPrefix (opt .GoType , "[]" ) {
1390
1428
arrayType := getArrayType (opt .GoType )
1391
1429
if arrayType == "double" {
1392
- result . WriteString ( fmt . Sprintf ( " VipsArrayDouble *%s_array = NULL; \n " , opt . Name ))
1393
- result . WriteString ( fmt .Sprintf (" if (%s != NULL && %s_n > 0) { %s_array = vips_array_double_new(%s , %s_n); } \n " , opt . Name , opt . Name , opt . Name , opt .Name , opt .Name ))
1430
+ allParamsList = append ( allParamsList ,
1431
+ fmt .Sprintf ("vipsgen_set_array_double(operation, \" %s \" , %s_array)" , opt .Name , opt .Name ))
1394
1432
} else if arrayType == "int" {
1395
- result . WriteString ( fmt . Sprintf ( " VipsArrayInt *%s_array = NULL; \n " , opt . Name ))
1396
- result . WriteString ( fmt .Sprintf (" if (%s != NULL && %s_n > 0) { %s_array = vips_array_int_new(%s , %s_n); } \n " , opt . Name , opt . Name , opt . Name , opt .Name , opt .Name ))
1433
+ allParamsList = append ( allParamsList ,
1434
+ fmt .Sprintf ("vipsgen_set_array_int(operation, \" %s \" , %s_array)" , opt .Name , opt .Name ))
1397
1435
} else if arrayType == "image" {
1398
- result . WriteString ( fmt . Sprintf ( " VipsArrayImage *%s_array = NULL; \n " , opt . Name ))
1399
- result . WriteString ( fmt .Sprintf (" if (%s != NULL && %s_n > 0) { %s_array = vips_array_image_new(%s , %s_n); } \n " , opt . Name , opt . Name , opt . Name , opt .Name , opt .Name ))
1436
+ allParamsList = append ( allParamsList ,
1437
+ fmt .Sprintf ("vipsgen_set_array_image(operation, \" %s \" , %s_array)" , opt .Name , opt .Name ))
1400
1438
}
1439
+ } else if opt .GoType == "bool" {
1440
+ allParamsList = append (allParamsList ,
1441
+ fmt .Sprintf ("vipsgen_set_bool(operation, \" %s\" , %s)" , opt .Name , opt .Name ))
1442
+ } else if opt .GoType == "string" {
1443
+ allParamsList = append (allParamsList ,
1444
+ fmt .Sprintf ("vipsgen_set_string(operation, \" %s\" , %s)" , opt .Name , opt .Name ))
1445
+ } else if opt .IsEnum {
1446
+ allParamsList = append (allParamsList ,
1447
+ fmt .Sprintf ("vipsgen_set_int(operation, \" %s\" , %s)" , opt .Name , opt .Name ))
1448
+ } else if opt .GoType == "*C.VipsImage" {
1449
+ allParamsList = append (allParamsList ,
1450
+ fmt .Sprintf ("vipsgen_set_image(operation, \" %s\" , %s)" , opt .Name , opt .Name ))
1451
+ } else if opt .GoType == "*Interpolate" || opt .GoType == "*C.VipsInterpolate" {
1452
+ // Handle interpolate parameters
1453
+ allParamsList = append (allParamsList ,
1454
+ fmt .Sprintf ("vipsgen_set_interpolate(operation, \" %s\" , %s)" , opt .Name , opt .Name ))
1455
+ } else if opt .IsSource {
1456
+ // Handle source parameters
1457
+ allParamsList = append (allParamsList ,
1458
+ fmt .Sprintf ("vipsgen_set_source(operation, \" %s\" , %s)" , opt .Name , opt .Name ))
1459
+ } else if opt .GoType == "int" {
1460
+ allParamsList = append (allParamsList ,
1461
+ fmt .Sprintf ("vipsgen_set_int(operation, \" %s\" , %s)" , opt .Name , opt .Name ))
1462
+ } else if opt .GoType == "float64" {
1463
+ allParamsList = append (allParamsList ,
1464
+ fmt .Sprintf ("vipsgen_set_double(operation, \" %s\" , %s)" , opt .Name , opt .Name ))
1465
+ } else if strings .Contains (opt .CType , "guint64" ) {
1466
+ // Handle guint64 parameters
1467
+ allParamsList = append (allParamsList ,
1468
+ fmt .Sprintf ("vipsgen_set_guint64(operation, \" %s\" , %s)" , opt .Name , opt .Name ))
1469
+ } else if strings .Contains (opt .CType , "unsigned int" ) || strings .Contains (opt .CType , "guint" ) {
1470
+ // Handle unsigned int parameters
1471
+ allParamsList = append (allParamsList ,
1472
+ fmt .Sprintf ("set_uint_param(operation, \" %s\" , %s)" , opt .Name , opt .Name ))
1473
+ } else if strings .Contains (opt .CType , "*" ) || strings .Contains (opt .GoType , "*" ) {
1474
+ // This is a pointer type - use general pointer handler
1475
+ allParamsList = append (allParamsList ,
1476
+ fmt .Sprintf ("set_pointer_param(operation, \" %s\" , %s)" , opt .Name , opt .Name ))
1477
+ } else {
1478
+ // For any other non-pointer scalar types, default to int
1479
+ allParamsList = append (allParamsList ,
1480
+ fmt .Sprintf ("vipsgen_set_int(operation, \" %s\" , %s)" , opt .Name , opt .Name ))
1401
1481
}
1402
1482
}
1403
1483
1404
- // Handle optional arguments - only set if they have non-default values
1405
- for _ , opt := range op .OptionalInputs {
1406
- // Create a cleanup function for error cases
1407
- cleanupCode := "g_object_unref(operation); "
1484
+ // Join all parameters with the || operator for short-circuit evaluation
1485
+ if len (allParamsList ) > 0 {
1486
+ result .WriteString (" if (\n " )
1487
+ result .WriteString (strings .Join (allParamsList , " ||\n " ))
1488
+ result .WriteString ("\n ) {\n " )
1489
+ result .WriteString (" g_object_unref(operation);\n " )
1490
+
1491
+ // Free all array resources on error
1408
1492
for _ , cleanupOpt := range op .OptionalInputs {
1409
1493
if strings .HasPrefix (cleanupOpt .GoType , "[]" ) {
1410
1494
arrayType := getArrayType (cleanupOpt .GoType )
1411
1495
if arrayType != "unknown" {
1412
- cleanupCode += fmt .Sprintf ("if (%s_array != NULL) { vips_area_unref(VIPS_AREA(%s_array)); } " , cleanupOpt .Name , cleanupOpt .Name )
1496
+ result . WriteString ( fmt .Sprintf (" if (%s_array != NULL) { vips_area_unref(VIPS_AREA(%s_array)); }\n " , cleanupOpt .Name , cleanupOpt .Name ) )
1413
1497
}
1414
1498
}
1415
1499
}
1416
- cleanupCode += "return 1;"
1417
1500
1418
- // Different handling for different types of optional arguments
1419
- if strings .HasPrefix (opt .GoType , "[]" ) {
1420
- arrayType := getArrayType (opt .GoType )
1421
- if arrayType != "unknown" {
1422
- result .WriteString (fmt .Sprintf (" if (%s_array != NULL) { if (vips_object_set(VIPS_OBJECT(operation), \" %s\" , %s_array, NULL)) { %s } }\n " ,
1423
- opt .Name , opt .Name , opt .Name , cleanupCode ))
1424
- }
1425
- } else if opt .GoType == "bool" {
1426
- result .WriteString (fmt .Sprintf (" if (%s) { if (vips_object_set(VIPS_OBJECT(operation), \" %s\" , %s, NULL)) { %s } }\n " ,
1427
- opt .Name , opt .Name , opt .Name , cleanupCode ))
1428
- } else if opt .GoType == "string" {
1429
- result .WriteString (fmt .Sprintf (" if (%s != NULL && strlen(%s) > 0) { if (vips_object_set(VIPS_OBJECT(operation), \" %s\" , %s, NULL)) { %s } }\n " ,
1430
- opt .Name , opt .Name , opt .Name , opt .Name , cleanupCode ))
1431
- } else if opt .IsEnum {
1432
- result .WriteString (fmt .Sprintf (" if (%s != 0) { if (vips_object_set(VIPS_OBJECT(operation), \" %s\" , %s, NULL)) { %s } }\n " ,
1433
- opt .Name , opt .Name , opt .Name , cleanupCode ))
1434
- } else if opt .GoType == "*C.VipsImage" {
1435
- result .WriteString (fmt .Sprintf (" if (%s != NULL) { if (vips_object_set(VIPS_OBJECT(operation), \" %s\" , %s, NULL)) { %s } }\n " ,
1436
- opt .Name , opt .Name , opt .Name , cleanupCode ))
1437
- } else if opt .GoType == "int" || opt .GoType == "float64" {
1438
- result .WriteString (fmt .Sprintf (" if (%s != 0) { if (vips_object_set(VIPS_OBJECT(operation), \" %s\" , %s, NULL)) { %s } }\n " ,
1439
- opt .Name , opt .Name , opt .Name , cleanupCode ))
1440
- }
1501
+ result .WriteString (" return 1;\n }\n \n " )
1441
1502
}
1442
1503
1443
- result .WriteString ("\n " )
1444
-
1445
1504
// Collect the output parameters
1446
1505
var outputParams []string
1447
1506
for _ , arg := range op .Arguments {
@@ -1465,26 +1524,23 @@ func generateCFunctionImplementation(op introspection.Operation) string {
1465
1524
// Add NULL terminator
1466
1525
outputParams = append (outputParams , "NULL" )
1467
1526
1468
- // Clean up array objects in case of error
1469
- cleanupArraysCode := ""
1527
+ // Generate the call to the helper function
1528
+ result .WriteString (fmt .Sprintf (" int result = vipsgen_operation_execute(&operation, %s);\n " , strings .Join (outputParams , ", " )))
1529
+
1530
+ // Clean up array objects
1531
+ hasArrays := false
1470
1532
for _ , opt := range op .OptionalInputs {
1471
1533
if strings .HasPrefix (opt .GoType , "[]" ) {
1472
1534
arrayType := getArrayType (opt .GoType )
1473
1535
if arrayType != "unknown" {
1474
- cleanupArraysCode += fmt .Sprintf (" if (%s_array != NULL) { vips_area_unref(VIPS_AREA(%s_array)); }\n " , opt .Name , opt .Name )
1536
+ if ! hasArrays {
1537
+ hasArrays = true
1538
+ }
1539
+ result .WriteString (fmt .Sprintf (" if (%s_array != NULL) { vips_area_unref(VIPS_AREA(%s_array)); }\n " , opt .Name , opt .Name ))
1475
1540
}
1476
1541
}
1477
1542
}
1478
1543
1479
- // Generate the call to the helper function
1480
- result .WriteString (fmt .Sprintf (" int result = vipsgen_operation_execute(&operation, %s);\n " , strings .Join (outputParams , ", " )))
1481
-
1482
- // Clean up array objects
1483
- if cleanupArraysCode != "" {
1484
- result .WriteString ("\n " )
1485
- result .WriteString (cleanupArraysCode )
1486
- }
1487
-
1488
1544
result .WriteString (" return result;\n }" )
1489
1545
}
1490
1546
0 commit comments