Coverage Report

Created: 2026-02-09 06:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmCacheManager.cxx
Line
Count
Source
1
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2
   file LICENSE.rst or https://cmake.org/licensing for details.  */
3
#include "cmCacheManager.h"
4
5
#include <algorithm>
6
#include <cstdio>
7
#include <cstring>
8
#include <sstream>
9
#include <string>
10
11
#include "cmsys/FStream.hxx"
12
#include "cmsys/Glob.hxx"
13
14
#include "cmGeneratedFileStream.h"
15
#include "cmList.h"
16
#include "cmMessageType.h"
17
#include "cmMessenger.h"
18
#include "cmState.h"
19
#include "cmStringAlgorithms.h"
20
#include "cmSystemTools.h"
21
#include "cmVersion.h"
22
23
void cmCacheManager::CleanCMakeFiles(std::string const& path)
24
0
{
25
0
  std::string glob = cmStrCat(path, "/CMakeFiles/*.cmake");
26
0
  cmsys::Glob globIt;
27
0
  globIt.FindFiles(glob);
28
0
  std::vector<std::string> files = globIt.GetFiles();
29
0
  std::for_each(files.begin(), files.end(), cmSystemTools::RemoveFile);
30
0
}
31
32
bool cmCacheManager::LoadCache(std::string const& path, bool internal,
33
                               std::set<std::string>& excludes,
34
                               std::set<std::string>& includes)
