From b9ce1555b2baf9be209775dbd4c8b217db5cd735 Mon Sep 17 00:00:00 2001 From: manuel Date: Fri, 1 May 2009 20:18:51 +0200 Subject: rewrote pixmap::read to do more sanity checks --- ue2/imgsynth2/cpixmap.cpp | 422 ++++++++++++++++++++++++++-------------------- 1 file changed, 243 insertions(+), 179 deletions(-) (limited to 'ue2/imgsynth2/cpixmap.cpp') diff --git a/ue2/imgsynth2/cpixmap.cpp b/ue2/imgsynth2/cpixmap.cpp index 6f8c8d6..d3e10d8 100644 --- a/ue2/imgsynth2/cpixmap.cpp +++ b/ue2/imgsynth2/cpixmap.cpp @@ -5,25 +5,23 @@ * @date 27.04.2009 */ +#include +#include +#include +#include +#include #include -#include - #ifdef DEBUG # include #endif -#include -#include -# include -# include - - - #include "cpixmap.h" #include "cpixelformat_indexed8.h" using namespace std; +using namespace boost; CPixmap::CPixmap() + : m_imagename("") { m_types.insert("XPM"); @@ -33,236 +31,302 @@ CPixmap::CPixmap() /*----------------------------------------------------------------------------*/ -void CPixmap::read(std::ifstream& in) +std::string CPixmap::getLine(std::ifstream& in, bool ignore_comments) { + string line(""); + while(!in.eof() && in.good()) + { + getline(in, line); + trim(line); + /* ignore simple ansi c comments. only one-liners */ + if (ignore_comments && line.find_first_of("/*") == 0) + continue; + if (!line.empty()) + break; + } + return line; +} - string str; - m_fileheader._XPMEXT = false; - m_fileheader._HOTSPOT = false; +/*----------------------------------------------------------------------------*/ - /* parse the values section */ - getline( in, str, '"'); - getline( in, str, '"'); - stringstream istr (str ); +std::string CPixmap::getArrayLine(std::ifstream& in, bool ignore_comments) +{ + string line = getLine(in, ignore_comments); + if (line.empty()) + return line; + + /* this stuff isn't correct too, but we are no c-parser anyway */ + if (line[0] != '"') + throw FileError("Pixmap array has invalid c-syntax."); + if (line[line.length() - 1] != ',' && line[line.length() - 1] != '}') + throw FileError("Pixmap array has invalid c-syntax."); + size_t end = line.find_last_of("\""); + if (end == string::npos) + throw FileError("Pixmap array has invalid c-syntax."); + + return line.substr(1, end - 1); +} - istr >> m_fileheader.xpmWidth ; - istr >> m_fileheader.xpmHeight ; - istr >> m_fileheader.nColor ; - istr >> m_fileheader.nChar ; +/*----------------------------------------------------------------------------*/ + +void CPixmap::read(std::ifstream& in) +{ + /* + * XPM + * static char * [] = { + * + * + * + * + * }; + */ + + string line, tmp; + stringstream istr; + std::vector list; + m_fileheader._XPMEXT = false; + m_fileheader._HOTSPOT = false; - /*optional values */ - if (istr.good()) + /* first line has to be PIXMAP_IDENTIFIER */ + line = getLine(in, false); + if (line != PIXMAP_IDENTIFIER) + throw FileError("Pixmap has no identifier."); + + /* second line is a c array. we don't do much syntax checking */ + line = getLine(in); + istr.str(line); + while(m_imagename.empty() && !istr.eof() && istr.good()) { - string tmp; + size_t end; istr >> tmp; - if(tmp.compare("XPMEXT") == 0) - m_fileheader._XPMEXT = true; - else + if ((end = tmp.find_first_of("[]")) != string::npos) { - m_fileheader._HOTSPOT = true; - m_fileheader.xHotspot = static_cast(strtoul(tmp.c_str(), NULL, 16)); - istr >> m_fileheader.yHotspot; + /* *[] */ + size_t start = tmp.find_first_of('*'); + start = (start == string::npos) ? 0 : start + 1; + m_imagename = tmp.substr(start, end - start); } - if (istr.good()) + } + if (m_imagename.empty()) + throw FileError("Pixmap has no imagename."); + + /* additional: check "{" exists */ + if (line[line.length() - 1] != '{') + throw FileError("Pixmap array has no opening bracket."); + + /* parse -section */ + line = getArrayLine(in); + if (line.empty()) + throw FileError("Pixmap has no Values-section."); + algorithm::split(list, line, is_any_of(" \t")); + if (list.size() < 4) + throw FileError("Pixmap has invalid Values-section."); + try + { + m_fileheader.width = lexical_cast(list[0]); + m_fileheader.height = lexical_cast(list[1]); + m_fileheader.nColor = lexical_cast(list[2]); + m_fileheader.nChar = lexical_cast(list[3]); + + if (list.size() > 4) { - istr >> tmp; - if (tmp.compare("XPMEXT") == 0) - m_fileheader._XPMEXT = true; + if (list.size() >= 6) + { + m_fileheader._HOTSPOT = true; + m_fileheader.xHotspot = lexical_cast(list[4]); + m_fileheader.yHotspot = lexical_cast(list[5]); + } + if (list.size() != 6) + { + if (list[list.size() - 1] != "XPMEXT") + throw FileError("Unknown parameter count in Values-Section."); + else + m_fileheader._XPMEXT = true; + } } } + catch(bad_lexical_cast& ex) + { + throw FileError("Value of Values-section is invalid: " + string(ex.what())); + } + /* parse -table */ + string character; + map colors; + for(uint32_t i = 0; i < m_fileheader.nColor; i++) + { + line = getArrayLine(in); + if (line.empty()) + throw FileError("Pixmap has missing colortable-entry."); + algorithm::split(list, line, is_any_of(" \t")); + if (list.size() < 3) + throw FileError("Pixmap colortable-entry is invalid."); + + /* read pixel character */ + character = list[0]; + if (character.length() != m_fileheader.nChar) + throw FileError("Pixmap colorcharacter is invalid."); + + /* read colors */ + string color(""); + if ((list.size() - 1) % 2 != 0) + throw FileError("Pixmap color entrys are invalid."); + for(uint32_t j = 1; j < list.size(); j = j + 2) + { + if (list[j + 1].length() != 7) + throw FileError("Pixmap color value is invalid."); + if (list[j + 1].at(0) != '#') + throw FileError("Pixmap color table value is not hexadecimal."); + + /* we only support c-colors! */ + if (list[j] != "c") + continue; + + CPixelFormat::RGBPIXEL *pixel = new CPixelFormat::RGBPIXEL; + pixel->red = strtoul(list[j + 1].substr(1, 2).c_str(), NULL, 16); + pixel->green = strtoul(list[j + 1].substr(3, 2).c_str(), NULL, 16); + pixel->blue = strtoul(list[j + 1].substr(5, 2).c_str(), NULL, 16); + colors[ list[j] ] = pixel; + } + /* we only support c-colors! */ + if (colors.find("c") == colors.end()) + throw FileError("Pixmap color entry has missing c-value."); - /* parse color table*/ - getline( in, str, '"'); - string character, mode, colors; - for (unsigned int i = 0; i < m_fileheader.nColor; i++ ) - { - getline( in, str, '"' ); - stringstream istr2 (str ); - - istr2 >> character; - istr2 >> mode; - istr2 >> colors; - - if ( colors.size() != 7) - throw FileError("Pixmap color tabel is invalid."); - if ( colors.at(0) != '#') - throw FileError("Pixmap color tabel value is not hexadecimal."); - - xpmColors[character][mode] = new (nothrow) unsigned int[3]; - if (xpmColors[character][mode] == 0) - throw FileError("Bad color table allocation."); - - xpmColors[character][mode][0] = - static_cast(strtoul(colors.substr(1,2).c_str(), NULL, 16)); - xpmColors[character][mode][1] = - static_cast(strtoul(colors.substr(3,2).c_str(), NULL, 16)); - xpmColors[character][mode][2] = - static_cast(strtoul(colors.substr(5,2).c_str(), NULL, 16)); - - - - - - - getline( in, str, '"' ); + /* add pixel to colortable */ + m_colortable[character] = colors["c"]; } - - /* read pixel data using separate class */ + + /* read pixel data */ if (getPixelDataSize() > 0) { if (m_pixeldata != NULL) delete[] m_pixeldata; m_pixeldata = new uint8_t[getPixelDataSize()]; - - for (unsigned int y = 0; y < getHeight(); y++ ) - { - for (unsigned int x = 0; x < getWidth(); x++ ) - m_pixeldata[y * getWidth() + x] = static_cast(in.get()); - getline( in, str); - if ( y != ( getHeight() - 1 )) - in.get(); - + for (uint32_t y = 0; y < getHeight(); y++) + { + line = getArrayLine(in); + if (line.empty()) + throw FileError("Pixmap has no pixel data."); + if (line.length() != getWidth()) + throw FileError("Pixmap pixeldata width is larger than header width."); + copy(line.c_str(), line.c_str() + line.length(), m_pixeldata + y * getWidth()); } } - /* parse extension */ - if ( m_fileheader._XPMEXT ) - getline( in, m_fileheader.extension, '}' ); - /* debug*/ - CPixmap::dump (cout); - + /* get extension */ + if (m_fileheader._XPMEXT) + getline(in, m_fileheader.extension, '}'); + if (!in.good()) + throw FileError("Pixmap array isn't closed properly."); + /* get pixelformat instance */ m_pixelformat = NULL; set::iterator it; for (it = m_handlers.begin(); it != m_handlers.end(); it++) { - /* check color mode */ - //TODO if (mode.compare((*it)->getColorMode()) == 0) - if (mode == "c") - { - m_pixelformat = *it; - break; - } + /* we only have one! */ + m_pixelformat = *it; + break; } if (m_pixelformat == NULL) - throw FileError("Pixmap color mode \""+mode+"\" is not supported."); + throw FileError("Pixmap color mode is not supported."); + +#ifdef DEBUG + /* debug*/ + CPixmap::dump(cout); +#endif } /*----------------------------------------------------------------------------*/ -void CPixmap::write(std::ofstream& out, std::string& filename) +void CPixmap::write(std::ofstream& out) { - /* header comment */ - out<<"/* XPM */"< >::iterator it1; - map::iterator it2; - - for ( it1= xpmColors.begin() ; it1 != xpmColors.end(); it1++ ) - { - out << "\""<<(*it1).first; - for ( it2=(*it1).second.begin() ; it2 != (*it1).second.end(); it2++ ) - { - - out<<"\t" <<(*it2).first<<"\t#"; - - for (int i = 0 ; i < 3; i++ ) - { - out.width(2); - out << hex <::iterator it; + for (it = m_colortable.begin(); it != m_colortable.end(); it++) + { + out << "\"" << (*it).first; + /* we only support c-colors! */ + out << "\tc #"; + out << setfill('0') << setw(2) << hex << uppercase << (*it).second->red + << setfill('0') << setw(2) << hex << uppercase << (*it).second->green + << setfill('0') << setw(2) << hex << uppercase << (*it).second->blue; + out << "\"," << endl; } - + /* pixel data */ - for (unsigned int y = 0; y < getHeight(); y++ ){ - out <<"\""; - for (unsigned int x = 0; x < getWidth(); x++ ) + //TODO: better via copy? + for (uint32_t y = 0; y < getHeight(); y++) + { + out << "\""; + for (uint32_t x = 0; x < getWidth(); x++) out << m_pixeldata[y * getWidth() + x]; - out <<"\""; - if ( y != ( getHeight() - 1 )) - out <<","; - out <::iterator it; + cout << "[Color Table]" << endl; + for (it = m_colortable.begin(); it != m_colortable.end(); it++) + { + out << (*it).first << " " + << setfill('0') << setw(3) << (*it).second->red << " " + << setfill('0') << setw(3) << (*it).second->green << " " + << setfill('0') << setw(3) << (*it).second->blue << " " + << endl; } - } #endif -- cgit v1.2.3