Now you can download a copy of these docs so you can use them offline! Download now
Preferences.cpp
00001 /*----------------------------------------------------------------------------*/ 00002 /* Copyright (c) FIRST 2011. All Rights Reserved. */ 00003 /* Open Source Software - may be modified and shared by FRC teams. The code */ 00004 /* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */ 00005 /*----------------------------------------------------------------------------*/ 00006 00007 #include "Preferences.h" 00008 00009 #include "NetworkTables/NetworkTable.h" 00010 #include "Synchronized.h" 00011 #include "WPIErrors.h" 00012 00013 #include <stdio.h> 00014 00016 extern "C" int Priv_SetWriteFileAllowed(UINT32 enable); 00017 00019 static const char *kTableName = "Preferences"; 00021 static const char *kSaveField = "~S A V E~"; 00023 static const char *kFileName = "/c/wpilib-preferences.ini"; 00025 static const char *kValuePrefix = "=\""; 00027 static const char *kValueSuffix = "\"\n"; 00029 Preferences *Preferences::_instance = NULL; 00030 00031 Preferences::Preferences() : 00032 m_fileLock(NULL), 00033 m_fileOpStarted(NULL), 00034 m_tableLock(NULL), 00035 m_readTask("PreferencesReadTask", (FUNCPTR)Preferences::InitReadTask), 00036 m_writeTask("PreferencesWriteTask", (FUNCPTR)Preferences::InitWriteTask) 00037 { 00038 m_fileLock = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE | SEM_DELETE_SAFE); 00039 m_fileOpStarted = semBCreate (SEM_Q_PRIORITY, SEM_EMPTY); 00040 m_tableLock = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE | SEM_DELETE_SAFE); 00041 00042 Synchronized sync(m_fileLock); 00043 m_readTask.Start((UINT32)this); 00044 semTake(m_fileOpStarted, WAIT_FOREVER); 00045 00046 NetworkTable::GetTable(kTableName)->PutBoolean(kSaveField, false); 00047 NetworkTable::GetTable(kTableName)->AddChangeListenerAny(this); 00048 } 00049 00050 Preferences::~Preferences() 00051 { 00052 semTake(m_tableLock, WAIT_FOREVER); 00053 semDelete(m_tableLock); 00054 semTake(m_fileLock, WAIT_FOREVER); 00055 semDelete(m_fileOpStarted); 00056 semDelete(m_fileLock); 00057 } 00058 00063 Preferences *Preferences::GetInstance() 00064 { 00065 if (_instance == NULL) 00066 _instance = new Preferences; 00067 return _instance; 00068 } 00069 00074 std::vector<std::string> Preferences::GetKeys() 00075 { 00076 return m_keys; 00077 } 00078 00086 std::string Preferences::GetString(const char *key, const char *defaultValue) 00087 { 00088 std::string value = Get(key); 00089 return value.empty() ? defaultValue : value; 00090 } 00091 00101 int Preferences::GetString(const char *key, char *value, int valueSize, const char *defaultValue) 00102 { 00103 std::string stringValue = GetString(key, defaultValue); 00104 stringValue.copy(value, valueSize); 00105 return stringValue.size(); 00106 } 00107 00115 int Preferences::GetInt(const char *key, int defaultValue) 00116 { 00117 std::string value = Get(key); 00118 if (value.empty()) 00119 return defaultValue; 00120 00121 return strtol(value.c_str(), NULL, 0); 00122 } 00123 00131 double Preferences::GetDouble(const char *key, double defaultValue) 00132 { 00133 std::string value = Get(key); 00134 if (value.empty()) 00135 return defaultValue; 00136 00137 return strtod(value.c_str(), NULL); 00138 } 00139 00147 float Preferences::GetFloat(const char *key, float defaultValue) 00148 { 00149 std::string value = Get(key); 00150 if (value.empty()) 00151 return defaultValue; 00152 00153 return strtod(value.c_str(), NULL); 00154 } 00155 00163 bool Preferences::GetBoolean(const char *key, bool defaultValue) 00164 { 00165 std::string value = Get(key); 00166 if (value.empty()) 00167 return defaultValue; 00168 00169 if (value.compare("true") == 0) 00170 return true; 00171 else if (value.compare("false") == 0) 00172 return false; 00173 00174 wpi_setWPIErrorWithContext(ParameterOutOfRange, "Boolean value does not contain \"true\" or \"false\""); 00175 return false; 00176 } 00177 00185 INT64 Preferences::GetLong(const char *key, INT64 defaultValue) 00186 { 00187 std::string value = Get(key); 00188 if (value.empty()) 00189 return defaultValue; 00190 00191 // Ummm... not available in our VxWorks... 00192 //return strtoll(value.c_str(), NULL, 0); 00193 INT64 intVal; 00194 sscanf(value.c_str(), "%lld", &intVal); 00195 return intVal; 00196 } 00197 00210 void Preferences::PutString(const char *key, const char *value) 00211 { 00212 if (value == NULL) 00213 { 00214 wpi_setWPIErrorWithContext(NullParameter, "value"); 00215 return; 00216 } 00217 if (std::string(value).find_first_of("\"") != std::string::npos) 00218 { 00219 wpi_setWPIErrorWithContext(ParameterOutOfRange, "value contains illegal characters"); 00220 return; 00221 } 00222 Put(key, value); 00223 } 00224 00236 void Preferences::PutInt(const char *key, int value) 00237 { 00238 char buf[32]; 00239 snprintf(buf, 32, "%d", value); 00240 Put(key, buf); 00241 } 00242 00254 void Preferences::PutDouble(const char *key, double value) 00255 { 00256 char buf[32]; 00257 snprintf(buf, 32, "%f", value); 00258 Put(key, buf); 00259 } 00260 00272 void Preferences::PutFloat(const char *key, float value) 00273 { 00274 char buf[32]; 00275 snprintf(buf, 32, "%f", value); 00276 Put(key, buf); 00277 } 00278 00290 void Preferences::PutBoolean(const char *key, bool value) 00291 { 00292 Put(key, value ? "true" : "false"); 00293 } 00294 00306 void Preferences::PutLong(const char *key, INT64 value) 00307 { 00308 char buf[32]; 00309 snprintf(buf, 32, "%lld", value); 00310 Put(key, buf); 00311 } 00312 00324 void Preferences::Save() 00325 { 00326 Synchronized sync(m_fileLock); 00327 m_writeTask.Start((UINT32)this); 00328 semTake(m_fileOpStarted, WAIT_FOREVER); 00329 } 00330 00336 bool Preferences::ContainsKey(const char *key) 00337 { 00338 return !Get(key).empty(); 00339 } 00340 00345 void Preferences::Remove(const char *key) 00346 { 00347 m_values.erase(std::string(key)); 00348 std::vector<std::string>::iterator it = m_keys.begin(); 00349 for (; it != m_keys.end(); it++) 00350 { 00351 if (it->compare(key) == 0) 00352 { 00353 m_keys.erase(it); 00354 break; 00355 } 00356 } 00357 } 00358 00364 std::string Preferences::Get(const char *key) 00365 { 00366 Synchronized sync(m_tableLock); 00367 if (key == NULL) 00368 { 00369 wpi_setWPIErrorWithContext(NullParameter, "key"); 00370 return std::string(""); 00371 } 00372 return m_values[std::string(key)]; 00373 } 00374 00380 void Preferences::Put(const char *key, std::string value) 00381 { 00382 Synchronized sync(m_tableLock); 00383 if (key == NULL) 00384 { 00385 wpi_setWPIErrorWithContext(NullParameter, "key"); 00386 return; 00387 } 00388 00389 if (std::string(key).find_first_of("=\n\r \t\"") != std::string::npos) 00390 { 00391 wpi_setWPIErrorWithContext(ParameterOutOfRange, "key contains illegal characters"); 00392 return; 00393 } 00394 00395 std::pair<StringMap::iterator, bool> ret = 00396 m_values.insert(StringMap::value_type(key, value)); 00397 if (ret.second) 00398 m_keys.push_back(key); 00399 else 00400 ret.first->second = value; 00401 00402 NetworkTable::GetTable(kTableName)->PutString(key, value); 00403 } 00404 00410 void Preferences::ReadTaskRun() 00411 { 00412 Synchronized sync(m_tableLock); 00413 semGive(m_fileOpStarted); 00414 00415 std::string comment; 00416 00417 FILE *file = NULL; 00418 file = fopen(kFileName, "r"); 00419 00420 if (file != NULL) 00421 { 00422 std::string buffer; 00423 while (true) 00424 { 00425 char value; 00426 do 00427 { 00428 value = fgetc(file); 00429 } while (value == ' ' || value == '\t'); 00430 00431 if (value == '\n' || value == ';') 00432 { 00433 if (value == '\n') 00434 { 00435 comment += "\n"; 00436 } 00437 else 00438 { 00439 buffer.clear(); 00440 for (; value != '\n' && !feof(file); value = fgetc(file)) 00441 buffer += value; 00442 buffer += '\n'; 00443 comment += buffer; 00444 } 00445 } 00446 else if (value == '[') 00447 { 00448 // Find the end of the section and the new line after it and throw it away 00449 for (; value != ']' && !feof(file); value = fgetc(file)); 00450 for (; value != '\n' && !feof(file); value = fgetc(file)); 00451 } 00452 else 00453 { 00454 buffer.clear(); 00455 for (; value != '=' && !feof(file); ) 00456 { 00457 buffer += value; 00458 do 00459 { 00460 value = fgetc(file); 00461 } while (value == ' ' || value == '\t'); 00462 } 00463 std::string name = buffer; 00464 buffer.clear(); 00465 00466 bool shouldBreak = false; 00467 00468 do 00469 { 00470 value = fgetc(file); 00471 } while (value == ' ' || value == '\t'); 00472 00473 if (value == '"') 00474 { 00475 for (value = fgetc(file); value != '"' && !feof(file); value = fgetc(file)) 00476 buffer += value; 00477 00478 // Clear the line 00479 while (fgetc(file) != '\n' && !feof(file)); 00480 } 00481 else 00482 { 00483 for (; value != '\n' && !feof(file);) 00484 { 00485 buffer += value; 00486 do 00487 { 00488 value = fgetc(file); 00489 } while (value == ' ' || value == '\t'); 00490 } 00491 if (feof(file)) 00492 shouldBreak = true; 00493 } 00494 00495 std::string value = buffer; 00496 00497 if (!name.empty() && !value.empty()) 00498 { 00499 m_keys.push_back(name); 00500 m_values.insert(std::pair<std::string, std::string>(name, value)); 00501 NetworkTable::GetTable(kTableName)->PutString(name, value); 00502 00503 if (!comment.empty()) 00504 { 00505 m_comments.insert(std::pair<std::string, std::string>(name, comment)); 00506 comment.clear(); 00507 } 00508 } 00509 00510 if (shouldBreak) 00511 break; 00512 } 00513 } 00514 } 00515 else 00516 { 00517 wpi_setWPIErrorWithContext(NoAvailableResources, "Failed to open preferences file."); 00518 } 00519 00520 if (file != NULL) 00521 fclose(file); 00522 00523 if (!comment.empty()) 00524 m_endComment = comment; 00525 } 00526 00531 void Preferences::WriteTaskRun() 00532 { 00533 Synchronized sync(m_tableLock); 00534 semGive(m_fileOpStarted); 00535 00536 FILE *file = NULL; 00537 Priv_SetWriteFileAllowed(1); 00538 file = fopen(kFileName, "w"); 00539 00540 fputs("[Preferences]\n", file); 00541 std::vector<std::string>::iterator it = m_keys.begin(); 00542 for (; it != m_keys.end(); it++) 00543 { 00544 std::string key = *it; 00545 std::string value = m_values[key]; 00546 std::string comment = m_comments[key]; 00547 00548 if (!comment.empty()) 00549 fputs(comment.c_str(), file); 00550 00551 fputs(key.c_str(), file); 00552 fputs(kValuePrefix, file); 00553 fputs(value.c_str(), file); 00554 fputs(kValueSuffix, file); 00555 } 00556 00557 if (!m_endComment.empty()) 00558 fputs(m_endComment.c_str(), file); 00559 00560 if (file != NULL) 00561 fclose(file); 00562 00563 NetworkTable::GetTable(kTableName)->PutBoolean(kSaveField, false); 00564 } 00565 00566 void Preferences::ValueChanged(NetworkTable *table, const char *name, NetworkTables_Types type) 00567 { 00568 if (strcmp(name, kSaveField) == 0) 00569 { 00570 if (table->GetBoolean(kSaveField)) 00571 Save(); 00572 } 00573 else 00574 { 00575 Synchronized sync(m_tableLock); 00576 00577 std::string key = name; 00578 if (key.find_first_of("=\n\r \t") != std::string::npos) 00579 { 00580 // The key is bogus... ignore it 00581 } 00582 else if (table->GetString(key).find_first_of("\"") != std::string::npos) 00583 { 00584 table->PutString(key, "\""); 00585 m_values.erase(key); 00586 std::vector<std::string>::iterator it = m_keys.begin(); 00587 for (; it != m_keys.end(); it++) 00588 { 00589 if (it->compare(name) == 0) 00590 { 00591 m_keys.erase(it); 00592 break; 00593 } 00594 } 00595 } 00596 else 00597 { 00598 std::pair<StringMap::iterator, bool> ret = 00599 m_values.insert(StringMap::value_type(key, table->GetString(key))); 00600 if (ret.second) 00601 m_keys.push_back(key); 00602 else 00603 ret.first->second = table->GetString(key); 00604 } 00605 } 00606 } 00607 00608 void Preferences::ValueConfirmed(NetworkTable *table, const char *name, NetworkTables_Types type) 00609 { 00610 }
Generated on Thu Jan 12 2012 22:35:23 for WPILibC++ by
1.7.1