35
0
{
36
0
  std::string cacheFile = cmStrCat(path, "/CMakeCache.txt");
37
  // clear the old cache, if we are reading in internal values
38
0
  if (internal) {
39
0
    this->Cache.clear();
40
0
  }
41
0
  if (!cmSystemTools::FileExists(cacheFile)) {
42
0
    this->CleanCMakeFiles(path);
43
0
    return false;
44
0
  }
45
46
0
  cmsys::ifstream fin(cacheFile.c_str());
47
0
  if (!fin) {
48
0
    return false;
49
0
  }
50
0
  char const* realbuffer;
51
0
  std::string buffer;
52
0
  std::string entryKey;
53
0
  unsigned int lineno = 0;
54
0
  while (fin) {
55
    // Format is key:type=value
56
0
    std::string helpString;
57
0
    CacheEntry e;
58
0
    cmSystemTools::GetLineFromStream(fin, buffer);
59
0
    lineno++;
60
0
    realbuffer = buffer.c_str();
61
0
    while (*realbuffer == ' ' || *realbuffer == '\t' || *realbuffer == '\r' ||
62
0
           *realbuffer == '\n') {
63
0
      if (*realbuffer == '\n') {
64
0
        lineno++;
65
0
      }
66
0
      realbuffer++;
67
0
    }
68
    // skip blank lines and comment lines
69
0
    if (realbuffer[0] == '#' || realbuffer[0] == 0) {
70
0
      continue;
71
0
    }
72
0
    while (realbuffer[0] == '/' && realbuffer[1] == '/') {
73
0
      if ((realbuffer[2] == '\\') && (realbuffer[3] == 'n')) {
74
0
        helpString = cmStrCat(std::move(helpString), '\n', &realbuffer[4]);
75
0
      } else {
76
0
        helpString = cmStrCat(std::move(helpString), &realbuffer[2]);
77
0
      }
78
0
      cmSystemTools::GetLineFromStream(fin, buffer);
79
0
      lineno++;
80
0
      realbuffer = buffer.c_str();
81
0
      if (!fin) {
82
0
        continue;
83
0
      }
84
0
    }
85
0
    e.SetProperty("HELPSTRING", helpString);
86
0
    if (cmState::ParseCacheEntry(realbuffer, entryKey, e.Value, e.Type)) {
87
0
      if (excludes.find(entryKey) == excludes.end()) {
88
        // Load internal values if internal is set.
89
        // If the entry is not internal to the cache being loaded
90
        // or if it is in the list of internal entries to be
91
        // imported, load it.
92
0
        if (internal || (e.Type != cmStateEnums::INTERNAL) ||
93
0
            (includes.find(entryKey) != includes.end())) {
94
          // If we are loading the cache from another project,
95
          // make all loaded entries internal so that it is
96
          // not visible in the gui
97
0
          if (!internal) {
98
0
            e.Type = cmStateEnums::INTERNAL;
99
0
            helpString = cmStrCat("DO NOT EDIT, ", entryKey,
100
0
                                  " loaded from external file.  "
101
0
                                  "To change this value edit this file: ",
102
0
                                  path, "/CMakeCache.txt");
103
0
            e.SetProperty("HELPSTRING", helpString);
104
0
          }
105
0
          if (!this->ReadPropertyEntry(entryKey, e)) {
106
0
            e.Initialized = true;
107
0
            this->Cache[entryKey] = e;
108
0
          }
109
0
        }
110
0
      }
111
0
    } else {
112
0
      std::ostringstream error;
113
0
      error << "Parse error in cache file " << cacheFile << " on line "
114
0
            << lineno << ". Offending entry: " << realbuffer;
115
0
      cmSystemTools::Error(error.str());
116
0
    }
117
0
  }
118
0
  this->CacheMajorVersion = 0;
119
0
  this->CacheMinorVersion = 0;
120
0
  if (cmValue cmajor =
121
0
        this->GetInitializedCacheValue("CMAKE_CACHE_MAJOR_VERSION")) {
122
0
    unsigned int v = 0;
123
0
    if (sscanf(cmajor->c_str(), "%u", &v) == 1) {
124
0
      this->CacheMajorVersion = v;
125
0
    }
126
0
    if (cmValue cminor =
127
0
          this->GetInitializedCacheValue("CMAKE_CACHE_MINOR_VERSION")) {
128
0
      if (sscanf(cminor->c_str(), "%u", &v) == 1) {
129
0
        this->CacheMinorVersion = v;
130
0
      }
131
0
    }
132
0
  } else {
133
    // CMake version not found in the list file.
134
    // Set as version 0.0
135
0
    this->AddCacheEntry("CMAKE_CACHE_MINOR_VERSION", "0",
136
0
                        "Minor version of cmake used to create the "
137
0
                        "current loaded cache",
138
0
                        cmStateEnums::INTERNAL);
139
0
    this->AddCacheEntry("CMAKE_CACHE_MAJOR_VERSION", "0",
140
0
                        "Major version of cmake used to create the "
141
0
                        "current loaded cache",
142
0
                        cmStateEnums::INTERNAL);
143
0
  }
144
  // check to make sure the cache directory has not
145
  // been moved
146
0
  cmValue oldDir = this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR");
147
0
  if (internal && oldDir) {
148
0
    std::string currentcwd = path;
149
0
    std::string oldcwd = *oldDir;
150
0
    cmSystemTools::ConvertToUnixSlashes(currentcwd);
151
0
    currentcwd = cmStrCat(std::move(currentcwd), "/CMakeCache.txt");
152
0
    oldcwd = cmStrCat(std::move(oldcwd), "/CMakeCache.txt");
153
0
    if (!cmSystemTools::SameFile(oldcwd, currentcwd)) {
154
0
      cmValue dir = this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR");
155
0
      std::string message =
156
0
        cmStrCat("The current CMakeCache.txt directory ", currentcwd,
157
0
                 " is different than the directory ", (dir ? *dir : ""),
158
0
                 " where CMakeCache.txt was created. This may result "
159
0
                 "in binaries being created in the wrong place. If you "
160
0
                 "are not sure, reedit the CMakeCache.txt");
161
0
      cmSystemTools::Error(message);
162
0
    }
163
0
  }
164
0
  this->CacheLoaded = true;
165
0
  return true;
166
0
}
167
168
char const* cmCacheManager::PersistentProperties[] = { "ADVANCED", "MODIFIED",
169
                                                       "STRINGS" };
