package.cpp (4038B)
1 /* ReaPack: Package manager for REAPER 2 * Copyright (C) 2015-2025 Christian Fillion 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU Lesser General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #include "package.hpp" 19 20 #include "errors.hpp" 21 #include "index.hpp" 22 23 #include <algorithm> 24 #include <boost/range/adaptor/reversed.hpp> 25 26 Package::Type Package::getType(const char *type) 27 { 28 constexpr std::pair<const char *, Type> map[] { 29 {"script", ScriptType}, 30 {"extension", ExtensionType}, 31 {"effect", EffectType}, 32 {"data", DataType}, 33 {"theme", ThemeType}, 34 {"langpack", LangPackType}, 35 {"webinterface", WebInterfaceType}, 36 {"projecttpl", ProjectTemplateType}, 37 {"tracktpl", TrackTemplateType}, 38 {"midinotenames", MIDINoteNamesType}, 39 {"autoitem", AutomationItemType}, 40 }; 41 42 for(auto &[key, value] : map) { 43 if(!strcmp(type, key)) 44 return value; 45 } 46 47 return UnknownType; 48 } 49 50 const char *Package::displayType(const Type type) 51 { 52 switch(type) { 53 case UnknownType: 54 break; 55 case ScriptType: 56 return "Script"; 57 case ExtensionType: 58 return "Extension"; 59 case EffectType: 60 return "Effect"; 61 case DataType: 62 return "Data"; 63 case ThemeType: 64 return "Theme"; 65 case LangPackType: 66 return "Language Pack"; 67 case WebInterfaceType: 68 return "Web Interface"; 69 case ProjectTemplateType: 70 return "Project Template"; 71 case TrackTemplateType: 72 return "Track Template"; 73 case MIDINoteNamesType: 74 return "MIDI Note Names"; 75 case AutomationItemType: 76 return "Automation Item"; 77 } 78 79 return "Unknown"; 80 } 81 82 const std::string &Package::displayName(const std::string &name, const std::string &desc) 83 { 84 return desc.empty() ? name : desc; 85 } 86 87 Package::Package(const Type type, const std::string &name, const Category *cat) 88 : m_category(cat), m_type(type), m_name(name) 89 { 90 if(m_name.empty()) 91 throw reapack_error("empty package name"); 92 else if(m_name.find_first_of("/\\") != std::string::npos) { 93 throw reapack_error( 94 String::format("invalid package name '%s'", m_name.c_str())); 95 } 96 } 97 98 Package::~Package() 99 { 100 for(const Version *ver : m_versions) 101 delete ver; 102 } 103 104 std::string Package::fullName() const 105 { 106 return m_category ? m_category->fullName() + "/" + displayName() : displayName(); 107 } 108 109 bool Package::addVersion(const Version *ver) 110 { 111 if(ver->package() != this) 112 throw reapack_error("version belongs to another package"); 113 else if(ver->sources().empty()) 114 return false; 115 else if(m_versions.count(ver)) { 116 throw reapack_error(String::format("duplicate version '%s'", 117 ver->fullName().c_str())); 118 } 119 120 m_versions.insert(ver); 121 122 return true; 123 } 124 125 const Version *Package::version(const size_t index) const 126 { 127 auto it = m_versions.begin(); 128 advance(it, index); 129 130 return *it; 131 } 132 133 const Version *Package::lastVersion(const bool pres, const VersionName &from) const 134 { 135 if(m_versions.empty()) 136 return nullptr; 137 138 for(const Version *ver : m_versions | boost::adaptors::reversed) { 139 if(ver->name() < from) 140 break; 141 else if(ver->name().isStable() || pres) 142 return ver; 143 } 144 145 return from.isStable() ? nullptr : *m_versions.rbegin(); 146 } 147 148 const Version *Package::findVersion(const VersionName &ver) const 149 { 150 const auto &it = find_if(m_versions.begin(), m_versions.end(), 151 [=] (const Version *cur) { return cur->name() == ver; }); 152 153 if(it == m_versions.end()) 154 return nullptr; 155 else 156 return *it; 157 }