git subrepo clone https://github.com/libretro/libretro-common.git deps/libretro-common
[pcsx_rearmed.git] / deps / libretro-common / playlists / label_sanitization.c
diff --git a/deps/libretro-common/playlists/label_sanitization.c b/deps/libretro-common/playlists/label_sanitization.c
new file mode 100644 (file)
index 0000000..50a95ee
--- /dev/null
@@ -0,0 +1,209 @@
+/* Copyright  (C) 2010-2020 The RetroArch team
+ *
+ * ---------------------------------------------------------------------------------------
+ * The following license statement only applies to this file (label_sanitization.c).
+ * ---------------------------------------------------------------------------------------
+ *
+ * Permission is hereby granted, free of charge,
+ * to any person obtaining a copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <playlists/label_sanitization.h>
+#include <compat/strl.h>
+#include <retro_miscellaneous.h>
+#include <string/stdstring.h>
+#include <string.h>
+
+#define DISC_STRINGS_LENGTH   3
+#define REGION_STRINGS_LENGTH 20
+
+const char *disc_strings[DISC_STRINGS_LENGTH] = {
+   "(CD",
+   "(Disc",
+   "(Disk"
+};
+
+/*
+ * We'll use the standard No-Intro regions for now.
+ */
+const char *region_strings[REGION_STRINGS_LENGTH] = {
+   "(Australia)", /* Don’t use with Europe */
+   "(Brazil)",
+   "(Canada)",    /* Don’t use with USA */
+   "(China)",
+   "(France)",
+   "(Germany)",
+   "(Hong Kong)",
+   "(Italy)",
+   "(Japan)",
+   "(Korea)",
+   "(Netherlands)",
+   "(Spain)",
+   "(Sweden)",
+   "(USA)",       /* Includes Canada */
+   "(World)",
+   "(Europe)",    /* Includes Australia */
+   "(Asia)",
+   "(Japan, USA)",
+   "(Japan, Europe)",
+   "(USA, Europe)"
+};
+
+/**
+ * label_sanitize:
+ *
+ * NOTE: Does not work with nested blocks.
+ **/
+void label_sanitize(char *label, bool (*left)(char*), bool (*right)(char*))
+{
+   bool copy = true;
+   int rindex = 0;
+   int lindex = 0;
+   char new_label[PATH_MAX_LENGTH];
+
+   for (; lindex < PATH_MAX_LENGTH && label[lindex] != '\0'; lindex++)
+   {
+      if (copy)
+      {
+         /* check for the start of the range */
+         if ((*left)(&label[lindex]))
+            copy                = false;
+         else
+         {
+            const bool whitespace = label[lindex] == ' ' && (rindex == 0 || new_label[rindex - 1] == ' ');
+
+            /* Simplify consecutive whitespaces */
+            if (!whitespace)
+               new_label[rindex++] = label[lindex];
+         }
+      }
+      else if ((*right)(&label[lindex]))
+         copy = true;
+   }
+
+   /* Trim trailing whitespace */
+   if (rindex > 0 && new_label[rindex - 1] == ' ')
+      new_label[rindex - 1] = '\0';
+   else
+      new_label[rindex] = '\0';
+
+   strlcpy(label, new_label, PATH_MAX_LENGTH);
+}
+
+static bool left_parens(char *left)
+{
+   return left[0] == '(';
+}
+
+static bool right_parens(char *right)
+{
+   return right[0] == ')';
+}
+
+static bool left_brackets(char *left)
+{
+   return left[0] == '[';
+}
+
+static bool right_brackets(char *right)
+{
+   return right[0] == ']';
+}
+
+static bool left_parens_or_brackets(char *left)
+{
+   return left[0] == '(' || left[0] == '[';
+}
+
+static bool right_parens_or_brackets(char *right)
+{
+   return right[0] == ')' || right[0] == ']';
+}
+
+static bool left_exclusion(char *left,
+      const char **strings, const size_t strings_count)
+{
+   unsigned i;
+   char exclusion_string[32];
+   char comparison_string[32];
+
+   strlcpy(exclusion_string, left, sizeof(exclusion_string));
+   string_to_upper(exclusion_string);
+
+   for (i = 0; i < (unsigned)strings_count; i++)
+   {
+      strlcpy(comparison_string, strings[i], sizeof(comparison_string));
+      string_to_upper(comparison_string);
+
+      if (string_starts_with(exclusion_string,
+               comparison_string))
+         return true;
+   }
+
+   return false;
+}
+
+static bool left_parens_or_brackets_excluding_region(char *left)
+{
+   return left_parens_or_brackets(left)
+      && !left_exclusion(left, region_strings, REGION_STRINGS_LENGTH);
+}
+
+static bool left_parens_or_brackets_excluding_disc(char *left)
+{
+   return left_parens_or_brackets(left)
+      && !left_exclusion(left, disc_strings, DISC_STRINGS_LENGTH);
+}
+
+static bool left_parens_or_brackets_excluding_region_or_disc(char *left)
+{
+   return left_parens_or_brackets(left)
+      && !left_exclusion(left, region_strings, REGION_STRINGS_LENGTH)
+      && !left_exclusion(left, disc_strings, DISC_STRINGS_LENGTH);
+}
+
+void label_remove_parens(char *label)
+{
+   label_sanitize(label, left_parens, right_parens);
+}
+
+void label_remove_brackets(char *label)
+{
+   label_sanitize(label, left_brackets, right_brackets);
+}
+
+void label_remove_parens_and_brackets(char *label)
+{
+   label_sanitize(label, left_parens_or_brackets,
+         right_parens_or_brackets);
+}
+
+void label_keep_region(char *label)
+{
+   label_sanitize(label, left_parens_or_brackets_excluding_region,
+         right_parens_or_brackets);
+}
+
+void label_keep_disc(char *label)
+{
+   label_sanitize(label, left_parens_or_brackets_excluding_disc,
+         right_parens_or_brackets);
+}
+
+void label_keep_region_and_disc(char *label)
+{
+   label_sanitize(label, left_parens_or_brackets_excluding_region_or_disc,
+         right_parens_or_brackets);
+}