170
171
bool cmCacheManager::ReadPropertyEntry(std::string const& entryKey,
172
                                       CacheEntry const& e)
173
0
{
174
  // All property entries are internal.
175
0
  if (e.Type != cmStateEnums::INTERNAL) {
176
0
    return false;
177
0
  }
178
179
0
  char const* end = entryKey.c_str() + entryKey.size();
180
0
  for (char const* p : cmCacheManager::PersistentProperties) {
181
0
    std::string::size_type plen = strlen(p) + 1;
182
0
    if (entryKey.size() > plen && *(end - plen) == '-' &&
183
0
        strcmp(end - plen + 1, p) == 0) {
184
0
      std::string key = entryKey.substr(0, entryKey.size() - plen);
185
0
      if (auto* entry = this->GetCacheEntry(key)) {
186
        // Store this property on its entry.
187
0
        entry->SetProperty(p, e.Value);
188
0
      } else {
189
        // Create an entry and store the property.
190
0
        CacheEntry& ne = this->Cache[key];
191
0
        ne.SetProperty(p, e.Value);
192
0
      }
193
0
      return true;
194
0
    }
195
0
  }
196
0
  return false;
197
0
}
198
199
void cmCacheManager::WritePropertyEntries(std::ostream& os,
200
                                          std::string const& entryKey,
201
                                          CacheEntry const& e,
202
                                          cmMessenger* messenger) const
