using System;
using System.Diagnostics.CodeAnalysis;
namespace MediaBrowser.Common.Providers
{
///
/// Parsers for provider ids.
///
public static class ProviderIdParsers
{
private const int ImdbMinNumbers = 7;
private const int ImdbMaxNumbers = 8;
private const string ImdbPrefix = "tt";
///
/// Parses an IMDb id from a string.
///
/// The text to parse.
/// The parsed IMDb id.
/// True if parsing was successful, false otherwise.
public static bool TryFindImdbId(ReadOnlySpan text, out ReadOnlySpan imdbId)
{
// IMDb id is at least 9 chars (tt + 7 numbers)
while (text.Length >= 2 + ImdbMinNumbers)
{
var ttPos = text.IndexOf(ImdbPrefix);
if (ttPos == -1)
{
imdbId = default;
return false;
}
text = text.Slice(ttPos);
var i = 2;
var limit = Math.Min(text.Length, ImdbMaxNumbers + 2);
for (; i < limit; i++)
{
var c = text[i];
if (!IsDigit(c))
{
break;
}
}
// Skip if more than 8 digits + 2 chars for tt
if (i <= ImdbMaxNumbers + 2 && i >= ImdbMinNumbers + 2)
{
imdbId = text.Slice(0, i);
return true;
}
text = text.Slice(i);
}
imdbId = default;
return false;
}
///
/// Parses an TMDb id from a movie url.
///
/// The text with the url to parse.
/// The parsed TMDb id.
/// True if parsing was successful, false otherwise.
public static bool TryFindTmdbMovieId(ReadOnlySpan text, out ReadOnlySpan tmdbId)
=> TryFindProviderId(text, "themoviedb.org/movie/", out tmdbId);
///
/// Parses an TMDb id from a series url.
///
/// The text with the url to parse.
/// The parsed TMDb id.
/// True if parsing was successful, false otherwise.
public static bool TryFindTmdbSeriesId(ReadOnlySpan text, out ReadOnlySpan tmdbId)
=> TryFindProviderId(text, "themoviedb.org/tv/", out tmdbId);
///
/// Parses an TVDb id from a url.
///
/// The text with the url to parse.
/// The parsed TVDb id.
/// True if parsing was successful, false otherwise.
public static bool TryFindTvdbId(ReadOnlySpan text, out ReadOnlySpan tvdbId)
=> TryFindProviderId(text, "thetvdb.com/?tab=series&id=", out tvdbId);
private static bool TryFindProviderId(ReadOnlySpan text, ReadOnlySpan searchString, [NotNullWhen(true)] out ReadOnlySpan providerId)
{
var searchPos = text.IndexOf(searchString);
if (searchPos == -1)
{
providerId = default;
return false;
}
text = text.Slice(searchPos + searchString.Length);
int i = 0;
for (; i < text.Length; i++)
{
var c = text[i];
if (!IsDigit(c))
{
break;
}
}
if (i >= 1)
{
providerId = text.Slice(0, i);
return true;
}
providerId = default;
return false;
}
private static bool IsDigit(char c)
{
return c >= '0' && c <= '9';
}
}
}