#include <phantasmal/log.h> #include <phantasmal/lpc_names.h> #include <limits.h> private object dtd; private string dtd_text; private string dtd_filename; private void update_dtd_vars(void); mixed* to_dtd_unq(void); void from_unq(mixed* unq); void from_dtd_unq(mixed* unq); static void create(varargs int clone) { if(!find_object(UNQ_PARSER)) { compile_object(UNQ_PARSER); } if(!find_object(UNQ_DTD)) { compile_object(UNQ_DTD); } } void destructed(int clone) { if(dtd) destruct_object(dtd); } void upgraded(varargs int clone) { if(dtd_filename) { update_dtd_vars(); } } /* This sets the DTD object given as this object's DTD. That means the object may destruct the DTD at its leisure, among other things. */ void set_dtd(object new_dtd) { dtd = new_dtd; } /* This supplies the text of a DTD file to be this object's DTD. */ void set_dtd_text(string new_dtd_text) { dtd_text = new_dtd_text; update_dtd_vars(); } /* This supplies a filename to load the object's DTD from. */ void set_dtd_file(string new_dtd_filename) { dtd_filename = new_dtd_filename; update_dtd_vars(); } /* The updates dtd and dtd_text from themselves and dtd_filename. */ private void update_dtd_vars(void) { if(dtd_filename) { string buf; buf = read_file(dtd_filename); if(!buf) { error("Can't read DTD file " + dtd_filename + "!"); } if(strlen(buf) > MAX_STRING_SIZE - 3) { error("DTD file is too large in update_dtd_vars!"); } dtd_text = buf; } if(dtd_text) { if(dtd) { dtd->clear(); } else { dtd = clone_object(UNQ_DTD); } dtd->load(dtd_text); } } /* This method serializes the object as UNQ text and returns the appropriate string, suitable for writing to an UNQ file. */ string to_unq_text(void) { string result; if(!dtd) { error("You must override the default to_unq_text method for " + object_name(this_object()) + " or supply a DTD!"); } result = dtd->serialize_to_dtd(to_dtd_unq()); if(!result) { LOGD->write_syslog(dtd->get_parse_error_stack(), LOG_WARNING); } return result; } /* Just in case we need it... */ string get_parse_error_stack(void) { return dtd->get_parse_error_stack(); } /* This method converts the object to the same sort of template that parsing an UNQ file with a DTD yields. This template can then be converted to text. */ mixed* to_dtd_unq(void) { error("You must override the default to_dtd_unq method for " + object_name(this_object())); } /* This method takes a string of UNQ text as loads it into the object. */ void from_unq_text(string text) { from_unq(UNQ_PARSER->basic_unq_parse(text)); } /* This method takes a chunk of parsed UNQ and loads it into the object. */ void from_unq(mixed* unq) { mixed* dtd_unq; if(!dtd) { error("You must override the default from_unq method for " + object_name(this_object()) + " or supply a DTD!"); } dtd_unq = dtd->parse_to_dtd(unq); if(!dtd_unq) error("Can't parse UNQ according to DTD!"); from_dtd_unq(dtd_unq); } /* This method takes the result of parsing the object according to its DTD and loads it into the object. */ void from_dtd_unq(mixed* unq) { error("You must override the default from_dtd_unq method for " + object_name(this_object())); } /* This method loads the necessary file, parses it with the supplied DTD, and calls the from_dtd_unq method to load its contents into the object. */ void load_from_file(string filename) { string str; mixed* unq, *dtd_unq; str = read_file(filename); if(!str) error("Can't read file '" + filename + "' in load_from_file!"); if(strlen(str) > MAX_STRING_SIZE - 3) error("File '" + filename + "' is too large in load_from_file!"); unq = UNQ_PARSER->basic_unq_parse(str); if(!unq) error("Can't parse file contents to UNQ! (" + filename + ")"); dtd_unq = dtd->parse_to_dtd(unq); if(!dtd_unq) { LOGD->write_syslog("Error stack:\n" + dtd->get_parse_error_stack(), LOG_WARN); error("Can't parse UNQ according to DTD!"); } from_dtd_unq(dtd_unq); }