203
0
{
204
0
  for (char const* p : cmCacheManager::PersistentProperties) {
205
0
    if (cmValue value = e.GetProperty(p)) {
206
0
      std::string helpstring =
207
0
        cmStrCat(p, " property for variable: ", entryKey);
208
0
      cmCacheManager::OutputHelpString(os, helpstring);
209
210
0
      std::string key = cmStrCat(entryKey, '-', p);
211
0
      cmCacheManager::OutputKey(os, key);
212
0
      os << ":INTERNAL=";
213
0
      cmCacheManager::OutputValue(os, *value);
214
0
      os << '\n';
215
0
      cmCacheManager::OutputNewlineTruncationWarning(os, key, *value,
216
0
                                                     messenger);
217
0
    }
218
0
  }
219
0
}
220
221
bool cmCacheManager::SaveCache(std::string const& path, cmMessenger* messenger)
222
0
{
223
0
  std::string cacheFile = cmStrCat(path, "/CMakeCache.txt");
224
0
  cmGeneratedFileStream fout(cacheFile);
225
0
  fout.SetCopyIfDifferent(true);
226
0
  if (!fout) {
227
0
    cmSystemTools::Error(
228
0
      cmStrCat("Unable to open cache file for save. ", std::move(cacheFile)));
229
0
    cmSystemTools::ReportLastSystemError("");
230
0
    return false;
231
0
  }
232
  // before writing the cache, update the version numbers
233
  // to the
234
0
  this->AddCacheEntry("CMAKE_CACHE_MAJOR_VERSION",
235
0
                      std::to_string(cmVersion::GetMajorVersion()),
236
0
                      "Major version of cmake used to create the "
237
0
                      "current loaded cache",
238
0
                      cmStateEnums::INTERNAL);
239
0
  this->AddCacheEntry("CMAKE_CACHE_MINOR_VERSION",
240
0
                      std::to_string(cmVersion::GetMinorVersion()),
241
0
                      "Minor version of cmake used to create the "
242
0
                      "current loaded cache",
243
0
                      cmStateEnums::INTERNAL);
244
0
  this->AddCacheEntry("CMAKE_CACHE_PATCH_VERSION",
245
0
                      std::to_string(cmVersion::GetPatchVersion()),
246
0
                      "Patch version of cmake used to create the "
247
0
                      "current loaded cache",
248
0
                      cmStateEnums::INTERNAL);
249
250
  // Let us store the current working directory so that if somebody
251
  // Copies it, he will not be surprised
252
0
  std::string currentcwd = path;
253
0
  if (currentcwd[0] >= 'A' && currentcwd[0] <= 'Z' && currentcwd[1] == ':') {
254
    // Cast added to avoid compiler warning. Cast is ok because
255
    // value is guaranteed to fit in char by the above if...
256
0
    currentcwd[0] = static_cast<char>(currentcwd[0] - 'A' + 'a');
257
0
  }
258
0
  cmSystemTools::ConvertToUnixSlashes(currentcwd);
259
0
  this->AddCacheEntry("CMAKE_CACHEFILE_DIR", currentcwd,
260
0
                      "This is the directory where this CMakeCache.txt"
261
0
                      " was created",
262
0
                      cmStateEnums::INTERNAL);
263
264
  /* clang-format off */
265
0
  fout << "# This is the CMakeCache file.\n"
266
0
          "# For build in directory: " << currentcwd << "\n"
267
0
          "# It was generated by CMake: "
268
0
       << cmSystemTools::GetCMakeCommand()
269
0
       << "\n"
270
0
          "# You can edit this file to change values found and used by cmake."
271
0
          "\n"
272
0
          "# If you do not want to change any of the values, simply exit the "
273
0
          "editor.\n"
274
0
          "# If you do want to change a value, simply edit, save, and exit "
275
0
          "the editor.\n"
276
0
          "# The syntax for the file is as follows:\n"
277
0
          "# KEY:TYPE=VALUE\n"
278
0
          "# KEY is the name of a variable in the cache.\n"
279
0
          "# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!."
280
0
          "\n"
281
0
          "# VALUE is the current value for the KEY.\n"
282
0
          "\n"
283
0
          "########################\n"
284
0
          "# EXTERNAL cache entries\n"
285
0
          "########################\n"
286
0
          "\n";
287
  /* clang-format on */
288
289
0
  for (auto const& i : this->Cache) {
290
0
    CacheEntry const& ce = i.second;
291
0
    cmStateEnums::CacheEntryType t = ce.Type;
292
0
    if (!ce.Initialized) {
293
      /*
294
        // This should be added in, but is not for now.
295
      cmSystemTools::Error(cmStrCat("Cache entry \"", i.first, "\" is
296
      uninitialized"));
297
      */
298
0
    } else if (t != cmStateEnums::INTERNAL) {
299
      // Format is key:type=value
300
0
      if (cmValue help = ce.GetProperty("HELPSTRING")) {
301
0
        cmCacheManager::OutputHelpString(fout, *help);
302
0
      } else {
303
0
        cmCacheManager::OutputHelpString(fout, "Missing description");
304
0
      }
305
0
      cmCacheManager::OutputKey(fout, i.first);
306
0
      fout << ':' << cmState::CacheEntryTypeToString(t) << '=';
307
0
      cmCacheManager::OutputValue(fout, ce.Value);
308
0
      fout << '\n';
309
0
      cmCacheManager::OutputNewlineTruncationWarning(fout, i.first, ce.Value,
310
0
                                                     messenger);
311
0
      fout << '\n';
312
0
    }
313
0
  }
314
315
0
  fout << "\n"
316
0
          "########################\n"
317
0
          "# INTERNAL cache entries\n"
318
0
          "########################\n"
319
0
          "\n";
320
321
0
  for (auto const& i : this->Cache) {
322
0
    if (!i.second.Initialized) {
323
0
      continue;
324
0
    }
325
326
0
    cmStateEnums::CacheEntryType t = i.second.GetType();
327
0
    this->WritePropertyEntries(fout, i.first, i.second, messenger);
328
0
    if (t == cmStateEnums::INTERNAL) {
329
      // Format is key:type=value
330
0
      if (cmValue help = i.second.GetProperty("HELPSTRING")) {
331
0
        cmCacheManager::OutputHelpString(fout, *help);
332
0
      }
333
0
      cmCacheManager::OutputKey(fout, i.first);
334
0
      fout << ':' << cmState::CacheEntryTypeToString(t) << '=';
335
0
      cmCacheManager::OutputValue(fout, i.second.GetValue());
336
0
      fout << '\n';
337
0
      cmCacheManager::OutputNewlineTruncationWarning(
338
0
        fout, i.first, i.second.GetValue(), messenger);
339
0
    }
340
0
  }
341
0
  fout << '\n';
342
0
  fout.Close();
343
0
  std::string checkCacheFile = cmStrCat(path, "/CMakeFiles");
344
0
  cmSystemTools::MakeDirectory(checkCacheFile);
345
0
  checkCacheFile = cmStrCat(std::move(checkCacheFile), "/cmake.check_cache");
346
0
  cmsys::ofstream checkCache(checkCacheFile.c_str());
347
0
  if (!checkCache) {
348
0
    cmSystemTools::Error(
349
0
      cmStrCat("Unable to open check cache file for write. ",
350
0
               std::move(checkCacheFile)));
351
0
    return false;
352
0
  }
353
0
  checkCache << "# This file is generated by cmake for dependency checking "
354
0
                "of the CMakeCache.txt file\n";
355
0
  return true;
356
0
}
357
358
bool cmCacheManager::DeleteCache(std::string const& path)
359
0
{
360
0
  std::string cacheFile = path;
361
0
  cmSystemTools::ConvertToUnixSlashes(cacheFile);
362
0
  std::string cmakeFiles = cacheFile;
363
0
  cacheFile += "/CMakeCache.txt";
364
0
  if (cmSystemTools::FileExists(cacheFile)) {
365
0
    cmSystemTools::RemoveFile(cacheFile);
366
    // now remove the files in the CMakeFiles directory
367
    // this cleans up language cache files
368
0
    cmakeFiles += "/CMakeFiles";
369
0
    if (cmSystemTools::FileIsDirectory(cmakeFiles)) {
370
0
      cmSystemTools::RemoveADirectory(cmakeFiles);
371
0
    }
372
0
  }
373
0
  return true;
374
0
}
375
376
void cmCacheManager::OutputKey(std::ostream& fout, std::string const& key)
377
0
{
378
  // support : in key name by double quoting
379
0
  char const* q =
380
0
    (key.find(':') != std::string::npos || cmHasLiteralPrefix(key, "//"))
381
0
    ? "\""
382
0
    : "";
383
0
  fout << q << key << q;
384
0
}
385
386
void cmCacheManager::OutputValue(std::ostream& fout, std::string const& value)
387
0
{
388
  // look for and truncate newlines
389
0
  std::string::size_type newline = value.find('\n');
390
0
  if (newline != std::string::npos) {
391
0
    std::string truncated = value.substr(0, newline);
392
0
    OutputValueNoNewlines(fout, truncated);
393
0
  } else {
394
0
    OutputValueNoNewlines(fout, value);
395
0
  }
396
0
}
397
398
void cmCacheManager::OutputValueNoNewlines(std::ostream& fout,
399
                                           std::string const& value)
