TLELib  0.1.0
tlefunc.cpp
Go to the documentation of this file.
00001 /*-----------------------------------------------------------------------------+
00002  | TLELib                                                                      |
00003  | Copyright 2011 Sergei V. Fundaev                                            |
00004  +-----------------------------------------------------------------------------+
00005  | This file is part of TLELib.                                                |
00006  |                                                                             |
00007  | TLELib is free software: you can redistribute it and/or modify              |
00008  | it under the terms of the GNU Lesser General Public License as published by |
00009  | the Free Software Foundation, either version 3 of the License, or           |
00010  | (at your option) any later version.                                         |
00011  |                                                                             |
00012  | TLELib is distributed in the hope that it will be useful,                   |
00013  | but WITHOUT ANY WARRANTY; without even the implied warranty of              |
00014  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |
00015  | GNU Lesser General Public License for more details.                         |
00016  |                                                                             |
00017  | You should have received a copy of the GNU Lesser General Public License    |
00018  | along with TLELib. If not, see <http://www.gnu.org/licenses/>.              |
00019  +----------------------------------------------------------------------------*/
00026 #define UNIX_FIRST_YEAR 1970
00027 
00028 #include <cmath>
00029 #include <cstdio>
00030 #include <cstdlib>
00031 #include <iostream>
00032 
00033 #include <tlelib/tlefunc.h>
00034 #include <tlelib/tleexception.h>
00035 
00036 namespace tlelib
00037 {
00038 
00039 std::string int2string(const int val, const std::size_t fieldLength, const bool leftAlign)
00040 {
00041     char *str = new char(6);
00042     sprintf(str, "%d", val);
00043     std::string res(str);
00044     delete str;
00045 
00046     return string2string(trim(res), fieldLength, leftAlign, false);
00047 }
00048 //------------------------------------------------------------------------------
00049 
00050 std::string double2string(const double val, const std::size_t fieldLength, const std::size_t precission, const bool scientific, const bool decimalPointAssumed, const bool leftAlign)
00051 {
00052     char str[fieldLength]; 
00053     double val1 = val;
00054     if (decimalPointAssumed)
00055     {
00056         double val3;
00057         val1 = modf(val, &val3);
00058     }
00059     sprintf(str, ("%" + int2string(fieldLength) + "." + int2string(precission+(scientific ? 1 : 0)) + (scientific ? "e" : "f")).c_str(), val1);
00060     std::string res(str);
00061 
00062     // Remove decimal point
00063     std::size_t pos = res.find(".");
00064     bool replaced = false;
00065     int n = 0;
00066     if (decimalPointAssumed && pos != std::string::npos && scientific)
00067     {
00068         n = -pos;
00069         res.replace(pos, 1, "");
00070         replaced = true;
00071     }
00072     else
00073         if (decimalPointAssumed && !scientific)
00074         {
00075             pos = res.find("0.");
00076             if (pos != std::string::npos)
00077                 res.replace(pos, 2, "");
00078         }
00079 
00080     // Remove point from scientific format
00081     if (scientific)
00082     {
00083         std::size_t e_pos = res.find("e");
00084         std::string base = res.substr(0, e_pos);
00085         std::string a = res.substr(e_pos + 1, res.length() - e_pos - 1);
00086         std::size_t pos1 = base.find(".");
00087         if (pos1 != std::string::npos)
00088         {
00089             n = base.length() - pos1 - 1;
00090             base.replace(pos1, 1, "");
00091         } 
00092         int new_a = string2int(a) - n;
00093         if (string2double(base) == 0) new_a = 0;
00094         res = base + (new_a > 0 ? "+" : "-") + int2string(abs(new_a));
00095     }
00096     res = trim(res);
00097 
00098     // Correct "0." or "-0."
00099     if (res.substr(0, 2) == "0.")
00100         res = res.substr(1, res.length() - 1);
00101     else
00102         if (res.substr(0, 3) == "-0.")
00103             res = "-" + res.substr(2, res.length() - 2);
00104 
00105     return string2string(res, fieldLength, leftAlign, false);
00106 }
00107 //------------------------------------------------------------------------------
00108 
00109 std::string string2string(const std::string &str, const std::size_t fieldLength, const bool leftAlign, const bool allowCutOff)
00110 {
00111     std::string res(str);
00112     if (res.length() > fieldLength && allowCutOff)
00113     {
00114         res = res.substr(0, fieldLength);
00115     }
00116     else
00117         if (res.length() <= fieldLength)
00118         {
00119             while (res.length() < fieldLength)
00120             {
00121                 if (leftAlign)
00122                     res += " ";
00123                 else
00124                     res = " " + res;
00125             }
00126         }
00127     return res;
00128 }
00129 //------------------------------------------------------------------------------
00130 
00131 std::string date2string(const double date, const std::size_t fieldLength, const bool leftAlign)
00132 {
00133     double dt = date;
00134     std::size_t year = UNIX_FIRST_YEAR;
00135     while (true)
00136     {
00137         bool leap = !(year % 4) && ( (year % 100) || !(year % 400)); 
00138         std::time_t l = (leap ? 366 : 365) * 86400;
00139         if (dt < l) break;
00140         dt -= l;
00141         year++;
00142     }
00143     year -= year>2000 ? 2000 : 1900;
00144     double res = year * 1000 + dt / 86400.0;
00145 
00146     std::string pref = year < 10 ? "0" : "";
00147     std::size_t length = year < 10 ? fieldLength - 1 : fieldLength; 
00148     return pref + double2string(res, length, fieldLength - 6, false, false, leftAlign);
00149 }
00150 //------------------------------------------------------------------------------
00151 
00152 int string2int(const std::string &str)
00153 {
00154     std::string val = trim(str);
00155     // Validate string
00156     for (std::size_t i=0; i<val.length(); i++)
00157         if (!isdigit(val[i]) && !( i == 0 && (val[i] == '-' || val[i] == '+') ))
00158             throw tle_invalid_format(str);
00159 
00160     return atoi(val.c_str());
00161 }
00162 //------------------------------------------------------------------------------
00163 
00164 double string2double(const std::string &str)
00165 {
00166     std::string val = trim(str);
00167     // Validate string
00168     for (std::size_t i=0; i<val.length(); i++)
00169     {
00170         bool valid = isdigit(val[i]); // it is a digit
00171         valid = valid || (i == 0 && (val[i] == '-' || val[i] == '+')); // it is not a digit, but it is a sign at the start
00172         // it is not a gigit and not a sign at the start, but it is 'e' or 'E'
00173         valid = valid || (i>0 && (val[i] == 'e' || val[i] == 'E') && (isdigit(val[i-1]) || val[i-1] == '.') && i < val.length()-1);
00174         // it is not a gigit and not a sign at the start and not 'e' or 'E', but it is a sign after 'e' or 'E'
00175         valid = valid || (i>0 && (val[i] == '-' || val[i] == '+') && (val[i-1] == 'e' || val[i-1] == 'E') && i < val.length()-1);
00176         // may be it is a decimal point?..
00177         valid = valid || (val[i] == '.');
00178 
00179         if (!valid)
00180         {
00181             throw tle_invalid_format(str);
00182         }
00183     }
00184     return atof(val.c_str());
00185 }
00186 //------------------------------------------------------------------------------
00187 
00188 std::string trim(const std::string &str)
00189 {
00190     std::string res(str);
00191     while (res.length() && res[0] == ' ') res = res.substr(1, res.length() - 1);
00192     while (res.length() && res[res.length() - 1] == ' ') res = res.substr(0, res.length() - 1);
00193     return res;
00194 }
00195 //------------------------------------------------------------------------------
00196 
00197 char parseChar(const std::string *line, const std::size_t index)
00198 {
00199     char res = '\0';
00200     if (line)
00201     {
00202         if (line->length() - 1 < index)
00203             throw tle_too_short_string(*line);
00204         res = (*line)[index];
00205     }
00206 
00207     return res;
00208 }
00209 //------------------------------------------------------------------------------
00210 
00211 std::string parseString(const std::string *line, const std::size_t start, const std::size_t length)
00212 {
00213     std::string res = "";
00214     if (line)
00215     {
00216         if (line->length() < start + length)
00217             throw tle_too_short_string(*line);
00218 
00219         res = line->substr(start, length);
00220     }
00221 
00222     return res;
00223 }
00224 //------------------------------------------------------------------------------
00225 
00226 int parseInt(const std::string *line, const std::size_t start, const std::size_t length)
00227 {
00228     int res = 0;
00229     if (line)
00230     {
00231         if (line->length() < start + length)
00232             throw tle_too_short_string(*line);
00233 
00234         std::string val = trim(line->substr(start, length));
00235 
00236         // Parsing
00237         try{
00238             res = string2int(val.c_str());
00239         } catch(...) {
00240             throw tle_invalid_format(*line);
00241         }
00242     }
00243 
00244     return res;
00245 }
00246 //------------------------------------------------------------------------------
00247 
00248 double parseDouble(const std::string *line, const std::size_t start, const std::size_t length, const bool decimalPointAssumed)
00249 {
00250     double res = 0;
00251     if (line)
00252     {
00253         if (line->length() < start + length)
00254             throw tle_too_short_string(*line);
00255 
00256         std::string val = trim(line->substr(start, length));
00257 
00258         // Prepare string
00259         if (decimalPointAssumed) val = "0." + val;
00260         // -- 123-4 or 123+4 -> 123e-4 or 123e4 --
00261         std::size_t pos = val.rfind('-');
00262         if (pos != std::string::npos && pos && val[pos - 1] != 'e' && val[pos - 1] != 'E')
00263         {
00264             val.replace(pos, 1, "e-");
00265         }
00266         else
00267             {
00268                 std::size_t pos = val.rfind('+');
00269                 if (pos != std::string::npos)
00270                     val.replace(pos, 1, "e");
00271             }
00272 
00273         // Parsing
00274         try{
00275             res = string2double(val.c_str());
00276         } catch(...) {
00277             throw tle_invalid_format(*line);
00278         }
00279     }
00280 
00281     return res;
00282 }
00283 //------------------------------------------------------------------------------
00284 
00285 double string2date(const std::string &str)
00286 {
00287     std::string str1(trim(str));
00288     // Validate
00289     if (str1.find('-') != std::string::npos)
00290         throw tle_invalid_format(str);
00291 
00292     // Year
00293     int year = string2int(str1.substr(0, 2).c_str());
00294     year += year < (UNIX_FIRST_YEAR - (UNIX_FIRST_YEAR / 100) * 100) ? 2000 : 1900;
00295 
00296     double res = 0;
00297     for (int y = UNIX_FIRST_YEAR; y < year; y++)
00298     {
00299         // If current year is leap
00300         bool leap = !(y % 4) && ( (y % 100) || !(y % 400));
00301         res += leap ? 366 : 365;
00302     }
00303 
00304     // Years -> seconds
00305     res *= 86400;
00306 
00307     // Additional part
00308     res += string2double(str1.substr(2, str1.length() - 2)) * 86400;
00309     return res;
00310 }
00311 //------------------------------------------------------------------------------
00312 
00313 int checksum(const std::string &str)
00314 {
00315     int checksum = 0;
00316     for (std::size_t i=0; i<str.length(); i++)
00317         checksum += isdigit(str[i]) ? atoi(str.substr(i, 1).c_str()) : (str[i] == '-' ? 1 : 0);
00318     // Get the last digit
00319     checksum -= (checksum/10) * 10;
00320 
00321     return checksum;
00322 }
00323 //------------------------------------------------------------------------------
00324 
00325 } // namespace tlelib
 All Classes Namespaces Files Functions Variables Defines