static void ParseForIoPattern()

in ctsTraffic/ctsConfig.cpp [824:1061]


static void ParseForIoPattern(vector<const wchar_t*>& args)
{
    auto foundArgument = ranges::find_if(args, [](const wchar_t* parameter) -> bool {
        const auto* const value = ParseArgument(parameter, L"-pattern");
        return value != nullptr;
    });
    if (foundArgument != end(args))
    {
        if (g_configSettings->Protocol != ProtocolType::TCP)
        {
            throw invalid_argument("-pattern (only applicable to TCP)");
        }

        // ReSharper disable once CppTooWideScopeInitStatement
        const auto* const value = ParseArgument(*foundArgument, L"-pattern");
        if (ctString::ctOrdinalEqualsCaseInsensative(L"push", value))
        {
            g_configSettings->IoPattern = IoPatternType::Push;
        }
        else if (ctString::ctOrdinalEqualsCaseInsensative(L"pull", value))
        {
            g_configSettings->IoPattern = IoPatternType::Pull;
        }
        else if (ctString::ctOrdinalEqualsCaseInsensative(L"pushpull", value))
        {
            g_configSettings->IoPattern = IoPatternType::PushPull;
        }
        else if (ctString::ctOrdinalEqualsCaseInsensative(L"flood", value) || ctString::ctOrdinalEqualsCaseInsensative(L"duplex", value))
        {
            // the old name for this was 'flood'
            g_configSettings->IoPattern = IoPatternType::Duplex;
        }
        else
        {
            throw invalid_argument("-pattern");
        }

        // always remove the arg from our vector
        args.erase(foundArgument);
    }
    else
    {
        if (g_configSettings->Protocol == ProtocolType::UDP)
        {
            g_configSettings->IoPattern = IoPatternType::MediaStream;
        }
        else
        {
            // default the TCP pattern to Push
            g_configSettings->IoPattern = IoPatternType::Push;
        }
    }

    // Now look for options tightly coupled to Protocol
    // ReSharper disable once CppTooWideScopeInitStatement
    const auto foundPushbytes = ranges::find_if(args, [](const wchar_t* parameter) -> bool {
        const auto* const value = ParseArgument(parameter, L"-pushbytes");
        return value != nullptr;
    });
    if (foundPushbytes != end(args))
    {
        if (g_configSettings->IoPattern != IoPatternType::PushPull)
        {
            throw invalid_argument("-PushBytes can only be set with -Pattern:PushPull");
        }
        g_configSettings->PushBytes = ConvertToIntegral<uint32_t>(ParseArgument(*foundPushbytes, L"-pushbytes"));
        // always remove the arg from our vector
        args.erase(foundPushbytes);
    }
    else
    {
        g_configSettings->PushBytes = c_defaultPushBytes;
    }

    // ReSharper disable once CppTooWideScopeInitStatement
    const auto foundPullbytes = ranges::find_if(args, [](const wchar_t* parameter) -> bool {
        const auto* const value = ParseArgument(parameter, L"-pullbytes");
        return value != nullptr;
    });
    if (foundPullbytes != end(args))
    {
        if (g_configSettings->IoPattern != IoPatternType::PushPull)
        {
            throw invalid_argument("-PullBytes can only be set with -Pattern:PushPull");
        }
        g_configSettings->PullBytes = ConvertToIntegral<uint32_t>(ParseArgument(*foundPullbytes, L"-pullbytes"));
        // always remove the arg from our vector
        args.erase(foundPullbytes);
    }
    else
    {
        g_configSettings->PullBytes = c_defaultPullBytes;
    }

    // ReSharper disable once CppTooWideScopeInitStatement
    const auto foundBurstCount = ranges::find_if(args, [](const wchar_t* parameter) -> bool {
        const auto* const value = ParseArgument(parameter, L"-burstcount");
        return value != nullptr;
    });
    if (foundBurstCount != end(args))
    {
        if (g_configSettings->Protocol != ProtocolType::TCP)
        {
            throw invalid_argument("-BurstCount requires -Protocol:TCP");
        }

        g_configSettings->BurstCount = ConvertToIntegral<uint32_t>(ParseArgument(*foundBurstCount, L"-burstcount"));
        if (g_configSettings->BurstCount == 0ul)
        {
            throw invalid_argument("-BurstCount requires a non-zero value");
        }
        // always remove the arg from our vector
        args.erase(foundBurstCount);
    }

    // ReSharper disable once CppTooWideScopeInitStatement
    const auto foundBurstDelay = ranges::find_if(args, [](const wchar_t* parameter) -> bool {
        const auto* const value = ParseArgument(parameter, L"-burstdelay");
        return value != nullptr;
    });
    if (foundBurstDelay != end(args))
    {
        if (g_configSettings->Protocol != ProtocolType::TCP)
        {
            throw invalid_argument("-BurstDelay requires -Protocol:TCP");
        }

        g_configSettings->BurstDelay = ConvertToIntegral<uint32_t>(ParseArgument(*foundBurstDelay, L"-burstdelay"));
        if (g_configSettings->BurstDelay == 0ul)
        {
            throw invalid_argument("-BurstDelay requires a non-zero value");
        }
        // always remove the arg from our vector
        args.erase(foundBurstDelay);
    }

    // ReSharper disable CppRedundantParentheses
    if ((g_configSettings->BurstCount.has_value() && !g_configSettings->BurstDelay.has_value()) ||
        (!g_configSettings->BurstCount.has_value() && g_configSettings->BurstDelay.has_value()))
    {
        throw invalid_argument("-BurstCount and -BurstDelay must both be set if either are set");
    }
    // ReSharper restore CppRedundantParentheses

    //
    // Options for the UDP protocol
    //

    foundArgument = ranges::find_if(args, [](const wchar_t* parameter) -> bool {
        const auto* const value = ParseArgument(parameter, L"-BitsPerSecond");
        return value != nullptr;
    });
    if (foundArgument != end(args))
    {
        if (g_configSettings->Protocol != ProtocolType::UDP)
        {
            throw invalid_argument("-BitsPerSecond requires -Protocol:UDP");
        }
        g_mediaStreamSettings.BitsPerSecond = ConvertToIntegral<int64_t>(ParseArgument(*foundArgument, L"-BitsPerSecond"));
        // bitspersecond must align on a byte-boundary
        if (g_mediaStreamSettings.BitsPerSecond % 8 != 0)
        {
            g_mediaStreamSettings.BitsPerSecond -= g_mediaStreamSettings.BitsPerSecond % 8;
        }
        // always remove the arg from our vector
        args.erase(foundArgument);
    }

    foundArgument = ranges::find_if(args, [](const wchar_t* parameter) -> bool {
        const auto* const value = ParseArgument(parameter, L"-FrameRate");
        return value != nullptr;
    });
    if (foundArgument != end(args))
    {
        if (g_configSettings->Protocol != ProtocolType::UDP)
        {
            throw invalid_argument("-FrameRate requires -Protocol:UDP");
        }
        g_mediaStreamSettings.FramesPerSecond = ConvertToIntegral<uint32_t>(ParseArgument(*foundArgument, L"-FrameRate"));
        // always remove the arg from our vector
        args.erase(foundArgument);
    }

    foundArgument = ranges::find_if(args, [](const wchar_t* parameter) -> bool {
        const auto* const value = ParseArgument(parameter, L"-BufferDepth");
        return value != nullptr;
    });
    if (foundArgument != end(args))
    {
        if (g_configSettings->Protocol != ProtocolType::UDP)
        {
            throw invalid_argument("-BufferDepth requires -Protocol:UDP");
        }
        g_mediaStreamSettings.BufferDepthSeconds = ConvertToIntegral<uint32_t>(ParseArgument(*foundArgument, L"-BufferDepth"));
        // always remove the arg from our vector
        args.erase(foundArgument);
    }
    else
    {
        // default buffer depth to 1
        g_mediaStreamSettings.BufferDepthSeconds = 1;
    }

    foundArgument = ranges::find_if(args, [](const wchar_t* parameter) -> bool {
        const auto* const value = ParseArgument(parameter, L"-StreamLength");
        return value != nullptr;
    });
    if (foundArgument != end(args))
    {
        if (g_configSettings->Protocol != ProtocolType::UDP)
        {
            throw invalid_argument("-StreamLength requires -Protocol:UDP");
        }
        g_mediaStreamSettings.StreamLengthSeconds = ConvertToIntegral<uint32_t>(ParseArgument(*foundArgument, L"-StreamLength"));
        // always remove the arg from our vector
        args.erase(foundArgument);
    }

    // validate and resolve the UDP protocol options
    if (ProtocolType::UDP == g_configSettings->Protocol)
    {
        if (0 == g_mediaStreamSettings.BitsPerSecond)
        {
            throw invalid_argument("-BitsPerSecond is required");
        }
        if (0 == g_mediaStreamSettings.FramesPerSecond)
        {
            throw invalid_argument("-FrameRate is required");
        }
        if (0 == g_mediaStreamSettings.StreamLengthSeconds)
        {
            throw invalid_argument("-StreamLength is required");
        }

        // finally calculate the total stream length after all settings are captured from the user
        g_transferSizeLow = g_mediaStreamSettings.CalculateTransferSize();
    }
}