400
0
{
401
  // if value has trailing space or tab, enclose it in single quotes
402
0
  if (!value.empty() && (value.back() == ' ' || value.back() == '\t')) {
403
0
    fout << '\'' << value << '\'';
404
0
  } else {
405
0
    fout << value;
406
0
  }
407
0
}
408
409
void cmCacheManager::OutputHelpString(std::ostream& fout,
410
                                      std::string const& helpString)
411
0
{
412
0
  std::string::size_type end = helpString.size();
413
0
  if (end == 0) {
414
0
    return;
415
0
  }
416
0
  std::string oneLine;
417
0
  std::string::size_type pos = 0;
418
0
  for (std::string::size_type i = 1; i <= end; i++) {
419
0
    if ((i == end) || (helpString[i] == '\n') ||
420
0
        ((i - pos >= 60) && (helpString[i] == ' '))) {
421
0
      fout << "//";
422
0
      if (helpString[pos] == '\n') {
423
0
        pos++;
424
0
        fout << "\\n";
425
0
      }
426
0
      oneLine = helpString.substr(pos, i - pos);
427
0
      fout << oneLine << '\n';
428
0
      pos = i;
429
0
    }
430
0
  }
431
0
}
432
433
void cmCacheManager::OutputWarningComment(std::ostream& fout,
434
                                          std::string const& message,
435
                                          bool wrapSpaces)
