1 /*
2 * Copyright (C) 2016-2020 Team Kodi (https://kodi.tv)
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 * See LICENSE.md for more information.
6 */
7
8 #include "LibretroSetting.h"
9 #include "libretro/libretro.h"
10
11 using namespace LIBRETRO;
12
CLibretroSetting(const retro_variable * libretroVariable)13 CLibretroSetting::CLibretroSetting(const retro_variable* libretroVariable) :
14 m_key(libretroVariable->key)
15 {
16 Parse(libretroVariable->value);
17
18 SetCurrentValue(DefaultValue());
19 }
20
DefaultValue() const21 const std::string& CLibretroSetting::DefaultValue() const
22 {
23 static std::string empty;
24
25 if (!m_values.empty())
26 return m_values[0];
27
28 return empty;
29 }
30
Parse(const std::string & libretroValue)31 void CLibretroSetting::Parse(const std::string& libretroValue)
32 {
33 // Example retro_variable:
34 // { "foo_option", "Speed hack coprocessor X; false|true" }
35 //
36 // Text before first ';' is description. This ';' must be followed by
37 // a space, and followed by a list of possible values split up with '|'.
38
39 // First, Split the string into description and value list
40 auto SplitDescription = [](const std::string& retroVal, std::string& description, std::string& values)
41 {
42 // Look for ; separating the description from the pipe-separated values
43 size_t pos;
44 if ((pos = retroVal.find(';')) != std::string::npos)
45 {
46 // Set description
47 description = retroVal.substr(0, pos);
48
49 // Advance past semicolon
50 pos++;
51
52 // Advance past spaces
53 while (pos < retroVal.size() && retroVal[pos] == ' ')
54 pos++;
55
56 // Set values
57 values = retroVal.substr(pos);
58 }
59 else
60 {
61 // No semicolon found
62 values = retroVal;
63 }
64 };
65
66 std::string strDescription;
67 std::string strValues;
68 SplitDescription(libretroValue, strDescription, strValues);
69
70 if (strDescription.empty())
71 {
72 // Use key name as a backup
73 strDescription = m_key;
74 }
75
76 // Split the values on | delimiter
77 auto SplitValues = [](const std::string& strValues, std::vector<std::string>& vecValues)
78 {
79 std::string remainingValues = strValues;
80 while (!remainingValues.empty())
81 {
82 std::string strValue;
83
84 size_t pos;
85 if ((pos = remainingValues.find('|')) == std::string::npos)
86 {
87 strValue = remainingValues;
88 remainingValues.clear();
89 }
90 else
91 {
92 strValue = remainingValues.substr(0, pos);
93 remainingValues.erase(0, pos + 1);
94 }
95
96 vecValues.push_back(strValue);
97 }
98 };
99
100 std::vector<std::string> vecValues;
101 SplitValues(strValues, vecValues);
102
103 m_description = std::move(strDescription);
104 m_values = std::move(vecValues);
105 m_valuesStr = std::move(strValues);
106 }
107