|
Isis 3.0 Object Programmers' Reference |
Home |
00001 00023 #include "IException.h" 00024 #include "IString.h" 00025 #include "Message.h" 00026 #include "FileName.h" 00027 #include "PvlKeyword.h" 00028 #include "TextFile.h" 00029 #include "Pvl.h" 00030 #include "PvlFormat.h" 00031 00032 using namespace std; 00033 00034 namespace Isis { 00035 00036 /* 00037 * Constructs an empty PvlFormat 00038 */ 00039 PvlFormat::PvlFormat() { 00040 Init(); 00041 } 00042 00043 00044 /* 00045 * Constructs a PvlFormat using the file name to ingest as the keyword to type 00046 * mapping. This is provided as a convience for child objects. The map is not 00047 * used for output of PvlKeywords in Normal Isis format. 00048 * 00049 * @param file A file name with keyword=type. Where KEYWORD is the name of a 00050 * keyword in this PvlKeyword and TYPE is one of [QString | integer | float ] 00051 */ 00052 PvlFormat::PvlFormat(const QString &file) { 00053 Init(); 00054 Add(file); 00055 } 00056 00057 00058 /* 00059 * Constructs a PvlFormat using the specified pre populated Pvl map of keyword 00060 * name (QString) vs keyword type (KeywordType). 00061 * 00062 * @param keywordType A Pvl with keyword=type. Where keyword is the name of a 00063 * keyword in a PvlKeyword and type is one of [QString | integer | float ] 00064 */ 00065 PvlFormat::PvlFormat(Pvl &keywordType) { 00066 Init(); 00067 Add(keywordType); 00068 } 00069 00070 00072 void PvlFormat::Init() { 00073 p_keywordMap.Clear(); 00074 p_keywordMapFile.clear(); 00075 p_charLimit = 80; 00076 } 00077 00078 00079 /* 00080 * Add the contents of a file to the keyword type mapping. The file should 00081 * contain KEYWORD=TYPE (one per line), where TYPE is one of the QStrings 00082 * KeywordType can convert. 00083 */ 00084 void PvlFormat::Add(const QString &file) { 00085 p_keywordMapFile = file; 00086 00087 // Open the file and internalize it into the Pvl map 00088 try { 00089 Pvl pvl(file); 00090 Add(pvl); 00091 } 00092 catch(IException &e) { 00093 QString msg; 00094 msg += "Unable to open or read keyword to type mapping file ["; 00095 msg += file + "]"; 00096 throw IException(e, IException::Programmer, msg, _FILEINFO_); 00097 } 00098 } 00099 00100 00101 /* 00102 * Add the contents of a Pvl to the keyword type mapping. The pvl should 00103 * contain KEYWORD=TYPE, where TYPE is one of the QStrings KeywordType can 00104 * convert. 00105 */ 00106 void PvlFormat::Add(Pvl &pvl) { 00107 for(int i = 0; i < pvl.Keywords(); ++i) { 00108 PvlKeyword &key = pvl[i]; 00109 QString name = key.Name().toUpper(); 00110 QString type = key[0].toUpper(); 00111 PvlKeyword newKey(name, type); 00112 for(int j = 1; j < key.Size(); ++j) newKey.AddValue(key[j]); 00113 // Make sure we don't duplicate Keys 00114 if (p_keywordMap.HasKeyword(name)) { 00115 p_keywordMap.DeleteKeyword(name); 00116 } 00117 p_keywordMap.AddKeyword(newKey); 00118 } 00119 } 00120 00121 00122 /* 00123 * Returns the type of the keyword from the supplied map if any 00124 * 00125 * @param keyword The PvlKeyword to have its type returned 00126 */ 00127 KeywordType PvlFormat::Type(const PvlKeyword &keyword) { 00128 QString name = keyword.Name().toUpper(); 00129 if(p_keywordMap.HasKeyword(name)) { 00130 PvlKeyword &key = p_keywordMap.FindKeyword(name); 00131 return ToKeywordType(key[0]); 00132 } 00133 return NoTypeKeyword; 00134 } 00135 00136 00137 /* 00138 * Returns the number of digits of accuracy (right of decimal place) this 00139 * keyword should be output with 00140 * 00141 * @param keyword The PvlKeyword the accuracy is need for 00142 * @return The number of decimal places to be output. If this number is not 00143 * available in keyword map return -1. 00144 */ 00145 int PvlFormat::Accuracy(const PvlKeyword &keyword) { 00146 QString name = keyword.Name().toUpper(); 00147 if(p_keywordMap.HasKeyword(name)) { 00148 PvlKeyword &key = p_keywordMap.FindKeyword(name); 00149 if(key.Size() > 1) { 00150 return toInt(key[1]); 00151 } 00152 } 00153 return -1; 00154 } 00155 00156 00157 /* 00158 * Returns the keyword name and value(s) formatted in "Normal" Isis format 00159 * 00160 * @param keyword The PvlKeyword to be formatted 00161 * @param num Use the ith value of the keyword 00162 */ 00163 QString PvlFormat::FormatValue(const PvlKeyword &keyword, int num) { 00164 00165 QString val; 00166 val.clear(); 00167 00168 // Find out if the units are the same for all values 00169 bool singleUnit = IsSingleUnit(keyword); 00170 00171 // Create a Null value if the value index is greater than the number of values 00172 if(num >= keyword.Size()) { 00173 return "Null"; 00174 } 00175 00176 // Create a Null value if the requested index is an empty QString 00177 if(keyword[num].size() == 0) { 00178 val += "Null"; 00179 } 00180 else { 00181 val += keyword[num]; 00182 } 00183 00184 val = AddQuotes(val); 00185 00186 // If it is an array start it off with a paren 00187 if((keyword.Size() > 1) && (num == 0)) { 00188 val = "(" + val; 00189 } 00190 00191 // Add the units to this value 00192 if((!singleUnit) && (keyword.Unit(num).size() > 0)) { 00193 val += " <" + keyword.Unit(num) + ">"; 00194 } 00195 00196 // Add a comma for arrays 00197 if(num != keyword.Size() - 1) { 00198 val += ", "; 00199 } 00200 // If it is an array close it off 00201 else if(keyword.Size() > 1) { 00202 val += ")"; 00203 } 00204 00205 // Add the units to the end if all values have the same units 00206 if((singleUnit) && (num == keyword.Size() - 1) && 00207 (keyword.Unit(num).size() > 0)) { 00208 val += " <" + keyword.Unit(num) + ">"; 00209 } 00210 00211 return val; 00212 } 00213 00214 00215 /* 00216 * Format the name of the container 00217 * 00218 * @param keyword The PvlContainer being closed. 00219 */ 00220 QString PvlFormat::FormatName(const PvlKeyword &keyword) { 00221 return keyword.Name(); 00222 } 00223 00224 00225 /* 00226 * Format the end of a container 00227 * 00228 * @param name The text used to signify the end of a container 00229 * @param keyword The PvlContainer being closed. 00230 */ 00231 QString PvlFormat::FormatEnd(const QString name, 00232 const PvlKeyword &keyword) { 00233 return "End_" + FormatName(keyword); 00234 }; 00235 00236 00237 /* 00238 * Add single or double quotes around a value if necessary. The Isis definition 00239 * of when quotes are necessary is used. 00240 * 00241 * @param value The PvlKeyword value to be quoted if necessary. 00242 */ 00243 QString PvlFormat::AddQuotes(const QString value) { 00244 QString val = value; 00245 00246 bool needQuotes = false; 00247 00248 // find out if we need quotes and what kind of quotes might already exist 00249 char existingQuoteType = '\0'; 00250 for(int pos = 0; !needQuotes && pos < val.size(); pos++) { 00251 // check for values indicating we need quotes, if we have a sequence 00252 // it should already be properly quoted... 00253 if(pos == 0) { 00254 if(val[pos] == '(' && val[val.size() - 1] == ')') break; 00255 if(val[pos] == '{' && val[val.size() - 1] == '}') break; 00256 } 00257 00258 if(val[pos] == ' ' || val[pos] == '(' || 00259 val[pos] == '(' || val[pos] == ')' || 00260 val[pos] == '{' || val[pos] == '}' || 00261 val[pos] == ',') { 00262 needQuotes = true; 00263 } 00264 00265 if(pos == val.size() - 1 && val[pos] == '-') 00266 needQuotes = true; 00267 00268 // remember if we are a quote, what quote type we are 00269 if(existingQuoteType == '\0') { 00270 if(val[pos] == '"') { 00271 existingQuoteType = '"'; 00272 } 00273 else if(val[pos] == '\'') { 00274 existingQuoteType = '\''; 00275 } 00276 } 00277 else { 00278 // make sure we dont have mixing of our outside quote type 00279 if(val[pos] == '"' || val[pos] == '\'') { 00280 val[pos] = existingQuoteType; 00281 } 00282 } 00283 } 00284 00285 // figure out what kind of quotes we want to add 00286 char quoteValue = '"'; 00287 00288 if(existingQuoteType == '"') { 00289 quoteValue = '\''; 00290 } 00291 00292 if(needQuotes) { 00293 val = quoteValue + val + quoteValue; 00294 } 00295 00296 return val; 00297 } 00298 00299 00306 bool PvlFormat::IsSingleUnit(const PvlKeyword &keyword) { 00307 00308 // See if the units are all the same 00309 bool singleUnit = true; 00310 for(int i = 0; i < keyword.Size(); i ++) { 00311 if(!keyword.StringEqual(keyword.Unit(i), keyword.Unit(0))) { 00312 singleUnit = false; 00313 } 00314 } 00315 00316 return singleUnit; 00317 } 00318 } 00319