// Copyright 2003 Regents of the University of California // SETI_BOINC is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2, or (at your option) any later // version. // SETI_BOINC is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for // more details. // You should have received a copy of the GNU General Public License along // with SETI_BOINC; see the file COPYING. If not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "sah_config.h" #include #include #include #include #include #include "sqlrow.h" const SQL_ROW empty_row; const std::string empty_string(""); #define found(x) ((x != std::string::npos)) std::string *SQL_ROW::string_delimited(std::string &s, char c_start, char c_end) { // return the substring of a string delimited by c_start and c_end. // c_start and c_end. The substring returned will include everything from // c_start and before the comma or end or string following c_end. std::string::size_type open,cls,strt,comma; std::string::size_type q(s.find(c_start)); // find the opening delimiter. if (found(q)) { strt=q; int nopen=1; // since any of the items inside this type could be sql defined // types themselves, we need to find the matching close delimiter do { open=s.find(c_start,q+1); cls=s.find(c_end,q+1); if (found(cls) && (cls SQL_ROW::parse_delimited(std::string &s,char c_start,char c_end) { // parse a section of a comma separated string delimited by the characters // c_start and c_end. The substring parsed will include everything after // c_start and before the comma or end of string following c_end. This allows // sql types of the format "ROW(a,b,c)::type_name" to be properly parsed // to return a,b and c. std::string *sub(string_delimited(s,c_start,c_end)); // Get delimited string std::string tmp(*sub,1,sub->size()-1); // Remove opening delimiter std::vector rv(parse_row(tmp)); delete sub; #ifdef DEBUG_ALLOCATIONS fprintf(stderr,"std::string deleted at 0x%p\n",sub); fflush(stderr); #endif return rv; } std::vector SQL_ROW::parse_type(std::string &s) { // Parses informix defined types of the format "ROW(a,b,c)::typename" return parse_delimited(s,'(',')'); } std::vector SQL_ROW::parse_list(std::string &s) { // Parses informix lists of the format "LIST{a,b,c}" return parse_delimited(s,'{','}'); } std::string *SQL_ROW::parse_blob(std::string &s) { // Parsed binary objects of the format "fasd874235vxzfdgas" // or binary objects consisting of the entire string. std::string *rv; std::string::size_type etag=s.find('>'); ssize_t length; if (found(etag)) { std::string::size_type p(s.find('=')); if (p SQL_ROW::parse_row(std::string &s) { // parses a SQL row of the format "value,value,value,value", // where value can be of the form: // number (i.e. 10) // "string" // 'string' // LIST{value,value,value} // ROW(value,value,value)::typename // the passed string is consumed by this routine. // WARNING: NOT THREAD SAFE std::string::size_type comma,dquote,quote,p; std::string::size_type s_end=s.size(); std::vector::iterator i; std::vector rv; static bool outer=true; while (s.size()) { // While there's still bits of string left to process // get rid of leading spaces and commas while (isspace(s[0]) && s.size()) s.erase(0,1); while (s[0]==',') s.erase(0,1); // Handle the special cases first... if (s.find("LIST")==0) { // only parse a LIST if the entire string passed to parse_row was a list if (outer) { outer=false; std::vector tmprow(parse_list(s)); for (i=tmprow.begin();i tmprow(parse_type(s)); for (i=tmprow.begin();i("SQL_ROW") { if (s) { std::string tmp(s); pval=parse_row(tmp); } else { pval.clear(); for (size_t i=0;i("SQL_ROW") { ssize_t i; std::string *p; if (end_col<(ssize_t)start_col) end_col=(ssize_t)s.argc()-1; for (i=start_col;i<(end_col+1);i++) { if (s.exists(i)) { p=new std::string(*(s[i])); #ifdef DEBUG_ALLOCATIONS fprintf(stderr,"std::string allocated at 0x%p\n",p); fflush(stderr); #endif } else { p=0; } pval.push_back(p); } } SQL_ROW &SQL_ROW::operator =(const SQL_ROW &s) { if (this != &s) { size_t i; std::string *p; for (i=0;i