436
0
{
437
0
  std::string::size_type end = message.size();
438
0
  std::string oneLine;
439
0
  std::string::size_type pos = 0;
440
0
  for (std::string::size_type i = 0; i <= end; i++) {
441
0
    if ((i == end) || (message[i] == '\n') ||
442
0
        ((i - pos >= 60) && (message[i] == ' ') && wrapSpaces)) {
443
0
      fout << "# ";
444
0
      if (message[pos] == '\n') {
445
0
        pos++;
446
0
        fout << "\\n";
447
0
      }
448
0
      oneLine = message.substr(pos, i - pos);
449
0
      fout << oneLine << '\n';
450
0
      pos = i;
451
0
    }
452
0
  }
453
0
}
454
455
void cmCacheManager::OutputNewlineTruncationWarning(std::ostream& fout,
456
                                                    std::string const& key,
457
                                                    std::string const& value,
458
                                                    cmMessenger* messenger)
459
0
{
460
0
  if (value.find('\n') != std::string::npos) {
461
0
    if (messenger) {
462
0
      std::string message =
463
0
        cmStrCat("Value of ", key, " contained a newline; truncating");
464
0
      messenger->IssueMessage(MessageType::WARNING, message);
465
0
    }
466
467
0
    std::string comment =
468
0
      cmStrCat("WARNING: Value of ", key,
469
0
               " contained a newline and was truncated. Original value:");
470
471
0
    OutputWarningComment(fout, comment, true);
472
0
    OutputWarningComment(fout, value, false);
473
0
  }
474
0
}
475
476
void cmCacheManager::RemoveCacheEntry(std::string const& key)
477
0
{
478
0
  this->Cache.erase(key);
479
0
}
480
481
cmCacheManager::CacheEntry* cmCacheManager::GetCacheEntry(
482
  std::string const& key)
483
0
{
484
0
  auto i = this->Cache.find(key);
485
0
  if (i != this->Cache.end()) {
486
0
    return &i->second;
487
0
  }
488
0
  return nullptr;
489
0
}
490
491
cmCacheManager::CacheEntry const* cmCacheManager::GetCacheEntry(
492
  std::string const& key) const
493
3
{
494
3
  auto i = this->Cache.find(key);
495
3
  if (i != this->Cache.end()) {
496
0
    return &i->second;
497
0
  }
498
3
  return nullptr;
499
3
}
500
501
cmValue cmCacheManager::GetInitializedCacheValue(std::string const& key) const
502
3
{
503
3
  if (auto const* entry = this->GetCacheEntry(key)) {
504
0
    if (entry->Initialized) {
505
0
      return cmValue(entry->GetValue());
506
0
    }
507
0
  }
508
3
  return nullptr;
509
3
}
510
511
void cmCacheManager::PrintCache(std::ostream& out) const
512
0
{
513
0
  out << "=================================================\n"
514
0
         "CMakeCache Contents:\n";
515
0
  for (auto const& i : this->Cache) {
516
0
    if (i.second.Type != cmStateEnums::INTERNAL) {
517
0
      out << i.first << " = " << i.second.Value << '\n';
518
0
    }
519
0
  }
520
0
  out << "\n\n"
521
0
         "To change values in the CMakeCache, \n"
522
0
         "edit CMakeCache.txt in your output directory.\n"
523
0
         "=================================================\n";
524
0
}
525
526
void cmCacheManager::AddCacheEntry(std::string const& key, cmValue value,
527
                                   cmValue helpString,
528
                                   cmStateEnums::CacheEntryType type)
