7 #include "Preferences.h"
9 #include "NetworkCommunication/UsageReporting.h"
10 #include "Synchronized.h"
11 #include "WPIErrors.h"
17 extern "C" int Priv_SetWriteFileAllowed(uint32_t enable);
20 static const char *kTableName =
"Preferences";
22 static const char *kSaveField =
"~S A V E~";
24 static const char *kFileName =
"/c/wpilib-preferences.ini";
26 static const char *kValuePrefix =
"=\"";
28 static const char *kValueSuffix =
"\"\n";
32 Preferences::Preferences() :
34 m_fileOpStarted(NULL),
36 m_readTask(
"PreferencesReadTask", (FUNCPTR)
Preferences::InitReadTask),
37 m_writeTask(
"PreferencesWriteTask", (FUNCPTR)
Preferences::InitWriteTask)
39 m_fileLock = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE | SEM_DELETE_SAFE);
40 m_fileOpStarted = semBCreate (SEM_Q_PRIORITY, SEM_EMPTY);
41 m_tableLock = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE | SEM_DELETE_SAFE);
44 m_readTask.Start((uint32_t)
this);
45 semTake(m_fileOpStarted, WAIT_FOREVER);
47 nUsageReporting::report(nUsageReporting::kResourceType_Preferences, 0);
50 Preferences::~Preferences()
52 semTake(m_tableLock, WAIT_FOREVER);
53 semDelete(m_tableLock);
54 semTake(m_fileLock, WAIT_FOREVER);
55 semDelete(m_fileOpStarted);
56 semDelete(m_fileLock);
65 if (_instance == NULL)
88 std::string value = Get(key);
89 return value.empty() ? defaultValue : value;
103 std::string stringValue =
GetString(key, defaultValue);
104 stringValue.copy(value, valueSize);
105 return stringValue.size();
117 std::string value = Get(key);
121 return strtol(value.c_str(), NULL, 0);
133 std::string value = Get(key);
137 return strtod(value.c_str(), NULL);
149 std::string value = Get(key);
153 return strtod(value.c_str(), NULL);
165 std::string value = Get(key);
169 if (value.compare(
"true") == 0)
171 else if (value.compare(
"false") == 0)
174 wpi_setWPIErrorWithContext(ParameterOutOfRange,
"Boolean value does not contain \"true\" or \"false\"");
187 std::string value = Get(key);
194 sscanf(value.c_str(),
"%lld", &intVal);
214 wpi_setWPIErrorWithContext(NullParameter,
"value");
217 if (std::string(value).find_first_of(
"\"") != std::string::npos)
219 wpi_setWPIErrorWithContext(ParameterOutOfRange,
"value contains illegal characters");
239 snprintf(buf, 32,
"%d", value);
257 snprintf(buf, 32,
"%f", value);
275 snprintf(buf, 32,
"%f", value);
292 Put(key, value ?
"true" :
"false");
309 snprintf(buf, 32,
"%lld", value);
327 m_writeTask.
Start((uint32_t)
this);
328 semTake(m_fileOpStarted, WAIT_FOREVER);
338 return !Get(key).empty();
347 m_values.erase(std::string(key));
348 std::vector<std::string>::iterator it = m_keys.begin();
349 for (; it != m_keys.end(); it++)
351 if (it->compare(key) == 0)
364 std::string Preferences::Get(
const char *key)
369 wpi_setWPIErrorWithContext(NullParameter,
"key");
370 return std::string(
"");
372 return m_values[std::string(key)];
380 void Preferences::Put(
const char *key, std::string value)
385 wpi_setWPIErrorWithContext(NullParameter,
"key");
389 if (std::string(key).find_first_of(
"=\n\r \t\"") != std::string::npos)
391 wpi_setWPIErrorWithContext(ParameterOutOfRange,
"key contains illegal characters");
395 std::pair<StringMap::iterator, bool> ret =
396 m_values.insert(StringMap::value_type(key, value));
398 m_keys.push_back(key);
400 ret.first->second = value;
410 void Preferences::ReadTaskRun()
413 semGive(m_fileOpStarted);
418 file = fopen(kFileName,
"r");
429 }
while (value ==
' ' || value ==
'\t');
431 if (value ==
'\n' || value ==
';')
440 for (; value !=
'\n' && !feof(file); value = fgetc(file))
446 else if (value ==
'[')
449 for (; value !=
']' && !feof(file); value = fgetc(file));
450 for (; value !=
'\n' && !feof(file); value = fgetc(file));
455 for (; value !=
'=' && !feof(file); )
461 }
while (value ==
' ' || value ==
'\t');
463 std::string name = buffer;
466 bool shouldBreak =
false;
471 }
while (value ==
' ' || value ==
'\t');
475 for (value = fgetc(file); value !=
'"' && !feof(file); value = fgetc(file))
479 while (fgetc(file) !=
'\n' && !feof(file));
483 for (; value !=
'\n' && !feof(file);)
489 }
while (value ==
' ' || value ==
'\t');
495 std::string value = buffer;
497 if (!name.empty() && !value.empty())
499 m_keys.push_back(name);
500 m_values.insert(std::pair<std::string, std::string>(name, value));
503 if (!comment.empty())
505 m_comments.insert(std::pair<std::string, std::string>(name, comment));
517 wpi_setWPIErrorWithContext(NoAvailableResources,
"Failed to open preferences file.");
523 if (!comment.empty())
524 m_endComment = comment;
534 void Preferences::WriteTaskRun()
537 semGive(m_fileOpStarted);
540 Priv_SetWriteFileAllowed(1);
541 file = fopen(kFileName,
"w");
543 fputs(
"[Preferences]\n", file);
544 std::vector<std::string>::iterator it = m_keys.begin();
545 for (; it != m_keys.end(); it++)
547 std::string key = *it;
548 std::string value = m_values[key];
549 std::string comment = m_comments[key];
551 if (!comment.empty())
552 fputs(comment.c_str(), file);
554 fputs(key.c_str(), file);
555 fputs(kValuePrefix, file);
556 fputs(value.c_str(), file);
557 fputs(kValueSuffix, file);
560 if (!m_endComment.empty())
561 fputs(m_endComment.c_str(), file);
569 static bool isKeyAcceptable(
const std::string& value) {
570 for (
unsigned int i = 0; i < value.length(); i++) {
571 char letter = value.at(i);
594 if (!isKeyAcceptable(key) || table->
GetString(key,
"").find(
'"')!=std::string::npos)
596 if(m_values.find(key) != m_values.end()){
598 std::vector<std::string>::iterator it = m_keys.begin();
599 for (; it != m_keys.end(); it++)
612 std::pair<StringMap::iterator, bool> ret =
613 m_values.insert(StringMap::value_type(key, table->
GetString(key,
"")));
615 m_keys.push_back(key);
617 ret.first->second = table->
GetString(key,
"");
bool Start(uint32_t arg0=0, uint32_t arg1=0, uint32_t arg2=0, uint32_t arg3=0, uint32_t arg4=0, uint32_t arg5=0, uint32_t arg6=0, uint32_t arg7=0, uint32_t arg8=0, uint32_t arg9=0)
std::vector< std::string > GetKeys()
std::string GetString(const char *key, const char *defaultValue="")
static NetworkTable * GetTable(std::string key)
void ValueChanged(ITable *source, const std::string &key, EntryValue value, bool isNew)
bool GetBoolean(const char *key, bool defaultValue=false)
void PutBoolean(std::string key, bool value)
void PutDouble(const char *key, double value)
void PutBoolean(const char *key, bool value)
void PutFloat(const char *key, float value)
void Remove(const char *key)
void PutString(const char *key, const char *value)
int GetInt(const char *key, int defaultValue=0)
void PutInt(const char *key, int value)
double GetDouble(const char *key, double defaultValue=0.0)
void PutLong(const char *key, INT64 value)
INT64 GetLong(const char *key, INT64 defaultValue=0)
virtual std::string GetString(std::string key)=0
void AddTableListener(ITableListener *listener)
void PutString(std::string key, std::string value)
bool ContainsKey(const char *key)
virtual bool GetBoolean(std::string key)=0
float GetFloat(const char *key, float defaultValue=0.0)
virtual void PutString(std::string key, std::string value)=0
static Preferences * GetInstance()