Commit d2fe0529 authored by sagnowski's avatar sagnowski
Browse files

Integrate mandatory parameters into CmdlnParser, improve usage printout

parent 7cdaa419
Loading
Loading
Loading
Loading
+6 −44
Original line number Diff line number Diff line
@@ -58,7 +58,6 @@
 *------------------------------------------------------------------------------------------*/

#define POST_REND_MAX_CLI_ARG_LENGTH ( FILENAME_MAX )
#define POST_REND_NUM_MANDATORY_CMD_LINE_PARAMS 3

#define ISAR_MAX16B_FLT 32767.0f
#define ISAR_MIN16B_FLT ( -32768.0f )
@@ -140,18 +139,21 @@ static const CmdLnParser_Option cliOptions[] = {
        .match = "input_file",
        .matchShort = "i",
        .description = "Path to the input file (WAV or raw PCM with BINAURAL_SPLIT_PCM input format, coded ISAR file with BINAURAL_SPLIT_CODED)",
        .isMandatory = true,
    },
    {
        .id = CmdLnOptionId_inputFormat,
        .match = "input_format",
        .matchShort = "if",
        .description = "Audio format of input file (e.g. BINAURAL_SPLIT_CODED, BINAURAL_SPLIT_PCM, ... Use -l for a list)",
        .isMandatory = true,
    },
    {
        .id = CmdLnOptionId_outputFile,
        .match = "output_file",
        .matchShort = "o",
        .description = "Path to the output file",
        .isMandatory = true,
    },
    {
        .id = CmdLnOptionId_inputMetadata,
@@ -394,41 +396,6 @@ static IVAS_AUDIO_CONFIG parseAudioConfig(
}


static bool checkRequiredArgs(
    CmdlnArgs args )
{
    const CmdLnParser_Option *tmpOption;

    /* Check required arguments */
    bool missingRequiredArg = false;
    if ( isEmptyString( args.inputFilePath ) )
    {
        tmpOption = findOptionById( CmdLnOptionId_inputFile );
        fprintf( stderr, "Missing mandatory parameter: --%s/-%s\n", tmpOption->match, tmpOption->matchShort );
        missingRequiredArg = true;
    }

    if ( args.inConfig.numBinBuses == 0 )
    {
        tmpOption = findOptionById( CmdLnOptionId_inputFormat );
        fprintf( stderr, "Missing mandatory parameter: --%s/-%s\n", tmpOption->match, tmpOption->matchShort );
        missingRequiredArg = true;
    }

    if ( isEmptyString( args.outputFilePath ) )
    {
        tmpOption = findOptionById( CmdLnOptionId_outputFile );
        fprintf( stderr, "Missing mandatory parameter: --%s/-%s\n", tmpOption->match, tmpOption->matchShort );
        missingRequiredArg = true;
    }

    if ( missingRequiredArg )
    {
        CmdLnParser_printUsage( args.executableName, cliOptions, numCliOptions, POST_REND_NUM_MANDATORY_CMD_LINE_PARAMS );
    }

    return !missingRequiredArg;
}


static CmdlnArgs defaultArgs(
@@ -643,7 +610,7 @@ static int16_t parseOption(
            strncpy( args->srParamsFilePath, optionValues[0], POST_REND_MAX_CLI_ARG_LENGTH - 1 );
            break;
        case CmdLnOptionId_help:
            CmdLnParser_printUsage( args->executableName, cliOptions, numCliOptions, POST_REND_NUM_MANDATORY_CMD_LINE_PARAMS );
            CmdLnParser_printUsage( args->executableName, cliOptions, numCliOptions );
            exit( 0 );
        default:
            fprintf( stderr, "Error: Incorrect or invalid command-line usage!\n" );
@@ -661,12 +628,7 @@ static CmdlnArgs parseCmdlnArgs(
{
    CmdlnArgs args = defaultArgs( argv[0] );

    if ( CmdLnParser_parseArgs( argc, argv, cliOptions, numCliOptions, &args, parseOption, POST_REND_NUM_MANDATORY_CMD_LINE_PARAMS ) != 0 )
    {
        exit( -1 ); /* Error printout handled by failing function */
    }

    if ( !checkRequiredArgs( args ) )
    if ( CmdLnParser_parseArgs( argc, argv, cliOptions, numCliOptions, &args, parseOption ) != 0 )
    {
        exit( -1 ); /* Error printout handled by failing function */
    }
+8 −57
Original line number Diff line number Diff line
@@ -68,7 +68,6 @@
#define RENDERER_MAX_CLI_ARG_LENGTH       ( FILENAME_MAX )
#define RENDERER_MAX_METADATA_LENGTH      8192
#define RENDERER_MAX_METADATA_LINE_LENGTH 1024
#define RENDERER_NUM_MANDATORY_CMD_LINE_PARAMS 1000

#define IVAS_MAX16B_FLT 32767.0f
#define IVAS_MIN16B_FLT ( -32768.0f )
@@ -236,12 +235,14 @@ static const CmdLnParser_Option cliOptions[] = {
        .match = "input_file",
        .matchShort = "i",
        .description = "Path to the input file (WAV, raw PCM or scene description file)",
        .isMandatory = true,
    },
    {
        .id = CmdLnOptionId_inputFormat,
        .match = "input_format",
        .matchShort = "if",
        .description = "Audio format of input file (e.g. 5_1 or HOA3 or META,\nuse -l for a list)",
        .isMandatory = true,
    },
    {
        .id = CmdLnOptionId_inputMetadata,
@@ -254,12 +255,14 @@ static const CmdLnParser_Option cliOptions[] = {
        .match = "output_file",
        .matchShort = "o",
        .description = "Path to the output file",
        .isMandatory = true,
    },
    {
        .id = CmdLnOptionId_outputFormat,
        .match = "output_format",
        .matchShort = "of",
        .description = "Output format to render.\nAlternatively, can be a custom loudspeaker layout file",
        .isMandatory = true,
    },
    {
        .id = CmdLnOptionId_sampleRate,
@@ -2596,53 +2599,6 @@ static bool parseReverbRoomSize(
    return true;
}


static bool checkRequiredArgs(
    CmdlnArgs args )
{
    const CmdLnParser_Option *tmpOption;

    /* Check required arguments */
    bool missingRequiredArg = false;
    if ( isEmptyString( args.inputFilePath ) )
    {
        tmpOption = findOptionById( CmdLnOptionId_inputFile );
        fprintf( stderr, "Missing required argument: %s (%s)\n", tmpOption->match, tmpOption->matchShort );
        missingRequiredArg = true;
    }

    const bool singleInputSpecified = args.inConfig.numAudioObjects != 0 ||
                                      args.inConfig.numAmbisonicsBuses != 0 ||
                                      args.inConfig.numMultiChannelBuses != 0 ||
                                      args.inConfig.numMasaBuses != 0;

    if ( !args.sceneDescriptionInput && !singleInputSpecified )
    {
        /* Neither scene description input nor single-type input was specified on command line */
        tmpOption = findOptionById( CmdLnOptionId_inputFormat );
        fprintf( stderr, "Missing required argument: %s (%s)\n", tmpOption->match, tmpOption->matchShort );
        missingRequiredArg = true;
    }
    if ( isEmptyString( args.outputFilePath ) )
    {
        tmpOption = findOptionById( CmdLnOptionId_outputFile );
        fprintf( stderr, "Missing required argument: %s (%s)\n", tmpOption->match, tmpOption->matchShort );
        missingRequiredArg = true;
    }
    if ( args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_INVALID )
    {
        tmpOption = findOptionById( CmdLnOptionId_outputFormat );
        fprintf( stderr, "Missing required argument: %s (%s)\n", tmpOption->match, tmpOption->matchShort );
        missingRequiredArg = true;
    }
    if ( missingRequiredArg )
    {
        CmdLnParser_printUsage( args.executableName, cliOptions, numCliOptions, 100 );
    }

    return !missingRequiredArg;
}

static CmdlnArgs defaultArgs(
    const char *executableName )
{
@@ -2921,12 +2877,7 @@ static CmdlnArgs parseCmdlnArgs(
{
    CmdlnArgs args = defaultArgs( argv[0] );

    if ( CmdLnParser_parseArgs( argc, argv, cliOptions, numCliOptions, &args, parseOption, RENDERER_NUM_MANDATORY_CMD_LINE_PARAMS ) != 0 )
    {
        exit( -1 ); /* Error printout handled by failing function */
    }

    if ( !checkRequiredArgs( args ) )
    if ( CmdLnParser_parseArgs( argc, argv, cliOptions, numCliOptions, &args, parseOption ) != 0 )
    {
        exit( -1 ); /* Error printout handled by failing function */
    }
+68 −29
Original line number Diff line number Diff line
@@ -131,7 +131,7 @@ static int8_t stringLooksLikeOption(
static const char *stringToOptionName(
    const char *str )
{
    while ( ( *str == '-' ) && ( ( str[1] != '0' ) || ( str[1] != '1' ) ) )
    while ( *str == '-' )
    {
        ++str;
    }
@@ -202,7 +202,7 @@ static int16_t parseOpts(
                /* Check if already parsed */
                if ( optToMatch->hasBeenParsed )
                {
                    fprintf( stderr, "Duplicate option: %s (%s)\n", optToMatch->props.match, optToMatch->props.matchShort );
                    fprintf( stderr, "Duplicate option provided: --%s/-%s\n", optToMatch->props.match, optToMatch->props.matchShort );
                    return -1;
                }

@@ -216,7 +216,7 @@ static int16_t parseOpts(
            /* Invalid option */
            if ( stringLooksLikeOption( argv[argIdx] ) )
            {
                fprintf( stderr, "Unknown option `%s`\n", stringToOptionName( argv[argIdx] ) );
                fprintf( stderr, "Unknown option `%s`\n", argv[argIdx] );
                return -1;
            }

@@ -263,6 +263,23 @@ static int16_t parseOpts(
        currOpt->hasBeenParsed = 1;
    }

    /* Check mandatory options */
    bool missingMandatory = false;
    for ( int32_t optIdx = 0; optIdx < numOpts; ++optIdx )
    {
        Option opt = opts[optIdx];

        if ( opt.props.isMandatory && !opt.hasBeenParsed )
        {
            fprintf( stderr, "Missing mandatory parameter: --%s/-%s\n", opt.props.match, opt.props.matchShort );
            missingMandatory = true;
        }
    }
    if ( missingMandatory )
    {
        return -1;
    }

    return 0;
}

@@ -331,49 +348,73 @@ static void printOptDescriptionAligned(
    return;
}

static void printOptions(
    const OptionProps *optionProps,
    const int32_t numOptions,
    const bool mandatory,
    const int32_t maxOptNameLength
    )
{
    const int32_t preDescriptionWhitespace = 4;
    const int32_t leftColumnAdditionalChars = 7;
    int32_t optNameLength;

    for ( int32_t i = 0; i < numOptions; ++i )
    {
        OptionProps opt = optionProps[i];

        if ( opt.isMandatory != mandatory )
        {
            continue;
        }

        optNameLength = totalOptionNameLength( optionProps[i] );

        fprintf( stderr, "  --%s, -%s", opt.match, opt.matchShort );

        printWhitespace( maxOptNameLength - optNameLength + preDescriptionWhitespace - 2 );
        fprintf( stderr, ": " );
        printOptDescriptionAligned( opt.description, maxOptNameLength + leftColumnAdditionalChars + preDescriptionWhitespace );
    }
}

static void printUsage(
    const char *argv0,
    const OptionProps *optionProps,
    const int32_t numOptions,
    const int16_t numMandatoryCmdLineParams )
    const int32_t numOptions )
{
    int32_t optNameLength;
    bool hasMandatoryOptions = false;

    fprintf( stderr, "\n" );
    fprintf( stderr, "Usage: %s [options]\n", getBasename( argv0 ) );
    fprintf( stderr, "\n" );

    /* Find option with longest name, used for pretty formatting */
    int32_t maxOptNameLength = 0;
    for ( int32_t i = 0; i < numOptions; ++i )
    {
        /* Find option with longest name, used for pretty formatting */
        optNameLength = totalOptionNameLength( optionProps[i] );
        if ( maxOptNameLength < optNameLength )
        {
            maxOptNameLength = optNameLength;
        }
    }

    fprintf( stderr, "Mandatory parameters:\n" );

    const int32_t preDescriptionWhitespace = 8;
    const int32_t leftColumnAdditionalChars = 7;
    for ( int32_t i = 0; i < numOptions; ++i )
        /* Check if mandatory parameters should be printed separately */
        if ( optionProps[i].isMandatory )
        {
        OptionProps opt = optionProps[i];
        optNameLength = totalOptionNameLength( optionProps[i] );
            hasMandatoryOptions = true;
        }
    }

        if ( i == numMandatoryCmdLineParams )
    if ( hasMandatoryOptions )
    {
            fprintf( stderr, "\nOptions:\n" );
        fprintf( stderr, "Mandatory parameters:\n---------------------\n" );
        printOptions( optionProps, numOptions, true, maxOptNameLength );
    }

        /* TODO(sgi): make matchShort optional */
        fprintf( stderr, "  --%s, -%s", opt.match, opt.matchShort );

        printWhitespace( maxOptNameLength - optNameLength + preDescriptionWhitespace );
        printOptDescriptionAligned( opt.description, maxOptNameLength + preDescriptionWhitespace + leftColumnAdditionalChars );
    }
    fprintf( stderr, "\nOptions:\n--------\n" );
    printOptions( optionProps, numOptions, false, maxOptNameLength );

    return;
}
@@ -384,8 +425,7 @@ int16_t CmdLnParser_parseArgs(
    const OptionProps *optionProps,
    const int32_t numOptions,
    void *pOutputStruct,
    CmdLnParser_FnPtr_ParseOption parseOption,
    const int16_t numMandatoryCmdLineParams )
    CmdLnParser_FnPtr_ParseOption parseOption )
{
    assert( numOptions <= MAX_SUPPORTED_OPTS );

@@ -405,17 +445,16 @@ int16_t CmdLnParser_parseArgs(
    return 0;

fail:
    printUsage( argv[0], optionProps, numOptions, numMandatoryCmdLineParams );
    printUsage( argv[0], optionProps, numOptions );
    return -1;
}

void CmdLnParser_printUsage(
    char *executableName,
    const CmdLnParser_Option *options,
    const int32_t numOptions,
    const int16_t numMandatoryCmdLineParams )
    const int32_t numOptions )
{
    printUsage( executableName, options, numOptions, numMandatoryCmdLineParams );
    printUsage( executableName, options, numOptions );

    return;
}
+3 −2
Original line number Diff line number Diff line
@@ -42,13 +42,14 @@ typedef struct
    const char *match;
    const char *matchShort;
    const char *description;
    bool isMandatory;
} CmdLnParser_Option;

/* Function for parsing option values into an output struct, to be implemented by the user */
typedef int16_t ( *CmdLnParser_FnPtr_ParseOption )( int32_t optionId, char **optionValues, int16_t numOptionValues, void *pOutputStruct );

int16_t CmdLnParser_parseArgs( int32_t argc, char **argv, const CmdLnParser_Option *options, const int32_t numOptions, void *pOutputStruct, CmdLnParser_FnPtr_ParseOption parseOption, const int16_t numMandatoryCmdLineParams );
int16_t CmdLnParser_parseArgs( int32_t argc, char **argv, const CmdLnParser_Option *options, const int32_t numOptions, void *pOutputStruct, CmdLnParser_FnPtr_ParseOption parseOption );

void CmdLnParser_printUsage( char *executableName, const CmdLnParser_Option *options, const int32_t numOptions, const int16_t numMandatoryCmdLineParams );
void CmdLnParser_printUsage( char *executableName, const CmdLnParser_Option *options, const int32_t numOptions );

#endif /* CMDLN_PARSER_H */