529
3
{
530
3
  CacheEntry& e = this->Cache[key];
531
3
  e.SetValue(value);
532
3
  e.Type = type;
533
  // make sure we only use unix style paths
534
3
  if (type == cmStateEnums::FILEPATH || type == cmStateEnums::PATH) {
535
0
    if (e.Value.find(';') != std::string::npos) {
536
0
      cmList paths{ e.Value };
537
0
      for (std::string& i : paths) {
538
0
        cmSystemTools::ConvertToUnixSlashes(i);
539
0
      }
540
0
      e.Value = paths.to_string();
541
0
    } else {
542
0
      cmSystemTools::ConvertToUnixSlashes(e.Value);
543
0
    }
544
0
  }
545
3
  e.SetProperty(
546
3
    "HELPSTRING",
547
3
    helpString ? *helpString
548
3
               : std::string{
549
0
                   "(This variable does not exist and should not be used)" });
550
3
}
551
552
void cmCacheManager::CacheEntry::SetValue(cmValue value)
553
3
{
554
3
  if (value) {
555
3
    this->Value = *value;
556
3
    this->Initialized = true;
557
3
  } else {
558
0
    this->Value.clear();
559
0
  }
560
3
}
561
562
std::vector<std::string> cmCacheManager::CacheEntry::GetPropertyList() const
563
0
{
564
0
  return this->Properties.GetKeys();
565
0
}
566
567
cmValue cmCacheManager::CacheEntry::GetProperty(std::string const& prop) const
568
0
{
569
0
  if (prop == "TYPE") {
570
0
    return cmValue(cmState::CacheEntryTypeToString(this->Type));
571
0
  }
572
0
  if (prop == "VALUE") {
573
0
    return cmValue(this->Value);
574
0
  }
575
0
  return this->Properties.GetPropertyValue(prop);
576
0
}
577
578
bool cmCacheManager::CacheEntry::GetPropertyAsBool(
579
  std::string const& prop) const
580
0
{
581
0
  return this->GetProperty(prop).IsOn();
582
0
}
583
584
void cmCacheManager::CacheEntry::SetProperty(std::string const& prop,
585
                                             std::string const& value)
586
3
{
587
3
  if (prop == "TYPE") {
588
0
    this->Type = cmState::StringToCacheEntryType(value);
589
3
  } else if (prop == "VALUE") {
590
0
    this->Value = value;
591
3
  } else {
592
3
    this->Properties.SetProperty(prop, value);
593
3
  }
594
3
}
595
596
void cmCacheManager::CacheEntry::SetProperty(std::string const& p, bool v)
597
0
{
598
0
  this->SetProperty(p, v ? std::string{ "ON" } : std::string{ "OFF" });
599
0
}
600
601
void cmCacheManager::CacheEntry::RemoveProperty(std::string const& prop)
602
0
{
603
0
  if (prop == "TYPE") {
604
0
    this->Type = cmState::StringToCacheEntryType("STRING");
605
0
  } else if (prop == "VALUE") {
606
0
    this->Value.clear();
607
0
  } else {
608
0
    this->Properties.RemoveProperty(prop);
609
0
  }
610
0
}
611
612
void cmCacheManager::CacheEntry::AppendProperty(std::string const& prop,
613
                                                std::string const& value,
614
                                                bool asString)
615
0
{
616
0
  if (prop == "TYPE") {
617
0
    this->Type =
618
0
      cmState::StringToCacheEntryType(!value.empty() ? value : "STRING");
619
0
  } else if (prop == "VALUE") {
620
0
    if (!value.empty()) {
621
0
      if (!this->Value.empty() && !asString) {
622
0
        this->Value += ";";
623
0
      }
624
0
      this->Value += value;
625
0
    }
626
0
  } else {
627
0
    this->Properties.AppendProperty(prop, value, asString);
628
0
  }
629
0
}