// -*- C++ -*- /* * Gnome Chemistry Utils * chemistry/xml-utils.cc * * Copyright (C) 2002-2006 Jean Bréfort * * This program 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 of the * License, or (at your option) any later version. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 * USA */ #include "xml-utils.h" #include #include #include using namespace std; xmlNodePtr FindNodeByNameAndId (xmlNodePtr node, const char* name, const char* id) { xmlNodePtr child = node->children; char* tmp; while (child) { if (!strcmp ((char*) child->name, name)) { tmp = (char*) xmlGetProp (child, (xmlChar*) "id"); if ((!id && !tmp) || (id && tmp && !strcmp (tmp, id))) { if (tmp) xmlFree (tmp); break; } else if (tmp) xmlFree (tmp); } child = child->next; } return child; } bool ReadPosition (xmlNodePtr node, const char* id, double* x, double* y, double* z) { xmlNodePtr child = FindNodeByNameAndId (node, "position", id); if (!child) return false; char* tmp; tmp = (char*) xmlGetProp (child, (xmlChar*) "x"); if (tmp) { sscanf (tmp, "%lg", x); xmlFree (tmp); } else return false; tmp = (char*) xmlGetProp (child, (xmlChar*) "y"); if (tmp) { sscanf (tmp, "%lg", y); xmlFree (tmp); } else return false; if (z) { tmp = (char*) xmlGetProp (child, (xmlChar*) "z"); if (tmp) { sscanf (tmp, "%lg", z); xmlFree (tmp); } else *z = 0.0; } return true; } bool WritePosition (xmlDocPtr xml, xmlNodePtr node, const char* id, double x, double y, double z) { xmlNodePtr child; char buf[16]; child = xmlNewDocNode (xml, NULL, (xmlChar*) "position", NULL); if (child) xmlAddChild (node, child); else return false; if (id) xmlNewProp (child, (xmlChar*) "id", (xmlChar*) id); snprintf (buf, sizeof (buf), "%g", x); xmlNewProp (child, (xmlChar*) "x", (xmlChar*) buf); snprintf (buf, sizeof (buf), "%g", y); xmlNewProp (child, (xmlChar*) "y", (xmlChar*) buf); if (z != 0.0) { snprintf (buf, sizeof (buf), "%g", z); xmlNewProp (child, (xmlChar*) "z", (xmlChar*) buf); } return true; } bool ReadColor (xmlNodePtr node, const char* id, float* red, float* green, float* blue, float* alpha) { xmlNodePtr child = FindNodeByNameAndId (node, "color", id); if (!child) return false; char* tmp; tmp = (char*) xmlGetProp (child, (xmlChar*) "red"); if (tmp) { sscanf (tmp, "%g", red); xmlFree (tmp); } else return false; tmp = (char*) xmlGetProp (child, (xmlChar*) "green"); if (tmp) { sscanf (tmp, "%g", green); xmlFree (tmp); } else return false; tmp = (char*) xmlGetProp (child, (xmlChar*) "blue"); if (tmp) { sscanf (tmp, "%g", blue); xmlFree (tmp); } else return false; if (alpha) { tmp = (char*) xmlGetProp (child, (xmlChar*) "alpha"); if (tmp) { sscanf (tmp, "%g", alpha); xmlFree (tmp); } else *alpha = 1.0; } return true; } bool WriteColor (xmlDocPtr xml, xmlNodePtr node, const char* id, double red, double green, double blue, double alpha) { xmlNodePtr child; char buf[16]; child = xmlNewDocNode (xml, NULL, (xmlChar*) "color", NULL); if (child) xmlAddChild (node, child); else return false; if (id) xmlNewProp (child, (xmlChar*) "id", (xmlChar*) id); snprintf (buf, sizeof (buf), "%g", red); xmlNewProp (child, (xmlChar*) "red", (xmlChar*) buf); snprintf (buf, sizeof (buf), "%g", green); xmlNewProp (child, (xmlChar*) "green", (xmlChar*) buf); snprintf (buf, sizeof (buf), "%g", blue); xmlNewProp (child, (xmlChar*) "blue", (xmlChar*) buf); if (alpha != 1.0) { snprintf (buf, sizeof (buf), "%g", alpha); xmlNewProp (child, (xmlChar*) "alpha", (xmlChar*) buf); } return true; } bool ReadRadius (xmlNodePtr node, GcuAtomicRadius& radius) { char *tmp, *dot, *end; tmp = (char*) xmlGetProp (node, (xmlChar*) "type"); if (!tmp || ((!((!strcmp (tmp, "unknown")) && (radius.type = GCU_RADIUS_UNKNOWN))) && (!((!strcmp (tmp, "covalent")) && (radius.type = GCU_COVALENT))) && (!((!strcmp (tmp, "vdW")) && (radius.type = GCU_VAN_DER_WAALS))) && (!((!strcmp (tmp, "ionic")) && (radius.type = GCU_IONIC))) && (!((!strcmp (tmp, "metallic")) && (radius.type = GCU_METALLIC))) && (!((!strcmp (tmp, "atomic")) && (radius.type = GCU_ATOMIC))))) radius.type = GCU_RADIUS_UNKNOWN; if (tmp) xmlFree (tmp); tmp = (char*) xmlGetProp (node, (xmlChar*) "scale"); if (tmp) { radius.scale = GetStaticScale (tmp); xmlFree (tmp); } else radius.scale = NULL; tmp = (char*) xmlGetProp (node, (xmlChar*) "charge"); if (tmp) { radius.charge = strtol (tmp, NULL, 10); xmlFree (tmp); } else radius.charge = 0; tmp = (char*) xmlGetProp (node, (xmlChar*)"cn"); if (tmp) { radius.cn = strtol (tmp, NULL, 10); xmlFree (tmp); } else radius.cn = -1; tmp = (char*) xmlGetProp(node, (xmlChar*) "spin"); if ((!tmp) || ((!((!strcmp (tmp, "low")) && (radius.spin = GCU_LOW_SPIN))) && (!((!strcmp (tmp, "high")) && (radius.spin = GCU_HIGH_SPIN))))) radius.spin = GCU_N_A_SPIN; if (tmp) xmlFree(tmp); if (((tmp = (char*) xmlGetProp (node, (xmlChar*) "value")) || (tmp = (char*) xmlNodeGetContent (node))) && *tmp) { radius.value.value = strtod (tmp, &end); dot = strchr (tmp, '.'); radius.value.prec = (dot)? end - dot - 1: 0; radius.scale = "custom"; xmlFree(tmp); } else { if (tmp) xmlFree(tmp); if (radius.scale && (!strcmp (radius.scale, "custom"))) return false; else if (!gcu_element_get_radius (&radius)) return false; } if (radius.value.value <= 0.0) return false; return true; } bool WriteRadius (xmlDocPtr xml, xmlNodePtr node, const GcuAtomicRadius& radius) { xmlNodePtr child; gchar buf[256], *tmp; child = xmlNewDocNode (xml, NULL, (xmlChar*) "radius", NULL); if (child) xmlAddChild (node, child); else return false; switch (radius.type) { case GCU_RADIUS_UNKNOWN: tmp = NULL; break; case GCU_ATOMIC: tmp = (char*) "atomic"; break; case GCU_IONIC: tmp = (char*) "ionic"; break; case GCU_METALLIC: tmp = (char*) "metallic"; break; case GCU_COVALENT: tmp = (char*) "covalent"; break; case GCU_VAN_DER_WAALS: tmp = (char*) "vdW"; break; default: tmp = NULL; } if (tmp) xmlNewProp (child, (xmlChar*) "type", (xmlChar*) tmp); if ((radius.type == GCU_RADIUS_UNKNOWN) || (radius.scale && (!strcmp (radius.scale, "custom")))) { char *format = g_strdup_printf ("%%0.%df",radius.value.prec); g_snprintf (buf, sizeof (buf) - 1, format, radius.value.value); g_free (format); xmlNewProp (child, (xmlChar*) "value", (xmlChar*) buf); } if (radius.scale && strcmp (radius.scale, "custom")) xmlNewProp (child, (xmlChar*) "scale", (xmlChar*) radius.scale); if (radius.charge) { g_snprintf (buf, sizeof (buf) - 1, "%d", radius.charge); xmlNewProp (child, (xmlChar*) "charge", (xmlChar*) buf); } if (radius.cn != -1) { g_snprintf (buf, sizeof (buf) - 1, "%d", radius.cn); xmlNewProp (child, (xmlChar*) "cn", (xmlChar*) buf); } if (radius.spin != GCU_N_A_SPIN) xmlNewProp (child, (xmlChar*) "spin", (xmlChar*)((radius.spin == GCU_LOW_SPIN)? "low": "high")); return true; } // we must have static strings static set ScaleNames; char const *GetStaticScale (char *buf) { set ::iterator i = ScaleNames.find (buf); if (i == ScaleNames.end ()) { std::pair::iterator,bool> res = ScaleNames.insert (buf); if (res.second) return (*res.first).c_str (); else return NULL; } return (*i).c_str (); }