diff options
Diffstat (limited to 'Project')
53 files changed, 6535 insertions, 214 deletions
diff --git a/Project/Bus.cpp b/Project/Bus.cpp index a684ed4..f41b0d1 100644 --- a/Project/Bus.cpp +++ b/Project/Bus.cpp @@ -165,7 +165,7 @@ void Bus::Rotate(bool clockwise) if(!clockwise) rotAngle = -m_rotationAngle; m_angle += rotAngle; - if(m_angle >= 360.0) m_angle = 0.0; + if(m_angle >= 360 || m_angle <= -360) m_angle = 0.0; } bool Bus::GetContextMenu(wxMenu& menu) diff --git a/Project/Capacitor.cpp b/Project/Capacitor.cpp index 0110df3..332582d 100644 --- a/Project/Capacitor.cpp +++ b/Project/Capacitor.cpp @@ -91,6 +91,7 @@ void Capacitor::Rotate(bool clockwise) if(!clockwise) rotAngle = -m_rotationAngle; m_angle += rotAngle; + if(m_angle >= 360 || m_angle <= -360) m_angle = 0.0; m_pointList[2] = RotateAtPosition(m_pointList[2], rotAngle); m_pointList[3] = RotateAtPosition(m_pointList[3], rotAngle); UpdateSwitchesPosition(); diff --git a/Project/Element.h b/Project/Element.h index f5a2edb..512fc8f 100644 --- a/Project/Element.h +++ b/Project/Element.h @@ -98,6 +98,7 @@ public: void ShowPickbox(bool showPickbox = true) { m_showPickbox = showPickbox; } void SetBorderSize(double borderSize) { m_borderSize = borderSize; } void SetOnline(bool online = true); + virtual void SetPointList(std::vector<wxPoint2DDouble> pointList) { m_pointList = pointList; } // Getters wxRect2DDouble GetRect() const { return m_rect; } wxPoint2DDouble GetPosition() const { return m_position; } @@ -106,8 +107,11 @@ public: bool IsSelected() const { return m_selected; } double GetWidth() const { return m_width; } double GetAngle() const { return m_angle; } + double GetRotationAngle() const { return m_rotationAngle; } bool IsPickboxShown() const { return m_showPickbox; } bool IsOnline() const { return m_online; } + virtual std::vector<wxPoint2DDouble> GetPointList() const { return m_pointList; } + // Pure-virtuals methods virtual bool AddParent(Element* parent, wxPoint2DDouble position) = 0; virtual bool Contains(wxPoint2DDouble position) const = 0; diff --git a/Project/FileHanding.cpp b/Project/FileHanding.cpp new file mode 100644 index 0000000..33d66cc --- /dev/null +++ b/Project/FileHanding.cpp @@ -0,0 +1,1775 @@ +#include "FileHanding.h" + +FileHanding::~FileHanding() {} + +FileHanding::FileHanding(Workspace* workspace) { m_workspace = workspace; } + +FileHanding::FileHanding() {} + +void FileHanding::SaveProject(wxFileName path) +{ + // Erase the file (if exists or not) and write the initial data + std::ofstream writeProjectsFile(path.GetFullPath()); + writeProjectsFile.close(); + + rapidxml::xml_document<> doc; + rapidxml::file<> xmlFile(path.GetFullPath()); + doc.parse<0>(xmlFile.data()); + + rapidxml::xml_node<>* decl = doc.allocate_node(rapidxml::node_declaration); + rapidxml::xml_attribute<>* ver = doc.allocate_attribute("version", "1.0"); + rapidxml::xml_attribute<>* encoding = doc.allocate_attribute("encoding", "utf-8"); + decl->append_attribute(ver); + decl->append_attribute(encoding); + doc.append_node(decl); + + rapidxml::xml_node<>* rootNode = doc.allocate_node(rapidxml::node_element, "Project"); + doc.append_node(rootNode); + + rapidxml::xml_node<>* projectNameNode = AppendNode(doc, rootNode, "Name"); + SetNodeValue(doc, projectNameNode, path.GetName()); + + auto elementsNode = AppendNode(doc, rootNode, "Elements"); + + // Save all the data + ElectricCalculation allElements; + allElements.GetElementsFromList(m_workspace->GetElementList()); + + //{ Buses + auto busesNode = AppendNode(doc, elementsNode, "BusList"); + auto busList = allElements.GetBusList(); + for(int i = 0; i < (int)busList.size(); i++) { + Bus* bus = busList[i]; + auto busNode = AppendNode(doc, busesNode, "Bus"); + SetNodeAttribute(doc, busNode, "ID", i); + auto cadProp = AppendNode(doc, busNode, "CADProperties"); + auto position = AppendNode(doc, cadProp, "Position"); + auto posX = AppendNode(doc, position, "X"); + SetNodeValue(doc, posX, bus->GetPosition().m_x); + auto posY = AppendNode(doc, position, "Y"); + SetNodeValue(doc, posY, bus->GetPosition().m_y); + auto size = AppendNode(doc, cadProp, "Size"); + auto width = AppendNode(doc, size, "Width"); + SetNodeValue(doc, width, bus->GetWidth()); + auto height = AppendNode(doc, size, "Height"); + SetNodeValue(doc, height, bus->GetHeight()); + auto angle = AppendNode(doc, cadProp, "Angle"); + SetNodeValue(doc, angle, bus->GetAngle()); + + BusElectricalData data = bus->GetEletricalData(); + auto electricalProp = AppendNode(doc, busNode, "ElectricalProperties"); + auto name = AppendNode(doc, electricalProp, "Name"); + SetNodeValue(doc, name, data.name); + auto nominalVoltage = AppendNode(doc, electricalProp, "NominalVoltage"); + SetNodeValue(doc, nominalVoltage, data.nominalVoltage); + SetNodeAttribute(doc, nominalVoltage, "UnitID", data.nominalVoltageUnit); + auto isVoltageControlled = AppendNode(doc, electricalProp, "IsVoltageControlled"); + SetNodeValue(doc, isVoltageControlled, data.isVoltageControlled); + auto controlledVoltage = AppendNode(doc, electricalProp, "ControlledVoltage"); + SetNodeValue(doc, controlledVoltage, data.controlledVoltage); + SetNodeAttribute(doc, controlledVoltage, "Choice", data.controlledVoltageUnitChoice); + auto slackBus = AppendNode(doc, electricalProp, "SlackBus"); + SetNodeValue(doc, slackBus, data.slackBus); + + auto fault = AppendNode(doc, electricalProp, "Fault"); + auto hasFault = AppendNode(doc, fault, "HasFault"); + SetNodeValue(doc, hasFault, data.hasFault); + auto faultType = AppendNode(doc, fault, "Type"); + SetNodeValue(doc, faultType, data.faultType); + auto faultLocation = AppendNode(doc, fault, "Location"); + SetNodeValue(doc, faultLocation, data.faultLocation); + auto faultResistance = AppendNode(doc, fault, "Resistance"); + SetNodeValue(doc, faultResistance, data.faultResistance); + auto faultReactance = AppendNode(doc, fault, "Reactance"); + SetNodeValue(doc, faultReactance, data.faultReactance); + + auto stability = AppendNode(doc, electricalProp, "Stability"); + auto plotBus = AppendNode(doc, stability, "Plot"); + SetNodeValue(doc, plotBus, data.plotBus); + auto stabHasFault = AppendNode(doc, stability, "HasFault"); + SetNodeValue(doc, stabHasFault, data.stabHasFault); + auto stabFaultTime = AppendNode(doc, stability, "FaultTime"); + SetNodeValue(doc, stabFaultTime, data.stabFaultTime); + auto stabFaultLength = AppendNode(doc, stability, "FaultLength"); + SetNodeValue(doc, stabFaultLength, data.stabFaultLength); + auto stabFaultResistance = AppendNode(doc, stability, "FaultResistance"); + SetNodeValue(doc, stabFaultResistance, data.stabFaultResistance); + auto stabFaultReactance = AppendNode(doc, stability, "FaultReactance"); + SetNodeValue(doc, stabFaultReactance, data.stabFaultReactance); + + data.number = i; + bus->SetElectricalData(data); + } //} + + //{ Capacitor + auto capacitorsNode = AppendNode(doc, elementsNode, "CapacitorList"); + auto capacitorList = allElements.GetCapacitorList(); + for(int i = 0; i < (int)capacitorList.size(); i++) { + Capacitor* capacitor = capacitorList[i]; + auto capacitorNode = AppendNode(doc, capacitorsNode, "Capacitor"); + SetNodeAttribute(doc, capacitorNode, "ID", i); + auto cadProp = AppendNode(doc, capacitorNode, "CADProperties"); + auto position = AppendNode(doc, cadProp, "Position"); + auto posX = AppendNode(doc, position, "X"); + SetNodeValue(doc, posX, capacitor->GetPosition().m_x); + auto posY = AppendNode(doc, position, "Y"); + SetNodeValue(doc, posY, capacitor->GetPosition().m_y); + auto size = AppendNode(doc, cadProp, "Size"); + auto width = AppendNode(doc, size, "Width"); + SetNodeValue(doc, width, capacitor->GetWidth()); + auto height = AppendNode(doc, size, "Height"); + SetNodeValue(doc, height, capacitor->GetHeight()); + auto angle = AppendNode(doc, cadProp, "Angle"); + SetNodeValue(doc, angle, capacitor->GetAngle()); + auto nodePos = AppendNode(doc, cadProp, "NodePosition"); + auto nodePosX = AppendNode(doc, nodePos, "X"); + SetNodeValue(doc, nodePosX, capacitor->GetPointList()[0].m_x); + auto nodePosY = AppendNode(doc, nodePos, "Y"); + SetNodeValue(doc, nodePosY, capacitor->GetPointList()[0].m_y); + auto parentID = AppendNode(doc, cadProp, "ParentID"); + Bus* parent = (Bus*)capacitor->GetParentList()[0]; + if(parent) SetNodeValue(doc, parentID, parent->GetEletricalData().number); + + CapacitorElectricalData data = capacitor->GetElectricalData(); + auto electricalProp = AppendNode(doc, capacitorNode, "ElectricalProperties"); + auto isOnline = AppendNode(doc, electricalProp, "IsOnline"); + SetNodeValue(doc, isOnline, capacitor->IsOnline()); + auto name = AppendNode(doc, electricalProp, "Name"); + SetNodeValue(doc, name, data.name); + auto reactivePower = AppendNode(doc, electricalProp, "ReactivePower"); + SetNodeValue(doc, reactivePower, data.reactivePower); + SetNodeAttribute(doc, reactivePower, "UnitID", data.reactivePowerUnit); + + auto switchingList = AppendNode(doc, electricalProp, "SwitchingList"); + SwitchingData swData = capacitor->GetSwitchingData(); + for(int j = 0; j < (int)swData.swType.size(); j++) { + auto switching = AppendNode(doc, switchingList, "Switching"); + SetNodeAttribute(doc, switching, "ID", j); + auto swType = AppendNode(doc, switching, "Type"); + SetNodeValue(doc, swType, swData.swType[j]); + auto swTime = AppendNode(doc, switching, "Time"); + SetNodeValue(doc, swTime, swData.swTime[j]); + } + } //} + + //{ IndMotor + auto indMotorsNode = AppendNode(doc, elementsNode, "IndMotorList"); + auto indMotorList = allElements.GetIndMotorList(); + for(int i = 0; i < (int)indMotorList.size(); i++) { + IndMotor* indMotor = indMotorList[i]; + auto indMotorNode = AppendNode(doc, indMotorsNode, "IndMotor"); + SetNodeAttribute(doc, indMotorNode, "ID", i); + auto cadProp = AppendNode(doc, indMotorNode, "CADProperties"); + auto position = AppendNode(doc, cadProp, "Position"); + auto posX = AppendNode(doc, position, "X"); + SetNodeValue(doc, posX, indMotor->GetPosition().m_x); + auto posY = AppendNode(doc, position, "Y"); + SetNodeValue(doc, posY, indMotor->GetPosition().m_y); + auto size = AppendNode(doc, cadProp, "Size"); + auto width = AppendNode(doc, size, "Width"); + SetNodeValue(doc, width, indMotor->GetWidth()); + auto height = AppendNode(doc, size, "Height"); + SetNodeValue(doc, height, indMotor->GetHeight()); + auto angle = AppendNode(doc, cadProp, "Angle"); + SetNodeValue(doc, angle, indMotor->GetAngle()); + auto nodePos = AppendNode(doc, cadProp, "NodePosition"); + auto nodePosX = AppendNode(doc, nodePos, "X"); + SetNodeValue(doc, nodePosX, indMotor->GetPointList()[0].m_x); + auto nodePosY = AppendNode(doc, nodePos, "Y"); + SetNodeValue(doc, nodePosY, indMotor->GetPointList()[0].m_y); + auto parentID = AppendNode(doc, cadProp, "ParentID"); + Bus* parent = (Bus*)indMotor->GetParentList()[0]; + if(parent) SetNodeValue(doc, parentID, parent->GetEletricalData().number); + + IndMotorElectricalData data = indMotor->GetElectricalData(); + auto electricalProp = AppendNode(doc, indMotorNode, "ElectricalProperties"); + auto isOnline = AppendNode(doc, electricalProp, "IsOnline"); + SetNodeValue(doc, isOnline, indMotor->IsOnline()); + auto name = AppendNode(doc, electricalProp, "Name"); + SetNodeValue(doc, name, data.name); + auto activePower = AppendNode(doc, electricalProp, "ActivePower"); + SetNodeValue(doc, activePower, data.activePower); + SetNodeAttribute(doc, activePower, "UnitID", data.activePowerUnit); + auto reactivePower = AppendNode(doc, electricalProp, "ReactivePower"); + SetNodeValue(doc, reactivePower, data.reactivePower); + SetNodeAttribute(doc, reactivePower, "UnitID", data.reactivePowerUnit); + } //} + + //{ Inductor + auto inductorsNode = AppendNode(doc, elementsNode, "InductorList"); + auto inductorList = allElements.GetInductorList(); + for(int i = 0; i < (int)inductorList.size(); i++) { + Inductor* inductor = inductorList[i]; + auto inductorNode = AppendNode(doc, inductorsNode, "Inductor"); + SetNodeAttribute(doc, inductorNode, "ID", i); + auto cadProp = AppendNode(doc, inductorNode, "CADProperties"); + auto position = AppendNode(doc, cadProp, "Position"); + auto posX = AppendNode(doc, position, "X"); + SetNodeValue(doc, posX, inductor->GetPosition().m_x); + auto posY = AppendNode(doc, position, "Y"); + SetNodeValue(doc, posY, inductor->GetPosition().m_y); + auto size = AppendNode(doc, cadProp, "Size"); + auto width = AppendNode(doc, size, "Width"); + SetNodeValue(doc, width, inductor->GetWidth()); + auto height = AppendNode(doc, size, "Height"); + SetNodeValue(doc, height, inductor->GetHeight()); + auto angle = AppendNode(doc, cadProp, "Angle"); + SetNodeValue(doc, angle, inductor->GetAngle()); + auto nodePos = AppendNode(doc, cadProp, "NodePosition"); + auto nodePosX = AppendNode(doc, nodePos, "X"); + SetNodeValue(doc, nodePosX, inductor->GetPointList()[0].m_x); + auto nodePosY = AppendNode(doc, nodePos, "Y"); + SetNodeValue(doc, nodePosY, inductor->GetPointList()[0].m_y); + auto parentID = AppendNode(doc, cadProp, "ParentID"); + Bus* parent = (Bus*)inductor->GetParentList()[0]; + if(parent) SetNodeValue(doc, parentID, parent->GetEletricalData().number); + + InductorElectricalData data = inductor->GetElectricalData(); + auto electricalProp = AppendNode(doc, inductorNode, "ElectricalProperties"); + auto isOnline = AppendNode(doc, electricalProp, "IsOnline"); + SetNodeValue(doc, isOnline, inductor->IsOnline()); + auto name = AppendNode(doc, electricalProp, "Name"); + SetNodeValue(doc, name, data.name); + auto reactivePower = AppendNode(doc, electricalProp, "ReactivePower"); + SetNodeValue(doc, reactivePower, data.reactivePower); + SetNodeAttribute(doc, reactivePower, "UnitID", data.reactivePowerUnit); + + auto switchingList = AppendNode(doc, electricalProp, "SwitchingList"); + SwitchingData swData = inductor->GetSwitchingData(); + for(int j = 0; j < (int)swData.swType.size(); j++) { + auto switching = AppendNode(doc, switchingList, "Switching"); + SetNodeAttribute(doc, switching, "ID", j); + auto swType = AppendNode(doc, switching, "Type"); + SetNodeValue(doc, swType, swData.swType[j]); + auto swTime = AppendNode(doc, switching, "Time"); + SetNodeValue(doc, swTime, swData.swTime[j]); + } + } //} + + //{ Line + auto linesNode = AppendNode(doc, elementsNode, "LineList"); + auto lineList = allElements.GetLineList(); + for(int i = 0; i < (int)lineList.size(); i++) { + Line* line = lineList[i]; + auto lineNode = AppendNode(doc, linesNode, "Line"); + SetNodeAttribute(doc, lineNode, "ID", i); + auto cadProp = AppendNode(doc, lineNode, "CADProperties"); + auto nodeList = AppendNode(doc, cadProp, "NodeList"); + auto ptList = line->GetPointList(); + int nodeID = 0; + for(int j = 0; j < (int)ptList.size(); j++) { + if((j != 1) && (j != (int)ptList.size() - 2)) { + auto nodePos = AppendNode(doc, nodeList, "Node"); + SetNodeAttribute(doc, nodePos, "ID", nodeID); + auto nodePosX = AppendNode(doc, nodePos, "X"); + SetNodeValue(doc, nodePosX, ptList[j].m_x); + auto nodePosY = AppendNode(doc, nodePos, "Y"); + SetNodeValue(doc, nodePosY, ptList[j].m_y); + nodeID++; + } + } + + auto parentIDList = AppendNode(doc, cadProp, "ParentIDList"); + for(int j = 0; j < (int)line->GetParentList().size(); j++) { + Bus* parent = (Bus*)line->GetParentList()[j]; + if(parent) { + auto parentID = AppendNode(doc, parentIDList, "ParentID"); + SetNodeAttribute(doc, parentID, "ID", j); + SetNodeValue(doc, parentID, parent->GetEletricalData().number); + } + } + + LineElectricalData data = line->GetElectricalData(); + auto electricalProp = AppendNode(doc, lineNode, "ElectricalProperties"); + auto isOnline = AppendNode(doc, electricalProp, "IsOnline"); + SetNodeValue(doc, isOnline, line->IsOnline()); + auto name = AppendNode(doc, electricalProp, "Name"); + SetNodeValue(doc, name, data.name); + auto nominalVoltage = AppendNode(doc, electricalProp, "NominalVoltage"); + SetNodeValue(doc, nominalVoltage, data.nominalVoltage); + SetNodeAttribute(doc, nominalVoltage, "UnitID", data.nominalVoltageUnit); + auto nominalPower = AppendNode(doc, electricalProp, "NominalPower"); + SetNodeValue(doc, nominalPower, data.nominalPower); + SetNodeAttribute(doc, nominalPower, "UnitID", data.nominalPowerUnit); + auto resistance = AppendNode(doc, electricalProp, "Resistance"); + SetNodeValue(doc, resistance, data.resistance); + SetNodeAttribute(doc, resistance, "UnitID", data.resistanceUnit); + auto indReactance = AppendNode(doc, electricalProp, "IndReactance"); + SetNodeValue(doc, indReactance, data.indReactance); + SetNodeAttribute(doc, indReactance, "UnitID", data.indReactanceUnit); + auto capSusceptance = AppendNode(doc, electricalProp, "CapSusceptance"); + SetNodeValue(doc, capSusceptance, data.capSusceptance); + SetNodeAttribute(doc, capSusceptance, "UnitID", data.capSusceptanceUnit); + auto lineSize = AppendNode(doc, electricalProp, "LineSize"); + SetNodeValue(doc, lineSize, data.lineSize); + auto useLinePower = AppendNode(doc, electricalProp, "UseLinePower"); + SetNodeValue(doc, useLinePower, data.useLinePower); + + auto fault = AppendNode(doc, electricalProp, "Fault"); + auto zeroResistance = AppendNode(doc, fault, "ZeroResistance"); + SetNodeValue(doc, zeroResistance, data.zeroResistance); + auto zeroIndReactance = AppendNode(doc, fault, "ZeroIndReactance"); + SetNodeValue(doc, zeroIndReactance, data.zeroIndReactance); + auto zeroCapSusceptance = AppendNode(doc, fault, "ZeroCapSusceptance"); + SetNodeValue(doc, zeroCapSusceptance, data.zeroCapSusceptance); + + auto switchingList = AppendNode(doc, electricalProp, "SwitchingList"); + SwitchingData swData = line->GetSwitchingData(); + for(int j = 0; j < (int)swData.swType.size(); j++) { + auto switching = AppendNode(doc, switchingList, "Switching"); + SetNodeAttribute(doc, switching, "ID", j); + auto swType = AppendNode(doc, switching, "Type"); + SetNodeValue(doc, swType, swData.swType[j]); + auto swTime = AppendNode(doc, switching, "Time"); + SetNodeValue(doc, swTime, swData.swTime[j]); + } + } //} + + //{ Load + auto loadsNode = AppendNode(doc, elementsNode, "LoadList"); + auto loadList = allElements.GetLoadList(); + for(int i = 0; i < (int)loadList.size(); i++) { + Load* load = loadList[i]; + auto loadNode = AppendNode(doc, loadsNode, "Load"); + SetNodeAttribute(doc, loadNode, "ID", i); + auto cadProp = AppendNode(doc, loadNode, "CADProperties"); + auto position = AppendNode(doc, cadProp, "Position"); + auto posX = AppendNode(doc, position, "X"); + SetNodeValue(doc, posX, load->GetPosition().m_x); + auto posY = AppendNode(doc, position, "Y"); + SetNodeValue(doc, posY, load->GetPosition().m_y); + auto size = AppendNode(doc, cadProp, "Size"); + auto width = AppendNode(doc, size, "Width"); + SetNodeValue(doc, width, load->GetWidth()); + auto height = AppendNode(doc, size, "Height"); + SetNodeValue(doc, height, load->GetHeight()); + auto angle = AppendNode(doc, cadProp, "Angle"); + SetNodeValue(doc, angle, load->GetAngle()); + auto nodePos = AppendNode(doc, cadProp, "NodePosition"); + auto nodePosX = AppendNode(doc, nodePos, "X"); + SetNodeValue(doc, nodePosX, load->GetPointList()[0].m_x); + auto nodePosY = AppendNode(doc, nodePos, "Y"); + SetNodeValue(doc, nodePosY, load->GetPointList()[0].m_y); + auto parentID = AppendNode(doc, cadProp, "ParentID"); + Bus* parent = (Bus*)load->GetParentList()[0]; + if(parent) SetNodeValue(doc, parentID, parent->GetEletricalData().number); + + LoadElectricalData data = load->GetElectricalData(); + auto electricalProp = AppendNode(doc, loadNode, "ElectricalProperties"); + auto isOnline = AppendNode(doc, electricalProp, "IsOnline"); + SetNodeValue(doc, isOnline, load->IsOnline()); + auto name = AppendNode(doc, electricalProp, "Name"); + SetNodeValue(doc, name, data.name); + auto activePower = AppendNode(doc, electricalProp, "ActivePower"); + SetNodeValue(doc, activePower, data.activePower); + SetNodeAttribute(doc, activePower, "UnitID", data.activePowerUnit); + auto reactivePower = AppendNode(doc, electricalProp, "ReactivePower"); + SetNodeValue(doc, reactivePower, data.reactivePower); + SetNodeAttribute(doc, reactivePower, "UnitID", data.reactivePowerUnit); + auto loadType = AppendNode(doc, electricalProp, "LoadType"); + SetNodeValue(doc, loadType, data.loadType); + + auto switchingList = AppendNode(doc, electricalProp, "SwitchingList"); + SwitchingData swData = load->GetSwitchingData(); + for(int j = 0; j < (int)swData.swType.size(); j++) { + auto switching = AppendNode(doc, switchingList, "Switching"); + SetNodeAttribute(doc, switching, "ID", j); + auto swType = AppendNode(doc, switching, "Type"); + SetNodeValue(doc, swType, swData.swType[j]); + auto swTime = AppendNode(doc, switching, "Time"); + SetNodeValue(doc, swTime, swData.swTime[j]); + } + } //} + + //{ SyncGenerator + auto syncGeneratorsNode = AppendNode(doc, elementsNode, "SyncGeneratorList"); + auto syncGeneratorList = allElements.GetSyncGeneratorList(); + for(int i = 0; i < (int)syncGeneratorList.size(); i++) { + SyncGenerator* syncGenerator = syncGeneratorList[i]; + auto syncGeneratorNode = AppendNode(doc, syncGeneratorsNode, "SyncGenerator"); + SetNodeAttribute(doc, syncGeneratorNode, "ID", i); + auto cadProp = AppendNode(doc, syncGeneratorNode, "CADProperties"); + auto position = AppendNode(doc, cadProp, "Position"); + auto posX = AppendNode(doc, position, "X"); + SetNodeValue(doc, posX, syncGenerator->GetPosition().m_x); + auto posY = AppendNode(doc, position, "Y"); + SetNodeValue(doc, posY, syncGenerator->GetPosition().m_y); + auto size = AppendNode(doc, cadProp, "Size"); + auto width = AppendNode(doc, size, "Width"); + SetNodeValue(doc, width, syncGenerator->GetWidth()); + auto height = AppendNode(doc, size, "Height"); + SetNodeValue(doc, height, syncGenerator->GetHeight()); + auto angle = AppendNode(doc, cadProp, "Angle"); + SetNodeValue(doc, angle, syncGenerator->GetAngle()); + auto nodePos = AppendNode(doc, cadProp, "NodePosition"); + auto nodePosX = AppendNode(doc, nodePos, "X"); + SetNodeValue(doc, nodePosX, syncGenerator->GetPointList()[0].m_x); + auto nodePosY = AppendNode(doc, nodePos, "Y"); + SetNodeValue(doc, nodePosY, syncGenerator->GetPointList()[0].m_y); + auto parentID = AppendNode(doc, cadProp, "ParentID"); + Bus* parent = (Bus*)syncGenerator->GetParentList()[0]; + if(parent) SetNodeValue(doc, parentID, parent->GetEletricalData().number); + + SyncGeneratorElectricalData data = syncGenerator->GetElectricalData(); + auto electricalProp = AppendNode(doc, syncGeneratorNode, "ElectricalProperties"); + auto isOnline = AppendNode(doc, electricalProp, "IsOnline"); + SetNodeValue(doc, isOnline, syncGenerator->IsOnline()); + auto name = AppendNode(doc, electricalProp, "Name"); + SetNodeValue(doc, name, data.name); + auto nominalPower = AppendNode(doc, electricalProp, "NominalPower"); + SetNodeValue(doc, nominalPower, data.nominalPower); + SetNodeAttribute(doc, nominalPower, "UnitID", data.nominalPowerUnit); + auto nominalVoltage = AppendNode(doc, electricalProp, "NominalVoltage"); + SetNodeValue(doc, nominalVoltage, data.nominalVoltage); + SetNodeAttribute(doc, nominalVoltage, "UnitID", data.nominalVoltageUnit); + auto activePower = AppendNode(doc, electricalProp, "ActivePower"); + SetNodeValue(doc, activePower, data.activePower); + SetNodeAttribute(doc, activePower, "UnitID", data.activePowerUnit); + auto reactivePower = AppendNode(doc, electricalProp, "ReactivePower"); + SetNodeValue(doc, reactivePower, data.reactivePower); + SetNodeAttribute(doc, reactivePower, "UnitID", data.reactivePowerUnit); + auto haveMaxReactive = AppendNode(doc, electricalProp, "HaveMaxReactive"); + SetNodeValue(doc, haveMaxReactive, data.haveMaxReactive); + auto maxReactive = AppendNode(doc, electricalProp, "MaxReactive"); + SetNodeValue(doc, maxReactive, data.maxReactive); + SetNodeAttribute(doc, maxReactive, "UnitID", data.maxReactiveUnit); + auto haveMinReactive = AppendNode(doc, electricalProp, "HaveMinReactive"); + SetNodeValue(doc, haveMinReactive, data.haveMinReactive); + auto minReactive = AppendNode(doc, electricalProp, "MinReactive"); + SetNodeValue(doc, minReactive, data.minReactive); + SetNodeAttribute(doc, minReactive, "UnitID", data.minReactiveUnit); + auto useMachineBase = AppendNode(doc, electricalProp, "UseMachineBase"); + SetNodeValue(doc, useMachineBase, data.useMachineBase); + + auto fault = AppendNode(doc, electricalProp, "Fault"); + auto positiveResistance = AppendNode(doc, fault, "PositiveResistance"); + SetNodeValue(doc, positiveResistance, data.positiveResistance); + auto positiveReactance = AppendNode(doc, fault, "PositiveReactance"); + SetNodeValue(doc, positiveReactance, data.positiveReactance); + auto negativeResistance = AppendNode(doc, fault, "NegativeResistance"); + SetNodeValue(doc, negativeResistance, data.negativeResistance); + auto negativeReactance = AppendNode(doc, fault, "NegativeReactance"); + SetNodeValue(doc, negativeReactance, data.negativeReactance); + auto zeroResistance = AppendNode(doc, fault, "ZeroResistance"); + SetNodeValue(doc, zeroResistance, data.zeroResistance); + auto zeroReactance = AppendNode(doc, fault, "ZeroReactance"); + SetNodeValue(doc, zeroReactance, data.zeroReactance); + auto groundResistance = AppendNode(doc, fault, "GroundResistance"); + SetNodeValue(doc, groundResistance, data.groundResistance); + auto groundReactance = AppendNode(doc, fault, "GroundReactance"); + SetNodeValue(doc, groundReactance, data.groundReactance); + auto groundNeutral = AppendNode(doc, fault, "GroundNeutral"); + SetNodeValue(doc, groundNeutral, data.groundNeutral); + + auto stability = AppendNode(doc, electricalProp, "Stability"); + auto plotSyncMachine = AppendNode(doc, stability, "PlotSyncMachine"); + SetNodeValue(doc, plotSyncMachine, data.plotSyncMachine); + auto inertia = AppendNode(doc, stability, "Inertia"); + SetNodeValue(doc, inertia, data.inertia); + auto damping = AppendNode(doc, stability, "Damping"); + SetNodeValue(doc, damping, data.damping); + auto useAVR = AppendNode(doc, stability, "UseAVR"); + SetNodeValue(doc, useAVR, data.useAVR); + auto useSpeedGovernor = AppendNode(doc, stability, "UseSpeedGovernor"); + SetNodeValue(doc, useSpeedGovernor, data.useSpeedGovernor); + auto armResistance = AppendNode(doc, stability, "ArmResistance"); + SetNodeValue(doc, armResistance, data.armResistance); + auto potierReactance = AppendNode(doc, stability, "PotierReactance"); + SetNodeValue(doc, potierReactance, data.potierReactance); + auto satFactor = AppendNode(doc, stability, "SatFactor"); + SetNodeValue(doc, satFactor, data.satFactor); + auto syncXd = AppendNode(doc, stability, "SyncXd"); + SetNodeValue(doc, syncXd, data.syncXd); + auto syncXq = AppendNode(doc, stability, "SyncXq"); + SetNodeValue(doc, syncXq, data.syncXq); + auto transXd = AppendNode(doc, stability, "TransXd"); + SetNodeValue(doc, transXd, data.transXd); + auto transXq = AppendNode(doc, stability, "TransXq"); + SetNodeValue(doc, transXq, data.transXq); + auto transTd0 = AppendNode(doc, stability, "TransTd0"); + SetNodeValue(doc, transTd0, data.transTd0); + auto transTq0 = AppendNode(doc, stability, "TransTq0"); + SetNodeValue(doc, transTq0, data.transTq0); + auto subXd = AppendNode(doc, stability, "SubXd"); + SetNodeValue(doc, subXd, data.subXd); + auto subXq = AppendNode(doc, stability, "SubXq"); + SetNodeValue(doc, subXq, data.subXq); + auto subTd0 = AppendNode(doc, stability, "SubTd0"); + SetNodeValue(doc, subTd0, data.subTd0); + auto subTq0 = AppendNode(doc, stability, "SubTq0"); + SetNodeValue(doc, subTq0, data.subTq0); + + auto switchingList = AppendNode(doc, electricalProp, "SwitchingList"); + SwitchingData swData = syncGenerator->GetSwitchingData(); + for(int j = 0; j < (int)swData.swType.size(); j++) { + auto switching = AppendNode(doc, switchingList, "Switching"); + SetNodeAttribute(doc, switching, "ID", j); + auto swType = AppendNode(doc, switching, "Type"); + SetNodeValue(doc, swType, swData.swType[j]); + auto swTime = AppendNode(doc, switching, "Time"); + SetNodeValue(doc, swTime, swData.swTime[j]); + } + } //} + + //{ SyncMotor + auto syncMotorsNode = AppendNode(doc, elementsNode, "SyncMotorList"); + auto syncMotorList = allElements.GetSyncMotorList(); + for(int i = 0; i < (int)syncMotorList.size(); i++) { + SyncMotor* syncMotor = syncMotorList[i]; + auto syncMotorNode = AppendNode(doc, syncMotorsNode, "SyncMotor"); + SetNodeAttribute(doc, syncMotorNode, "ID", i); + auto cadProp = AppendNode(doc, syncMotorNode, "CADProperties"); + auto position = AppendNode(doc, cadProp, "Position"); + auto posX = AppendNode(doc, position, "X"); + SetNodeValue(doc, posX, syncMotor->GetPosition().m_x); + auto posY = AppendNode(doc, position, "Y"); + SetNodeValue(doc, posY, syncMotor->GetPosition().m_y); + auto size = AppendNode(doc, cadProp, "Size"); + auto width = AppendNode(doc, size, "Width"); + SetNodeValue(doc, width, syncMotor->GetWidth()); + auto height = AppendNode(doc, size, "Height"); + SetNodeValue(doc, height, syncMotor->GetHeight()); + auto angle = AppendNode(doc, cadProp, "Angle"); + SetNodeValue(doc, angle, syncMotor->GetAngle()); + auto nodePos = AppendNode(doc, cadProp, "NodePosition"); + auto nodePosX = AppendNode(doc, nodePos, "X"); + SetNodeValue(doc, nodePosX, syncMotor->GetPointList()[0].m_x); + auto nodePosY = AppendNode(doc, nodePos, "Y"); + SetNodeValue(doc, nodePosY, syncMotor->GetPointList()[0].m_y); + auto parentID = AppendNode(doc, cadProp, "ParentID"); + Bus* parent = (Bus*)syncMotor->GetParentList()[0]; + if(parent) SetNodeValue(doc, parentID, parent->GetEletricalData().number); + + SyncMotorElectricalData data = syncMotor->GetElectricalData(); + auto electricalProp = AppendNode(doc, syncMotorNode, "ElectricalProperties"); + auto isOnline = AppendNode(doc, electricalProp, "IsOnline"); + SetNodeValue(doc, isOnline, syncMotor->IsOnline()); + auto name = AppendNode(doc, electricalProp, "Name"); + SetNodeValue(doc, name, data.name); + auto nominalPower = AppendNode(doc, electricalProp, "NominalPower"); + SetNodeValue(doc, nominalPower, data.nominalPower); + SetNodeAttribute(doc, nominalPower, "UnitID", data.nominalPowerUnit); + // auto nominalVoltage = AppendNode(doc, electricalProp, "NominalVoltage"); + // SetNodeValue(doc, nominalVoltage, data.nominalVoltage); + // SetNodeAttribute(doc, nominalVoltage, "UnitID", data.nominalVoltageUnit); + auto activePower = AppendNode(doc, electricalProp, "ActivePower"); + SetNodeValue(doc, activePower, data.activePower); + SetNodeAttribute(doc, activePower, "UnitID", data.activePowerUnit); + auto reactivePower = AppendNode(doc, electricalProp, "ReactivePower"); + SetNodeValue(doc, reactivePower, data.reactivePower); + SetNodeAttribute(doc, reactivePower, "UnitID", data.reactivePowerUnit); + auto haveMaxReactive = AppendNode(doc, electricalProp, "HaveMaxReactive"); + SetNodeValue(doc, haveMaxReactive, data.haveMaxReactive); + auto maxReactive = AppendNode(doc, electricalProp, "MaxReactive"); + SetNodeValue(doc, maxReactive, data.maxReactive); + SetNodeAttribute(doc, maxReactive, "UnitID", data.maxReactiveUnit); + auto haveMinReactive = AppendNode(doc, electricalProp, "HaveMinReactive"); + SetNodeValue(doc, haveMinReactive, data.haveMinReactive); + auto minReactive = AppendNode(doc, electricalProp, "MinReactive"); + SetNodeValue(doc, minReactive, data.minReactive); + SetNodeAttribute(doc, minReactive, "UnitID", data.minReactiveUnit); + auto useMachineBase = AppendNode(doc, electricalProp, "UseMachineBase"); + SetNodeValue(doc, useMachineBase, data.useMachineBase); + + auto fault = AppendNode(doc, electricalProp, "Fault"); + auto positiveResistance = AppendNode(doc, fault, "PositiveResistance"); + SetNodeValue(doc, positiveResistance, data.positiveResistance); + auto positiveReactance = AppendNode(doc, fault, "PositiveReactance"); + SetNodeValue(doc, positiveReactance, data.positiveReactance); + auto negativeResistance = AppendNode(doc, fault, "NegativeResistance"); + SetNodeValue(doc, negativeResistance, data.negativeResistance); + auto negativeReactance = AppendNode(doc, fault, "NegativeReactance"); + SetNodeValue(doc, negativeReactance, data.negativeReactance); + auto zeroResistance = AppendNode(doc, fault, "ZeroResistance"); + SetNodeValue(doc, zeroResistance, data.zeroResistance); + auto zeroReactance = AppendNode(doc, fault, "ZeroReactance"); + SetNodeValue(doc, zeroReactance, data.zeroReactance); + auto groundResistance = AppendNode(doc, fault, "GroundResistance"); + SetNodeValue(doc, groundResistance, data.groundResistance); + auto groundReactance = AppendNode(doc, fault, "GroundReactance"); + SetNodeValue(doc, groundReactance, data.groundReactance); + auto groundNeutral = AppendNode(doc, fault, "GroundNeutral"); + SetNodeValue(doc, groundNeutral, data.groundNeutral); + + // To future use... + /*auto stability = AppendNode(doc, electricalProp, "Stability"); + auto plotSyncMachine = AppendNode(doc, stability, "PlotSyncMotor"); + SetNodeValue(doc, plotSyncMachine, data.plotSyncMachine); + auto inertia = AppendNode(doc, stability, "Inertia"); + SetNodeValue(doc, inertia, data.inertia); + auto damping = AppendNode(doc, stability, "Damping"); + SetNodeValue(doc, damping, data.damping); + auto useAVR = AppendNode(doc, stability, "UseAVR"); + SetNodeValue(doc, useAVR, data.useAVR); + auto armResistance = AppendNode(doc, stability, "ArmResistance"); + SetNodeValue(doc, armResistance, data.armResistance); + auto potierReactance = AppendNode(doc, stability, "PotierReactance"); + SetNodeValue(doc, potierReactance, data.potierReactance); + auto satFactor = AppendNode(doc, stability, "SatFactor"); + SetNodeValue(doc, satFactor, data.satFactor); + auto syncXd = AppendNode(doc, stability, "SyncXd"); + SetNodeValue(doc, syncXd, data.syncXd); + auto syncXq = AppendNode(doc, stability, "SyncXq"); + SetNodeValue(doc, syncXq, data.syncXq); + auto transXd = AppendNode(doc, stability, "TransXd"); + SetNodeValue(doc, transXd, data.transXd); + auto transXq = AppendNode(doc, stability, "TransXq"); + SetNodeValue(doc, transXq, data.transXq); + auto transTd0 = AppendNode(doc, stability, "TransTd0"); + SetNodeValue(doc, transTd0, data.transTd0); + auto transTq0 = AppendNode(doc, stability, "TransTq0"); + SetNodeValue(doc, transTq0, data.transTq0); + auto subXd = AppendNode(doc, stability, "SubXd"); + SetNodeValue(doc, subXd, data.subXd); + auto subXq = AppendNode(doc, stability, "SubXq"); + SetNodeValue(doc, subXq, data.subXq); + auto subTd0 = AppendNode(doc, stability, "SubTd0"); + SetNodeValue(doc, subTd0, data.subTd0); + auto subTq0 = AppendNode(doc, stability, "SubTq0"); + SetNodeValue(doc, subTq0, data.subTq0); + + auto switchingList = AppendNode(doc, electricalProp, "SwitchingList"); + SwitchingData swData = syncGenerator->GetSwitchingData(); + for(int j = 0; j < (int)swData.swType.size(); j++) { + auto switching = AppendNode(doc, switchingList, "Switching"); + SetNodeAttribute(doc, switching, "ID", j); + auto swType = AppendNode(doc, switching, "Type"); + SetNodeValue(doc, swType, swData.swType[j]); + auto swTime = AppendNode(doc, switching, "Time"); + SetNodeValue(doc, swTime, swData.swTime[j]); + }*/ + } //} + + //{ Transfomer + auto transformersNode = AppendNode(doc, elementsNode, "TransformerList"); + auto transformerList = allElements.GetTransformerList(); + for(int i = 0; i < (int)transformerList.size(); i++) { + Transformer* transfomer = transformerList[i]; + auto transformerNode = AppendNode(doc, transformersNode, "Transfomer"); + SetNodeAttribute(doc, transformerNode, "ID", i); + auto cadProp = AppendNode(doc, transformerNode, "CADProperties"); + auto position = AppendNode(doc, cadProp, "Position"); + auto posX = AppendNode(doc, position, "X"); + SetNodeValue(doc, posX, transfomer->GetPosition().m_x); + auto posY = AppendNode(doc, position, "Y"); + SetNodeValue(doc, posY, transfomer->GetPosition().m_y); + auto size = AppendNode(doc, cadProp, "Size"); + auto width = AppendNode(doc, size, "Width"); + SetNodeValue(doc, width, transfomer->GetWidth()); + auto height = AppendNode(doc, size, "Height"); + SetNodeValue(doc, height, transfomer->GetHeight()); + auto angle = AppendNode(doc, cadProp, "Angle"); + SetNodeValue(doc, angle, transfomer->GetAngle()); + auto nodeList = AppendNode(doc, cadProp, "NodeList"); + auto nodePos1 = AppendNode(doc, nodeList, "Node"); + SetNodeAttribute(doc, nodePos1, "ID", 0); + auto nodePosX1 = AppendNode(doc, nodePos1, "X"); + SetNodeValue(doc, nodePosX1, transfomer->GetPointList()[0].m_x); + auto nodePosY1 = AppendNode(doc, nodePos1, "Y"); + SetNodeValue(doc, nodePosY1, transfomer->GetPointList()[0].m_y); + auto nodePos2 = AppendNode(doc, nodeList, "Node"); + SetNodeAttribute(doc, nodePos2, "ID", 1); + auto nodePosX2 = AppendNode(doc, nodePos2, "X"); + SetNodeValue(doc, nodePosX2, transfomer->GetPointList()[transfomer->GetPointList().size() - 1].m_x); + auto nodePosY2 = AppendNode(doc, nodePos2, "Y"); + SetNodeValue(doc, nodePosY2, transfomer->GetPointList()[transfomer->GetPointList().size() - 1].m_y); + + auto parentIDList = AppendNode(doc, cadProp, "ParentIDList"); + for(int j = 0; j < (int)transfomer->GetParentList().size(); j++) { + Bus* parent = (Bus*)transfomer->GetParentList()[j]; + if(parent) { + auto parentID = AppendNode(doc, parentIDList, "ParentID"); + SetNodeAttribute(doc, parentID, "ID", j); + SetNodeValue(doc, parentID, parent->GetEletricalData().number); + } + } + + TransformerElectricalData data = transfomer->GetElectricalData(); + auto electricalProp = AppendNode(doc, transformerNode, "ElectricalProperties"); + auto isOnline = AppendNode(doc, electricalProp, "IsOnline"); + SetNodeValue(doc, isOnline, transfomer->IsOnline()); + auto name = AppendNode(doc, electricalProp, "Name"); + SetNodeValue(doc, name, data.name); + auto primaryNominalVoltage = AppendNode(doc, electricalProp, "PrimaryNominalVoltage"); + SetNodeValue(doc, primaryNominalVoltage, data.primaryNominalVoltage); + SetNodeAttribute(doc, primaryNominalVoltage, "UnitID", data.primaryNominalVoltageUnit); + auto secondaryNominalVoltage = AppendNode(doc, electricalProp, "SecondaryNominalVoltage"); + SetNodeValue(doc, secondaryNominalVoltage, data.secondaryNominalVoltage); + SetNodeAttribute(doc, secondaryNominalVoltage, "UnitID", data.secondaryNominalVoltageUnit); + auto nominalPower = AppendNode(doc, electricalProp, "NominalPower"); + SetNodeValue(doc, nominalPower, data.nominalPower); + SetNodeAttribute(doc, nominalPower, "UnitID", data.nominalPowerUnit); + auto resistance = AppendNode(doc, electricalProp, "Resistance"); + SetNodeValue(doc, resistance, data.resistance); + SetNodeAttribute(doc, resistance, "UnitID", data.resistanceUnit); + auto indReactance = AppendNode(doc, electricalProp, "IndReactance"); + SetNodeValue(doc, indReactance, data.indReactance); + SetNodeAttribute(doc, indReactance, "UnitID", data.indReactanceUnit); + auto connection = AppendNode(doc, electricalProp, "Connection"); + SetNodeValue(doc, connection, data.connection); + auto turnsRatio = AppendNode(doc, electricalProp, "TurnsRatio"); + SetNodeValue(doc, turnsRatio, data.turnsRatio); + auto phaseShift = AppendNode(doc, electricalProp, "PhaseShift"); + SetNodeValue(doc, phaseShift, data.phaseShift); + auto useTransformerPower = AppendNode(doc, electricalProp, "UseTransfomerPower"); + SetNodeValue(doc, useTransformerPower, data.useTransformerPower); + + auto fault = AppendNode(doc, electricalProp, "Fault"); + auto zeroResistance = AppendNode(doc, fault, "ZeroResistance"); + SetNodeValue(doc, zeroResistance, data.zeroResistance); + auto zeroIndReactance = AppendNode(doc, fault, "ZeroIndReactance"); + SetNodeValue(doc, zeroIndReactance, data.zeroIndReactance); + auto primaryGrndResistance = AppendNode(doc, fault, "PrimaryGrndResistance"); + SetNodeValue(doc, primaryGrndResistance, data.primaryGrndResistance); + auto primaryGrndReactance = AppendNode(doc, fault, "PrimaryGrndReactance"); + SetNodeValue(doc, primaryGrndReactance, data.primaryGrndReactance); + auto secondaryGrndResistance = AppendNode(doc, fault, "SecondaryGrndResistance"); + SetNodeValue(doc, secondaryGrndResistance, data.secondaryGrndResistance); + auto secondaryGrndReactance = AppendNode(doc, fault, "SecondaryGrndReactance"); + SetNodeValue(doc, secondaryGrndReactance, data.secondaryGrndReactance); + + auto switchingList = AppendNode(doc, electricalProp, "SwitchingList"); + SwitchingData swData = transfomer->GetSwitchingData(); + for(int j = 0; j < (int)swData.swType.size(); j++) { + auto switching = AppendNode(doc, switchingList, "Switching"); + SetNodeAttribute(doc, switching, "ID", j); + auto swType = AppendNode(doc, switching, "Type"); + SetNodeValue(doc, swType, swData.swType[j]); + auto swTime = AppendNode(doc, switching, "Time"); + SetNodeValue(doc, swTime, swData.swTime[j]); + } + } //} + + //{ Text + auto textsNode = AppendNode(doc, elementsNode, "TextList"); + auto textList = m_workspace->GetTextList(); + for(int i = 0; i < (int)textList.size(); i++) { + Text* text = textList[i]; + auto textNode = AppendNode(doc, textsNode, "Text"); + SetNodeAttribute(doc, textNode, "ID", i); + auto cadProp = AppendNode(doc, textNode, "CADProperties"); + auto position = AppendNode(doc, cadProp, "Position"); + auto posX = AppendNode(doc, position, "X"); + SetNodeValue(doc, posX, text->GetPosition().m_x); + auto posY = AppendNode(doc, position, "Y"); + SetNodeValue(doc, posY, text->GetPosition().m_y); + auto size = AppendNode(doc, cadProp, "Size"); + auto width = AppendNode(doc, size, "Width"); + SetNodeValue(doc, width, text->GetWidth()); + auto height = AppendNode(doc, size, "Height"); + SetNodeValue(doc, height, text->GetHeight()); + auto angle = AppendNode(doc, cadProp, "Angle"); + SetNodeValue(doc, angle, text->GetAngle()); + auto textProperties = AppendNode(doc, textNode, "TextProperties"); + auto elementType = AppendNode(doc, textProperties, "ElementType"); + SetNodeValue(doc, elementType, text->GetElementType()); + auto elementNumber = AppendNode(doc, textProperties, "ElementNumber"); + SetNodeValue(doc, elementNumber, text->GetElementNumber()); + auto dataType = AppendNode(doc, textProperties, "DataType"); + SetNodeValue(doc, dataType, text->GetDataType()); + auto dataUnit = AppendNode(doc, textProperties, "DataUnit"); + SetNodeValue(doc, dataUnit, text->GetUnit()); + auto direction = AppendNode(doc, textProperties, "Direction"); + SetNodeValue(doc, direction, text->GetDirection()); + auto decimalPlaces = AppendNode(doc, textProperties, "DecimalPlaces"); + SetNodeValue(doc, decimalPlaces, text->GetDecimalPlaces()); + } + //} + + std::ofstream writeXML(path.GetFullPath()); + writeXML << doc; + writeXML.close(); +} + +bool FileHanding::OpenProject(wxFileName path) +{ + rapidxml::xml_document<> doc; + rapidxml::file<> xmlFile(path.GetFullPath()); + + doc.parse<0>(xmlFile.data()); + + auto projectNode = doc.first_node("Project"); + if(!projectNode) return false; + auto nameNode = projectNode->first_node("Name"); + if(!nameNode) return false; + m_workspace->SetName(nameNode->value()); + + // Open elements + auto elementsNode = projectNode->first_node("Elements"); + if(!elementsNode) return false; + std::vector<Element*> elementList; + // Save lists individually to get parents + std::vector<Bus*> busList; + std::vector<Capacitor*> capacitorList; + std::vector<IndMotor*> indMotorList; + std::vector<Inductor*> inductorList; + std::vector<Line*> lineList; + std::vector<Load*> loadList; + std::vector<SyncGenerator*> syncGeneratorList; + std::vector<SyncMotor*> syncMotorList; + std::vector<Transformer*> transformerList; + std::vector<Text*> textList; + + //{ Bus + auto busListNode = elementsNode->first_node("BusList"); + if(!busListNode) return false; + auto busNode = busListNode->first_node("Bus"); + while(busNode) { + auto cadPropNode = busNode->first_node("CADProperties"); + if(!cadPropNode) return false; + + auto position = cadPropNode->first_node("Position"); + double posX = GetNodeValueDouble(position, "X"); + double posY = GetNodeValueDouble(position, "Y"); + Bus* bus = new Bus(wxPoint2DDouble(posX, posY)); + + auto size = cadPropNode->first_node("Size"); + double width = GetNodeValueDouble(size, "Width"); + double height = GetNodeValueDouble(size, "Height"); + double angle = GetNodeValueDouble(cadPropNode, "Angle"); + bus->SetWidth(width); + bus->SetHeight(height); + bus->SetPosition(bus->GetPosition()); // Update bus rectangle. + int numRot = angle / bus->GetRotationAngle(); + bool clockwise = true; + if(numRot < 0) { + numRot = std::abs(numRot); + clockwise = false; + } + for(int i = 0; i < numRot; i++) bus->Rotate(clockwise); + + BusElectricalData data = bus->GetEletricalData(); + auto electricalProp = busNode->first_node("ElectricalProperties"); + if(!electricalProp) return false; + + data.name = electricalProp->first_node("Name")->value(); + data.nominalVoltage = GetNodeValueDouble(electricalProp, "NominalVoltage"); + data.nominalVoltageUnit = (ElectricalUnit)GetAttributeValueInt(electricalProp, "NominalVoltage", "UnitID"); + data.isVoltageControlled = GetNodeValueInt(electricalProp, "IsVoltageControlled"); + data.controlledVoltage = GetNodeValueDouble(electricalProp, "ControlledVoltage"); + data.controlledVoltageUnitChoice = GetAttributeValueInt(electricalProp, "ControlledVoltage", "Choice"); + data.slackBus = GetNodeValueInt(electricalProp, "SlackBus"); + auto fault = electricalProp->first_node("Fault"); + data.hasFault = GetNodeValueInt(fault, "HasFault"); + data.faultType = (FaultData)GetNodeValueInt(fault, "Type"); + data.faultLocation = (FaultData)GetNodeValueInt(fault, "Location"); + data.faultResistance = GetNodeValueDouble(fault, "Resistance"); + data.faultReactance = GetNodeValueDouble(fault, "Reactance"); + auto stability = electricalProp->first_node("Stability"); + data.plotBus = GetNodeValueInt(stability, "Plot"); + data.stabHasFault = GetNodeValueInt(stability, "HasFault"); + data.stabFaultTime = GetNodeValueDouble(stability, "FaultTime"); + data.stabFaultLength = GetNodeValueDouble(stability, "FaultLength"); + data.stabFaultResistance = GetNodeValueDouble(stability, "FaultResistance"); + data.stabFaultReactance = GetNodeValueDouble(stability, "FaultReactance"); + + bus->SetElectricalData(data); + elementList.push_back(bus); + busList.push_back(bus); + busNode = busNode->next_sibling("Bus"); + } //} + + //{ Capacitor + auto capacitorListNode = elementsNode->first_node("CapacitorList"); + if(!capacitorListNode) return false; + auto capacitorNode = capacitorListNode->first_node("Capacitor"); + while(capacitorNode) { + Capacitor* capacitor = new Capacitor(); + + auto cadPropNode = capacitorNode->first_node("CADProperties"); + if(!cadPropNode) return false; + + auto position = cadPropNode->first_node("Position"); + double posX = GetNodeValueDouble(position, "X"); + double posY = GetNodeValueDouble(position, "Y"); + auto size = cadPropNode->first_node("Size"); + double width = GetNodeValueDouble(size, "Width"); + double height = GetNodeValueDouble(size, "Height"); + double angle = GetNodeValueDouble(cadPropNode, "Angle"); + auto nodePosition = cadPropNode->first_node("NodePosition"); + double nodePosX = GetNodeValueDouble(nodePosition, "X"); + double nodePosY = GetNodeValueDouble(nodePosition, "Y"); + int parentID = GetNodeValueInt(cadPropNode, "ParentID"); + if(parentID == -1) { + //If the element has no parent, create a temporary one, remove and delete. + Bus* parent = new Bus(wxPoint2DDouble(nodePosX, nodePosY)); + capacitor->AddParent(parent, wxPoint2DDouble(nodePosX, nodePosY)); + capacitor->StartMove(capacitor->GetPosition()); + capacitor->Move(wxPoint2DDouble(posX, posY)); + capacitor->RemoveParent(parent); + delete parent; + } else { + Bus* parent = busList[parentID]; + capacitor->AddParent(parent, wxPoint2DDouble(nodePosX, nodePosY)); + capacitor->StartMove(capacitor->GetPosition()); + capacitor->Move(wxPoint2DDouble(posX, posY)); + } + capacitor->SetWidth(width); + capacitor->SetHeight(height); + + int numRot = angle / capacitor->GetRotationAngle(); + bool clockwise = true; + if(numRot < 0) { + numRot = std::abs(numRot); + clockwise = false; + } + for(int i = 0; i < numRot; i++) capacitor->Rotate(clockwise); + + auto electricalProp = capacitorNode->first_node("ElectricalProperties"); + if(!electricalProp) return false; + + capacitor->SetOnline(GetNodeValueInt(electricalProp, "IsOnline")); + CapacitorElectricalData data = capacitor->GetElectricalData(); + data.name = electricalProp->first_node("Name")->value(); + data.reactivePower = GetNodeValueDouble(electricalProp, "ReactivePower"); + data.reactivePowerUnit = (ElectricalUnit)GetAttributeValueInt(electricalProp, "ReactivePower", "UnitID"); + + SwitchingData swData; + auto switchingList = electricalProp->first_node("SwitchingList"); + if(!switchingList) return false; + auto swNode = switchingList->first_node("Switching"); + while(swNode) { + swData.swType.push_back((SwitchingType)GetNodeValueInt(swNode, "Type")); + swData.swTime.push_back(GetNodeValueDouble(swNode, "Time")); + swNode = swNode->next_sibling("Switching"); + } + capacitor->SetSwitchingData(swData); + + capacitor->SetElectricalData(data); + elementList.push_back(capacitor); + capacitorList.push_back(capacitor); + capacitorNode = capacitorNode->next_sibling("Capacitor"); + } //} + + //{ IndMotor + auto indMotorListNode = elementsNode->first_node("IndMotorList"); + if(!indMotorListNode) return false; + auto indMotorNode = indMotorListNode->first_node("IndMotor"); + while(indMotorNode) { + IndMotor* indMotor = new IndMotor(); + + auto cadPropNode = indMotorNode->first_node("CADProperties"); + if(!cadPropNode) return false; + + auto position = cadPropNode->first_node("Position"); + double posX = GetNodeValueDouble(position, "X"); + double posY = GetNodeValueDouble(position, "Y"); + auto size = cadPropNode->first_node("Size"); + double width = GetNodeValueDouble(size, "Width"); + double height = GetNodeValueDouble(size, "Height"); + double angle = GetNodeValueDouble(cadPropNode, "Angle"); + auto nodePosition = cadPropNode->first_node("NodePosition"); + double nodePosX = GetNodeValueDouble(nodePosition, "X"); + double nodePosY = GetNodeValueDouble(nodePosition, "Y"); + int parentID = GetNodeValueInt(cadPropNode, "ParentID"); + if(parentID == -1) { + //If the element has no parent, create a temporary one, remove and delete. + Bus* parent = new Bus(wxPoint2DDouble(nodePosX, nodePosY)); + indMotor->AddParent(parent, wxPoint2DDouble(nodePosX, nodePosY)); + indMotor->StartMove(indMotor->GetPosition()); + indMotor->Move(wxPoint2DDouble(posX, posY)); + indMotor->RemoveParent(parent); + delete parent; + } else { + Bus* parent = busList[parentID]; + indMotor->AddParent(parent, wxPoint2DDouble(nodePosX, nodePosY)); + indMotor->StartMove(indMotor->GetPosition()); + indMotor->Move(wxPoint2DDouble(posX, posY)); + } + indMotor->SetWidth(width); + indMotor->SetHeight(height); + + int numRot = angle / indMotor->GetRotationAngle(); + bool clockwise = true; + if(numRot < 0) { + numRot = std::abs(numRot); + clockwise = false; + } + for(int i = 0; i < numRot; i++) indMotor->Rotate(clockwise); + + auto electricalProp = indMotorNode->first_node("ElectricalProperties"); + if(!electricalProp) return false; + + indMotor->SetOnline(GetNodeValueInt(electricalProp, "IsOnline")); + IndMotorElectricalData data = indMotor->GetElectricalData(); + data.name = electricalProp->first_node("Name")->value(); + data.activePower = GetNodeValueDouble(electricalProp, "ActivePower"); + data.activePowerUnit = (ElectricalUnit)GetAttributeValueInt(electricalProp, "ActivePower", "UnitID"); + data.reactivePower = GetNodeValueDouble(electricalProp, "ReactivePower"); + data.reactivePowerUnit = (ElectricalUnit)GetAttributeValueInt(electricalProp, "ReactivePower", "UnitID"); + + indMotor->SetElectricalData(data); + elementList.push_back(indMotor); + indMotorList.push_back(indMotor); + indMotorNode = indMotorNode->next_sibling("IndMotor"); + } //} + + //{ Inductor + auto inductorListNode = elementsNode->first_node("InductorList"); + if(!inductorListNode) return false; + auto inductorNode = inductorListNode->first_node("Inductor"); + while(inductorNode) { + Inductor* inductor = new Inductor(); + + auto cadPropNode = inductorNode->first_node("CADProperties"); + if(!cadPropNode) return false; + + auto position = cadPropNode->first_node("Position"); + double posX = GetNodeValueDouble(position, "X"); + double posY = GetNodeValueDouble(position, "Y"); + auto size = cadPropNode->first_node("Size"); + double width = GetNodeValueDouble(size, "Width"); + double height = GetNodeValueDouble(size, "Height"); + double angle = GetNodeValueDouble(cadPropNode, "Angle"); + auto nodePosition = cadPropNode->first_node("NodePosition"); + double nodePosX = GetNodeValueDouble(nodePosition, "X"); + double nodePosY = GetNodeValueDouble(nodePosition, "Y"); + int parentID = GetNodeValueInt(cadPropNode, "ParentID"); + if(parentID == -1) { + //If the element has no parent, create a temporary one, remove and delete. + Bus* parent = new Bus(wxPoint2DDouble(nodePosX, nodePosY)); + inductor->AddParent(parent, wxPoint2DDouble(nodePosX, nodePosY)); + inductor->StartMove(inductor->GetPosition()); + inductor->Move(wxPoint2DDouble(posX, posY)); + inductor->RemoveParent(parent); + delete parent; + } else { + Bus* parent = busList[parentID]; + inductor->AddParent(parent, wxPoint2DDouble(nodePosX, nodePosY)); + inductor->StartMove(inductor->GetPosition()); + inductor->Move(wxPoint2DDouble(posX, posY)); + } + inductor->SetWidth(width); + inductor->SetHeight(height); + + int numRot = angle / inductor->GetRotationAngle(); + bool clockwise = true; + if(numRot < 0) { + numRot = std::abs(numRot); + clockwise = false; + } + for(int i = 0; i < numRot; i++) inductor->Rotate(clockwise); + + auto electricalProp = inductorNode->first_node("ElectricalProperties"); + if(!electricalProp) return false; + + inductor->SetOnline(GetNodeValueInt(electricalProp, "IsOnline")); + InductorElectricalData data = inductor->GetElectricalData(); + data.name = electricalProp->first_node("Name")->value(); + data.reactivePower = GetNodeValueDouble(electricalProp, "ReactivePower"); + data.reactivePowerUnit = (ElectricalUnit)GetAttributeValueInt(electricalProp, "ReactivePower", "UnitID"); + + SwitchingData swData; + auto switchingList = electricalProp->first_node("SwitchingList"); + if(!switchingList) return false; + auto swNode = switchingList->first_node("Switching"); + while(swNode) { + swData.swType.push_back((SwitchingType)GetNodeValueInt(swNode, "Type")); + swData.swTime.push_back(GetNodeValueDouble(swNode, "Time")); + swNode = swNode->next_sibling("Switching"); + } + inductor->SetSwitchingData(swData); + + inductor->SetElectricalData(data); + elementList.push_back(inductor); + inductorList.push_back(inductor); + inductorNode = inductorNode->next_sibling("Inductor"); + } //} + + //{ Line + auto lineListNode = elementsNode->first_node("LineList"); + if(!lineListNode) return false; + auto lineNode = lineListNode->first_node("Line"); + while(lineNode) { + Line* line = new Line(); + + auto cadPropNode = lineNode->first_node("CADProperties"); + if(!cadPropNode) return false; + + // Get nodes points + std::vector<wxPoint2DDouble> ptsList; + auto nodePosList = cadPropNode->first_node("NodeList"); + if(!nodePosList) return false; + auto nodePos = nodePosList->first_node("Node"); + while(nodePos) { + double nodePosX = GetNodeValueDouble(nodePos, "X"); + double nodePosY = GetNodeValueDouble(nodePos, "Y"); + ptsList.push_back(wxPoint2DDouble(nodePosX, nodePosY)); + nodePos = nodePos->next_sibling("Node"); + } + + // Get parents IDs + auto parentIDList = cadPropNode->first_node("ParentIDList"); + if(!parentIDList) return false; + auto parentNode = parentIDList->first_node("ParentID"); + long parentID[2] = {-1, -1}; + while(parentNode) { + long index = 0; + wxString(parentNode->first_attribute("ID")->value()).ToLong(&index); + wxString(parentNode->value()).ToCLong(&parentID[index]); + parentNode = parentNode->next_sibling("ParentID"); + } + + // Set parents (if have) + Bus* parent1, *parent2; + if(parentID[0] == -1) { + parent1 = new Bus(ptsList[0]); + line->AddParent(parent1, ptsList[0]); + } else { + parent1 = busList[parentID[0]]; + line->AddParent(parent1, ptsList[0]); + } + if(parentID[1] == -1) { + parent2 = new Bus(ptsList[ptsList.size() - 1]); + line->AddParent(parent2, ptsList[ptsList.size() - 1]); + } else { + parent2 = busList[parentID[1]]; + line->AddParent(parent2, ptsList[ptsList.size() - 1]); + } + + // Add the others nodes (if have) + std::vector<wxPoint2DDouble> midPts; + for(int i=1; i<(int)ptsList.size() - 1; i++) midPts.push_back(ptsList[i]); + std::vector<wxPoint2DDouble> edgesPts = line->GetPointList(); + edgesPts.insert(edgesPts.begin() + 2, midPts.begin(), midPts.end()); + line->SetPointList(edgesPts); + + if(parentID[0] == -1){ + line->RemoveParent(parent1); + delete parent1; + } + if(parentID[1] == -1){ + line->RemoveParent(parent2); + delete parent2; + } + + + auto electricalProp = lineNode->first_node("ElectricalProperties"); + if(!electricalProp) return false; + + line->SetOnline(GetNodeValueInt(electricalProp, "IsOnline")); + LineElectricalData data = line->GetElectricalData(); + data.name = electricalProp->first_node("Name")->value(); + data.nominalVoltage = GetNodeValueDouble(electricalProp, "NominalVoltage"); + data.nominalVoltageUnit = (ElectricalUnit)GetAttributeValueInt(electricalProp, "NominalVoltage", "UnitID"); + data.nominalPower = GetNodeValueDouble(electricalProp, "NominalPower"); + data.nominalPowerUnit = (ElectricalUnit)GetAttributeValueInt(electricalProp, "NominalPower", "UnitID"); + data.resistance = GetNodeValueDouble(electricalProp, "Resistance"); + data.resistanceUnit = (ElectricalUnit)GetAttributeValueInt(electricalProp, "Resistance", "UnitID"); + data.indReactance = GetNodeValueDouble(electricalProp, "IndReactance"); + data.indReactanceUnit = (ElectricalUnit)GetAttributeValueInt(electricalProp, "IndReactance", "UnitID"); + data.capSusceptance = GetNodeValueDouble(electricalProp, "CapSusceptance"); + data.capSusceptanceUnit = (ElectricalUnit)GetAttributeValueInt(electricalProp, "CapSusceptance", "UnitID"); + data.lineSize = GetNodeValueDouble(electricalProp, "LineSize"); + data.useLinePower = GetNodeValueInt(electricalProp, "UseLinePower"); + + auto fault = electricalProp->first_node("Fault"); + data.zeroResistance = GetNodeValueDouble(fault, "ZeroResistance"); + data.zeroIndReactance = GetNodeValueDouble(fault, "ZeroIndReactance"); + data.zeroCapSusceptance = GetNodeValueDouble(fault, "ZeroCapSusceptance"); + + SwitchingData swData; + auto switchingList = electricalProp->first_node("SwitchingList"); + if(!switchingList) return false; + auto swNode = switchingList->first_node("Switching"); + while(swNode) { + swData.swType.push_back((SwitchingType)GetNodeValueInt(swNode, "Type")); + swData.swTime.push_back(GetNodeValueDouble(swNode, "Time")); + swNode = swNode->next_sibling("Switching"); + } + line->SetSwitchingData(swData); + + line->SetElectricalData(data); + elementList.push_back(line); + lineList.push_back(line); + lineNode = lineNode->next_sibling("Line"); + } //} + + //{ Load + auto loadListNode = elementsNode->first_node("LoadList"); + if(!loadListNode) return false; + auto loadNode = loadListNode->first_node("Load"); + while(loadNode) { + Load* load = new Load(); + + auto cadPropNode = loadNode->first_node("CADProperties"); + if(!cadPropNode) return false; + + auto position = cadPropNode->first_node("Position"); + double posX = GetNodeValueDouble(position, "X"); + double posY = GetNodeValueDouble(position, "Y"); + auto size = cadPropNode->first_node("Size"); + double width = GetNodeValueDouble(size, "Width"); + double height = GetNodeValueDouble(size, "Height"); + double angle = GetNodeValueDouble(cadPropNode, "Angle"); + auto nodePosition = cadPropNode->first_node("NodePosition"); + double nodePosX = GetNodeValueDouble(nodePosition, "X"); + double nodePosY = GetNodeValueDouble(nodePosition, "Y"); + int parentID = GetNodeValueInt(cadPropNode, "ParentID"); + if(parentID == -1) { + //If the element has no parent, create a temporary one, remove and delete. + Bus* parent = new Bus(wxPoint2DDouble(nodePosX, nodePosY)); + load->AddParent(parent, wxPoint2DDouble(nodePosX, nodePosY)); + load->StartMove(load->GetPosition()); + load->Move(wxPoint2DDouble(posX, posY)); + load->RemoveParent(parent); + delete parent; + } else { + Bus* parent = busList[parentID]; + load->AddParent(parent, wxPoint2DDouble(nodePosX, nodePosY)); + load->StartMove(load->GetPosition()); + load->Move(wxPoint2DDouble(posX, posY)); + } + load->SetWidth(width); + load->SetHeight(height); + + int numRot = angle / load->GetRotationAngle(); + bool clockwise = true; + if(numRot < 0) { + numRot = std::abs(numRot); + clockwise = false; + } + for(int i = 0; i < numRot; i++) load->Rotate(clockwise); + + auto electricalProp = loadNode->first_node("ElectricalProperties"); + if(!electricalProp) return false; + + load->SetOnline(GetNodeValueInt(electricalProp, "IsOnline")); + LoadElectricalData data = load->GetElectricalData(); + data.name = electricalProp->first_node("Name")->value(); + data.activePower = GetNodeValueDouble(electricalProp, "ActivePower"); + data.activePowerUnit = (ElectricalUnit)GetAttributeValueInt(electricalProp, "ActivePower", "UnitID"); + data.reactivePower = GetNodeValueDouble(electricalProp, "ReactivePower"); + data.reactivePowerUnit = (ElectricalUnit)GetAttributeValueInt(electricalProp, "ReactivePower", "UnitID"); + data.loadType = (LoadType)GetNodeValueInt(electricalProp, "LoadType"); + + SwitchingData swData; + auto switchingList = electricalProp->first_node("SwitchingList"); + if(!switchingList) return false; + auto swNode = switchingList->first_node("Switching"); + while(swNode) { + swData.swType.push_back((SwitchingType)GetNodeValueInt(swNode, "Type")); + swData.swTime.push_back(GetNodeValueDouble(swNode, "Time")); + swNode = swNode->next_sibling("Switching"); + } + load->SetSwitchingData(swData); + + load->SetElectricalData(data); + elementList.push_back(load); + loadList.push_back(load); + loadNode = loadNode->next_sibling("Load"); + } //} + + //{ SyncGenerator + auto syncGeneratorListNode = elementsNode->first_node("SyncGeneratorList"); + if(!syncGeneratorListNode) return false; + auto syncGeneratorNode = syncGeneratorListNode->first_node("SyncGenerator"); + while(syncGeneratorNode) { + SyncGenerator* syncGenerator = new SyncGenerator(); + + auto cadPropNode = syncGeneratorNode->first_node("CADProperties"); + if(!cadPropNode) return false; + + auto position = cadPropNode->first_node("Position"); + double posX = GetNodeValueDouble(position, "X"); + double posY = GetNodeValueDouble(position, "Y"); + auto size = cadPropNode->first_node("Size"); + double width = GetNodeValueDouble(size, "Width"); + double height = GetNodeValueDouble(size, "Height"); + double angle = GetNodeValueDouble(cadPropNode, "Angle"); + auto nodePosition = cadPropNode->first_node("NodePosition"); + double nodePosX = GetNodeValueDouble(nodePosition, "X"); + double nodePosY = GetNodeValueDouble(nodePosition, "Y"); + int parentID = GetNodeValueInt(cadPropNode, "ParentID"); + if(parentID == -1) { + //If the element has no parent, create a temporary one, remove and delete. + Bus* parent = new Bus(wxPoint2DDouble(nodePosX, nodePosY)); + syncGenerator->AddParent(parent, wxPoint2DDouble(nodePosX, nodePosY)); + syncGenerator->StartMove(syncGenerator->GetPosition()); + syncGenerator->Move(wxPoint2DDouble(posX, posY)); + syncGenerator->RemoveParent(parent); + delete parent; + } else { + Bus* parent = busList[parentID]; + syncGenerator->AddParent(parent, wxPoint2DDouble(nodePosX, nodePosY)); + syncGenerator->StartMove(syncGenerator->GetPosition()); + syncGenerator->Move(wxPoint2DDouble(posX, posY)); + } + syncGenerator->SetWidth(width); + syncGenerator->SetHeight(height); + + int numRot = angle / syncGenerator->GetRotationAngle(); + bool clockwise = true; + if(numRot < 0) { + numRot = std::abs(numRot); + clockwise = false; + } + for(int i = 0; i < numRot; i++) syncGenerator->Rotate(clockwise); + + auto electricalProp = syncGeneratorNode->first_node("ElectricalProperties"); + if(!electricalProp) return false; + + syncGenerator->SetOnline(GetNodeValueInt(electricalProp, "IsOnline")); + SyncGeneratorElectricalData data = syncGenerator->GetElectricalData(); + data.name = electricalProp->first_node("Name")->value(); + data.nominalPower = GetNodeValueDouble(electricalProp, "NominalPower"); + data.nominalPowerUnit = (ElectricalUnit)GetAttributeValueInt(electricalProp, "NominalPower", "UnitID"); + data.nominalVoltage = GetNodeValueDouble(electricalProp, "NominalVoltage"); + data.nominalVoltageUnit = (ElectricalUnit)GetAttributeValueInt(electricalProp, "NominalVoltage", "UnitID"); + data.activePower = GetNodeValueDouble(electricalProp, "ActivePower"); + data.activePowerUnit = (ElectricalUnit)GetAttributeValueInt(electricalProp, "ActivePower", "UnitID"); + data.reactivePower = GetNodeValueDouble(electricalProp, "ReactivePower"); + data.reactivePowerUnit = (ElectricalUnit)GetAttributeValueInt(electricalProp, "ReactivePower", "UnitID"); + data.haveMaxReactive = GetNodeValueInt(electricalProp, "HaveMaxReactive"); + data.maxReactive = GetNodeValueDouble(electricalProp, "MaxReactive"); + data.maxReactiveUnit = (ElectricalUnit)GetAttributeValueInt(electricalProp, "MaxReactive", "UnitID"); + data.haveMinReactive = GetNodeValueInt(electricalProp, "HaveMinReactive"); + data.minReactive = GetNodeValueDouble(electricalProp, "MinReactive"); + data.minReactiveUnit = (ElectricalUnit)GetAttributeValueInt(electricalProp, "MinReactive", "UnitID"); + data.useMachineBase = GetNodeValueInt(electricalProp, "UseMachineBase"); + + auto fault = electricalProp->first_node("Fault"); + if(!fault) return false; + data.positiveResistance = GetNodeValueDouble(fault, "PositiveResistance"); + data.positiveReactance = GetNodeValueDouble(fault, "PositiveReactance"); + data.negativeResistance = GetNodeValueDouble(fault, "NegativeResistance"); + data.negativeReactance = GetNodeValueDouble(fault, "NegativeReactance"); + data.zeroResistance = GetNodeValueDouble(fault, "ZeroResistance"); + data.zeroReactance = GetNodeValueDouble(fault, "ZeroReactance"); + data.groundResistance = GetNodeValueDouble(fault, "GroundResistance"); + data.groundReactance = GetNodeValueDouble(fault, "GroundReactance"); + data.groundNeutral = GetNodeValueInt(fault, "GroundNeutral"); + + auto stability = electricalProp->first_node("Stability"); + if(!stability) return false; + data.plotSyncMachine = GetNodeValueInt(stability, "PlotSyncMachine"); + data.inertia = GetNodeValueDouble(stability, "Inertia"); + data.damping = GetNodeValueDouble(stability, "Damping"); + data.useAVR = GetNodeValueInt(stability, "UseAVR"); + data.useSpeedGovernor = GetNodeValueInt(stability, "UseSpeedGovernor"); + data.armResistance = GetNodeValueDouble(stability, "ArmResistance"); + data.potierReactance = GetNodeValueDouble(stability, "PotierReactance"); + data.satFactor = GetNodeValueDouble(stability, "SatFactor"); + data.syncXd = GetNodeValueDouble(stability, "SyncXd"); + data.syncXq = GetNodeValueDouble(stability, "SyncXq"); + data.transXd = GetNodeValueDouble(stability, "TransXd"); + data.transXq = GetNodeValueDouble(stability, "TransXq"); + data.transTd0 = GetNodeValueDouble(stability, "TransTd0"); + data.transTq0 = GetNodeValueDouble(stability, "TransTq0"); + data.subXd = GetNodeValueDouble(stability, "SubXd"); + data.subXq = GetNodeValueDouble(stability, "SubXq"); + data.subTd0 = GetNodeValueDouble(stability, "SubTd0"); + data.subTq0 = GetNodeValueDouble(stability, "SubTq0"); + + SwitchingData swData; + auto switchingList = electricalProp->first_node("SwitchingList"); + if(!switchingList) return false; + auto swNode = switchingList->first_node("Switching"); + while(swNode) { + swData.swType.push_back((SwitchingType)GetNodeValueInt(swNode, "Type")); + swData.swTime.push_back(GetNodeValueDouble(swNode, "Time")); + swNode = swNode->next_sibling("Switching"); + } + syncGenerator->SetSwitchingData(swData); + + syncGenerator->SetElectricalData(data); + elementList.push_back(syncGenerator); + syncGeneratorList.push_back(syncGenerator); + syncGeneratorNode = syncGeneratorNode->next_sibling("SyncGenerator"); + } //} + + //{ SyncMotor + auto syncMotorListNode = elementsNode->first_node("SyncMotorList"); + if(!syncMotorListNode) return false; + auto syncMotorNode = syncMotorListNode->first_node("SyncMotor"); + while(syncMotorNode) { + SyncMotor* syncMotor = new SyncMotor(); + + auto cadPropNode = syncMotorNode->first_node("CADProperties"); + if(!cadPropNode) return false; + + auto position = cadPropNode->first_node("Position"); + double posX = GetNodeValueDouble(position, "X"); + double posY = GetNodeValueDouble(position, "Y"); + auto size = cadPropNode->first_node("Size"); + double width = GetNodeValueDouble(size, "Width"); + double height = GetNodeValueDouble(size, "Height"); + double angle = GetNodeValueDouble(cadPropNode, "Angle"); + auto nodePosition = cadPropNode->first_node("NodePosition"); + double nodePosX = GetNodeValueDouble(nodePosition, "X"); + double nodePosY = GetNodeValueDouble(nodePosition, "Y"); + int parentID = GetNodeValueInt(cadPropNode, "ParentID"); + if(parentID == -1) { + //If the element has no parent, create a temporary one, remove and delete. + Bus* parent = new Bus(wxPoint2DDouble(nodePosX, nodePosY)); + syncMotor->AddParent(parent, wxPoint2DDouble(nodePosX, nodePosY)); + syncMotor->StartMove(syncMotor->GetPosition()); + syncMotor->Move(wxPoint2DDouble(posX, posY)); + syncMotor->RemoveParent(parent); + delete parent; + } else { + Bus* parent = busList[parentID]; + syncMotor->AddParent(parent, wxPoint2DDouble(nodePosX, nodePosY)); + syncMotor->StartMove(syncMotor->GetPosition()); + syncMotor->Move(wxPoint2DDouble(posX, posY)); + } + syncMotor->SetWidth(width); + syncMotor->SetHeight(height); + + int numRot = angle / syncMotor->GetRotationAngle(); + bool clockwise = true; + if(numRot < 0) { + numRot = std::abs(numRot); + clockwise = false; + } + for(int i = 0; i < numRot; i++) syncMotor->Rotate(clockwise); + + auto electricalProp = syncMotorNode->first_node("ElectricalProperties"); + if(!electricalProp) return false; + + syncMotor->SetOnline(GetNodeValueInt(electricalProp, "IsOnline")); + SyncMotorElectricalData data = syncMotor->GetElectricalData(); + data.name = electricalProp->first_node("Name")->value(); + data.nominalPower = GetNodeValueDouble(electricalProp, "NominalPower"); + data.nominalPowerUnit = (ElectricalUnit)GetAttributeValueInt(electricalProp, "NominalPower", "UnitID"); + //data.nominalVoltage = GetNodeValueDouble(electricalProp, "NominalVoltage"); + //data.nominalVoltageUnit = (ElectricalUnit)GetAttributeValueInt(electricalProp, "NominalVoltage", "UnitID"); + data.activePower = GetNodeValueDouble(electricalProp, "ActivePower"); + data.activePowerUnit = (ElectricalUnit)GetAttributeValueInt(electricalProp, "ActivePower", "UnitID"); + data.reactivePower = GetNodeValueDouble(electricalProp, "ReactivePower"); + data.reactivePowerUnit = (ElectricalUnit)GetAttributeValueInt(electricalProp, "ReactivePower", "UnitID"); + data.haveMaxReactive = GetNodeValueInt(electricalProp, "HaveMaxReactive"); + data.maxReactive = GetNodeValueDouble(electricalProp, "MaxReactive"); + data.maxReactiveUnit = (ElectricalUnit)GetAttributeValueInt(electricalProp, "MaxReactive", "UnitID"); + data.haveMinReactive = GetNodeValueInt(electricalProp, "HaveMinReactive"); + data.minReactive = GetNodeValueDouble(electricalProp, "MinReactive"); + data.minReactiveUnit = (ElectricalUnit)GetAttributeValueInt(electricalProp, "MinReactive", "UnitID"); + data.useMachineBase = GetNodeValueInt(electricalProp, "UseMachineBase"); + + auto fault = electricalProp->first_node("Fault"); + if(!fault) return false; + data.positiveResistance = GetNodeValueDouble(fault, "PositiveResistance"); + data.positiveReactance = GetNodeValueDouble(fault, "PositiveReactance"); + data.negativeResistance = GetNodeValueDouble(fault, "NegativeResistance"); + data.negativeReactance = GetNodeValueDouble(fault, "NegativeReactance"); + data.zeroResistance = GetNodeValueDouble(fault, "ZeroResistance"); + data.zeroReactance = GetNodeValueDouble(fault, "ZeroReactance"); + data.groundResistance = GetNodeValueDouble(fault, "GroundResistance"); + data.groundReactance = GetNodeValueDouble(fault, "GroundReactance"); + data.groundNeutral = GetNodeValueInt(fault, "GroundNeutral"); + + /*SwitchingData swData; + auto switchingList = electricalProp->first_node("SwitchingList"); + if(!switchingList) return false; + auto swNode = switchingList->first_node("Switching"); + while(swNode) { + swData.swType.push_back((SwitchingType)GetNodeValueInt(swNode, "Type")); + swData.swTime.push_back(GetNodeValueDouble(swNode, "Time")); + swNode = swNode->next_sibling("Switching"); + } + syncMotor->SetSwitchingData(swData);*/ + + syncMotor->SetElectricalData(data); + elementList.push_back(syncMotor); + syncMotorList.push_back(syncMotor); + syncMotorNode = syncMotorNode->next_sibling("SyncMotor"); + } //} + + //{ Transformer + auto transformerListNode = elementsNode->first_node("TransformerList"); + if(!transformerListNode) return false; + auto transfomerNode = transformerListNode->first_node("Transfomer"); + while(transfomerNode) { + Transformer* transformer = new Transformer(); + + auto cadPropNode = transfomerNode->first_node("CADProperties"); + if(!cadPropNode) return false; + + auto position = cadPropNode->first_node("Position"); + double posX = GetNodeValueDouble(position, "X"); + double posY = GetNodeValueDouble(position, "Y"); + auto size = cadPropNode->first_node("Size"); + double width = GetNodeValueDouble(size, "Width"); + double height = GetNodeValueDouble(size, "Height"); + double angle = GetNodeValueDouble(cadPropNode, "Angle"); + + // Get nodes points + std::vector<wxPoint2DDouble> ptsList; + auto nodePosList = cadPropNode->first_node("NodeList"); + if(!nodePosList) return false; + auto nodePos = nodePosList->first_node("Node"); + while(nodePos) { + double nodePosX = GetNodeValueDouble(nodePos, "X"); + double nodePosY = GetNodeValueDouble(nodePos, "Y"); + ptsList.push_back(wxPoint2DDouble(nodePosX, nodePosY)); + nodePos = nodePos->next_sibling("Node"); + } + + // Get parents IDs + auto parentIDList = cadPropNode->first_node("ParentIDList"); + if(!parentIDList) return false; + auto parentNode = parentIDList->first_node("ParentID"); + long parentID[2] = {-1, -1}; + while(parentNode) { + long index = 0; + wxString(parentNode->first_attribute("ID")->value()).ToLong(&index); + wxString(parentNode->value()).ToCLong(&parentID[index]); + parentNode = parentNode->next_sibling("ParentID"); + } + + // Set parents (if have) + Bus* parent1, *parent2; + if(parentID[0] == -1) { + parent1 = new Bus(ptsList[0]); + transformer->AddParent(parent1, ptsList[0]); + } else { + parent1 = busList[parentID[0]]; + transformer->AddParent(parent1, ptsList[0]); + } + if(parentID[1] == -1) { + parent2 = new Bus(ptsList[ptsList.size() - 1]); + transformer->AddParent(parent2, ptsList[ptsList.size() - 1]); + } else { + parent2 = busList[parentID[1]]; + transformer->AddParent(parent2, ptsList[ptsList.size() - 1]); + } + + transformer->StartMove(transformer->GetPosition()); + transformer->Move(wxPoint2DDouble(posX, posY)); + + if(parentID[0] == -1){ + transformer->RemoveParent(parent1); + delete parent1; + } + if(parentID[1] == -1){ + transformer->RemoveParent(parent2); + delete parent2; + } + + transformer->SetWidth(width); + transformer->SetHeight(height); + + int numRot = angle / transformer->GetRotationAngle(); + bool clockwise = true; + if(numRot < 0) { + numRot = std::abs(numRot); + clockwise = false; + } + for(int i = 0; i < numRot; i++) transformer->Rotate(clockwise); + + auto electricalProp = transfomerNode->first_node("ElectricalProperties"); + if(!electricalProp) return false; + + transformer->SetOnline(GetNodeValueInt(electricalProp, "IsOnline")); + TransformerElectricalData data = transformer->GetElectricalData(); + data.name = electricalProp->first_node("Name")->value(); + data.primaryNominalVoltage = GetNodeValueDouble(electricalProp, "PrimaryNominalVoltage"); + data.primaryNominalVoltageUnit = (ElectricalUnit)GetAttributeValueInt(electricalProp, "PrimaryNominalVoltage", "UnitID"); + data.secondaryNominalVoltage = GetNodeValueDouble(electricalProp, "SecondaryNominalVoltage"); + data.secondaryNominalVoltageUnit = (ElectricalUnit)GetAttributeValueInt(electricalProp, "SecondaryNominalVoltage", "UnitID"); + data.nominalPower = GetNodeValueDouble(electricalProp, "NominalPower"); + data.nominalPowerUnit = (ElectricalUnit)GetAttributeValueInt(electricalProp, "NominalPower", "UnitID"); + data.resistance = GetNodeValueDouble(electricalProp, "Resistance"); + data.resistanceUnit = (ElectricalUnit)GetAttributeValueInt(electricalProp, "Resistance", "UnitID"); + data.indReactance = GetNodeValueDouble(electricalProp, "IndReactance"); + data.indReactanceUnit = (ElectricalUnit)GetAttributeValueInt(electricalProp, "IndReactance", "UnitID"); + data.connection = (TransformerConnection) GetNodeValueInt(electricalProp, "Connection"); + data.turnsRatio = GetNodeValueDouble(electricalProp, "TurnsRatio"); + data.phaseShift = GetNodeValueDouble(electricalProp, "PhaseShift"); + data.useTransformerPower = GetNodeValueInt(electricalProp, "UseTransfomerPower"); + + auto fault = electricalProp->first_node("Fault"); + data.zeroResistance = GetNodeValueDouble(fault, "ZeroResistance"); + data.zeroIndReactance = GetNodeValueDouble(fault, "ZeroIndReactance"); + data.primaryGrndResistance = GetNodeValueDouble(fault, "PrimaryGrndResistance"); + data.primaryGrndReactance = GetNodeValueDouble(fault, "PrimaryGrndReactance"); + data.secondaryGrndResistance = GetNodeValueDouble(fault, "SecondaryGrndResistance"); + data.secondaryGrndReactance = GetNodeValueDouble(fault, "SecondaryGrndReactance"); + + SwitchingData swData; + auto switchingList = electricalProp->first_node("SwitchingList"); + if(!switchingList) return false; + auto swNode = switchingList->first_node("Switching"); + while(swNode) { + swData.swType.push_back((SwitchingType)GetNodeValueInt(swNode, "Type")); + swData.swTime.push_back(GetNodeValueDouble(swNode, "Time")); + swNode = swNode->next_sibling("Switching"); + } + transformer->SetSwitchingData(swData); + + transformer->SetElectricaData(data); + elementList.push_back(transformer); + transformerList.push_back(transformer); + transfomerNode = transfomerNode->next_sibling("Transfomer"); + } //} + + //{ Text + auto textListNode = elementsNode->first_node("TextList"); + if(!textListNode) return false; + auto textNode = textListNode->first_node("Text"); + while(textNode) { + + auto cadPropNode = textNode->first_node("CADProperties"); + if(!cadPropNode) return false; + + auto position = cadPropNode->first_node("Position"); + double posX = GetNodeValueDouble(position, "X"); + double posY = GetNodeValueDouble(position, "Y"); + auto size = cadPropNode->first_node("Size"); + double width = GetNodeValueDouble(size, "Width"); + double height = GetNodeValueDouble(size, "Height"); + double angle = GetNodeValueDouble(cadPropNode, "Angle"); + + Text* text = new Text(wxPoint2DDouble(posX, posY)); + + text->SetWidth(width); + text->SetHeight(height); + + auto textProperties = textNode->first_node("TextProperties"); + if(!textProperties) return false; + text->SetElementType((ElementType)GetNodeValueDouble(textProperties, "ElementType")); + text->SetElementNumber(GetNodeValueInt(textProperties, "ElementNumber")); + switch(text->GetElementType()) { + case TYPE_NONE: break; + case TYPE_BUS: { + Bus* bus = busList[text->GetElementNumber()]; + text->SetElement(bus); + } break; + case TYPE_CAPACITOR: { + Capacitor* capacitor = capacitorList[text->GetElementNumber()]; + text->SetElement(capacitor); + } break; + case TYPE_IND_MOTOR: { + IndMotor* indMotor = indMotorList[text->GetElementNumber()]; + text->SetElement(indMotor); + } break; + case TYPE_INDUCTOR: { + Inductor* inductor = inductorList[text->GetElementNumber()]; + text->SetElement(inductor); + } break; + case TYPE_LINE: { + Line* line = lineList[text->GetElementNumber()]; + text->SetElement(line); + } break; + case TYPE_LOAD: { + Load* load = loadList[text->GetElementNumber()]; + text->SetElement(load); + } break; + case TYPE_SYNC_GENERATOR: { + SyncGenerator* syncGenerator = syncGeneratorList[text->GetElementNumber()]; + text->SetElement(syncGenerator); + } break; + case TYPE_SYNC_MOTOR: { + SyncMotor* syncMotor = syncMotorList[text->GetElementNumber()]; + text->SetElement(syncMotor); + } break; + case TYPE_TRANSFORMER: { + Transformer* transformer = transformerList[text->GetElementNumber()]; + text->SetElement(transformer); + } break; + } + text->SetDataType((DataType)GetNodeValueDouble(textProperties, "DataType")); + text->SetUnit((ElectricalUnit)GetNodeValueDouble(textProperties, "DataUnit")); + text->SetDirection(GetNodeValueDouble(textProperties, "Direction")); + text->SetDecimalPlaces(GetNodeValueDouble(textProperties, "DecimalPlaces")); + + int numRot = angle / text->GetRotationAngle(); + bool clockwise = true; + if(numRot < 0) { + numRot = std::abs(numRot); + clockwise = false; + } + for(int i = 0; i < numRot; i++) text->Rotate(clockwise); + + textList.push_back(text); + textNode = textNode->next_sibling("Text"); + } //} + + m_workspace->SetElementList(elementList); + m_workspace->SetTextList(textList); + m_workspace->UpdateTextElements(); + return true; +} + +rapidxml::xml_node<>* FileHanding::AppendNode(rapidxml::xml_document<>& doc, + rapidxml::xml_node<>* parentNode, + const char* name, + rapidxml::node_type nodeType) +{ + rapidxml::xml_node<>* node = doc.allocate_node(nodeType, name); + parentNode->append_node(node); + return node; +} + +void FileHanding::SetNodeValue(rapidxml::xml_document<>& doc, rapidxml::xml_node<>* node, wxString value) +{ + node->value(doc.allocate_string(value.mb_str())); +} + +void FileHanding::SetNodeValue(rapidxml::xml_document<>& doc, rapidxml::xml_node<>* node, int value) +{ + node->value(doc.allocate_string(wxString::Format("%d", value))); +} + +void FileHanding::SetNodeValue(rapidxml::xml_document<>& doc, rapidxml::xml_node<>* node, double value) +{ + node->value(doc.allocate_string(wxString::FromCDouble(value, 13).mb_str())); +} + +void FileHanding::SetNodeAttribute(rapidxml::xml_document<>& doc, + rapidxml::xml_node<>* node, + const char* atrName, + wxString value) +{ + node->append_attribute(doc.allocate_attribute(atrName, doc.allocate_string(value.mb_str()))); +} + +void FileHanding::SetNodeAttribute(rapidxml::xml_document<>& doc, + rapidxml::xml_node<>* node, + const char* atrName, + int value) +{ + node->append_attribute(doc.allocate_attribute(atrName, doc.allocate_string(wxString::Format("%d", value)))); +} + +void FileHanding::SetNodeAttribute(rapidxml::xml_document<>& doc, + rapidxml::xml_node<>* node, + const char* atrName, + double value) +{ + node->append_attribute( + doc.allocate_attribute(atrName, doc.allocate_string(wxString::FromCDouble(value, 13).mb_str()))); +} + +double FileHanding::GetNodeValueDouble(rapidxml::xml_node<>* parent, const char* nodeName) +{ + double dValue = 0.0; + if(parent) { + auto node = parent->first_node(nodeName); + if(node) wxString(node->value()).ToCDouble(&dValue); + } + return dValue; +} + +int FileHanding::GetNodeValueInt(rapidxml::xml_node<>* parent, const char* nodeName) +{ + long iValue = -1; + if(parent) { + auto node = parent->first_node(nodeName); + if(node) wxString(node->value()).ToCLong(&iValue); + } + return (int)iValue; +} + +int FileHanding::GetAttributeValueInt(rapidxml::xml_node<>* parent, const char* nodeName, const char* atrName) +{ + long iValue = -1; + if(parent) { + auto node = parent->first_node(nodeName); + if(node){ + auto atr = node->first_attribute(atrName); + if(atr) wxString(atr->value()).ToCLong(&iValue); + } + } + return (int)iValue; +} diff --git a/Project/FileHanding.h b/Project/FileHanding.h new file mode 100644 index 0000000..ba95177 --- /dev/null +++ b/Project/FileHanding.h @@ -0,0 +1,47 @@ +#ifndef FILEHANDING_H +#define FILEHANDING_H + +#include <wx/string.h> +#include <fstream> +#include <sstream> + +#include "Workspace.h" +#include "ElectricCalculation.h" +#include "Text.h" + +#include "rapidXML/rapidxml.hpp" +// Modified: http://stackoverflow.com/questions/14113923/rapidxml-print-header-has-undefined-methods +#include "rapidXML/rapidxml_print.hpp" +#include "rapidXML/rapidxml_utils.hpp" + +class FileHanding +{ +public: + FileHanding(); + FileHanding(Workspace* workspace); + ~FileHanding(); + + void SetWorkspace(Workspace* workspace) { m_workspace = workspace; } + + void SaveProject(wxFileName path); + bool OpenProject(wxFileName path); + +protected: + Workspace* m_workspace; + + rapidxml::xml_node<>* AppendNode(rapidxml::xml_document<>& doc, + rapidxml::xml_node<>* parentNode, + const char* name, + rapidxml::node_type nodeType = rapidxml::node_element); + void SetNodeValue(rapidxml::xml_document<>& doc, rapidxml::xml_node<>* node, wxString value); + void SetNodeValue(rapidxml::xml_document<>& doc, rapidxml::xml_node<>* node, int value); + void SetNodeValue(rapidxml::xml_document<>& doc, rapidxml::xml_node<>* node, double value); + void SetNodeAttribute(rapidxml::xml_document<>& doc, rapidxml::xml_node<>* node, const char* atrName, wxString value); + void SetNodeAttribute(rapidxml::xml_document<>& doc, rapidxml::xml_node<>* node, const char* atrName, int value); + void SetNodeAttribute(rapidxml::xml_document<>& doc, rapidxml::xml_node<>* node, const char* atrName, double value); + double GetNodeValueDouble(rapidxml::xml_node<>* parent, const char* nodeName); + int GetNodeValueInt(rapidxml::xml_node<>* parent, const char* nodeName); + int GetAttributeValueInt(rapidxml::xml_node<>* parent, const char* nodeName, const char* atrName); +}; + +#endif // FILEHANDING_H diff --git a/Project/Inductor.cpp b/Project/Inductor.cpp index 9c85d9a..9c13f15 100644 --- a/Project/Inductor.cpp +++ b/Project/Inductor.cpp @@ -89,6 +89,7 @@ void Inductor::Rotate(bool clockwise) if(!clockwise) rotAngle = -m_rotationAngle; m_angle += rotAngle; + if(m_angle >= 360 || m_angle <= -360) m_angle = 0.0; m_pointList[2] = RotateAtPosition(m_pointList[2], rotAngle); m_pointList[3] = RotateAtPosition(m_pointList[3], rotAngle); UpdateSwitchesPosition(); diff --git a/Project/Line.cpp b/Project/Line.cpp index ae5e0b3..836ca3c 100644 --- a/Project/Line.cpp +++ b/Project/Line.cpp @@ -480,3 +480,10 @@ void Line::RotateNode(Element* parent, bool clockwise) UpdateSwitchesPosition(); UpdatePowerFlowArrowsPosition(); } + +void Line::SetPointList(std::vector<wxPoint2DDouble> pointList) +{ + m_pointList = pointList; + UpdateSwitchesPosition(); + UpdatePowerFlowArrowsPosition(); +} diff --git a/Project/Line.h b/Project/Line.h index 012f68d..2a2902c 100644 --- a/Project/Line.h +++ b/Project/Line.h @@ -60,6 +60,7 @@ class Line : public Branch virtual LineElectricalData GetElectricalData() const { return m_electricaData; } virtual void SetElectricalData(LineElectricalData electricalData) { m_electricaData = electricalData; } virtual void SetNominalVoltage(std::vector<double> nominalVoltage, std::vector<ElectricalUnit> nominalVoltageUnit); + virtual void SetPointList(std::vector<wxPoint2DDouble> pointList); protected: double PointToLineDistance(wxPoint2DDouble point, int* segmentNumber = NULL) const; diff --git a/Project/Load.cpp b/Project/Load.cpp index e46b48b..9889215 100644 --- a/Project/Load.cpp +++ b/Project/Load.cpp @@ -97,6 +97,7 @@ void Load::Rotate(bool clockwise) if(!clockwise) rotAngle = -m_rotationAngle; m_angle += rotAngle; + if(m_angle >= 360 || m_angle <= -360) m_angle = 0.0; m_pointList[2] = RotateAtPosition(m_pointList[2], rotAngle); m_pointList[3] = RotateAtPosition(m_pointList[3], rotAngle); UpdateSwitchesPosition(); diff --git a/Project/Machines.cpp b/Project/Machines.cpp index f859831..c24deaf 100644 --- a/Project/Machines.cpp +++ b/Project/Machines.cpp @@ -1,95 +1,96 @@ #include "Machines.h" -Machines::Machines() : Element() {} +Machines::Machines() + : Element() +{ +} Machines::~Machines() {} bool Machines::AddParent(Element* parent, wxPoint2DDouble position) { if(parent) { - m_parentList.push_back(parent); - wxPoint2DDouble parentPt = - parent->RotateAtPosition(position, -parent->GetAngle()); // Rotate click to horizontal position. - parentPt.m_y = parent->GetPosition().m_y; // Centralize on bus. - parentPt = parent->RotateAtPosition(parentPt, parent->GetAngle()); // Rotate back. - - m_position = parentPt + wxPoint2DDouble(-100.0, 0.0); // Shifts the position to the left of the bus. - m_width = m_height = 50.0; - m_rect = wxRect2DDouble(m_position.m_x - 25.0, m_position.m_y - 25.0, m_width, m_height); - - m_pointList.push_back(parentPt); - m_pointList.push_back(GetSwitchPoint(parent, parentPt, m_position)); - m_pointList.push_back(m_position + wxPoint2DDouble(35.0, 0.0)); - m_pointList.push_back(m_position + wxPoint2DDouble(25.0, 0.0)); - m_inserted = true; - - wxRect2DDouble genRect(0,0,0,0); - m_switchRect.push_back(genRect); // Push a general rectangle. - UpdateSwitches(); + m_parentList.push_back(parent); + wxPoint2DDouble parentPt = + parent->RotateAtPosition(position, -parent->GetAngle()); // Rotate click to horizontal position. + parentPt.m_y = parent->GetPosition().m_y; // Centralize on bus. + parentPt = parent->RotateAtPosition(parentPt, parent->GetAngle()); // Rotate back. + + m_position = parentPt + wxPoint2DDouble(-100.0, 0.0); // Shifts the position to the left of the bus. + m_width = m_height = 50.0; + m_rect = wxRect2DDouble(m_position.m_x - 25.0, m_position.m_y - 25.0, m_width, m_height); + + m_pointList.push_back(parentPt); + m_pointList.push_back(GetSwitchPoint(parent, parentPt, m_position)); + m_pointList.push_back(m_position + wxPoint2DDouble(35.0, 0.0)); + m_pointList.push_back(m_position + wxPoint2DDouble(25.0, 0.0)); + m_inserted = true; + + wxRect2DDouble genRect(0, 0, 0, 0); + m_switchRect.push_back(genRect); // Push a general rectangle. + UpdateSwitches(); UpdatePowerFlowArrowsPosition(); - return true; - } + return true; + } return false; } void Machines::Draw(wxPoint2DDouble translation, double scale) const { if(m_inserted) { - - // Draw Selection (layer 1). - if(m_selected) { - glLineWidth(1.5 + m_borderSize * 2.0); - glColor4d(0.0, 0.5, 1.0, 0.5); - DrawCircle(m_position, 25.0 + (m_borderSize + 1.5) / scale, 20, GL_POLYGON); - DrawLine(m_pointList); - - // Draw node selection. - DrawCircle(m_pointList[0], 5.0 + m_borderSize / scale, 10, GL_POLYGON); - } - - // Draw Machines (layer 2). - glLineWidth(1.5); - - // Draw node. - glColor4d(0.2, 0.2, 0.2, 1.0); - DrawCircle(m_pointList[0], 5.0, 10, GL_POLYGON); - - DrawLine(m_pointList); - - DrawSwitches(); + + // Draw Selection (layer 1). + if(m_selected) { + glLineWidth(1.5 + m_borderSize * 2.0); + glColor4d(0.0, 0.5, 1.0, 0.5); + DrawCircle(m_position, 25.0 + (m_borderSize + 1.5) / scale, 20, GL_POLYGON); + DrawLine(m_pointList); + + // Draw node selection. + DrawCircle(m_pointList[0], 5.0 + m_borderSize / scale, 10, GL_POLYGON); + } + + // Draw Machines (layer 2). + glLineWidth(1.5); + + // Draw node. + glColor4d(0.2, 0.2, 0.2, 1.0); + DrawCircle(m_pointList[0], 5.0, 10, GL_POLYGON); + + DrawLine(m_pointList); + + DrawSwitches(); DrawPowerFlowPts(); - glColor4d(1.0, 1.0, 1.0, 1.0); - DrawCircle(m_position, 25.0, 20, GL_POLYGON); + glColor4d(1.0, 1.0, 1.0, 1.0); + DrawCircle(m_position, 25.0, 20, GL_POLYGON); - glColor4d(0.2, 0.2, 0.2, 1.0); - DrawCircle(m_position, 25.0, 20); + glColor4d(0.2, 0.2, 0.2, 1.0); + DrawCircle(m_position, 25.0, 20); - // Draw machine symbol. - glLineWidth(2.0); - DrawSymbol(); - } + // Draw machine symbol. + glLineWidth(2.0); + DrawSymbol(); + } } void Machines::UpdateSwitchesPosition() { if(m_parentList[0]) { - m_pointList[1] = GetSwitchPoint(m_parentList[0], m_pointList[0], m_pointList[2]); - } - else - { - m_pointList[1] = m_pointList[0]; - } - UpdateSwitches(); + m_pointList[1] = GetSwitchPoint(m_parentList[0], m_pointList[0], m_pointList[2]); + } else { + m_pointList[1] = m_pointList[0]; + } + UpdateSwitches(); } void Machines::Move(wxPoint2DDouble position) { SetPosition(m_movePos + position - m_moveStartPt); for(int i = 2; i < (int)m_pointList.size(); i++) { - m_pointList[i] = m_movePts[i] + position - m_moveStartPt; - } + m_pointList[i] = m_movePts[i] + position - m_moveStartPt; + } if(!m_parentList[0]) { - m_pointList[0] = m_movePts[0] + position - m_moveStartPt; - } + m_pointList[0] = m_movePts[0] + position - m_moveStartPt; + } UpdateSwitchesPosition(); UpdatePowerFlowArrowsPosition(); } @@ -97,18 +98,16 @@ void Machines::Move(wxPoint2DDouble position) void Machines::MoveNode(Element* element, wxPoint2DDouble position) { if(element) { - if(element == m_parentList[0]) { - m_pointList[0] = m_movePts[0] + position - m_moveStartPt; - } - } - else - { - if(m_activeNodeID == 1) { - m_pointList[0] = m_movePts[0] + position - m_moveStartPt; - m_parentList[0] = NULL; - m_online = false; - } - } + if(element == m_parentList[0]) { + m_pointList[0] = m_movePts[0] + position - m_moveStartPt; + } + } else { + if(m_activeNodeID == 1) { + m_pointList[0] = m_movePts[0] + position - m_moveStartPt; + m_parentList[0] = NULL; + m_online = false; + } + } // Recalculate switches positions UpdateSwitchesPosition(); @@ -124,33 +123,33 @@ void Machines::StartMove(wxPoint2DDouble position) void Machines::RotateNode(Element* parent, bool clockwise) { - double rotAngle = m_rotationAngle; - if(!clockwise) rotAngle = -m_rotationAngle; - + double rotAngle = m_rotationAngle; + if(!clockwise) rotAngle = -m_rotationAngle; + if(parent == m_parentList[0]) { - m_pointList[0] = parent->RotateAtPosition(m_pointList[0], rotAngle); - UpdateSwitchesPosition(); - } + m_pointList[0] = parent->RotateAtPosition(m_pointList[0], rotAngle); + UpdateSwitchesPosition(); + } } void Machines::RemoveParent(Element* parent) { if(parent == m_parentList[0]) { - m_parentList[0] = NULL; - UpdateSwitchesPosition(); + m_parentList[0] = NULL; + UpdateSwitchesPosition(); UpdatePowerFlowArrowsPosition(); - } + } } bool Machines::NodeContains(wxPoint2DDouble position) { wxRect2DDouble nodeRect(m_pointList[0].m_x - 5.0 - m_borderSize, m_pointList[0].m_y - 5.0 - m_borderSize, - 10 + 2.0 * m_borderSize, 10 + 2.0 * m_borderSize); + 10 + 2.0 * m_borderSize, 10 + 2.0 * m_borderSize); if(nodeRect.Contains(position)) { - m_activeNodeID = 1; - return true; - } + m_activeNodeID = 1; + return true; + } m_activeNodeID = 0; return false; @@ -159,52 +158,52 @@ bool Machines::NodeContains(wxPoint2DDouble position) bool Machines::SetNodeParent(Element* parent) { if(parent && m_activeNodeID != 0) { - wxRect2DDouble nodeRect(m_pointList[0].m_x - 5.0 - m_borderSize, m_pointList[0].m_y - 5.0 - m_borderSize, - 10 + 2.0 * m_borderSize, 10 + 2.0 * m_borderSize); + wxRect2DDouble nodeRect(m_pointList[0].m_x - 5.0 - m_borderSize, m_pointList[0].m_y - 5.0 - m_borderSize, + 10 + 2.0 * m_borderSize, 10 + 2.0 * m_borderSize); - if(parent->Intersects(nodeRect)) { - m_parentList[0] = parent; + if(parent->Intersects(nodeRect)) { + m_parentList[0] = parent; - // Centralize the node on bus. - wxPoint2DDouble parentPt = parent->RotateAtPosition( - m_pointList[0], -parent->GetAngle()); // Rotate click to horizontal position. - parentPt.m_y = parent->GetPosition().m_y; // Centralize on bus. - parentPt = parent->RotateAtPosition(parentPt, parent->GetAngle()); - m_pointList[0] = parentPt; + // Centralize the node on bus. + wxPoint2DDouble parentPt = + parent->RotateAtPosition(m_pointList[0], -parent->GetAngle()); // Rotate click to horizontal position. + parentPt.m_y = parent->GetPosition().m_y; // Centralize on bus. + parentPt = parent->RotateAtPosition(parentPt, parent->GetAngle()); + m_pointList[0] = parentPt; - UpdateSwitchesPosition(); + UpdateSwitchesPosition(); UpdatePowerFlowArrowsPosition(); - return true; - } - else - { - m_parentList[0] = NULL; - m_online = false; - } - } + return true; + } else { + m_parentList[0] = NULL; + m_online = false; + } + } return false; } void Machines::UpdateNodes() { if(m_parentList[0]) { - wxRect2DDouble nodeRect(m_pointList[0].m_x - 5.0 - m_borderSize, m_pointList[0].m_y - 5.0 - m_borderSize, - 10 + 2.0 * m_borderSize, 10 + 2.0 * m_borderSize); + wxRect2DDouble nodeRect(m_pointList[0].m_x - 5.0 - m_borderSize, m_pointList[0].m_y - 5.0 - m_borderSize, + 10 + 2.0 * m_borderSize, 10 + 2.0 * m_borderSize); - if(!m_parentList[0]->Intersects(nodeRect)) { - m_parentList[0] = NULL; - m_online = false; - UpdateSwitchesPosition(); + if(!m_parentList[0]->Intersects(nodeRect)) { + m_parentList[0] = NULL; + m_online = false; + UpdateSwitchesPosition(); UpdatePowerFlowArrowsPosition(); - } - } + } + } } void Machines::Rotate(bool clockwise) { - double rotAngle = m_rotationAngle; - if(!clockwise) rotAngle = -m_rotationAngle; - + double rotAngle = m_rotationAngle; + if(!clockwise) rotAngle = -m_rotationAngle; + + m_angle += rotAngle; + if(m_angle >= 360 || m_angle <= -360) m_angle = 0.0; m_pointList[2] = RotateAtPosition(m_pointList[2], rotAngle); m_pointList[3] = RotateAtPosition(m_pointList[3], rotAngle); UpdateSwitchesPosition(); @@ -229,7 +228,7 @@ void Machines::UpdatePowerFlowArrowsPosition() default: break; } - + CalculatePowerFlowPts(edges); } diff --git a/Project/MainFrame.cpp b/Project/MainFrame.cpp index 83864f3..78b4fcd 100644 --- a/Project/MainFrame.cpp +++ b/Project/MainFrame.cpp @@ -10,9 +10,14 @@ #include "Load.h" #include "Inductor.h" #include "Capacitor.h" +#include "FileHanding.h" -MainFrame::MainFrame() : MainFrameBase(NULL) {} -MainFrame::MainFrame(wxWindow* parent, wxLocale* locale) : MainFrameBase(parent) +MainFrame::MainFrame() + : MainFrameBase(NULL) +{ +} +MainFrame::MainFrame(wxWindow* parent, wxLocale* locale) + : MainFrameBase(parent) { m_locale = locale; @@ -22,8 +27,8 @@ MainFrame::~MainFrame() { // if(m_artMetro) delete m_artMetro; if(m_addElementsMenu) { - m_addElementsMenu->Disconnect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OnAddElementsClick), - NULL, this); + m_addElementsMenu->Disconnect( + wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OnAddElementsClick), NULL, this); delete m_addElementsMenu; } } @@ -81,21 +86,20 @@ void MainFrame::CreateAddElementsMenu() // busElement->SetBitmap(wxArtProvider::GetBitmap(wxART_WARNING)); wxMenuItem* lineElement = new wxMenuItem(m_addElementsMenu, ID_ADDMENU_LINE, _("&Line\tL"), _("Adds a power line at the circuit")); - wxMenuItem* transformerElement = new wxMenuItem(m_addElementsMenu, ID_ADDMENU_TRANSFORMER, _("&Transformer\tT"), - _("Adds a transformer at the circuit")); - wxMenuItem* generatorElement = new wxMenuItem(m_addElementsMenu, ID_ADDMENU_GENERATOR, _("&Generator\tG"), - _("Adds a generator at the circuit")); - wxMenuItem* indMotorElement = new wxMenuItem(m_addElementsMenu, ID_ADDMENU_INDMOTOR, _("&Induction motor\tI"), - _("Adds an induction motor at the circuit")); - wxMenuItem* syncCompElement = - new wxMenuItem(m_addElementsMenu, ID_ADDMENU_SYNCCOMP, _("&Synchronous compensator \tK"), - _("Adds an induction motor at the circuit")); + wxMenuItem* transformerElement = new wxMenuItem( + m_addElementsMenu, ID_ADDMENU_TRANSFORMER, _("&Transformer\tT"), _("Adds a transformer at the circuit")); + wxMenuItem* generatorElement = new wxMenuItem( + m_addElementsMenu, ID_ADDMENU_GENERATOR, _("&Generator\tG"), _("Adds a generator at the circuit")); + wxMenuItem* indMotorElement = new wxMenuItem( + m_addElementsMenu, ID_ADDMENU_INDMOTOR, _("&Induction motor\tI"), _("Adds an induction motor at the circuit")); + wxMenuItem* syncCompElement = new wxMenuItem(m_addElementsMenu, ID_ADDMENU_SYNCCOMP, + _("&Synchronous compensator \tK"), _("Adds an induction motor at the circuit")); wxMenuItem* loadElement = new wxMenuItem(m_addElementsMenu, ID_ADDMENU_LOAD, _("&Load\tShift-L"), _("Adds a load at the circuit")); - wxMenuItem* capacitorElement = new wxMenuItem(m_addElementsMenu, ID_ADDMENU_CAPACITOR, _("&Capacitor\tShift-C"), - _("Adds a shunt capacitor at the circuit")); - wxMenuItem* inductorElement = new wxMenuItem(m_addElementsMenu, ID_ADDMENU_INDUCTOR, _("&Inductor\tShift-I"), - _("Adds a shunt inductor at the circuit")); + wxMenuItem* capacitorElement = new wxMenuItem( + m_addElementsMenu, ID_ADDMENU_CAPACITOR, _("&Capacitor\tShift-C"), _("Adds a shunt capacitor at the circuit")); + wxMenuItem* inductorElement = new wxMenuItem( + m_addElementsMenu, ID_ADDMENU_INDUCTOR, _("&Inductor\tShift-I"), _("Adds a shunt inductor at the circuit")); m_addElementsMenu->Append(busElement); m_addElementsMenu->Append(lineElement); @@ -107,8 +111,8 @@ void MainFrame::CreateAddElementsMenu() m_addElementsMenu->Append(capacitorElement); m_addElementsMenu->Append(inductorElement); - m_addElementsMenu->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OnAddElementsClick), NULL, - this); + m_addElementsMenu->Connect( + wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OnAddElementsClick), NULL, this); } void MainFrame::OnNewClick(wxRibbonButtonBarEvent& event) @@ -189,7 +193,36 @@ void MainFrame::OnMoveClick(wxRibbonButtonBarEvent& event) workspace->SetWorkspaceMode(MODE_MOVE_ELEMENT); } } -void MainFrame::OnOpenClick(wxRibbonButtonBarEvent& event) {} +void MainFrame::OnOpenClick(wxRibbonButtonBarEvent& event) +{ + wxFileDialog openFileDialog( + this, _("Open PSP file"), "", "", "PSP files (*.psp)|*.psp", wxFD_OPEN | wxFD_FILE_MUST_EXIST); + if(openFileDialog.ShowModal() == wxID_CANCEL) return; + + wxFileName fileName(openFileDialog.GetPath()); + + EnableCurrentProjectRibbon(); + Workspace* newWorkspace = new Workspace(this, _("Open project"), this->GetStatusBar()); + + FileHanding fileHandling(newWorkspace); + if(fileHandling.OpenProject(fileName)) { + newWorkspace->SetSavedPath(fileName); + + m_workspaceList.push_back(newWorkspace); + + m_ribbonButtonBarContinuous->ToggleButton(ID_RIBBON_DISABLESOL, true); + m_ribbonButtonBarContinuous->ToggleButton(ID_RIBBON_ENABLESOL, false); + + m_auiNotebook->AddPage(newWorkspace, newWorkspace->GetName(), true); + newWorkspace->Layout(); + newWorkspace->Redraw(); + m_projectNumber++; + } else { + // TODO: fail message. + delete newWorkspace; + } +} + void MainFrame::OnPSPGuideClick(wxRibbonButtonBarEvent& event) {} void MainFrame::OnPasteClick(wxRibbonButtonBarEvent& event) {} void MainFrame::OnPowerFlowClick(wxRibbonButtonBarEvent& event) @@ -204,8 +237,46 @@ void MainFrame::OnRedoClick(wxRibbonButtonBarEvent& event) {} void MainFrame::OnResetVoltagesClick(wxRibbonButtonBarEvent& event) {} void MainFrame::OnRunStabilityClick(wxRibbonButtonBarEvent& event) {} void MainFrame::OnSCPowerClick(wxRibbonButtonBarEvent& event) {} -void MainFrame::OnSaveAsClick(wxRibbonButtonBarEvent& event) {} -void MainFrame::OnSaveClick(wxRibbonButtonBarEvent& event) {} +void MainFrame::OnSaveAsClick(wxRibbonButtonBarEvent& event) +{ + Workspace* workspace = (Workspace*)m_auiNotebook->GetCurrentPage(); + if(workspace) { + FileHanding fileHandling(workspace); + + wxFileDialog saveFileDialog( + this, _("Save PSP file"), "", "", "PSP files (*.psp)|*.psp", wxFD_SAVE | wxFD_OVERWRITE_PROMPT); + if(saveFileDialog.ShowModal() == wxID_CANCEL) return; + + fileHandling.SaveProject(saveFileDialog.GetPath()); + wxFileName fileName(saveFileDialog.GetPath()); + workspace->SetName(fileName.GetName()); + m_auiNotebook->SetPageText(m_auiNotebook->GetPageIndex(workspace), workspace->GetName()); + workspace->SetSavedPath(fileName); + } +} + +void MainFrame::OnSaveClick(wxRibbonButtonBarEvent& event) +{ + Workspace* workspace = (Workspace*)m_auiNotebook->GetCurrentPage(); + if(workspace) { + FileHanding fileHandling(workspace); + + if(workspace->GetSavedPath().IsOk()) { + fileHandling.SaveProject(workspace->GetSavedPath()); + } else { + wxFileDialog saveFileDialog( + this, _("Save PSP file"), "", "", "PSP files (*.psp)|*.psp", wxFD_SAVE | wxFD_OVERWRITE_PROMPT); + if(saveFileDialog.ShowModal() == wxID_CANCEL) return; + + fileHandling.SaveProject(saveFileDialog.GetPath()); + wxFileName fileName(saveFileDialog.GetPath()); + workspace->SetName(fileName.GetName()); + m_auiNotebook->SetPageText(m_auiNotebook->GetPageIndex(workspace), workspace->GetName()); + workspace->SetSavedPath(fileName); + } + } +} + void MainFrame::OnSnapshotClick(wxRibbonButtonBarEvent& event) {} void MainFrame::OnStabilitySettingsClick(wxRibbonButtonBarEvent& event) {} void MainFrame::OnUndoClick(wxRibbonButtonBarEvent& event) {} @@ -221,8 +292,8 @@ void MainFrame::OnAddElementsClick(wxCommandEvent& event) switch(event.GetId()) { case ID_ADDMENU_BUS: { - Bus* newBus = new Bus(wxPoint2DDouble(0, 0), - wxString::Format(_("Bus %d"), workspace->GetElementNumber(ID_BUS))); + Bus* newBus = new Bus( + wxPoint2DDouble(0, 0), wxString::Format(_("Bus %d"), workspace->GetElementNumber(ID_BUS))); workspace->IncrementElementNumber(ID_BUS); elementList.push_back(newBus); statusBarText = _("Insert Bus: Click to insert, ESC to cancel."); @@ -244,8 +315,8 @@ void MainFrame::OnAddElementsClick(wxCommandEvent& event) newElement = true; } break; case ID_ADDMENU_GENERATOR: { - SyncGenerator* newGenerator = - new SyncGenerator(wxString::Format(_("Generator %d"), workspace->GetElementNumber(ID_SYNCGENERATOR))); + SyncGenerator* newGenerator = new SyncGenerator( + wxString::Format(_("Generator %d"), workspace->GetElementNumber(ID_SYNCGENERATOR))); workspace->IncrementElementNumber(ID_SYNCGENERATOR); elementList.push_back(newGenerator); statusBarText = _("Insert Generator: Click on a buses, ESC to cancel."); @@ -259,28 +330,32 @@ void MainFrame::OnAddElementsClick(wxCommandEvent& event) newElement = true; } break; case ID_ADDMENU_CAPACITOR: { - Capacitor* newCapacitor = new Capacitor(wxString::Format(_("Capacitor %d"), workspace->GetElementNumber(ID_CAPACITOR))); + Capacitor* newCapacitor = + new Capacitor(wxString::Format(_("Capacitor %d"), workspace->GetElementNumber(ID_CAPACITOR))); workspace->IncrementElementNumber(ID_CAPACITOR); elementList.push_back(newCapacitor); statusBarText = _("Insert Capacitor: Click on a buses, ESC to cancel."); newElement = true; } break; case ID_ADDMENU_INDUCTOR: { - Inductor* newInductor = new Inductor(wxString::Format(_("Inductor %d"), workspace->GetElementNumber(ID_INDUCTOR))); + Inductor* newInductor = + new Inductor(wxString::Format(_("Inductor %d"), workspace->GetElementNumber(ID_INDUCTOR))); workspace->IncrementElementNumber(ID_INDUCTOR); elementList.push_back(newInductor); statusBarText = _("Insert Inductor: Click on a buses, ESC to cancel."); newElement = true; } break; case ID_ADDMENU_INDMOTOR: { - IndMotor* newIndMotor = new IndMotor(wxString::Format(_("Induction motor %d"), workspace->GetElementNumber(ID_INDMOTOR))); + IndMotor* newIndMotor = new IndMotor( + wxString::Format(_("Induction motor %d"), workspace->GetElementNumber(ID_INDMOTOR))); workspace->IncrementElementNumber(ID_INDMOTOR); elementList.push_back(newIndMotor); statusBarText = _("Insert Induction Motor: Click on a buses, ESC to cancel."); newElement = true; } break; case ID_ADDMENU_SYNCCOMP: { - SyncMotor* newSyncCondenser = new SyncMotor(wxString::Format(_("Synchronous condenser %d"), workspace->GetElementNumber(ID_SYNCMOTOR))); + SyncMotor* newSyncCondenser = new SyncMotor( + wxString::Format(_("Synchronous condenser %d"), workspace->GetElementNumber(ID_SYNCMOTOR))); workspace->IncrementElementNumber(ID_SYNCMOTOR); elementList.push_back(newSyncCondenser); statusBarText = _("Insert Synchronous Condenser: Click on a buses, ESC to cancel."); diff --git a/Project/MainFrame.h b/Project/MainFrame.h index 057864b..9b60b47 100644 --- a/Project/MainFrame.h +++ b/Project/MainFrame.h @@ -3,12 +3,14 @@ #include <wx/menu.h> #include <wx/msgdlg.h> +#include <wx/filedlg.h> #include "MainFrameBase.h" class MainFrameBase; class wxRibbonMetroArtProvider; class Workspace; +class FileHanding; enum { diff --git a/Project/Project.mk b/Project/Project.mk index 83cac59..bd0847f 100644 --- a/Project/Project.mk +++ b/Project/Project.mk @@ -13,7 +13,7 @@ CurrentFileName := CurrentFilePath := CurrentFileFullPath := User :=Thales -Date :=09/12/2016 +Date :=15/12/2016 CodeLitePath :="C:/Program Files/CodeLite" LinkerName :=C:/TDM-GCC-64/bin/g++.exe SharedObjectLinkerName :=C:/TDM-GCC-64/bin/g++.exe -shared -fPIC @@ -64,10 +64,11 @@ AS := C:/TDM-GCC-64/bin/as.exe CodeLiteDir:=C:\Program Files\CodeLite WXWIN:=C:\wxWidgets-3.1.0 WXCFG:=gcc_dll\mswu -Objects0=$(IntermediateDirectory)/main.cpp$(ObjectSuffix) $(IntermediateDirectory)/win_resources.rc$(ObjectSuffix) $(IntermediateDirectory)/Text.cpp$(ObjectSuffix) $(IntermediateDirectory)/ArtMetro.cpp$(ObjectSuffix) $(IntermediateDirectory)/wxGLString.cpp$(ObjectSuffix) $(IntermediateDirectory)/MainFrame.cpp$(ObjectSuffix) $(IntermediateDirectory)/Workspace.cpp$(ObjectSuffix) $(IntermediateDirectory)/MainFrameBitmaps.cpp$(ObjectSuffix) $(IntermediateDirectory)/WorkspaceBitmaps.cpp$(ObjectSuffix) $(IntermediateDirectory)/BusFormBitmaps.cpp$(ObjectSuffix) \ - $(IntermediateDirectory)/ElementFormBitmaps.cpp$(ObjectSuffix) $(IntermediateDirectory)/MainFrameBase.cpp$(ObjectSuffix) $(IntermediateDirectory)/WorkspaceBase.cpp$(ObjectSuffix) $(IntermediateDirectory)/ElementForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/Bus.cpp$(ObjectSuffix) $(IntermediateDirectory)/Line.cpp$(ObjectSuffix) $(IntermediateDirectory)/Transformer.cpp$(ObjectSuffix) $(IntermediateDirectory)/Machines.cpp$(ObjectSuffix) $(IntermediateDirectory)/SyncGenerator.cpp$(ObjectSuffix) $(IntermediateDirectory)/IndMotor.cpp$(ObjectSuffix) \ - $(IntermediateDirectory)/Branch.cpp$(ObjectSuffix) $(IntermediateDirectory)/SyncMotor.cpp$(ObjectSuffix) $(IntermediateDirectory)/Shunt.cpp$(ObjectSuffix) $(IntermediateDirectory)/Load.cpp$(ObjectSuffix) $(IntermediateDirectory)/Inductor.cpp$(ObjectSuffix) $(IntermediateDirectory)/Capacitor.cpp$(ObjectSuffix) $(IntermediateDirectory)/Element.cpp$(ObjectSuffix) $(IntermediateDirectory)/ElectricCalculation.cpp$(ObjectSuffix) $(IntermediateDirectory)/PowerFlow.cpp$(ObjectSuffix) $(IntermediateDirectory)/BusForm.cpp$(ObjectSuffix) \ - $(IntermediateDirectory)/GeneratorStabForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/LineForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/SwitchingForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/TransformerForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/LoadForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/ReactiveShuntElementForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/IndMotorForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/SyncMachineForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/TextForm.cpp$(ObjectSuffix) +Objects0=$(IntermediateDirectory)/main.cpp$(ObjectSuffix) $(IntermediateDirectory)/win_resources.rc$(ObjectSuffix) $(IntermediateDirectory)/Text.cpp$(ObjectSuffix) $(IntermediateDirectory)/ArtMetro.cpp$(ObjectSuffix) $(IntermediateDirectory)/wxGLString.cpp$(ObjectSuffix) $(IntermediateDirectory)/MainFrame.cpp$(ObjectSuffix) $(IntermediateDirectory)/Workspace.cpp$(ObjectSuffix) $(IntermediateDirectory)/FileHanding.cpp$(ObjectSuffix) $(IntermediateDirectory)/MainFrameBitmaps.cpp$(ObjectSuffix) $(IntermediateDirectory)/WorkspaceBitmaps.cpp$(ObjectSuffix) \ + $(IntermediateDirectory)/BusFormBitmaps.cpp$(ObjectSuffix) $(IntermediateDirectory)/ElementFormBitmaps.cpp$(ObjectSuffix) $(IntermediateDirectory)/MainFrameBase.cpp$(ObjectSuffix) $(IntermediateDirectory)/WorkspaceBase.cpp$(ObjectSuffix) $(IntermediateDirectory)/ElementForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/Bus.cpp$(ObjectSuffix) $(IntermediateDirectory)/Line.cpp$(ObjectSuffix) $(IntermediateDirectory)/Transformer.cpp$(ObjectSuffix) $(IntermediateDirectory)/Machines.cpp$(ObjectSuffix) $(IntermediateDirectory)/SyncGenerator.cpp$(ObjectSuffix) \ + $(IntermediateDirectory)/IndMotor.cpp$(ObjectSuffix) $(IntermediateDirectory)/Branch.cpp$(ObjectSuffix) $(IntermediateDirectory)/SyncMotor.cpp$(ObjectSuffix) $(IntermediateDirectory)/Shunt.cpp$(ObjectSuffix) $(IntermediateDirectory)/Load.cpp$(ObjectSuffix) $(IntermediateDirectory)/Inductor.cpp$(ObjectSuffix) $(IntermediateDirectory)/Capacitor.cpp$(ObjectSuffix) $(IntermediateDirectory)/Element.cpp$(ObjectSuffix) $(IntermediateDirectory)/ElectricCalculation.cpp$(ObjectSuffix) $(IntermediateDirectory)/PowerFlow.cpp$(ObjectSuffix) \ + $(IntermediateDirectory)/BusForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/GeneratorStabForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/LineForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/SwitchingForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/TransformerForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/LoadForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/ReactiveShuntElementForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/IndMotorForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/SyncMachineForm.cpp$(ObjectSuffix) $(IntermediateDirectory)/TextForm.cpp$(ObjectSuffix) \ + @@ -148,6 +149,14 @@ $(IntermediateDirectory)/Workspace.cpp$(DependSuffix): Workspace.cpp $(IntermediateDirectory)/Workspace.cpp$(PreprocessSuffix): Workspace.cpp $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/Workspace.cpp$(PreprocessSuffix) Workspace.cpp +$(IntermediateDirectory)/FileHanding.cpp$(ObjectSuffix): FileHanding.cpp $(IntermediateDirectory)/FileHanding.cpp$(DependSuffix) + $(CXX) $(IncludePCH) $(SourceSwitch) "C:/Users/Thales/Documents/GitHub/PSP/Project/FileHanding.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/FileHanding.cpp$(ObjectSuffix) $(IncludePath) +$(IntermediateDirectory)/FileHanding.cpp$(DependSuffix): FileHanding.cpp + @$(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) -MG -MP -MT$(IntermediateDirectory)/FileHanding.cpp$(ObjectSuffix) -MF$(IntermediateDirectory)/FileHanding.cpp$(DependSuffix) -MM FileHanding.cpp + +$(IntermediateDirectory)/FileHanding.cpp$(PreprocessSuffix): FileHanding.cpp + $(CXX) $(CXXFLAGS) $(IncludePCH) $(IncludePath) $(PreprocessOnlySwitch) $(OutputSwitch) $(IntermediateDirectory)/FileHanding.cpp$(PreprocessSuffix) FileHanding.cpp + $(IntermediateDirectory)/MainFrameBitmaps.cpp$(ObjectSuffix): MainFrameBitmaps.cpp $(IntermediateDirectory)/MainFrameBitmaps.cpp$(DependSuffix) $(CXX) $(IncludePCH) $(SourceSwitch) "C:/Users/Thales/Documents/GitHub/PSP/Project/MainFrameBitmaps.cpp" $(CXXFLAGS) $(ObjectSwitch)$(IntermediateDirectory)/MainFrameBitmaps.cpp$(ObjectSuffix) $(IncludePath) $(IntermediateDirectory)/MainFrameBitmaps.cpp$(DependSuffix): MainFrameBitmaps.cpp diff --git a/Project/Project.project b/Project/Project.project index 7fdda15..5d4b6d2 100644 --- a/Project/Project.project +++ b/Project/Project.project @@ -49,6 +49,7 @@ <File Name="SyncMachineForm.cpp"/> <File Name="TextForm.cpp"/> </VirtualDirectory> + <File Name="FileHanding.cpp"/> </VirtualDirectory> <File Name="main.cpp"/> </VirtualDirectory> @@ -74,6 +75,12 @@ <File Name="PowerFlow.h"/> </VirtualDirectory> <File Name="Text.h"/> + <VirtualDirectory Name="rapidXML"> + <File Name="rapidXML/rapidxml.hpp"/> + <File Name="rapidXML/rapidxml_iterators.hpp"/> + <File Name="rapidXML/rapidxml_print.hpp"/> + <File Name="rapidXML/rapidxml_utils.hpp"/> + </VirtualDirectory> </VirtualDirectory> <VirtualDirectory Name="view"> <File Name="ArtMetro.h"/> @@ -94,6 +101,7 @@ <File Name="SyncMachineForm.h"/> <File Name="TextForm.h"/> </VirtualDirectory> + <File Name="FileHanding.h"/> </VirtualDirectory> </VirtualDirectory> <VirtualDirectory Name="resources"> diff --git a/Project/Project.txt b/Project/Project.txt index 5a024fc..1792b21 100644 --- a/Project/Project.txt +++ b/Project/Project.txt @@ -1 +1 @@ -./Release/main.cpp.o ./Release/win_resources.rc.o ./Release/Text.cpp.o ./Release/ArtMetro.cpp.o ./Release/wxGLString.cpp.o ./Release/MainFrame.cpp.o ./Release/Workspace.cpp.o ./Release/MainFrameBitmaps.cpp.o ./Release/WorkspaceBitmaps.cpp.o ./Release/BusFormBitmaps.cpp.o ./Release/ElementFormBitmaps.cpp.o ./Release/MainFrameBase.cpp.o ./Release/WorkspaceBase.cpp.o ./Release/ElementForm.cpp.o ./Release/Bus.cpp.o ./Release/Line.cpp.o ./Release/Transformer.cpp.o ./Release/Machines.cpp.o ./Release/SyncGenerator.cpp.o ./Release/IndMotor.cpp.o ./Release/Branch.cpp.o ./Release/SyncMotor.cpp.o ./Release/Shunt.cpp.o ./Release/Load.cpp.o ./Release/Inductor.cpp.o ./Release/Capacitor.cpp.o ./Release/Element.cpp.o ./Release/ElectricCalculation.cpp.o ./Release/PowerFlow.cpp.o ./Release/BusForm.cpp.o ./Release/GeneratorStabForm.cpp.o ./Release/LineForm.cpp.o ./Release/SwitchingForm.cpp.o ./Release/TransformerForm.cpp.o ./Release/LoadForm.cpp.o ./Release/ReactiveShuntElementForm.cpp.o ./Release/IndMotorForm.cpp.o ./Release/SyncMachineForm.cpp.o ./Release/TextForm.cpp.o +./Release/main.cpp.o ./Release/win_resources.rc.o ./Release/Text.cpp.o ./Release/ArtMetro.cpp.o ./Release/wxGLString.cpp.o ./Release/MainFrame.cpp.o ./Release/Workspace.cpp.o ./Release/FileHanding.cpp.o ./Release/MainFrameBitmaps.cpp.o ./Release/WorkspaceBitmaps.cpp.o ./Release/BusFormBitmaps.cpp.o ./Release/ElementFormBitmaps.cpp.o ./Release/MainFrameBase.cpp.o ./Release/WorkspaceBase.cpp.o ./Release/ElementForm.cpp.o ./Release/Bus.cpp.o ./Release/Line.cpp.o ./Release/Transformer.cpp.o ./Release/Machines.cpp.o ./Release/SyncGenerator.cpp.o ./Release/IndMotor.cpp.o ./Release/Branch.cpp.o ./Release/SyncMotor.cpp.o ./Release/Shunt.cpp.o ./Release/Load.cpp.o ./Release/Inductor.cpp.o ./Release/Capacitor.cpp.o ./Release/Element.cpp.o ./Release/ElectricCalculation.cpp.o ./Release/PowerFlow.cpp.o ./Release/BusForm.cpp.o ./Release/GeneratorStabForm.cpp.o ./Release/LineForm.cpp.o ./Release/SwitchingForm.cpp.o ./Release/TransformerForm.cpp.o ./Release/LoadForm.cpp.o ./Release/ReactiveShuntElementForm.cpp.o ./Release/IndMotorForm.cpp.o ./Release/SyncMachineForm.cpp.o ./Release/TextForm.cpp.o diff --git a/Project/Release/Branch.cpp.o b/Project/Release/Branch.cpp.o Binary files differindex 374429b..0f29378 100644 --- a/Project/Release/Branch.cpp.o +++ b/Project/Release/Branch.cpp.o diff --git a/Project/Release/Bus.cpp.o b/Project/Release/Bus.cpp.o Binary files differindex 54c9c29..41a53aa 100644 --- a/Project/Release/Bus.cpp.o +++ b/Project/Release/Bus.cpp.o diff --git a/Project/Release/BusForm.cpp.o b/Project/Release/BusForm.cpp.o Binary files differindex 3aff5ba..917f8b4 100644 --- a/Project/Release/BusForm.cpp.o +++ b/Project/Release/BusForm.cpp.o diff --git a/Project/Release/Capacitor.cpp.o b/Project/Release/Capacitor.cpp.o Binary files differindex bbf9649..80ab190 100644 --- a/Project/Release/Capacitor.cpp.o +++ b/Project/Release/Capacitor.cpp.o diff --git a/Project/Release/ElectricCalculation.cpp.o b/Project/Release/ElectricCalculation.cpp.o Binary files differindex 8fe31cc..3d144b8 100644 --- a/Project/Release/ElectricCalculation.cpp.o +++ b/Project/Release/ElectricCalculation.cpp.o diff --git a/Project/Release/Element.cpp.o b/Project/Release/Element.cpp.o Binary files differindex 76baaaf..3abe5a3 100644 --- a/Project/Release/Element.cpp.o +++ b/Project/Release/Element.cpp.o diff --git a/Project/Release/FileHanding.cpp.o b/Project/Release/FileHanding.cpp.o Binary files differnew file mode 100644 index 0000000..ba53135 --- /dev/null +++ b/Project/Release/FileHanding.cpp.o diff --git a/Project/Release/FileHanding.cpp.o.d b/Project/Release/FileHanding.cpp.o.d new file mode 100644 index 0000000..65cccdd --- /dev/null +++ b/Project/Release/FileHanding.cpp.o.d @@ -0,0 +1,910 @@ +Release/FileHanding.cpp.o: FileHanding.cpp FileHanding.h \ + C:/wxWidgets-3.1.0/include/wx/string.h \ + C:/wxWidgets-3.1.0/include/wx/defs.h \ + C:/wxWidgets-3.1.0/include/wx/platform.h \ + C:/wxWidgets-3.1.0/include/wx/compiler.h \ + C:/wxWidgets-3.1.0/lib/gcc_dll/mswu/wx/setup.h \ + C:/wxWidgets-3.1.0/include/wx/msw/libraries.h \ + C:/wxWidgets-3.1.0/include/wx/msw/gccpriv.h \ + C:/wxWidgets-3.1.0/include/wx/chkconf.h \ + C:/wxWidgets-3.1.0/include/wx/msw/chkconf.h \ + C:/wxWidgets-3.1.0/include/wx/version.h \ + C:/wxWidgets-3.1.0/include/wx/cpp.h \ + C:/wxWidgets-3.1.0/include/wx/dlimpexp.h \ + C:/wxWidgets-3.1.0/include/wx/debug.h \ + C:/wxWidgets-3.1.0/include/wx/chartype.h \ + C:/wxWidgets-3.1.0/include/wx/windowid.h \ + C:/wxWidgets-3.1.0/include/wx/msw/winundef.h \ + C:/wxWidgets-3.1.0/include/wx/features.h \ + C:/wxWidgets-3.1.0/include/wx/wxcrtbase.h \ + C:/wxWidgets-3.1.0/include/wx/strvararg.h \ + C:/wxWidgets-3.1.0/include/wx/strconv.h \ + C:/wxWidgets-3.1.0/include/wx/buffer.h \ + C:/wxWidgets-3.1.0/include/wx/fontenc.h \ + C:/wxWidgets-3.1.0/include/wx/unichar.h \ + C:/wxWidgets-3.1.0/include/wx/stringimpl.h \ + C:/wxWidgets-3.1.0/include/wx/beforestd.h \ + C:/wxWidgets-3.1.0/include/wx/afterstd.h \ + C:/wxWidgets-3.1.0/include/wx/stringops.h \ + C:/wxWidgets-3.1.0/include/wx/iosfwrap.h Workspace.h \ + C:/wxWidgets-3.1.0/include/wx/dcclient.h \ + C:/wxWidgets-3.1.0/include/wx/dc.h \ + C:/wxWidgets-3.1.0/include/wx/object.h \ + C:/wxWidgets-3.1.0/include/wx/memory.h \ + C:/wxWidgets-3.1.0/include/wx/msgout.h \ + C:/wxWidgets-3.1.0/include/wx/xti.h C:/wxWidgets-3.1.0/include/wx/rtti.h \ + C:/wxWidgets-3.1.0/include/wx/flags.h \ + C:/wxWidgets-3.1.0/include/wx/xti2.h \ + C:/wxWidgets-3.1.0/include/wx/intl.h \ + C:/wxWidgets-3.1.0/include/wx/translation.h \ + C:/wxWidgets-3.1.0/include/wx/language.h \ + C:/wxWidgets-3.1.0/include/wx/hashmap.h \ + C:/wxWidgets-3.1.0/include/wx/wxcrt.h \ + C:/wxWidgets-3.1.0/include/wx/scopedptr.h \ + C:/wxWidgets-3.1.0/include/wx/checkeddelete.h \ + C:/wxWidgets-3.1.0/include/wx/colour.h \ + C:/wxWidgets-3.1.0/include/wx/gdiobj.h \ + C:/wxWidgets-3.1.0/include/wx/variant.h \ + C:/wxWidgets-3.1.0/include/wx/arrstr.h \ + C:/wxWidgets-3.1.0/include/wx/list.h \ + C:/wxWidgets-3.1.0/include/wx/vector.h \ + C:/wxWidgets-3.1.0/include/wx/scopeguard.h \ + C:/wxWidgets-3.1.0/include/wx/except.h \ + C:/wxWidgets-3.1.0/include/wx/meta/movable.h \ + C:/wxWidgets-3.1.0/include/wx/meta/pod.h \ + C:/wxWidgets-3.1.0/include/wx/meta/if.h \ + C:/wxWidgets-3.1.0/include/wx/longlong.h \ + C:/wxWidgets-3.1.0/include/wx/datetime.h \ + C:/wxWidgets-3.1.0/include/wx/anystr.h \ + C:/wxWidgets-3.1.0/include/wx/dynarray.h \ + C:/wxWidgets-3.1.0/include/wx/any.h \ + C:/wxWidgets-3.1.0/include/wx/typeinfo.h \ + C:/wxWidgets-3.1.0/include/wx/msw/colour.h \ + C:/wxWidgets-3.1.0/include/wx/font.h \ + C:/wxWidgets-3.1.0/include/wx/gdicmn.h \ + C:/wxWidgets-3.1.0/include/wx/math.h \ + C:/wxWidgets-3.1.0/include/wx/msw/font.h \ + C:/wxWidgets-3.1.0/include/wx/bitmap.h \ + C:/wxWidgets-3.1.0/include/wx/image.h \ + C:/wxWidgets-3.1.0/include/wx/stream.h \ + C:/wxWidgets-3.1.0/include/wx/filefn.h \ + C:/wxWidgets-3.1.0/include/wx/imagbmp.h \ + C:/wxWidgets-3.1.0/include/wx/imagpng.h \ + C:/wxWidgets-3.1.0/include/wx/versioninfo.h \ + C:/wxWidgets-3.1.0/include/wx/imaggif.h \ + C:/wxWidgets-3.1.0/include/wx/imagpcx.h \ + C:/wxWidgets-3.1.0/include/wx/imagjpeg.h \ + C:/wxWidgets-3.1.0/include/wx/imagtga.h \ + C:/wxWidgets-3.1.0/include/wx/imagtiff.h \ + C:/wxWidgets-3.1.0/include/wx/imagpnm.h \ + C:/wxWidgets-3.1.0/include/wx/imagxpm.h \ + C:/wxWidgets-3.1.0/include/wx/imagiff.h \ + C:/wxWidgets-3.1.0/include/wx/msw/bitmap.h \ + C:/wxWidgets-3.1.0/include/wx/msw/gdiimage.h \ + C:/wxWidgets-3.1.0/include/wx/palette.h \ + C:/wxWidgets-3.1.0/include/wx/msw/palette.h \ + C:/wxWidgets-3.1.0/include/wx/brush.h \ + C:/wxWidgets-3.1.0/include/wx/msw/brush.h \ + C:/wxWidgets-3.1.0/include/wx/pen.h \ + C:/wxWidgets-3.1.0/include/wx/msw/pen.h \ + C:/wxWidgets-3.1.0/include/wx/region.h \ + C:/wxWidgets-3.1.0/include/wx/msw/region.h \ + C:/wxWidgets-3.1.0/include/wx/affinematrix2d.h \ + C:/wxWidgets-3.1.0/include/wx/affinematrix2dbase.h \ + C:/wxWidgets-3.1.0/include/wx/geometry.h \ + C:/wxWidgets-3.1.0/include/wx/utils.h \ + C:/wxWidgets-3.1.0/include/wx/meta/implicitconversion.h \ + C:/wxWidgets-3.1.0/include/wx/mousestate.h \ + C:/wxWidgets-3.1.0/include/wx/kbdstate.h \ + C:/wxWidgets-3.1.0/include/wx/platinfo.h \ + C:/wxWidgets-3.1.0/include/wx/msgdlg.h \ + C:/wxWidgets-3.1.0/include/wx/dialog.h \ + C:/wxWidgets-3.1.0/include/wx/toplevel.h \ + C:/wxWidgets-3.1.0/include/wx/nonownedwnd.h \ + C:/wxWidgets-3.1.0/include/wx/window.h \ + C:/wxWidgets-3.1.0/include/wx/event.h \ + C:/wxWidgets-3.1.0/include/wx/clntdata.h \ + C:/wxWidgets-3.1.0/include/wx/cursor.h \ + C:/wxWidgets-3.1.0/include/wx/msw/cursor.h \ + C:/wxWidgets-3.1.0/include/wx/thread.h \ + C:/wxWidgets-3.1.0/include/wx/tracker.h \ + C:/wxWidgets-3.1.0/include/wx/meta/convertible.h \ + C:/wxWidgets-3.1.0/include/wx/meta/removeref.h \ + C:/wxWidgets-3.1.0/include/wx/validate.h \ + C:/wxWidgets-3.1.0/include/wx/accel.h \ + C:/wxWidgets-3.1.0/include/wx/msw/accel.h \ + C:/wxWidgets-3.1.0/include/wx/msw/window.h \ + C:/wxWidgets-3.1.0/include/wx/settings.h \ + C:/wxWidgets-3.1.0/include/wx/msw/nonownedwnd.h \ + C:/wxWidgets-3.1.0/include/wx/iconbndl.h \ + C:/wxWidgets-3.1.0/include/wx/icon.h \ + C:/wxWidgets-3.1.0/include/wx/iconloc.h \ + C:/wxWidgets-3.1.0/include/wx/msw/icon.h \ + C:/wxWidgets-3.1.0/include/wx/weakref.h \ + C:/wxWidgets-3.1.0/include/wx/meta/int2type.h \ + C:/wxWidgets-3.1.0/include/wx/msw/toplevel.h \ + C:/wxWidgets-3.1.0/include/wx/containr.h \ + C:/wxWidgets-3.1.0/include/wx/sharedptr.h \ + C:/wxWidgets-3.1.0/include/wx/atomic.h \ + C:/wxWidgets-3.1.0/include/wx/msw/wrapwin.h \ + C:/wxWidgets-3.1.0/include/wx/msw/dialog.h \ + C:/wxWidgets-3.1.0/include/wx/panel.h \ + C:/wxWidgets-3.1.0/include/wx/msw/panel.h \ + C:/wxWidgets-3.1.0/include/wx/stockitem.h \ + C:/wxWidgets-3.1.0/include/wx/generic/msgdlgg.h \ + C:/wxWidgets-3.1.0/include/wx/msw/msgdlg.h \ + C:/wxWidgets-3.1.0/include/wx/statusbr.h \ + C:/wxWidgets-3.1.0/include/wx/control.h \ + C:/wxWidgets-3.1.0/include/wx/msw/control.h \ + C:/wxWidgets-3.1.0/include/wx/msw/statusbar.h \ + C:/wxWidgets-3.1.0/include/wx/tooltip.h \ + C:/wxWidgets-3.1.0/include/wx/msw/tooltip.h WorkspaceBase.h \ + C:/wxWidgets-3.1.0/include/wx/xrc/xmlres.h \ + C:/wxWidgets-3.1.0/include/wx/filesys.h \ + C:/wxWidgets-3.1.0/include/wx/filename.h \ + C:/wxWidgets-3.1.0/include/wx/file.h \ + C:/wxWidgets-3.1.0/include/wx/convauto.h \ + C:/wxWidgets-3.1.0/include/wx/artprov.h \ + C:/wxWidgets-3.1.0/include/wx/xrc/xmlreshandler.h \ + C:/wxWidgets-3.1.0/include/wx/imaglist.h \ + C:/wxWidgets-3.1.0/include/wx/msw/imaglist.h \ + C:/wxWidgets-3.1.0/include/wx/xrc/xh_bmp.h \ + C:/wxWidgets-3.1.0/include/wx/sizer.h \ + C:/wxWidgets-3.1.0/include/wx/glcanvas.h \ + C:/wxWidgets-3.1.0/include/wx/app.h \ + C:/wxWidgets-3.1.0/include/wx/eventfilter.h \ + C:/wxWidgets-3.1.0/include/wx/build.h \ + C:/wxWidgets-3.1.0/include/wx/cmdargs.h \ + C:/wxWidgets-3.1.0/include/wx/init.h \ + C:/wxWidgets-3.1.0/include/wx/msw/init.h \ + C:/wxWidgets-3.1.0/include/wx/log.h \ + C:/wxWidgets-3.1.0/include/wx/generic/logg.h \ + C:/wxWidgets-3.1.0/include/wx/msw/app.h \ + C:/wxWidgets-3.1.0/include/wx/msw/glcanvas.h \ + C:/wxWidgets-3.1.0/include/wx/persist.h \ + C:/wxWidgets-3.1.0/include/wx/confbase.h \ + C:/wxWidgets-3.1.0/include/wx/base64.h \ + C:/wxWidgets-3.1.0/include/wx/persist/toplevel.h \ + C:/wxWidgets-3.1.0/include/wx/persist/window.h \ + C:/wxWidgets-3.1.0/include/wx/display.h \ + C:/wxWidgets-3.1.0/include/wx/vidmode.h \ + C:/wxWidgets-3.1.0/include/wx/persist/bookctrl.h \ + C:/wxWidgets-3.1.0/include/wx/bookctrl.h \ + C:/wxWidgets-3.1.0/include/wx/withimages.h \ + C:/wxWidgets-3.1.0/include/wx/notebook.h \ + C:/wxWidgets-3.1.0/include/wx/msw/notebook.h \ + C:/wxWidgets-3.1.0/include/wx/persist/treebook.h \ + C:/wxWidgets-3.1.0/include/wx/treebook.h \ + C:/wxWidgets-3.1.0/include/wx/treectrl.h \ + C:/wxWidgets-3.1.0/include/wx/treebase.h \ + C:/wxWidgets-3.1.0/include/wx/itemid.h \ + C:/wxWidgets-3.1.0/include/wx/textctrl.h \ + C:/wxWidgets-3.1.0/include/wx/textentry.h \ + C:/wxWidgets-3.1.0/include/wx/msw/textentry.h \ + C:/wxWidgets-3.1.0/include/wx/ioswrap.h \ + C:/wxWidgets-3.1.0/include/wx/msw/textctrl.h \ + C:/wxWidgets-3.1.0/include/wx/systhemectrl.h \ + C:/wxWidgets-3.1.0/include/wx/msw/treectrl.h Bus.h BusForm.h \ + ElementForm.h C:/wxWidgets-3.1.0/include/wx/stattext.h \ + C:/wxWidgets-3.1.0/include/wx/msw/stattext.h \ + C:/wxWidgets-3.1.0/include/wx/choice.h \ + C:/wxWidgets-3.1.0/include/wx/ctrlsub.h \ + C:/wxWidgets-3.1.0/include/wx/msw/ctrlsub.h \ + C:/wxWidgets-3.1.0/include/wx/msw/choice.h \ + C:/wxWidgets-3.1.0/include/wx/checkbox.h \ + C:/wxWidgets-3.1.0/include/wx/msw/checkbox.h \ + C:/wxWidgets-3.1.0/include/wx/msw/ownerdrawnbutton.h \ + C:/wxWidgets-3.1.0/include/wx/button.h \ + C:/wxWidgets-3.1.0/include/wx/anybutton.h \ + C:/wxWidgets-3.1.0/include/wx/msw/anybutton.h \ + C:/wxWidgets-3.1.0/include/wx/msw/button.h \ + C:/wxWidgets-3.1.0/include/wx/statbox.h \ + C:/wxWidgets-3.1.0/include/wx/msw/statbox.h \ + C:/wxWidgets-3.1.0/include/wx/statline.h \ + C:/wxWidgets-3.1.0/include/wx/msw/statline.h \ + C:/wxWidgets-3.1.0/include/wx/propgrid/manager.h \ + C:/wxWidgets-3.1.0/include/wx/propgrid/propgrid.h \ + C:/wxWidgets-3.1.0/include/wx/scrolwin.h \ + C:/wxWidgets-3.1.0/include/wx/generic/scrolwin.h \ + C:/wxWidgets-3.1.0/include/wx/recguard.h \ + C:/wxWidgets-3.1.0/include/wx/time.h \ + C:/wxWidgets-3.1.0/include/wx/propgrid/property.h \ + C:/wxWidgets-3.1.0/include/wx/propgrid/propgriddefs.h \ + C:/wxWidgets-3.1.0/include/wx/hashset.h \ + C:/wxWidgets-3.1.0/include/wx/tokenzr.h \ + C:/wxWidgets-3.1.0/include/wx/propgrid/propgridiface.h \ + C:/wxWidgets-3.1.0/include/wx/propgrid/propgridpagestate.h \ + C:/wxWidgets-3.1.0/include/wx/propgrid/props.h \ + C:/wxWidgets-3.1.0/include/wx/propgrid/editors.h \ + C:/wxWidgets-3.1.0/include/wx/listbox.h \ + C:/wxWidgets-3.1.0/include/wx/msw/listbox.h \ + C:/wxWidgets-3.1.0/include/wx/valtext.h \ + C:/wxWidgets-3.1.0/include/wx/toolbar.h \ + C:/wxWidgets-3.1.0/include/wx/tbarbase.h \ + C:/wxWidgets-3.1.0/include/wx/msw/toolbar.h \ + C:/wxWidgets-3.1.0/include/wx/headerctrl.h \ + C:/wxWidgets-3.1.0/include/wx/headercol.h \ + C:/wxWidgets-3.1.0/include/wx/msw/headerctrl.h \ + C:/wxWidgets-3.1.0/include/wx/propgrid/advprops.h \ + C:/wxWidgets-3.1.0/include/wx/spinbutt.h \ + C:/wxWidgets-3.1.0/include/wx/range.h \ + C:/wxWidgets-3.1.0/include/wx/msw/spinbutt.h \ + C:/wxWidgets-3.1.0/include/wx/listctrl.h \ + C:/wxWidgets-3.1.0/include/wx/listbase.h \ + C:/wxWidgets-3.1.0/include/wx/msw/listctrl.h Element.h \ + C:/wxWidgets-3.1.0/include/wx/menu.h \ + C:/wxWidgets-3.1.0/include/wx/menuitem.h \ + C:/wxWidgets-3.1.0/include/wx/msw/menuitem.h \ + C:/wxWidgets-3.1.0/include/wx/ownerdrw.h \ + C:/wxWidgets-3.1.0/include/wx/msw/ownerdrw.h \ + C:/wxWidgets-3.1.0/include/wx/msw/menu.h ElectricCalculation.h \ + Capacitor.h Shunt.h IndMotor.h Machines.h Inductor.h Line.h LineForm.h \ + Branch.h Load.h LoadForm.h SyncGenerator.h SyncMotor.h Transformer.h \ + Text.h wxGLString.h C:/wxWidgets-3.1.0/include/wx/wx.h \ + C:/wxWidgets-3.1.0/include/wx/hash.h \ + C:/wxWidgets-3.1.0/include/wx/stopwatch.h \ + C:/wxWidgets-3.1.0/include/wx/timer.h \ + C:/wxWidgets-3.1.0/include/wx/module.h \ + C:/wxWidgets-3.1.0/include/wx/wxcrtvararg.h \ + C:/wxWidgets-3.1.0/include/wx/frame.h \ + C:/wxWidgets-3.1.0/include/wx/msw/frame.h \ + C:/wxWidgets-3.1.0/include/wx/dcmemory.h \ + C:/wxWidgets-3.1.0/include/wx/dcprint.h \ + C:/wxWidgets-3.1.0/include/wx/dcscreen.h \ + C:/wxWidgets-3.1.0/include/wx/dataobj.h \ + C:/wxWidgets-3.1.0/include/wx/msw/ole/dataform.h \ + C:/wxWidgets-3.1.0/include/wx/msw/ole/dataobj.h \ + C:/wxWidgets-3.1.0/include/wx/msw/ole/dataobj2.h \ + C:/wxWidgets-3.1.0/include/wx/bmpbuttn.h \ + C:/wxWidgets-3.1.0/include/wx/msw/bmpbuttn.h \ + C:/wxWidgets-3.1.0/include/wx/checklst.h \ + C:/wxWidgets-3.1.0/include/wx/msw/checklst.h \ + C:/wxWidgets-3.1.0/include/wx/scrolbar.h \ + C:/wxWidgets-3.1.0/include/wx/msw/scrolbar.h \ + C:/wxWidgets-3.1.0/include/wx/statbmp.h \ + C:/wxWidgets-3.1.0/include/wx/msw/statbmp.h \ + C:/wxWidgets-3.1.0/include/wx/radiobox.h \ + C:/wxWidgets-3.1.0/include/wx/msw/radiobox.h \ + C:/wxWidgets-3.1.0/include/wx/radiobut.h \ + C:/wxWidgets-3.1.0/include/wx/msw/radiobut.h \ + C:/wxWidgets-3.1.0/include/wx/slider.h \ + C:/wxWidgets-3.1.0/include/wx/msw/slider.h \ + C:/wxWidgets-3.1.0/include/wx/gauge.h \ + C:/wxWidgets-3.1.0/include/wx/msw/gauge.h \ + C:/wxWidgets-3.1.0/include/wx/dirdlg.h \ + C:/wxWidgets-3.1.0/include/wx/msw/dirdlg.h \ + C:/wxWidgets-3.1.0/include/wx/combobox.h \ + C:/wxWidgets-3.1.0/include/wx/msw/combobox.h \ + C:/wxWidgets-3.1.0/include/wx/layout.h \ + C:/wxWidgets-3.1.0/include/wx/choicdlg.h \ + C:/wxWidgets-3.1.0/include/wx/generic/choicdgg.h \ + C:/wxWidgets-3.1.0/include/wx/textdlg.h \ + C:/wxWidgets-3.1.0/include/wx/generic/textdlgg.h \ + C:/wxWidgets-3.1.0/include/wx/filedlg.h \ + C:/wxWidgets-3.1.0/include/wx/msw/filedlg.h \ + C:/wxWidgets-3.1.0/include/wx/mdi.h \ + C:/wxWidgets-3.1.0/include/wx/msw/mdi.h rapidXML/rapidxml.hpp \ + rapidXML/rapidxml_print.hpp rapidXML/rapidxml.hpp \ + rapidXML/rapidxml_utils.hpp + +FileHanding.h: + +C:/wxWidgets-3.1.0/include/wx/string.h: + +C:/wxWidgets-3.1.0/include/wx/defs.h: + +C:/wxWidgets-3.1.0/include/wx/platform.h: + +C:/wxWidgets-3.1.0/include/wx/compiler.h: + +C:/wxWidgets-3.1.0/lib/gcc_dll/mswu/wx/setup.h: + +C:/wxWidgets-3.1.0/include/wx/msw/libraries.h: + +C:/wxWidgets-3.1.0/include/wx/msw/gccpriv.h: + +C:/wxWidgets-3.1.0/include/wx/chkconf.h: + +C:/wxWidgets-3.1.0/include/wx/msw/chkconf.h: + +C:/wxWidgets-3.1.0/include/wx/version.h: + +C:/wxWidgets-3.1.0/include/wx/cpp.h: + +C:/wxWidgets-3.1.0/include/wx/dlimpexp.h: + +C:/wxWidgets-3.1.0/include/wx/debug.h: + +C:/wxWidgets-3.1.0/include/wx/chartype.h: + +C:/wxWidgets-3.1.0/include/wx/windowid.h: + +C:/wxWidgets-3.1.0/include/wx/msw/winundef.h: + +C:/wxWidgets-3.1.0/include/wx/features.h: + +C:/wxWidgets-3.1.0/include/wx/wxcrtbase.h: + +C:/wxWidgets-3.1.0/include/wx/strvararg.h: + +C:/wxWidgets-3.1.0/include/wx/strconv.h: + +C:/wxWidgets-3.1.0/include/wx/buffer.h: + +C:/wxWidgets-3.1.0/include/wx/fontenc.h: + +C:/wxWidgets-3.1.0/include/wx/unichar.h: + +C:/wxWidgets-3.1.0/include/wx/stringimpl.h: + +C:/wxWidgets-3.1.0/include/wx/beforestd.h: + +C:/wxWidgets-3.1.0/include/wx/afterstd.h: + +C:/wxWidgets-3.1.0/include/wx/stringops.h: + +C:/wxWidgets-3.1.0/include/wx/iosfwrap.h: + +Workspace.h: + +C:/wxWidgets-3.1.0/include/wx/dcclient.h: + +C:/wxWidgets-3.1.0/include/wx/dc.h: + +C:/wxWidgets-3.1.0/include/wx/object.h: + +C:/wxWidgets-3.1.0/include/wx/memory.h: + +C:/wxWidgets-3.1.0/include/wx/msgout.h: + +C:/wxWidgets-3.1.0/include/wx/xti.h: + +C:/wxWidgets-3.1.0/include/wx/rtti.h: + +C:/wxWidgets-3.1.0/include/wx/flags.h: + +C:/wxWidgets-3.1.0/include/wx/xti2.h: + +C:/wxWidgets-3.1.0/include/wx/intl.h: + +C:/wxWidgets-3.1.0/include/wx/translation.h: + +C:/wxWidgets-3.1.0/include/wx/language.h: + +C:/wxWidgets-3.1.0/include/wx/hashmap.h: + +C:/wxWidgets-3.1.0/include/wx/wxcrt.h: + +C:/wxWidgets-3.1.0/include/wx/scopedptr.h: + +C:/wxWidgets-3.1.0/include/wx/checkeddelete.h: + +C:/wxWidgets-3.1.0/include/wx/colour.h: + +C:/wxWidgets-3.1.0/include/wx/gdiobj.h: + +C:/wxWidgets-3.1.0/include/wx/variant.h: + +C:/wxWidgets-3.1.0/include/wx/arrstr.h: + +C:/wxWidgets-3.1.0/include/wx/list.h: + +C:/wxWidgets-3.1.0/include/wx/vector.h: + +C:/wxWidgets-3.1.0/include/wx/scopeguard.h: + +C:/wxWidgets-3.1.0/include/wx/except.h: + +C:/wxWidgets-3.1.0/include/wx/meta/movable.h: + +C:/wxWidgets-3.1.0/include/wx/meta/pod.h: + +C:/wxWidgets-3.1.0/include/wx/meta/if.h: + +C:/wxWidgets-3.1.0/include/wx/longlong.h: + +C:/wxWidgets-3.1.0/include/wx/datetime.h: + +C:/wxWidgets-3.1.0/include/wx/anystr.h: + +C:/wxWidgets-3.1.0/include/wx/dynarray.h: + +C:/wxWidgets-3.1.0/include/wx/any.h: + +C:/wxWidgets-3.1.0/include/wx/typeinfo.h: + +C:/wxWidgets-3.1.0/include/wx/msw/colour.h: + +C:/wxWidgets-3.1.0/include/wx/font.h: + +C:/wxWidgets-3.1.0/include/wx/gdicmn.h: + +C:/wxWidgets-3.1.0/include/wx/math.h: + +C:/wxWidgets-3.1.0/include/wx/msw/font.h: + +C:/wxWidgets-3.1.0/include/wx/bitmap.h: + +C:/wxWidgets-3.1.0/include/wx/image.h: + +C:/wxWidgets-3.1.0/include/wx/stream.h: + +C:/wxWidgets-3.1.0/include/wx/filefn.h: + +C:/wxWidgets-3.1.0/include/wx/imagbmp.h: + +C:/wxWidgets-3.1.0/include/wx/imagpng.h: + +C:/wxWidgets-3.1.0/include/wx/versioninfo.h: + +C:/wxWidgets-3.1.0/include/wx/imaggif.h: + +C:/wxWidgets-3.1.0/include/wx/imagpcx.h: + +C:/wxWidgets-3.1.0/include/wx/imagjpeg.h: + +C:/wxWidgets-3.1.0/include/wx/imagtga.h: + +C:/wxWidgets-3.1.0/include/wx/imagtiff.h: + +C:/wxWidgets-3.1.0/include/wx/imagpnm.h: + +C:/wxWidgets-3.1.0/include/wx/imagxpm.h: + +C:/wxWidgets-3.1.0/include/wx/imagiff.h: + +C:/wxWidgets-3.1.0/include/wx/msw/bitmap.h: + +C:/wxWidgets-3.1.0/include/wx/msw/gdiimage.h: + +C:/wxWidgets-3.1.0/include/wx/palette.h: + +C:/wxWidgets-3.1.0/include/wx/msw/palette.h: + +C:/wxWidgets-3.1.0/include/wx/brush.h: + +C:/wxWidgets-3.1.0/include/wx/msw/brush.h: + +C:/wxWidgets-3.1.0/include/wx/pen.h: + +C:/wxWidgets-3.1.0/include/wx/msw/pen.h: + +C:/wxWidgets-3.1.0/include/wx/region.h: + +C:/wxWidgets-3.1.0/include/wx/msw/region.h: + +C:/wxWidgets-3.1.0/include/wx/affinematrix2d.h: + +C:/wxWidgets-3.1.0/include/wx/affinematrix2dbase.h: + +C:/wxWidgets-3.1.0/include/wx/geometry.h: + +C:/wxWidgets-3.1.0/include/wx/utils.h: + +C:/wxWidgets-3.1.0/include/wx/meta/implicitconversion.h: + +C:/wxWidgets-3.1.0/include/wx/mousestate.h: + +C:/wxWidgets-3.1.0/include/wx/kbdstate.h: + +C:/wxWidgets-3.1.0/include/wx/platinfo.h: + +C:/wxWidgets-3.1.0/include/wx/msgdlg.h: + +C:/wxWidgets-3.1.0/include/wx/dialog.h: + +C:/wxWidgets-3.1.0/include/wx/toplevel.h: + +C:/wxWidgets-3.1.0/include/wx/nonownedwnd.h: + +C:/wxWidgets-3.1.0/include/wx/window.h: + +C:/wxWidgets-3.1.0/include/wx/event.h: + +C:/wxWidgets-3.1.0/include/wx/clntdata.h: + +C:/wxWidgets-3.1.0/include/wx/cursor.h: + +C:/wxWidgets-3.1.0/include/wx/msw/cursor.h: + +C:/wxWidgets-3.1.0/include/wx/thread.h: + +C:/wxWidgets-3.1.0/include/wx/tracker.h: + +C:/wxWidgets-3.1.0/include/wx/meta/convertible.h: + +C:/wxWidgets-3.1.0/include/wx/meta/removeref.h: + +C:/wxWidgets-3.1.0/include/wx/validate.h: + +C:/wxWidgets-3.1.0/include/wx/accel.h: + +C:/wxWidgets-3.1.0/include/wx/msw/accel.h: + +C:/wxWidgets-3.1.0/include/wx/msw/window.h: + +C:/wxWidgets-3.1.0/include/wx/settings.h: + +C:/wxWidgets-3.1.0/include/wx/msw/nonownedwnd.h: + +C:/wxWidgets-3.1.0/include/wx/iconbndl.h: + +C:/wxWidgets-3.1.0/include/wx/icon.h: + +C:/wxWidgets-3.1.0/include/wx/iconloc.h: + +C:/wxWidgets-3.1.0/include/wx/msw/icon.h: + +C:/wxWidgets-3.1.0/include/wx/weakref.h: + +C:/wxWidgets-3.1.0/include/wx/meta/int2type.h: + +C:/wxWidgets-3.1.0/include/wx/msw/toplevel.h: + +C:/wxWidgets-3.1.0/include/wx/containr.h: + +C:/wxWidgets-3.1.0/include/wx/sharedptr.h: + +C:/wxWidgets-3.1.0/include/wx/atomic.h: + +C:/wxWidgets-3.1.0/include/wx/msw/wrapwin.h: + +C:/wxWidgets-3.1.0/include/wx/msw/dialog.h: + +C:/wxWidgets-3.1.0/include/wx/panel.h: + +C:/wxWidgets-3.1.0/include/wx/msw/panel.h: + +C:/wxWidgets-3.1.0/include/wx/stockitem.h: + +C:/wxWidgets-3.1.0/include/wx/generic/msgdlgg.h: + +C:/wxWidgets-3.1.0/include/wx/msw/msgdlg.h: + +C:/wxWidgets-3.1.0/include/wx/statusbr.h: + +C:/wxWidgets-3.1.0/include/wx/control.h: + +C:/wxWidgets-3.1.0/include/wx/msw/control.h: + +C:/wxWidgets-3.1.0/include/wx/msw/statusbar.h: + +C:/wxWidgets-3.1.0/include/wx/tooltip.h: + +C:/wxWidgets-3.1.0/include/wx/msw/tooltip.h: + +WorkspaceBase.h: + +C:/wxWidgets-3.1.0/include/wx/xrc/xmlres.h: + +C:/wxWidgets-3.1.0/include/wx/filesys.h: + +C:/wxWidgets-3.1.0/include/wx/filename.h: + +C:/wxWidgets-3.1.0/include/wx/file.h: + +C:/wxWidgets-3.1.0/include/wx/convauto.h: + +C:/wxWidgets-3.1.0/include/wx/artprov.h: + +C:/wxWidgets-3.1.0/include/wx/xrc/xmlreshandler.h: + +C:/wxWidgets-3.1.0/include/wx/imaglist.h: + +C:/wxWidgets-3.1.0/include/wx/msw/imaglist.h: + +C:/wxWidgets-3.1.0/include/wx/xrc/xh_bmp.h: + +C:/wxWidgets-3.1.0/include/wx/sizer.h: + +C:/wxWidgets-3.1.0/include/wx/glcanvas.h: + +C:/wxWidgets-3.1.0/include/wx/app.h: + +C:/wxWidgets-3.1.0/include/wx/eventfilter.h: + +C:/wxWidgets-3.1.0/include/wx/build.h: + +C:/wxWidgets-3.1.0/include/wx/cmdargs.h: + +C:/wxWidgets-3.1.0/include/wx/init.h: + +C:/wxWidgets-3.1.0/include/wx/msw/init.h: + +C:/wxWidgets-3.1.0/include/wx/log.h: + +C:/wxWidgets-3.1.0/include/wx/generic/logg.h: + +C:/wxWidgets-3.1.0/include/wx/msw/app.h: + +C:/wxWidgets-3.1.0/include/wx/msw/glcanvas.h: + +C:/wxWidgets-3.1.0/include/wx/persist.h: + +C:/wxWidgets-3.1.0/include/wx/confbase.h: + +C:/wxWidgets-3.1.0/include/wx/base64.h: + +C:/wxWidgets-3.1.0/include/wx/persist/toplevel.h: + +C:/wxWidgets-3.1.0/include/wx/persist/window.h: + +C:/wxWidgets-3.1.0/include/wx/display.h: + +C:/wxWidgets-3.1.0/include/wx/vidmode.h: + +C:/wxWidgets-3.1.0/include/wx/persist/bookctrl.h: + +C:/wxWidgets-3.1.0/include/wx/bookctrl.h: + +C:/wxWidgets-3.1.0/include/wx/withimages.h: + +C:/wxWidgets-3.1.0/include/wx/notebook.h: + +C:/wxWidgets-3.1.0/include/wx/msw/notebook.h: + +C:/wxWidgets-3.1.0/include/wx/persist/treebook.h: + +C:/wxWidgets-3.1.0/include/wx/treebook.h: + +C:/wxWidgets-3.1.0/include/wx/treectrl.h: + +C:/wxWidgets-3.1.0/include/wx/treebase.h: + +C:/wxWidgets-3.1.0/include/wx/itemid.h: + +C:/wxWidgets-3.1.0/include/wx/textctrl.h: + +C:/wxWidgets-3.1.0/include/wx/textentry.h: + +C:/wxWidgets-3.1.0/include/wx/msw/textentry.h: + +C:/wxWidgets-3.1.0/include/wx/ioswrap.h: + +C:/wxWidgets-3.1.0/include/wx/msw/textctrl.h: + +C:/wxWidgets-3.1.0/include/wx/systhemectrl.h: + +C:/wxWidgets-3.1.0/include/wx/msw/treectrl.h: + +Bus.h: + +BusForm.h: + +ElementForm.h: + +C:/wxWidgets-3.1.0/include/wx/stattext.h: + +C:/wxWidgets-3.1.0/include/wx/msw/stattext.h: + +C:/wxWidgets-3.1.0/include/wx/choice.h: + +C:/wxWidgets-3.1.0/include/wx/ctrlsub.h: + +C:/wxWidgets-3.1.0/include/wx/msw/ctrlsub.h: + +C:/wxWidgets-3.1.0/include/wx/msw/choice.h: + +C:/wxWidgets-3.1.0/include/wx/checkbox.h: + +C:/wxWidgets-3.1.0/include/wx/msw/checkbox.h: + +C:/wxWidgets-3.1.0/include/wx/msw/ownerdrawnbutton.h: + +C:/wxWidgets-3.1.0/include/wx/button.h: + +C:/wxWidgets-3.1.0/include/wx/anybutton.h: + +C:/wxWidgets-3.1.0/include/wx/msw/anybutton.h: + +C:/wxWidgets-3.1.0/include/wx/msw/button.h: + +C:/wxWidgets-3.1.0/include/wx/statbox.h: + +C:/wxWidgets-3.1.0/include/wx/msw/statbox.h: + +C:/wxWidgets-3.1.0/include/wx/statline.h: + +C:/wxWidgets-3.1.0/include/wx/msw/statline.h: + +C:/wxWidgets-3.1.0/include/wx/propgrid/manager.h: + +C:/wxWidgets-3.1.0/include/wx/propgrid/propgrid.h: + +C:/wxWidgets-3.1.0/include/wx/scrolwin.h: + +C:/wxWidgets-3.1.0/include/wx/generic/scrolwin.h: + +C:/wxWidgets-3.1.0/include/wx/recguard.h: + +C:/wxWidgets-3.1.0/include/wx/time.h: + +C:/wxWidgets-3.1.0/include/wx/propgrid/property.h: + +C:/wxWidgets-3.1.0/include/wx/propgrid/propgriddefs.h: + +C:/wxWidgets-3.1.0/include/wx/hashset.h: + +C:/wxWidgets-3.1.0/include/wx/tokenzr.h: + +C:/wxWidgets-3.1.0/include/wx/propgrid/propgridiface.h: + +C:/wxWidgets-3.1.0/include/wx/propgrid/propgridpagestate.h: + +C:/wxWidgets-3.1.0/include/wx/propgrid/props.h: + +C:/wxWidgets-3.1.0/include/wx/propgrid/editors.h: + +C:/wxWidgets-3.1.0/include/wx/listbox.h: + +C:/wxWidgets-3.1.0/include/wx/msw/listbox.h: + +C:/wxWidgets-3.1.0/include/wx/valtext.h: + +C:/wxWidgets-3.1.0/include/wx/toolbar.h: + +C:/wxWidgets-3.1.0/include/wx/tbarbase.h: + +C:/wxWidgets-3.1.0/include/wx/msw/toolbar.h: + +C:/wxWidgets-3.1.0/include/wx/headerctrl.h: + +C:/wxWidgets-3.1.0/include/wx/headercol.h: + +C:/wxWidgets-3.1.0/include/wx/msw/headerctrl.h: + +C:/wxWidgets-3.1.0/include/wx/propgrid/advprops.h: + +C:/wxWidgets-3.1.0/include/wx/spinbutt.h: + +C:/wxWidgets-3.1.0/include/wx/range.h: + +C:/wxWidgets-3.1.0/include/wx/msw/spinbutt.h: + +C:/wxWidgets-3.1.0/include/wx/listctrl.h: + +C:/wxWidgets-3.1.0/include/wx/listbase.h: + +C:/wxWidgets-3.1.0/include/wx/msw/listctrl.h: + +Element.h: + +C:/wxWidgets-3.1.0/include/wx/menu.h: + +C:/wxWidgets-3.1.0/include/wx/menuitem.h: + +C:/wxWidgets-3.1.0/include/wx/msw/menuitem.h: + +C:/wxWidgets-3.1.0/include/wx/ownerdrw.h: + +C:/wxWidgets-3.1.0/include/wx/msw/ownerdrw.h: + +C:/wxWidgets-3.1.0/include/wx/msw/menu.h: + +ElectricCalculation.h: + +Capacitor.h: + +Shunt.h: + +IndMotor.h: + +Machines.h: + +Inductor.h: + +Line.h: + +LineForm.h: + +Branch.h: + +Load.h: + +LoadForm.h: + +SyncGenerator.h: + +SyncMotor.h: + +Transformer.h: + +Text.h: + +wxGLString.h: + +C:/wxWidgets-3.1.0/include/wx/wx.h: + +C:/wxWidgets-3.1.0/include/wx/hash.h: + +C:/wxWidgets-3.1.0/include/wx/stopwatch.h: + +C:/wxWidgets-3.1.0/include/wx/timer.h: + +C:/wxWidgets-3.1.0/include/wx/module.h: + +C:/wxWidgets-3.1.0/include/wx/wxcrtvararg.h: + +C:/wxWidgets-3.1.0/include/wx/frame.h: + +C:/wxWidgets-3.1.0/include/wx/msw/frame.h: + +C:/wxWidgets-3.1.0/include/wx/dcmemory.h: + +C:/wxWidgets-3.1.0/include/wx/dcprint.h: + +C:/wxWidgets-3.1.0/include/wx/dcscreen.h: + +C:/wxWidgets-3.1.0/include/wx/dataobj.h: + +C:/wxWidgets-3.1.0/include/wx/msw/ole/dataform.h: + +C:/wxWidgets-3.1.0/include/wx/msw/ole/dataobj.h: + +C:/wxWidgets-3.1.0/include/wx/msw/ole/dataobj2.h: + +C:/wxWidgets-3.1.0/include/wx/bmpbuttn.h: + +C:/wxWidgets-3.1.0/include/wx/msw/bmpbuttn.h: + +C:/wxWidgets-3.1.0/include/wx/checklst.h: + +C:/wxWidgets-3.1.0/include/wx/msw/checklst.h: + +C:/wxWidgets-3.1.0/include/wx/scrolbar.h: + +C:/wxWidgets-3.1.0/include/wx/msw/scrolbar.h: + +C:/wxWidgets-3.1.0/include/wx/statbmp.h: + +C:/wxWidgets-3.1.0/include/wx/msw/statbmp.h: + +C:/wxWidgets-3.1.0/include/wx/radiobox.h: + +C:/wxWidgets-3.1.0/include/wx/msw/radiobox.h: + +C:/wxWidgets-3.1.0/include/wx/radiobut.h: + +C:/wxWidgets-3.1.0/include/wx/msw/radiobut.h: + +C:/wxWidgets-3.1.0/include/wx/slider.h: + +C:/wxWidgets-3.1.0/include/wx/msw/slider.h: + +C:/wxWidgets-3.1.0/include/wx/gauge.h: + +C:/wxWidgets-3.1.0/include/wx/msw/gauge.h: + +C:/wxWidgets-3.1.0/include/wx/dirdlg.h: + +C:/wxWidgets-3.1.0/include/wx/msw/dirdlg.h: + +C:/wxWidgets-3.1.0/include/wx/combobox.h: + +C:/wxWidgets-3.1.0/include/wx/msw/combobox.h: + +C:/wxWidgets-3.1.0/include/wx/layout.h: + +C:/wxWidgets-3.1.0/include/wx/choicdlg.h: + +C:/wxWidgets-3.1.0/include/wx/generic/choicdgg.h: + +C:/wxWidgets-3.1.0/include/wx/textdlg.h: + +C:/wxWidgets-3.1.0/include/wx/generic/textdlgg.h: + +C:/wxWidgets-3.1.0/include/wx/filedlg.h: + +C:/wxWidgets-3.1.0/include/wx/msw/filedlg.h: + +C:/wxWidgets-3.1.0/include/wx/mdi.h: + +C:/wxWidgets-3.1.0/include/wx/msw/mdi.h: + +rapidXML/rapidxml.hpp: + +rapidXML/rapidxml_print.hpp: + +rapidXML/rapidxml.hpp: + +rapidXML/rapidxml_utils.hpp: diff --git a/Project/Release/GeneratorStabForm.cpp.o b/Project/Release/GeneratorStabForm.cpp.o Binary files differindex 6e3ecd6..64bbc6c 100644 --- a/Project/Release/GeneratorStabForm.cpp.o +++ b/Project/Release/GeneratorStabForm.cpp.o diff --git a/Project/Release/IndMotor.cpp.o b/Project/Release/IndMotor.cpp.o Binary files differindex c4ca27f..8afaa98 100644 --- a/Project/Release/IndMotor.cpp.o +++ b/Project/Release/IndMotor.cpp.o diff --git a/Project/Release/IndMotorForm.cpp.o b/Project/Release/IndMotorForm.cpp.o Binary files differindex 876b22e..1a91d40 100644 --- a/Project/Release/IndMotorForm.cpp.o +++ b/Project/Release/IndMotorForm.cpp.o diff --git a/Project/Release/Inductor.cpp.o b/Project/Release/Inductor.cpp.o Binary files differindex f65788c..36cb0b0 100644 --- a/Project/Release/Inductor.cpp.o +++ b/Project/Release/Inductor.cpp.o diff --git a/Project/Release/Line.cpp.o b/Project/Release/Line.cpp.o Binary files differindex 0fd9f2a..53728d5 100644 --- a/Project/Release/Line.cpp.o +++ b/Project/Release/Line.cpp.o diff --git a/Project/Release/LineForm.cpp.o b/Project/Release/LineForm.cpp.o Binary files differindex 4e36059..3f0094a 100644 --- a/Project/Release/LineForm.cpp.o +++ b/Project/Release/LineForm.cpp.o diff --git a/Project/Release/Load.cpp.o b/Project/Release/Load.cpp.o Binary files differindex c5641c2..8d03c53 100644 --- a/Project/Release/Load.cpp.o +++ b/Project/Release/Load.cpp.o diff --git a/Project/Release/Machines.cpp.o b/Project/Release/Machines.cpp.o Binary files differindex 78e4dd9..68a1fc6 100644 --- a/Project/Release/Machines.cpp.o +++ b/Project/Release/Machines.cpp.o diff --git a/Project/Release/MainFrame.cpp.o b/Project/Release/MainFrame.cpp.o Binary files differindex e852390..8db3bdb 100644 --- a/Project/Release/MainFrame.cpp.o +++ b/Project/Release/MainFrame.cpp.o diff --git a/Project/Release/MainFrame.cpp.o.d b/Project/Release/MainFrame.cpp.o.d index 1313645..c8ce32c 100644 --- a/Project/Release/MainFrame.cpp.o.d +++ b/Project/Release/MainFrame.cpp.o.d @@ -129,7 +129,9 @@ Release/MainFrame.cpp.o: MainFrame.cpp MainFrame.h \ C:/wxWidgets-3.1.0/include/wx/msw/panel.h \ C:/wxWidgets-3.1.0/include/wx/stockitem.h \ C:/wxWidgets-3.1.0/include/wx/generic/msgdlgg.h \ - C:/wxWidgets-3.1.0/include/wx/msw/msgdlg.h MainFrameBase.h \ + C:/wxWidgets-3.1.0/include/wx/msw/msgdlg.h \ + C:/wxWidgets-3.1.0/include/wx/filedlg.h \ + C:/wxWidgets-3.1.0/include/wx/msw/filedlg.h MainFrameBase.h \ C:/wxWidgets-3.1.0/include/wx/xrc/xmlres.h \ C:/wxWidgets-3.1.0/include/wx/filesys.h \ C:/wxWidgets-3.1.0/include/wx/filename.h \ @@ -253,7 +255,47 @@ Release/MainFrame.cpp.o: MainFrame.cpp MainFrame.h \ C:/wxWidgets-3.1.0/include/wx/listbase.h \ C:/wxWidgets-3.1.0/include/wx/msw/listctrl.h Element.h Line.h LineForm.h \ Branch.h Transformer.h SyncGenerator.h Machines.h IndMotor.h SyncMotor.h \ - Load.h LoadForm.h Shunt.h Inductor.h Capacitor.h + Load.h LoadForm.h Shunt.h Inductor.h Capacitor.h FileHanding.h \ + ElectricCalculation.h Text.h wxGLString.h \ + C:/wxWidgets-3.1.0/include/wx/wx.h C:/wxWidgets-3.1.0/include/wx/hash.h \ + C:/wxWidgets-3.1.0/include/wx/module.h \ + C:/wxWidgets-3.1.0/include/wx/wxcrtvararg.h \ + C:/wxWidgets-3.1.0/include/wx/dcmemory.h \ + C:/wxWidgets-3.1.0/include/wx/dcprint.h \ + C:/wxWidgets-3.1.0/include/wx/dcscreen.h \ + C:/wxWidgets-3.1.0/include/wx/dataobj.h \ + C:/wxWidgets-3.1.0/include/wx/msw/ole/dataform.h \ + C:/wxWidgets-3.1.0/include/wx/msw/ole/dataobj.h \ + C:/wxWidgets-3.1.0/include/wx/msw/ole/dataobj2.h \ + C:/wxWidgets-3.1.0/include/wx/bmpbuttn.h \ + C:/wxWidgets-3.1.0/include/wx/msw/bmpbuttn.h \ + C:/wxWidgets-3.1.0/include/wx/checklst.h \ + C:/wxWidgets-3.1.0/include/wx/msw/checklst.h \ + C:/wxWidgets-3.1.0/include/wx/scrolbar.h \ + C:/wxWidgets-3.1.0/include/wx/msw/scrolbar.h \ + C:/wxWidgets-3.1.0/include/wx/statbmp.h \ + C:/wxWidgets-3.1.0/include/wx/msw/statbmp.h \ + C:/wxWidgets-3.1.0/include/wx/radiobox.h \ + C:/wxWidgets-3.1.0/include/wx/msw/radiobox.h \ + C:/wxWidgets-3.1.0/include/wx/radiobut.h \ + C:/wxWidgets-3.1.0/include/wx/msw/radiobut.h \ + C:/wxWidgets-3.1.0/include/wx/slider.h \ + C:/wxWidgets-3.1.0/include/wx/msw/slider.h \ + C:/wxWidgets-3.1.0/include/wx/gauge.h \ + C:/wxWidgets-3.1.0/include/wx/msw/gauge.h \ + C:/wxWidgets-3.1.0/include/wx/dirdlg.h \ + C:/wxWidgets-3.1.0/include/wx/msw/dirdlg.h \ + C:/wxWidgets-3.1.0/include/wx/combobox.h \ + C:/wxWidgets-3.1.0/include/wx/msw/combobox.h \ + C:/wxWidgets-3.1.0/include/wx/layout.h \ + C:/wxWidgets-3.1.0/include/wx/choicdlg.h \ + C:/wxWidgets-3.1.0/include/wx/generic/choicdgg.h \ + C:/wxWidgets-3.1.0/include/wx/textdlg.h \ + C:/wxWidgets-3.1.0/include/wx/generic/textdlgg.h \ + C:/wxWidgets-3.1.0/include/wx/mdi.h \ + C:/wxWidgets-3.1.0/include/wx/msw/mdi.h rapidXML/rapidxml.hpp \ + rapidXML/rapidxml_print.hpp rapidXML/rapidxml.hpp \ + rapidXML/rapidxml_utils.hpp MainFrame.h: @@ -521,6 +563,10 @@ C:/wxWidgets-3.1.0/include/wx/generic/msgdlgg.h: C:/wxWidgets-3.1.0/include/wx/msw/msgdlg.h: +C:/wxWidgets-3.1.0/include/wx/filedlg.h: + +C:/wxWidgets-3.1.0/include/wx/msw/filedlg.h: + MainFrameBase.h: C:/wxWidgets-3.1.0/include/wx/xrc/xmlres.h: @@ -806,3 +852,95 @@ Shunt.h: Inductor.h: Capacitor.h: + +FileHanding.h: + +ElectricCalculation.h: + +Text.h: + +wxGLString.h: + +C:/wxWidgets-3.1.0/include/wx/wx.h: + +C:/wxWidgets-3.1.0/include/wx/hash.h: + +C:/wxWidgets-3.1.0/include/wx/module.h: + +C:/wxWidgets-3.1.0/include/wx/wxcrtvararg.h: + +C:/wxWidgets-3.1.0/include/wx/dcmemory.h: + +C:/wxWidgets-3.1.0/include/wx/dcprint.h: + +C:/wxWidgets-3.1.0/include/wx/dcscreen.h: + +C:/wxWidgets-3.1.0/include/wx/dataobj.h: + +C:/wxWidgets-3.1.0/include/wx/msw/ole/dataform.h: + +C:/wxWidgets-3.1.0/include/wx/msw/ole/dataobj.h: + +C:/wxWidgets-3.1.0/include/wx/msw/ole/dataobj2.h: + +C:/wxWidgets-3.1.0/include/wx/bmpbuttn.h: + +C:/wxWidgets-3.1.0/include/wx/msw/bmpbuttn.h: + +C:/wxWidgets-3.1.0/include/wx/checklst.h: + +C:/wxWidgets-3.1.0/include/wx/msw/checklst.h: + +C:/wxWidgets-3.1.0/include/wx/scrolbar.h: + +C:/wxWidgets-3.1.0/include/wx/msw/scrolbar.h: + +C:/wxWidgets-3.1.0/include/wx/statbmp.h: + +C:/wxWidgets-3.1.0/include/wx/msw/statbmp.h: + +C:/wxWidgets-3.1.0/include/wx/radiobox.h: + +C:/wxWidgets-3.1.0/include/wx/msw/radiobox.h: + +C:/wxWidgets-3.1.0/include/wx/radiobut.h: + +C:/wxWidgets-3.1.0/include/wx/msw/radiobut.h: + +C:/wxWidgets-3.1.0/include/wx/slider.h: + +C:/wxWidgets-3.1.0/include/wx/msw/slider.h: + +C:/wxWidgets-3.1.0/include/wx/gauge.h: + +C:/wxWidgets-3.1.0/include/wx/msw/gauge.h: + +C:/wxWidgets-3.1.0/include/wx/dirdlg.h: + +C:/wxWidgets-3.1.0/include/wx/msw/dirdlg.h: + +C:/wxWidgets-3.1.0/include/wx/combobox.h: + +C:/wxWidgets-3.1.0/include/wx/msw/combobox.h: + +C:/wxWidgets-3.1.0/include/wx/layout.h: + +C:/wxWidgets-3.1.0/include/wx/choicdlg.h: + +C:/wxWidgets-3.1.0/include/wx/generic/choicdgg.h: + +C:/wxWidgets-3.1.0/include/wx/textdlg.h: + +C:/wxWidgets-3.1.0/include/wx/generic/textdlgg.h: + +C:/wxWidgets-3.1.0/include/wx/mdi.h: + +C:/wxWidgets-3.1.0/include/wx/msw/mdi.h: + +rapidXML/rapidxml.hpp: + +rapidXML/rapidxml_print.hpp: + +rapidXML/rapidxml.hpp: + +rapidXML/rapidxml_utils.hpp: diff --git a/Project/Release/PSP-UFU.exe b/Project/Release/PSP-UFU.exe Binary files differindex 299db58..d477b79 100644 --- a/Project/Release/PSP-UFU.exe +++ b/Project/Release/PSP-UFU.exe diff --git a/Project/Release/PowerFlow.cpp.o b/Project/Release/PowerFlow.cpp.o Binary files differindex 3f8ce8e..1da8b90 100644 --- a/Project/Release/PowerFlow.cpp.o +++ b/Project/Release/PowerFlow.cpp.o diff --git a/Project/Release/ReactiveShuntElementForm.cpp.o b/Project/Release/ReactiveShuntElementForm.cpp.o Binary files differindex 1ce9ee8..58f30f9 100644 --- a/Project/Release/ReactiveShuntElementForm.cpp.o +++ b/Project/Release/ReactiveShuntElementForm.cpp.o diff --git a/Project/Release/Shunt.cpp.o b/Project/Release/Shunt.cpp.o Binary files differindex e898859..4ad87ec 100644 --- a/Project/Release/Shunt.cpp.o +++ b/Project/Release/Shunt.cpp.o diff --git a/Project/Release/SwitchingForm.cpp.o b/Project/Release/SwitchingForm.cpp.o Binary files differindex 88c8520..c5b64f5 100644 --- a/Project/Release/SwitchingForm.cpp.o +++ b/Project/Release/SwitchingForm.cpp.o diff --git a/Project/Release/SyncGenerator.cpp.o b/Project/Release/SyncGenerator.cpp.o Binary files differindex df5cc88..1c75992 100644 --- a/Project/Release/SyncGenerator.cpp.o +++ b/Project/Release/SyncGenerator.cpp.o diff --git a/Project/Release/SyncMachineForm.cpp.o b/Project/Release/SyncMachineForm.cpp.o Binary files differindex a2afa10..0c315ad 100644 --- a/Project/Release/SyncMachineForm.cpp.o +++ b/Project/Release/SyncMachineForm.cpp.o diff --git a/Project/Release/SyncMotor.cpp.o b/Project/Release/SyncMotor.cpp.o Binary files differindex dfeab4c..7d9b66b 100644 --- a/Project/Release/SyncMotor.cpp.o +++ b/Project/Release/SyncMotor.cpp.o diff --git a/Project/Release/Text.cpp.o b/Project/Release/Text.cpp.o Binary files differindex 830aa66..cd86899 100644 --- a/Project/Release/Text.cpp.o +++ b/Project/Release/Text.cpp.o diff --git a/Project/Release/TextForm.cpp.o b/Project/Release/TextForm.cpp.o Binary files differindex 26381da..7d9de3f 100644 --- a/Project/Release/TextForm.cpp.o +++ b/Project/Release/TextForm.cpp.o diff --git a/Project/Release/Transformer.cpp.o b/Project/Release/Transformer.cpp.o Binary files differindex 3c97848..bca1767 100644 --- a/Project/Release/Transformer.cpp.o +++ b/Project/Release/Transformer.cpp.o diff --git a/Project/Release/TransformerForm.cpp.o b/Project/Release/TransformerForm.cpp.o Binary files differindex 50fbf8c..1cff932 100644 --- a/Project/Release/TransformerForm.cpp.o +++ b/Project/Release/TransformerForm.cpp.o diff --git a/Project/Release/Workspace.cpp.o b/Project/Release/Workspace.cpp.o Binary files differindex 9a16fe7..9c5c5b2 100644 --- a/Project/Release/Workspace.cpp.o +++ b/Project/Release/Workspace.cpp.o diff --git a/Project/Text.cpp b/Project/Text.cpp index 411520f..f012044 100644 --- a/Project/Text.cpp +++ b/Project/Text.cpp @@ -131,7 +131,7 @@ void Text::Rotate(bool clockwise) if(!clockwise) rotAngle = -m_rotationAngle; m_angle += rotAngle; - if(m_angle >= 360.0) m_angle = 0.0; + if(m_angle >= 360 || m_angle <= -360) m_angle = 0.0; } bool Text::ShowForm(wxWindow* parent, std::vector<Element*> elementList) diff --git a/Project/Transformer.cpp b/Project/Transformer.cpp index 04770e4..42fffaf 100644 --- a/Project/Transformer.cpp +++ b/Project/Transformer.cpp @@ -172,7 +172,7 @@ void Transformer::Rotate(bool clockwise) if(!clockwise) rotAngle = -m_rotationAngle; m_angle += rotAngle; - if(m_angle >= 360.0) m_angle = 0.0; + if(m_angle >= 360 || m_angle <= -360) m_angle = 0.0; // Rotate all the points, except the switches and buses points. for(int i = 2; i < (int)m_pointList.size() - 2; i++) { diff --git a/Project/Workspace.h b/Project/Workspace.h index 818e07e..d0ac2be 100644 --- a/Project/Workspace.h +++ b/Project/Workspace.h @@ -12,7 +12,7 @@ class Camera; class Element; -//class Bus; +// class Bus; class Line; class Transformer; class SyncGenerator; @@ -26,69 +26,72 @@ class Text; class PowerFlow; -enum WorkspaceMode -{ +enum WorkspaceMode { MODE_EDIT = 0, MODE_MOVE_ELEMENT, MODE_MOVE_PICKBOX, - MODE_MOVE_NODE, + MODE_MOVE_NODE, MODE_DRAG, - MODE_DRAG_INSERT, + MODE_DRAG_INSERT, MODE_DRAG_INSERT_TEXT, MODE_INSERT, MODE_INSERT_TEXT, MODE_SELECTION_RECT }; -enum ElementID -{ - ID_BUS = 0, - ID_LINE, - ID_TRANSFORMER, - ID_SYNCGENERATOR, - ID_INDMOTOR, - ID_SYNCMOTOR, - ID_LOAD, - ID_CAPACITOR, - ID_INDUCTOR, - ID_TEXT, - - NUM_ELEMENTS +enum ElementID { + ID_BUS = 0, + ID_LINE, + ID_TRANSFORMER, + ID_SYNCGENERATOR, + ID_INDMOTOR, + ID_SYNCMOTOR, + ID_LOAD, + ID_CAPACITOR, + ID_INDUCTOR, + ID_TEXT, + + NUM_ELEMENTS }; class Workspace : public WorkspaceBase { - public: +public: Workspace(); Workspace(wxWindow* parent, wxString name = wxEmptyString, wxStatusBar* statusBar = NULL); ~Workspace(); wxString GetName() const { return m_name; } std::vector<Element*> GetElementList() const { return m_elementList; } - WorkspaceMode GetWorkspaceMode() const { return m_mode; } - Camera* GetCamera() const { return m_camera; } - - void SetName(wxString name) { m_name = name; } - void SetElementList(std::vector<Element*> elementList) { m_elementList = elementList; } - void SetStatusBarText(wxString text) { m_statusBar->SetStatusText(text); } - void SetWorkspaceMode(WorkspaceMode mode) { m_mode = mode; } - - void Redraw() { m_glCanvas->Refresh(); } - void RotateSelectedElements(bool clockwise = true); - void DeleteSelectedElements(); - void Fit(); - - void ValidateBusesVoltages(Element* initialBus); - void ValidateElementsVoltages(); + std::vector<Text*> GetTextList() const { return m_textList; } + WorkspaceMode GetWorkspaceMode() const { return m_mode; } + Camera* GetCamera() const { return m_camera; } + wxFileName GetSavedPath() const { return m_savedPath; } + + void SetName(wxString name) { m_name = name; } + void SetElementList(std::vector<Element*> elementList) { m_elementList = elementList; } + void SetTextList(std::vector<Text*> textList) { m_textList = textList; } + void SetStatusBarText(wxString text) { m_statusBar->SetStatusText(text); } + void SetWorkspaceMode(WorkspaceMode mode) { m_mode = mode; } + void SetSavedPath(wxFileName savedPath) { m_savedPath = savedPath; } + + void Redraw() { m_glCanvas->Refresh(); } + void RotateSelectedElements(bool clockwise = true); + void DeleteSelectedElements(); + void Fit(); + + void ValidateBusesVoltages(Element* initialBus); + void ValidateElementsVoltages(); + void UpdateTextElements(); - - int GetElementNumber(ElementID elementID) { return m_elementNumber[elementID]; } - void IncrementElementNumber(ElementID elementID) { m_elementNumber[elementID]++; } - + + int GetElementNumber(ElementID elementID) { return m_elementNumber[elementID]; } + void IncrementElementNumber(ElementID elementID) { m_elementNumber[elementID]++; } + bool RunPowerFlow(); - protected: +protected: virtual void OnLeftDoubleClick(wxMouseEvent& event); virtual void OnRightClickDown(wxMouseEvent& event); virtual void OnLeftClickUp(wxMouseEvent& event); @@ -102,6 +105,7 @@ class Workspace : public WorkspaceBase virtual void OnPopupClick(wxCommandEvent& event); void SetViewport(); + void UpdateStatusBar(); wxGLContext* m_glContext; wxStatusBar* m_statusBar; @@ -111,25 +115,25 @@ class Workspace : public WorkspaceBase WorkspaceMode m_mode = MODE_EDIT; std::vector<Element*> m_elementList; - int m_elementNumber[NUM_ELEMENTS]; - - std::vector<Text*> m_textList; + int m_elementNumber[NUM_ELEMENTS]; - void UpdateStatusBar(); + std::vector<Text*> m_textList; + + wxFileName m_savedPath; - private: +private: wxRect2DDouble m_selectionRect; wxPoint2DDouble m_startSelRect; }; class Camera { - public: +public: Camera(); ~Camera(); void SetScale(wxPoint2DDouble screenPoint, double delta); - void SetScale(double scale) { m_scale = scale; } + void SetScale(double scale) { m_scale = scale; } void SetTranslation(wxPoint2DDouble screenPoint); void StartTranslation(wxPoint2DDouble startPoint) { this->m_translationStartPt = startPoint; } void UpdateMousePosition(wxPoint2DDouble mousePosition) { this->m_mousePosition = mousePosition; } @@ -137,18 +141,18 @@ class Camera wxPoint2DDouble GetTranslation() const { return m_translation; } wxPoint2DDouble GetMousePosition(bool worldCoords = true) const; wxPoint2DDouble ScreenToWorld(wxPoint2DDouble screenCoords) const; - double GetZoomMin() const { return m_zoomMin; } - double GetZoomMax() const { return m_zoomMax; } + double GetZoomMin() const { return m_zoomMin; } + double GetZoomMax() const { return m_zoomMax; } - protected: +protected: wxPoint2DDouble m_translation; wxPoint2DDouble m_translationStartPt; double m_scale; wxPoint2DDouble m_mousePosition; - - double m_zoomMin = 0.05; - double m_zoomMax = 3.0; + + double m_zoomMin = 0.05; + double m_zoomMax = 3.0; }; -#endif // WORKSPACE_H +#endif // WORKSPACE_H diff --git a/Project/rapidXML/rapidxml.hpp b/Project/rapidXML/rapidxml.hpp new file mode 100644 index 0000000..ae91e08 --- /dev/null +++ b/Project/rapidXML/rapidxml.hpp @@ -0,0 +1,2596 @@ +#ifndef RAPIDXML_HPP_INCLUDED +#define RAPIDXML_HPP_INCLUDED + +// Copyright (C) 2006, 2009 Marcin Kalicinski +// Version 1.13 +// Revision $DateTime: 2009/05/13 01:46:17 $ +//! \file rapidxml.hpp This file contains rapidxml parser and DOM implementation + +// If standard library is disabled, user must provide implementations of required functions and typedefs +#if !defined(RAPIDXML_NO_STDLIB) + #include <cstdlib> // For std::size_t + #include <cassert> // For assert + #include <new> // For placement new +#endif + +// On MSVC, disable "conditional expression is constant" warning (level 4). +// This warning is almost impossible to avoid with certain types of templated code +#ifdef _MSC_VER + #pragma warning(push) + #pragma warning(disable:4127) // Conditional expression is constant +#endif + +/////////////////////////////////////////////////////////////////////////// +// RAPIDXML_PARSE_ERROR + +#if defined(RAPIDXML_NO_EXCEPTIONS) + +#define RAPIDXML_PARSE_ERROR(what, where) { parse_error_handler(what, where); assert(0); } + +namespace rapidxml +{ + //! When exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, + //! this function is called to notify user about the error. + //! It must be defined by the user. + //! <br><br> + //! This function cannot return. If it does, the results are undefined. + //! <br><br> + //! A very simple definition might look like that: + //! <pre> + //! void %rapidxml::%parse_error_handler(const char *what, void *where) + //! { + //! std::cout << "Parse error: " << what << "\n"; + //! std::abort(); + //! } + //! </pre> + //! \param what Human readable description of the error. + //! \param where Pointer to character data where error was detected. + void parse_error_handler(const char *what, void *where); +} + +#else + +#include <exception> // For std::exception + +#define RAPIDXML_PARSE_ERROR(what, where) throw parse_error(what, where) + +namespace rapidxml +{ + + //! Parse error exception. + //! This exception is thrown by the parser when an error occurs. + //! Use what() function to get human-readable error message. + //! Use where() function to get a pointer to position within source text where error was detected. + //! <br><br> + //! If throwing exceptions by the parser is undesirable, + //! it can be disabled by defining RAPIDXML_NO_EXCEPTIONS macro before rapidxml.hpp is included. + //! This will cause the parser to call rapidxml::parse_error_handler() function instead of throwing an exception. + //! This function must be defined by the user. + //! <br><br> + //! This class derives from <code>std::exception</code> class. + class parse_error: public std::exception + { + + public: + + //! Constructs parse error + parse_error(const char *what, void *where) + : m_what(what) + , m_where(where) + { + } + + //! Gets human readable description of error. + //! \return Pointer to null terminated description of the error. + virtual const char *what() const throw() + { + return m_what; + } + + //! Gets pointer to character data where error happened. + //! Ch should be the same as char type of xml_document that produced the error. + //! \return Pointer to location within the parsed string where error occured. + template<class Ch> + Ch *where() const + { + return reinterpret_cast<Ch *>(m_where); + } + + private: + + const char *m_what; + void *m_where; + + }; +} + +#endif + +/////////////////////////////////////////////////////////////////////////// +// Pool sizes + +#ifndef RAPIDXML_STATIC_POOL_SIZE + // Size of static memory block of memory_pool. + // Define RAPIDXML_STATIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value. + // No dynamic memory allocations are performed by memory_pool until static memory is exhausted. + #define RAPIDXML_STATIC_POOL_SIZE (64 * 1024) +#endif + +#ifndef RAPIDXML_DYNAMIC_POOL_SIZE + // Size of dynamic memory block of memory_pool. + // Define RAPIDXML_DYNAMIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value. + // After the static block is exhausted, dynamic blocks with approximately this size are allocated by memory_pool. + #define RAPIDXML_DYNAMIC_POOL_SIZE (64 * 1024) +#endif + +#ifndef RAPIDXML_ALIGNMENT + // Memory allocation alignment. + // Define RAPIDXML_ALIGNMENT before including rapidxml.hpp if you want to override the default value, which is the size of pointer. + // All memory allocations for nodes, attributes and strings will be aligned to this value. + // This must be a power of 2 and at least 1, otherwise memory_pool will not work. + #define RAPIDXML_ALIGNMENT sizeof(void *) +#endif + +namespace rapidxml +{ + // Forward declarations + template<class Ch> class xml_node; + template<class Ch> class xml_attribute; + template<class Ch> class xml_document; + + //! Enumeration listing all node types produced by the parser. + //! Use xml_node::type() function to query node type. + enum node_type + { + node_document, //!< A document node. Name and value are empty. + node_element, //!< An element node. Name contains element name. Value contains text of first data node. + node_data, //!< A data node. Name is empty. Value contains data text. + node_cdata, //!< A CDATA node. Name is empty. Value contains data text. + node_comment, //!< A comment node. Name is empty. Value contains comment text. + node_declaration, //!< A declaration node. Name and value are empty. Declaration parameters (version, encoding and standalone) are in node attributes. + node_doctype, //!< A DOCTYPE node. Name is empty. Value contains DOCTYPE text. + node_pi //!< A PI node. Name contains target. Value contains instructions. + }; + + /////////////////////////////////////////////////////////////////////// + // Parsing flags + + //! Parse flag instructing the parser to not create data nodes. + //! Text of first data node will still be placed in value of parent element, unless rapidxml::parse_no_element_values flag is also specified. + //! Can be combined with other flags by use of | operator. + //! <br><br> + //! See xml_document::parse() function. + const int parse_no_data_nodes = 0x1; + + //! Parse flag instructing the parser to not use text of first data node as a value of parent element. + //! Can be combined with other flags by use of | operator. + //! Note that child data nodes of element node take precendence over its value when printing. + //! That is, if element has one or more child data nodes <em>and</em> a value, the value will be ignored. + //! Use rapidxml::parse_no_data_nodes flag to prevent creation of data nodes if you want to manipulate data using values of elements. + //! <br><br> + //! See xml_document::parse() function. + const int parse_no_element_values = 0x2; + + //! Parse flag instructing the parser to not place zero terminators after strings in the source text. + //! By default zero terminators are placed, modifying source text. + //! Can be combined with other flags by use of | operator. + //! <br><br> + //! See xml_document::parse() function. + const int parse_no_string_terminators = 0x4; + + //! Parse flag instructing the parser to not translate entities in the source text. + //! By default entities are translated, modifying source text. + //! Can be combined with other flags by use of | operator. + //! <br><br> + //! See xml_document::parse() function. + const int parse_no_entity_translation = 0x8; + + //! Parse flag instructing the parser to disable UTF-8 handling and assume plain 8 bit characters. + //! By default, UTF-8 handling is enabled. + //! Can be combined with other flags by use of | operator. + //! <br><br> + //! See xml_document::parse() function. + const int parse_no_utf8 = 0x10; + + //! Parse flag instructing the parser to create XML declaration node. + //! By default, declaration node is not created. + //! Can be combined with other flags by use of | operator. + //! <br><br> + //! See xml_document::parse() function. + const int parse_declaration_node = 0x20; + + //! Parse flag instructing the parser to create comments nodes. + //! By default, comment nodes are not created. + //! Can be combined with other flags by use of | operator. + //! <br><br> + //! See xml_document::parse() function. + const int parse_comment_nodes = 0x40; + + //! Parse flag instructing the parser to create DOCTYPE node. + //! By default, doctype node is not created. + //! Although W3C specification allows at most one DOCTYPE node, RapidXml will silently accept documents with more than one. + //! Can be combined with other flags by use of | operator. + //! <br><br> + //! See xml_document::parse() function. + const int parse_doctype_node = 0x80; + + //! Parse flag instructing the parser to create PI nodes. + //! By default, PI nodes are not created. + //! Can be combined with other flags by use of | operator. + //! <br><br> + //! See xml_document::parse() function. + const int parse_pi_nodes = 0x100; + + //! Parse flag instructing the parser to validate closing tag names. + //! If not set, name inside closing tag is irrelevant to the parser. + //! By default, closing tags are not validated. + //! Can be combined with other flags by use of | operator. + //! <br><br> + //! See xml_document::parse() function. + const int parse_validate_closing_tags = 0x200; + + //! Parse flag instructing the parser to trim all leading and trailing whitespace of data nodes. + //! By default, whitespace is not trimmed. + //! This flag does not cause the parser to modify source text. + //! Can be combined with other flags by use of | operator. + //! <br><br> + //! See xml_document::parse() function. + const int parse_trim_whitespace = 0x400; + + //! Parse flag instructing the parser to condense all whitespace runs of data nodes to a single space character. + //! Trimming of leading and trailing whitespace of data is controlled by rapidxml::parse_trim_whitespace flag. + //! By default, whitespace is not normalized. + //! If this flag is specified, source text will be modified. + //! Can be combined with other flags by use of | operator. + //! <br><br> + //! See xml_document::parse() function. + const int parse_normalize_whitespace = 0x800; + + // Compound flags + + //! Parse flags which represent default behaviour of the parser. + //! This is always equal to 0, so that all other flags can be simply ored together. + //! Normally there is no need to inconveniently disable flags by anding with their negated (~) values. + //! This also means that meaning of each flag is a <i>negation</i> of the default setting. + //! For example, if flag name is rapidxml::parse_no_utf8, it means that utf-8 is <i>enabled</i> by default, + //! and using the flag will disable it. + //! <br><br> + //! See xml_document::parse() function. + const int parse_default = 0; + + //! A combination of parse flags that forbids any modifications of the source text. + //! This also results in faster parsing. However, note that the following will occur: + //! <ul> + //! <li>names and values of nodes will not be zero terminated, you have to use xml_base::name_size() and xml_base::value_size() functions to determine where name and value ends</li> + //! <li>entities will not be translated</li> + //! <li>whitespace will not be normalized</li> + //! </ul> + //! See xml_document::parse() function. + const int parse_non_destructive = parse_no_string_terminators | parse_no_entity_translation; + + //! A combination of parse flags resulting in fastest possible parsing, without sacrificing important data. + //! <br><br> + //! See xml_document::parse() function. + const int parse_fastest = parse_non_destructive | parse_no_data_nodes; + + //! A combination of parse flags resulting in largest amount of data being extracted. + //! This usually results in slowest parsing. + //! <br><br> + //! See xml_document::parse() function. + const int parse_full = parse_declaration_node | parse_comment_nodes | parse_doctype_node | parse_pi_nodes | parse_validate_closing_tags; + + /////////////////////////////////////////////////////////////////////// + // Internals + + //! \cond internal + namespace internal + { + + // Struct that contains lookup tables for the parser + // It must be a template to allow correct linking (because it has static data members, which are defined in a header file). + template<int Dummy> + struct lookup_tables + { + static const unsigned char lookup_whitespace[256]; // Whitespace table + static const unsigned char lookup_node_name[256]; // Node name table + static const unsigned char lookup_text[256]; // Text table + static const unsigned char lookup_text_pure_no_ws[256]; // Text table + static const unsigned char lookup_text_pure_with_ws[256]; // Text table + static const unsigned char lookup_attribute_name[256]; // Attribute name table + static const unsigned char lookup_attribute_data_1[256]; // Attribute data table with single quote + static const unsigned char lookup_attribute_data_1_pure[256]; // Attribute data table with single quote + static const unsigned char lookup_attribute_data_2[256]; // Attribute data table with double quotes + static const unsigned char lookup_attribute_data_2_pure[256]; // Attribute data table with double quotes + static const unsigned char lookup_digits[256]; // Digits + static const unsigned char lookup_upcase[256]; // To uppercase conversion table for ASCII characters + }; + + // Find length of the string + template<class Ch> + inline std::size_t measure(const Ch *p) + { + const Ch *tmp = p; + while (*tmp) + ++tmp; + return tmp - p; + } + + // Compare strings for equality + template<class Ch> + inline bool compare(const Ch *p1, std::size_t size1, const Ch *p2, std::size_t size2, bool case_sensitive) + { + if (size1 != size2) + return false; + if (case_sensitive) + { + for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2) + if (*p1 != *p2) + return false; + } + else + { + for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2) + if (lookup_tables<0>::lookup_upcase[static_cast<unsigned char>(*p1)] != lookup_tables<0>::lookup_upcase[static_cast<unsigned char>(*p2)]) + return false; + } + return true; + } + } + //! \endcond + + /////////////////////////////////////////////////////////////////////// + // Memory pool + + //! This class is used by the parser to create new nodes and attributes, without overheads of dynamic memory allocation. + //! In most cases, you will not need to use this class directly. + //! However, if you need to create nodes manually or modify names/values of nodes, + //! you are encouraged to use memory_pool of relevant xml_document to allocate the memory. + //! Not only is this faster than allocating them by using <code>new</code> operator, + //! but also their lifetime will be tied to the lifetime of document, + //! possibly simplyfing memory management. + //! <br><br> + //! Call allocate_node() or allocate_attribute() functions to obtain new nodes or attributes from the pool. + //! You can also call allocate_string() function to allocate strings. + //! Such strings can then be used as names or values of nodes without worrying about their lifetime. + //! Note that there is no <code>free()</code> function -- all allocations are freed at once when clear() function is called, + //! or when the pool is destroyed. + //! <br><br> + //! It is also possible to create a standalone memory_pool, and use it + //! to allocate nodes, whose lifetime will not be tied to any document. + //! <br><br> + //! Pool maintains <code>RAPIDXML_STATIC_POOL_SIZE</code> bytes of statically allocated memory. + //! Until static memory is exhausted, no dynamic memory allocations are done. + //! When static memory is exhausted, pool allocates additional blocks of memory of size <code>RAPIDXML_DYNAMIC_POOL_SIZE</code> each, + //! by using global <code>new[]</code> and <code>delete[]</code> operators. + //! This behaviour can be changed by setting custom allocation routines. + //! Use set_allocator() function to set them. + //! <br><br> + //! Allocations for nodes, attributes and strings are aligned at <code>RAPIDXML_ALIGNMENT</code> bytes. + //! This value defaults to the size of pointer on target architecture. + //! <br><br> + //! To obtain absolutely top performance from the parser, + //! it is important that all nodes are allocated from a single, contiguous block of memory. + //! Otherwise, cache misses when jumping between two (or more) disjoint blocks of memory can slow down parsing quite considerably. + //! If required, you can tweak <code>RAPIDXML_STATIC_POOL_SIZE</code>, <code>RAPIDXML_DYNAMIC_POOL_SIZE</code> and <code>RAPIDXML_ALIGNMENT</code> + //! to obtain best wasted memory to performance compromise. + //! To do it, define their values before rapidxml.hpp file is included. + //! \param Ch Character type of created nodes. + template<class Ch = char> + class memory_pool + { + + public: + + //! \cond internal + typedef void *(alloc_func)(std::size_t); // Type of user-defined function used to allocate memory + typedef void (free_func)(void *); // Type of user-defined function used to free memory + //! \endcond + + //! Constructs empty pool with default allocator functions. + memory_pool() + : m_alloc_func(0) + , m_free_func(0) + { + init(); + } + + //! Destroys pool and frees all the memory. + //! This causes memory occupied by nodes allocated by the pool to be freed. + //! Nodes allocated from the pool are no longer valid. + ~memory_pool() + { + clear(); + } + + //! Allocates a new node from the pool, and optionally assigns name and value to it. + //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>. + //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function + //! will call rapidxml::parse_error_handler() function. + //! \param type Type of node to create. + //! \param name Name to assign to the node, or 0 to assign no name. + //! \param value Value to assign to the node, or 0 to assign no value. + //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string. + //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string. + //! \return Pointer to allocated node. This pointer will never be NULL. + xml_node<Ch> *allocate_node(node_type type, + const Ch *name = 0, const Ch *value = 0, + std::size_t name_size = 0, std::size_t value_size = 0) + { + void *memory = allocate_aligned(sizeof(xml_node<Ch>)); + xml_node<Ch> *node = new(memory) xml_node<Ch>(type); + if (name) + { + if (name_size > 0) + node->name(name, name_size); + else + node->name(name); + } + if (value) + { + if (value_size > 0) + node->value(value, value_size); + else + node->value(value); + } + return node; + } + + //! Allocates a new attribute from the pool, and optionally assigns name and value to it. + //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>. + //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function + //! will call rapidxml::parse_error_handler() function. + //! \param name Name to assign to the attribute, or 0 to assign no name. + //! \param value Value to assign to the attribute, or 0 to assign no value. + //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string. + //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string. + //! \return Pointer to allocated attribute. This pointer will never be NULL. + xml_attribute<Ch> *allocate_attribute(const Ch *name = 0, const Ch *value = 0, + std::size_t name_size = 0, std::size_t value_size = 0) + { + void *memory = allocate_aligned(sizeof(xml_attribute<Ch>)); + xml_attribute<Ch> *attribute = new(memory) xml_attribute<Ch>; + if (name) + { + if (name_size > 0) + attribute->name(name, name_size); + else + attribute->name(name); + } + if (value) + { + if (value_size > 0) + attribute->value(value, value_size); + else + attribute->value(value); + } + return attribute; + } + + //! Allocates a char array of given size from the pool, and optionally copies a given string to it. + //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>. + //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function + //! will call rapidxml::parse_error_handler() function. + //! \param source String to initialize the allocated memory with, or 0 to not initialize it. + //! \param size Number of characters to allocate, or zero to calculate it automatically from source string length; if size is 0, source string must be specified and null terminated. + //! \return Pointer to allocated char array. This pointer will never be NULL. + Ch *allocate_string(const Ch *source = 0, std::size_t size = 0) + { + assert(source || size); // Either source or size (or both) must be specified + if (size == 0) + size = internal::measure(source) + 1; + Ch *result = static_cast<Ch *>(allocate_aligned(size * sizeof(Ch))); + if (source) + for (std::size_t i = 0; i < size; ++i) + result[i] = source[i]; + return result; + } + + //! Clones an xml_node and its hierarchy of child nodes and attributes. + //! Nodes and attributes are allocated from this memory pool. + //! Names and values are not cloned, they are shared between the clone and the source. + //! Result node can be optionally specified as a second parameter, + //! in which case its contents will be replaced with cloned source node. + //! This is useful when you want to clone entire document. + //! \param source Node to clone. + //! \param result Node to put results in, or 0 to automatically allocate result node + //! \return Pointer to cloned node. This pointer will never be NULL. + xml_node<Ch> *clone_node(const xml_node<Ch> *source, xml_node<Ch> *result = 0) + { + // Prepare result node + if (result) + { + result->remove_all_attributes(); + result->remove_all_nodes(); + result->type(source->type()); + } + else + result = allocate_node(source->type()); + + // Clone name and value + result->name(source->name(), source->name_size()); + result->value(source->value(), source->value_size()); + + // Clone child nodes and attributes + for (xml_node<Ch> *child = source->first_node(); child; child = child->next_sibling()) + result->append_node(clone_node(child)); + for (xml_attribute<Ch> *attr = source->first_attribute(); attr; attr = attr->next_attribute()) + result->append_attribute(allocate_attribute(attr->name(), attr->value(), attr->name_size(), attr->value_size())); + + return result; + } + + //! Clears the pool. + //! This causes memory occupied by nodes allocated by the pool to be freed. + //! Any nodes or strings allocated from the pool will no longer be valid. + void clear() + { + while (m_begin != m_static_memory) + { + char *previous_begin = reinterpret_cast<header *>(align(m_begin))->previous_begin; + if (m_free_func) + m_free_func(m_begin); + else + delete[] m_begin; + m_begin = previous_begin; + } + init(); + } + + //! Sets or resets the user-defined memory allocation functions for the pool. + //! This can only be called when no memory is allocated from the pool yet, otherwise results are undefined. + //! Allocation function must not return invalid pointer on failure. It should either throw, + //! stop the program, or use <code>longjmp()</code> function to pass control to other place of program. + //! If it returns invalid pointer, results are undefined. + //! <br><br> + //! User defined allocation functions must have the following forms: + //! <br><code> + //! <br>void *allocate(std::size_t size); + //! <br>void free(void *pointer); + //! </code><br> + //! \param af Allocation function, or 0 to restore default function + //! \param ff Free function, or 0 to restore default function + void set_allocator(alloc_func *af, free_func *ff) + { + assert(m_begin == m_static_memory && m_ptr == align(m_begin)); // Verify that no memory is allocated yet + m_alloc_func = af; + m_free_func = ff; + } + + private: + + struct header + { + char *previous_begin; + }; + + void init() + { + m_begin = m_static_memory; + m_ptr = align(m_begin); + m_end = m_static_memory + sizeof(m_static_memory); + } + + char *align(char *ptr) + { + std::size_t alignment = ((RAPIDXML_ALIGNMENT - (std::size_t(ptr) & (RAPIDXML_ALIGNMENT - 1))) & (RAPIDXML_ALIGNMENT - 1)); + return ptr + alignment; + } + + char *allocate_raw(std::size_t size) + { + // Allocate + void *memory; + if (m_alloc_func) // Allocate memory using either user-specified allocation function or global operator new[] + { + memory = m_alloc_func(size); + assert(memory); // Allocator is not allowed to return 0, on failure it must either throw, stop the program or use longjmp + } + else + { + memory = new char[size]; +#ifdef RAPIDXML_NO_EXCEPTIONS + if (!memory) // If exceptions are disabled, verify memory allocation, because new will not be able to throw bad_alloc + RAPIDXML_PARSE_ERROR("out of memory", 0); +#endif + } + return static_cast<char *>(memory); + } + + void *allocate_aligned(std::size_t size) + { + // Calculate aligned pointer + char *result = align(m_ptr); + + // If not enough memory left in current pool, allocate a new pool + if (result + size > m_end) + { + // Calculate required pool size (may be bigger than RAPIDXML_DYNAMIC_POOL_SIZE) + std::size_t pool_size = RAPIDXML_DYNAMIC_POOL_SIZE; + if (pool_size < size) + pool_size = size; + + // Allocate + std::size_t alloc_size = sizeof(header) + (2 * RAPIDXML_ALIGNMENT - 2) + pool_size; // 2 alignments required in worst case: one for header, one for actual allocation + char *raw_memory = allocate_raw(alloc_size); + + // Setup new pool in allocated memory + char *pool = align(raw_memory); + header *new_header = reinterpret_cast<header *>(pool); + new_header->previous_begin = m_begin; + m_begin = raw_memory; + m_ptr = pool + sizeof(header); + m_end = raw_memory + alloc_size; + + // Calculate aligned pointer again using new pool + result = align(m_ptr); + } + + // Update pool and return aligned pointer + m_ptr = result + size; + return result; + } + + char *m_begin; // Start of raw memory making up current pool + char *m_ptr; // First free byte in current pool + char *m_end; // One past last available byte in current pool + char m_static_memory[RAPIDXML_STATIC_POOL_SIZE]; // Static raw memory + alloc_func *m_alloc_func; // Allocator function, or 0 if default is to be used + free_func *m_free_func; // Free function, or 0 if default is to be used + }; + + /////////////////////////////////////////////////////////////////////////// + // XML base + + //! Base class for xml_node and xml_attribute implementing common functions: + //! name(), name_size(), value(), value_size() and parent(). + //! \param Ch Character type to use + template<class Ch = char> + class xml_base + { + + public: + + /////////////////////////////////////////////////////////////////////////// + // Construction & destruction + + // Construct a base with empty name, value and parent + xml_base() + : m_name(0) + , m_value(0) + , m_parent(0) + { + } + + /////////////////////////////////////////////////////////////////////////// + // Node data access + + //! Gets name of the node. + //! Interpretation of name depends on type of node. + //! Note that name will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse. + //! <br><br> + //! Use name_size() function to determine length of the name. + //! \return Name of node, or empty string if node has no name. + Ch *name() const + { + return m_name ? m_name : nullstr(); + } + + //! Gets size of node name, not including terminator character. + //! This function works correctly irrespective of whether name is or is not zero terminated. + //! \return Size of node name, in characters. + std::size_t name_size() const + { + return m_name ? m_name_size : 0; + } + + //! Gets value of node. + //! Interpretation of value depends on type of node. + //! Note that value will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse. + //! <br><br> + //! Use value_size() function to determine length of the value. + //! \return Value of node, or empty string if node has no value. + Ch *value() const + { + return m_value ? m_value : nullstr(); + } + + //! Gets size of node value, not including terminator character. + //! This function works correctly irrespective of whether value is or is not zero terminated. + //! \return Size of node value, in characters. + std::size_t value_size() const + { + return m_value ? m_value_size : 0; + } + + /////////////////////////////////////////////////////////////////////////// + // Node modification + + //! Sets name of node to a non zero-terminated string. + //! See \ref ownership_of_strings. + //! <br><br> + //! Note that node does not own its name or value, it only stores a pointer to it. + //! It will not delete or otherwise free the pointer on destruction. + //! It is reponsibility of the user to properly manage lifetime of the string. + //! The easiest way to achieve it is to use memory_pool of the document to allocate the string - + //! on destruction of the document the string will be automatically freed. + //! <br><br> + //! Size of name must be specified separately, because name does not have to be zero terminated. + //! Use name(const Ch *) function to have the length automatically calculated (string must be zero terminated). + //! \param name Name of node to set. Does not have to be zero terminated. + //! \param size Size of name, in characters. This does not include zero terminator, if one is present. + void name(const Ch *name, std::size_t size) + { + m_name = const_cast<Ch *>(name); + m_name_size = size; + } + + //! Sets name of node to a zero-terminated string. + //! See also \ref ownership_of_strings and xml_node::name(const Ch *, std::size_t). + //! \param name Name of node to set. Must be zero terminated. + void name(const Ch *name) + { + this->name(name, internal::measure(name)); + } + + //! Sets value of node to a non zero-terminated string. + //! See \ref ownership_of_strings. + //! <br><br> + //! Note that node does not own its name or value, it only stores a pointer to it. + //! It will not delete or otherwise free the pointer on destruction. + //! It is reponsibility of the user to properly manage lifetime of the string. + //! The easiest way to achieve it is to use memory_pool of the document to allocate the string - + //! on destruction of the document the string will be automatically freed. + //! <br><br> + //! Size of value must be specified separately, because it does not have to be zero terminated. + //! Use value(const Ch *) function to have the length automatically calculated (string must be zero terminated). + //! <br><br> + //! If an element has a child node of type node_data, it will take precedence over element value when printing. + //! If you want to manipulate data of elements using values, use parser flag rapidxml::parse_no_data_nodes to prevent creation of data nodes by the parser. + //! \param value value of node to set. Does not have to be zero terminated. + //! \param size Size of value, in characters. This does not include zero terminator, if one is present. + void value(const Ch *value, std::size_t size) + { + m_value = const_cast<Ch *>(value); + m_value_size = size; + } + + //! Sets value of node to a zero-terminated string. + //! See also \ref ownership_of_strings and xml_node::value(const Ch *, std::size_t). + //! \param value Vame of node to set. Must be zero terminated. + void value(const Ch *value) + { + this->value(value, internal::measure(value)); + } + + /////////////////////////////////////////////////////////////////////////// + // Related nodes access + + //! Gets node parent. + //! \return Pointer to parent node, or 0 if there is no parent. + xml_node<Ch> *parent() const + { + return m_parent; + } + + protected: + + // Return empty string + static Ch *nullstr() + { + static Ch zero = Ch('\0'); + return &zero; + } + + Ch *m_name; // Name of node, or 0 if no name + Ch *m_value; // Value of node, or 0 if no value + std::size_t m_name_size; // Length of node name, or undefined of no name + std::size_t m_value_size; // Length of node value, or undefined if no value + xml_node<Ch> *m_parent; // Pointer to parent node, or 0 if none + + }; + + //! Class representing attribute node of XML document. + //! Each attribute has name and value strings, which are available through name() and value() functions (inherited from xml_base). + //! Note that after parse, both name and value of attribute will point to interior of source text used for parsing. + //! Thus, this text must persist in memory for the lifetime of attribute. + //! \param Ch Character type to use. + template<class Ch = char> + class xml_attribute: public xml_base<Ch> + { + + friend class xml_node<Ch>; + + public: + + /////////////////////////////////////////////////////////////////////////// + // Construction & destruction + + //! Constructs an empty attribute with the specified type. + //! Consider using memory_pool of appropriate xml_document if allocating attributes manually. + xml_attribute() + { + } + + /////////////////////////////////////////////////////////////////////////// + // Related nodes access + + //! Gets document of which attribute is a child. + //! \return Pointer to document that contains this attribute, or 0 if there is no parent document. + xml_document<Ch> *document() const + { + if (xml_node<Ch> *node = this->parent()) + { + while (node->parent()) + node = node->parent(); + return node->type() == node_document ? static_cast<xml_document<Ch> *>(node) : 0; + } + else + return 0; + } + + //! Gets previous attribute, optionally matching attribute name. + //! \param name Name of attribute to find, or 0 to return previous attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found attribute, or 0 if not found. + xml_attribute<Ch> *previous_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + { + if (name) + { + if (name_size == 0) + name_size = internal::measure(name); + for (xml_attribute<Ch> *attribute = m_prev_attribute; attribute; attribute = attribute->m_prev_attribute) + if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive)) + return attribute; + return 0; + } + else + return this->m_parent ? m_prev_attribute : 0; + } + + //! Gets next attribute, optionally matching attribute name. + //! \param name Name of attribute to find, or 0 to return next attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found attribute, or 0 if not found. + xml_attribute<Ch> *next_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + { + if (name) + { + if (name_size == 0) + name_size = internal::measure(name); + for (xml_attribute<Ch> *attribute = m_next_attribute; attribute; attribute = attribute->m_next_attribute) + if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive)) + return attribute; + return 0; + } + else + return this->m_parent ? m_next_attribute : 0; + } + + private: + + xml_attribute<Ch> *m_prev_attribute; // Pointer to previous sibling of attribute, or 0 if none; only valid if parent is non-zero + xml_attribute<Ch> *m_next_attribute; // Pointer to next sibling of attribute, or 0 if none; only valid if parent is non-zero + + }; + + /////////////////////////////////////////////////////////////////////////// + // XML node + + //! Class representing a node of XML document. + //! Each node may have associated name and value strings, which are available through name() and value() functions. + //! Interpretation of name and value depends on type of the node. + //! Type of node can be determined by using type() function. + //! <br><br> + //! Note that after parse, both name and value of node, if any, will point interior of source text used for parsing. + //! Thus, this text must persist in the memory for the lifetime of node. + //! \param Ch Character type to use. + template<class Ch = char> + class xml_node: public xml_base<Ch> + { + + public: + + /////////////////////////////////////////////////////////////////////////// + // Construction & destruction + + //! Constructs an empty node with the specified type. + //! Consider using memory_pool of appropriate document to allocate nodes manually. + //! \param type Type of node to construct. + xml_node(node_type type) + : m_type(type) + , m_first_node(0) + , m_first_attribute(0) + { + } + + /////////////////////////////////////////////////////////////////////////// + // Node data access + + //! Gets type of node. + //! \return Type of node. + node_type type() const + { + return m_type; + } + + /////////////////////////////////////////////////////////////////////////// + // Related nodes access + + //! Gets document of which node is a child. + //! \return Pointer to document that contains this node, or 0 if there is no parent document. + xml_document<Ch> *document() const + { + xml_node<Ch> *node = const_cast<xml_node<Ch> *>(this); + while (node->parent()) + node = node->parent(); + return node->type() == node_document ? static_cast<xml_document<Ch> *>(node) : 0; + } + + //! Gets first child node, optionally matching node name. + //! \param name Name of child to find, or 0 to return first child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found child, or 0 if not found. + xml_node<Ch> *first_node(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + { + if (name) + { + if (name_size == 0) + name_size = internal::measure(name); + for (xml_node<Ch> *child = m_first_node; child; child = child->next_sibling()) + if (internal::compare(child->name(), child->name_size(), name, name_size, case_sensitive)) + return child; + return 0; + } + else + return m_first_node; + } + + //! Gets last child node, optionally matching node name. + //! Behaviour is undefined if node has no children. + //! Use first_node() to test if node has children. + //! \param name Name of child to find, or 0 to return last child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found child, or 0 if not found. + xml_node<Ch> *last_node(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + { + assert(m_first_node); // Cannot query for last child if node has no children + if (name) + { + if (name_size == 0) + name_size = internal::measure(name); + for (xml_node<Ch> *child = m_last_node; child; child = child->previous_sibling()) + if (internal::compare(child->name(), child->name_size(), name, name_size, case_sensitive)) + return child; + return 0; + } + else + return m_last_node; + } + + //! Gets previous sibling node, optionally matching node name. + //! Behaviour is undefined if node has no parent. + //! Use parent() to test if node has a parent. + //! \param name Name of sibling to find, or 0 to return previous sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found sibling, or 0 if not found. + xml_node<Ch> *previous_sibling(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + { + assert(this->m_parent); // Cannot query for siblings if node has no parent + if (name) + { + if (name_size == 0) + name_size = internal::measure(name); + for (xml_node<Ch> *sibling = m_prev_sibling; sibling; sibling = sibling->m_prev_sibling) + if (internal::compare(sibling->name(), sibling->name_size(), name, name_size, case_sensitive)) + return sibling; + return 0; + } + else + return m_prev_sibling; + } + + //! Gets next sibling node, optionally matching node name. + //! Behaviour is undefined if node has no parent. + //! Use parent() to test if node has a parent. + //! \param name Name of sibling to find, or 0 to return next sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found sibling, or 0 if not found. + xml_node<Ch> *next_sibling(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + { + assert(this->m_parent); // Cannot query for siblings if node has no parent + if (name) + { + if (name_size == 0) + name_size = internal::measure(name); + for (xml_node<Ch> *sibling = m_next_sibling; sibling; sibling = sibling->m_next_sibling) + if (internal::compare(sibling->name(), sibling->name_size(), name, name_size, case_sensitive)) + return sibling; + return 0; + } + else + return m_next_sibling; + } + + //! Gets first attribute of node, optionally matching attribute name. + //! \param name Name of attribute to find, or 0 to return first attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found attribute, or 0 if not found. + xml_attribute<Ch> *first_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + { + if (name) + { + if (name_size == 0) + name_size = internal::measure(name); + for (xml_attribute<Ch> *attribute = m_first_attribute; attribute; attribute = attribute->m_next_attribute) + if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive)) + return attribute; + return 0; + } + else + return m_first_attribute; + } + + //! Gets last attribute of node, optionally matching attribute name. + //! \param name Name of attribute to find, or 0 to return last attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero + //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string + //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters + //! \return Pointer to found attribute, or 0 if not found. + xml_attribute<Ch> *last_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const + { + if (name) + { + if (name_size == 0) + name_size = internal::measure(name); + for (xml_attribute<Ch> *attribute = m_last_attribute; attribute; attribute = attribute->m_prev_attribute) + if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive)) + return attribute; + return 0; + } + else + return m_first_attribute ? m_last_attribute : 0; + } + + /////////////////////////////////////////////////////////////////////////// + // Node modification + + //! Sets type of node. + //! \param type Type of node to set. + void type(node_type type) + { + m_type = type; + } + + /////////////////////////////////////////////////////////////////////////// + // Node manipulation + + //! Prepends a new child node. + //! The prepended child becomes the first child, and all existing children are moved one position back. + //! \param child Node to prepend. + void prepend_node(xml_node<Ch> *child) + { + assert(child && !child->parent() && child->type() != node_document); + if (first_node()) + { + child->m_next_sibling = m_first_node; + m_first_node->m_prev_sibling = child; + } + else + { + child->m_next_sibling = 0; + m_last_node = child; + } + m_first_node = child; + child->m_parent = this; + child->m_prev_sibling = 0; + } + + //! Appends a new child node. + //! The appended child becomes the last child. + //! \param child Node to append. + void append_node(xml_node<Ch> *child) + { + assert(child && !child->parent() && child->type() != node_document); + if (first_node()) + { + child->m_prev_sibling = m_last_node; + m_last_node->m_next_sibling = child; + } + else + { + child->m_prev_sibling = 0; + m_first_node = child; + } + m_last_node = child; + child->m_parent = this; + child->m_next_sibling = 0; + } + + //! Inserts a new child node at specified place inside the node. + //! All children after and including the specified node are moved one position back. + //! \param where Place where to insert the child, or 0 to insert at the back. + //! \param child Node to insert. + void insert_node(xml_node<Ch> *where, xml_node<Ch> *child) + { + assert(!where || where->parent() == this); + assert(child && !child->parent() && child->type() != node_document); + if (where == m_first_node) + prepend_node(child); + else if (where == 0) + append_node(child); + else + { + child->m_prev_sibling = where->m_prev_sibling; + child->m_next_sibling = where; + where->m_prev_sibling->m_next_sibling = child; + where->m_prev_sibling = child; + child->m_parent = this; + } + } + + //! Removes first child node. + //! If node has no children, behaviour is undefined. + //! Use first_node() to test if node has children. + void remove_first_node() + { + assert(first_node()); + xml_node<Ch> *child = m_first_node; + m_first_node = child->m_next_sibling; + if (child->m_next_sibling) + child->m_next_sibling->m_prev_sibling = 0; + else + m_last_node = 0; + child->m_parent = 0; + } + + //! Removes last child of the node. + //! If node has no children, behaviour is undefined. + //! Use first_node() to test if node has children. + void remove_last_node() + { + assert(first_node()); + xml_node<Ch> *child = m_last_node; + if (child->m_prev_sibling) + { + m_last_node = child->m_prev_sibling; + child->m_prev_sibling->m_next_sibling = 0; + } + else + m_first_node = 0; + child->m_parent = 0; + } + + //! Removes specified child from the node + // \param where Pointer to child to be removed. + void remove_node(xml_node<Ch> *where) + { + assert(where && where->parent() == this); + assert(first_node()); + if (where == m_first_node) + remove_first_node(); + else if (where == m_last_node) + remove_last_node(); + else + { + where->m_prev_sibling->m_next_sibling = where->m_next_sibling; + where->m_next_sibling->m_prev_sibling = where->m_prev_sibling; + where->m_parent = 0; + } + } + + //! Removes all child nodes (but not attributes). + void remove_all_nodes() + { + for (xml_node<Ch> *node = first_node(); node; node = node->m_next_sibling) + node->m_parent = 0; + m_first_node = 0; + } + + //! Prepends a new attribute to the node. + //! \param attribute Attribute to prepend. + void prepend_attribute(xml_attribute<Ch> *attribute) + { + assert(attribute && !attribute->parent()); + if (first_attribute()) + { + attribute->m_next_attribute = m_first_attribute; + m_first_attribute->m_prev_attribute = attribute; + } + else + { + attribute->m_next_attribute = 0; + m_last_attribute = attribute; + } + m_first_attribute = attribute; + attribute->m_parent = this; + attribute->m_prev_attribute = 0; + } + + //! Appends a new attribute to the node. + //! \param attribute Attribute to append. + void append_attribute(xml_attribute<Ch> *attribute) + { + assert(attribute && !attribute->parent()); + if (first_attribute()) + { + attribute->m_prev_attribute = m_last_attribute; + m_last_attribute->m_next_attribute = attribute; + } + else + { + attribute->m_prev_attribute = 0; + m_first_attribute = attribute; + } + m_last_attribute = attribute; + attribute->m_parent = this; + attribute->m_next_attribute = 0; + } + + //! Inserts a new attribute at specified place inside the node. + //! All attributes after and including the specified attribute are moved one position back. + //! \param where Place where to insert the attribute, or 0 to insert at the back. + //! \param attribute Attribute to insert. + void insert_attribute(xml_attribute<Ch> *where, xml_attribute<Ch> *attribute) + { + assert(!where || where->parent() == this); + assert(attribute && !attribute->parent()); + if (where == m_first_attribute) + prepend_attribute(attribute); + else if (where == 0) + append_attribute(attribute); + else + { + attribute->m_prev_attribute = where->m_prev_attribute; + attribute->m_next_attribute = where; + where->m_prev_attribute->m_next_attribute = attribute; + where->m_prev_attribute = attribute; + attribute->m_parent = this; + } + } + + //! Removes first attribute of the node. + //! If node has no attributes, behaviour is undefined. + //! Use first_attribute() to test if node has attributes. + void remove_first_attribute() + { + assert(first_attribute()); + xml_attribute<Ch> *attribute = m_first_attribute; + if (attribute->m_next_attribute) + { + attribute->m_next_attribute->m_prev_attribute = 0; + } + else + m_last_attribute = 0; + attribute->m_parent = 0; + m_first_attribute = attribute->m_next_attribute; + } + + //! Removes last attribute of the node. + //! If node has no attributes, behaviour is undefined. + //! Use first_attribute() to test if node has attributes. + void remove_last_attribute() + { + assert(first_attribute()); + xml_attribute<Ch> *attribute = m_last_attribute; + if (attribute->m_prev_attribute) + { + attribute->m_prev_attribute->m_next_attribute = 0; + m_last_attribute = attribute->m_prev_attribute; + } + else + m_first_attribute = 0; + attribute->m_parent = 0; + } + + //! Removes specified attribute from node. + //! \param where Pointer to attribute to be removed. + void remove_attribute(xml_attribute<Ch> *where) + { + assert(first_attribute() && where->parent() == this); + if (where == m_first_attribute) + remove_first_attribute(); + else if (where == m_last_attribute) + remove_last_attribute(); + else + { + where->m_prev_attribute->m_next_attribute = where->m_next_attribute; + where->m_next_attribute->m_prev_attribute = where->m_prev_attribute; + where->m_parent = 0; + } + } + + //! Removes all attributes of node. + void remove_all_attributes() + { + for (xml_attribute<Ch> *attribute = first_attribute(); attribute; attribute = attribute->m_next_attribute) + attribute->m_parent = 0; + m_first_attribute = 0; + } + + private: + + /////////////////////////////////////////////////////////////////////////// + // Restrictions + + // No copying + xml_node(const xml_node &); + void operator =(const xml_node &); + + /////////////////////////////////////////////////////////////////////////// + // Data members + + // Note that some of the pointers below have UNDEFINED values if certain other pointers are 0. + // This is required for maximum performance, as it allows the parser to omit initialization of + // unneded/redundant values. + // + // The rules are as follows: + // 1. first_node and first_attribute contain valid pointers, or 0 if node has no children/attributes respectively + // 2. last_node and last_attribute are valid only if node has at least one child/attribute respectively, otherwise they contain garbage + // 3. prev_sibling and next_sibling are valid only if node has a parent, otherwise they contain garbage + + node_type m_type; // Type of node; always valid + xml_node<Ch> *m_first_node; // Pointer to first child node, or 0 if none; always valid + xml_node<Ch> *m_last_node; // Pointer to last child node, or 0 if none; this value is only valid if m_first_node is non-zero + xml_attribute<Ch> *m_first_attribute; // Pointer to first attribute of node, or 0 if none; always valid + xml_attribute<Ch> *m_last_attribute; // Pointer to last attribute of node, or 0 if none; this value is only valid if m_first_attribute is non-zero + xml_node<Ch> *m_prev_sibling; // Pointer to previous sibling of node, or 0 if none; this value is only valid if m_parent is non-zero + xml_node<Ch> *m_next_sibling; // Pointer to next sibling of node, or 0 if none; this value is only valid if m_parent is non-zero + + }; + + /////////////////////////////////////////////////////////////////////////// + // XML document + + //! This class represents root of the DOM hierarchy. + //! It is also an xml_node and a memory_pool through public inheritance. + //! Use parse() function to build a DOM tree from a zero-terminated XML text string. + //! parse() function allocates memory for nodes and attributes by using functions of xml_document, + //! which are inherited from memory_pool. + //! To access root node of the document, use the document itself, as if it was an xml_node. + //! \param Ch Character type to use. + template<class Ch = char> + class xml_document: public xml_node<Ch>, public memory_pool<Ch> + { + + public: + + //! Constructs empty XML document + xml_document() + : xml_node<Ch>(node_document) + { + } + + //! Parses zero-terminated XML string according to given flags. + //! Passed string will be modified by the parser, unless rapidxml::parse_non_destructive flag is used. + //! The string must persist for the lifetime of the document. + //! In case of error, rapidxml::parse_error exception will be thrown. + //! <br><br> + //! If you want to parse contents of a file, you must first load the file into the memory, and pass pointer to its beginning. + //! Make sure that data is zero-terminated. + //! <br><br> + //! Document can be parsed into multiple times. + //! Each new call to parse removes previous nodes and attributes (if any), but does not clear memory pool. + //! \param text XML data to parse; pointer is non-const to denote fact that this data may be modified by the parser. + template<int Flags> + void parse(Ch *text) + { + assert(text); + + // Remove current contents + this->remove_all_nodes(); + this->remove_all_attributes(); + + // Parse BOM, if any + parse_bom<Flags>(text); + + // Parse children + while (1) + { + // Skip whitespace before node + skip<whitespace_pred, Flags>(text); + if (*text == 0) + break; + + // Parse and append new child + if (*text == Ch('<')) + { + ++text; // Skip '<' + if (xml_node<Ch> *node = parse_node<Flags>(text)) + this->append_node(node); + } + else + RAPIDXML_PARSE_ERROR("expected <", text); + } + + } + + //! Clears the document by deleting all nodes and clearing the memory pool. + //! All nodes owned by document pool are destroyed. + void clear() + { + this->remove_all_nodes(); + this->remove_all_attributes(); + memory_pool<Ch>::clear(); + } + + private: + + /////////////////////////////////////////////////////////////////////// + // Internal character utility functions + + // Detect whitespace character + struct whitespace_pred + { + static unsigned char test(Ch ch) + { + return internal::lookup_tables<0>::lookup_whitespace[static_cast<unsigned char>(ch)]; + } + }; + + // Detect node name character + struct node_name_pred + { + static unsigned char test(Ch ch) + { + return internal::lookup_tables<0>::lookup_node_name[static_cast<unsigned char>(ch)]; + } + }; + + // Detect attribute name character + struct attribute_name_pred + { + static unsigned char test(Ch ch) + { + return internal::lookup_tables<0>::lookup_attribute_name[static_cast<unsigned char>(ch)]; + } + }; + + // Detect text character (PCDATA) + struct text_pred + { + static unsigned char test(Ch ch) + { + return internal::lookup_tables<0>::lookup_text[static_cast<unsigned char>(ch)]; + } + }; + + // Detect text character (PCDATA) that does not require processing + struct text_pure_no_ws_pred + { + static unsigned char test(Ch ch) + { + return internal::lookup_tables<0>::lookup_text_pure_no_ws[static_cast<unsigned char>(ch)]; + } + }; + + // Detect text character (PCDATA) that does not require processing + struct text_pure_with_ws_pred + { + static unsigned char test(Ch ch) + { + return internal::lookup_tables<0>::lookup_text_pure_with_ws[static_cast<unsigned char>(ch)]; + } + }; + + // Detect attribute value character + template<Ch Quote> + struct attribute_value_pred + { + static unsigned char test(Ch ch) + { + if (Quote == Ch('\'')) + return internal::lookup_tables<0>::lookup_attribute_data_1[static_cast<unsigned char>(ch)]; + if (Quote == Ch('\"')) + return internal::lookup_tables<0>::lookup_attribute_data_2[static_cast<unsigned char>(ch)]; + return 0; // Should never be executed, to avoid warnings on Comeau + } + }; + + // Detect attribute value character + template<Ch Quote> + struct attribute_value_pure_pred + { + static unsigned char test(Ch ch) + { + if (Quote == Ch('\'')) + return internal::lookup_tables<0>::lookup_attribute_data_1_pure[static_cast<unsigned char>(ch)]; + if (Quote == Ch('\"')) + return internal::lookup_tables<0>::lookup_attribute_data_2_pure[static_cast<unsigned char>(ch)]; + return 0; // Should never be executed, to avoid warnings on Comeau + } + }; + + // Insert coded character, using UTF8 or 8-bit ASCII + template<int Flags> + static void insert_coded_character(Ch *&text, unsigned long code) + { + if (Flags & parse_no_utf8) + { + // Insert 8-bit ASCII character + // Todo: possibly verify that code is less than 256 and use replacement char otherwise? + text[0] = static_cast<unsigned char>(code); + text += 1; + } + else + { + // Insert UTF8 sequence + if (code < 0x80) // 1 byte sequence + { + text[0] = static_cast<unsigned char>(code); + text += 1; + } + else if (code < 0x800) // 2 byte sequence + { + text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6; + text[0] = static_cast<unsigned char>(code | 0xC0); + text += 2; + } + else if (code < 0x10000) // 3 byte sequence + { + text[2] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6; + text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6; + text[0] = static_cast<unsigned char>(code | 0xE0); + text += 3; + } + else if (code < 0x110000) // 4 byte sequence + { + text[3] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6; + text[2] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6; + text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6; + text[0] = static_cast<unsigned char>(code | 0xF0); + text += 4; + } + else // Invalid, only codes up to 0x10FFFF are allowed in Unicode + { + RAPIDXML_PARSE_ERROR("invalid numeric character entity", text); + } + } + } + + // Skip characters until predicate evaluates to true + template<class StopPred, int Flags> + static void skip(Ch *&text) + { + Ch *tmp = text; + while (StopPred::test(*tmp)) + ++tmp; + text = tmp; + } + + // Skip characters until predicate evaluates to true while doing the following: + // - replacing XML character entity references with proper characters (' & " < > &#...;) + // - condensing whitespace sequences to single space character + template<class StopPred, class StopPredPure, int Flags> + static Ch *skip_and_expand_character_refs(Ch *&text) + { + // If entity translation, whitespace condense and whitespace trimming is disabled, use plain skip + if (Flags & parse_no_entity_translation && + !(Flags & parse_normalize_whitespace) && + !(Flags & parse_trim_whitespace)) + { + skip<StopPred, Flags>(text); + return text; + } + + // Use simple skip until first modification is detected + skip<StopPredPure, Flags>(text); + + // Use translation skip + Ch *src = text; + Ch *dest = src; + while (StopPred::test(*src)) + { + // If entity translation is enabled + if (!(Flags & parse_no_entity_translation)) + { + // Test if replacement is needed + if (src[0] == Ch('&')) + { + switch (src[1]) + { + + // & ' + case Ch('a'): + if (src[2] == Ch('m') && src[3] == Ch('p') && src[4] == Ch(';')) + { + *dest = Ch('&'); + ++dest; + src += 5; + continue; + } + if (src[2] == Ch('p') && src[3] == Ch('o') && src[4] == Ch('s') && src[5] == Ch(';')) + { + *dest = Ch('\''); + ++dest; + src += 6; + continue; + } + break; + + // " + case Ch('q'): + if (src[2] == Ch('u') && src[3] == Ch('o') && src[4] == Ch('t') && src[5] == Ch(';')) + { + *dest = Ch('"'); + ++dest; + src += 6; + continue; + } + break; + + // > + case Ch('g'): + if (src[2] == Ch('t') && src[3] == Ch(';')) + { + *dest = Ch('>'); + ++dest; + src += 4; + continue; + } + break; + + // < + case Ch('l'): + if (src[2] == Ch('t') && src[3] == Ch(';')) + { + *dest = Ch('<'); + ++dest; + src += 4; + continue; + } + break; + + // &#...; - assumes ASCII + case Ch('#'): + if (src[2] == Ch('x')) + { + unsigned long code = 0; + src += 3; // Skip &#x + while (1) + { + unsigned char digit = internal::lookup_tables<0>::lookup_digits[static_cast<unsigned char>(*src)]; + if (digit == 0xFF) + break; + code = code * 16 + digit; + ++src; + } + insert_coded_character<Flags>(dest, code); // Put character in output + } + else + { + unsigned long code = 0; + src += 2; // Skip &# + while (1) + { + unsigned char digit = internal::lookup_tables<0>::lookup_digits[static_cast<unsigned char>(*src)]; + if (digit == 0xFF) + break; + code = code * 10 + digit; + ++src; + } + insert_coded_character<Flags>(dest, code); // Put character in output + } + if (*src == Ch(';')) + ++src; + else + RAPIDXML_PARSE_ERROR("expected ;", src); + continue; + + // Something else + default: + // Ignore, just copy '&' verbatim + break; + + } + } + } + + // If whitespace condensing is enabled + if (Flags & parse_normalize_whitespace) + { + // Test if condensing is needed + if (whitespace_pred::test(*src)) + { + *dest = Ch(' '); ++dest; // Put single space in dest + ++src; // Skip first whitespace char + // Skip remaining whitespace chars + while (whitespace_pred::test(*src)) + ++src; + continue; + } + } + + // No replacement, only copy character + *dest++ = *src++; + + } + + // Return new end + text = src; + return dest; + + } + + /////////////////////////////////////////////////////////////////////// + // Internal parsing functions + + // Parse BOM, if any + template<int Flags> + void parse_bom(Ch *&text) + { + // UTF-8? + if (static_cast<unsigned char>(text[0]) == 0xEF && + static_cast<unsigned char>(text[1]) == 0xBB && + static_cast<unsigned char>(text[2]) == 0xBF) + { + text += 3; // Skup utf-8 bom + } + } + + // Parse XML declaration (<?xml...) + template<int Flags> + xml_node<Ch> *parse_xml_declaration(Ch *&text) + { + // If parsing of declaration is disabled + if (!(Flags & parse_declaration_node)) + { + // Skip until end of declaration + while (text[0] != Ch('?') || text[1] != Ch('>')) + { + if (!text[0]) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + text += 2; // Skip '?>' + return 0; + } + + // Create declaration + xml_node<Ch> *declaration = this->allocate_node(node_declaration); + + // Skip whitespace before attributes or ?> + skip<whitespace_pred, Flags>(text); + + // Parse declaration attributes + parse_node_attributes<Flags>(text, declaration); + + // Skip ?> + if (text[0] != Ch('?') || text[1] != Ch('>')) + RAPIDXML_PARSE_ERROR("expected ?>", text); + text += 2; + + return declaration; + } + + // Parse XML comment (<!--...) + template<int Flags> + xml_node<Ch> *parse_comment(Ch *&text) + { + // If parsing of comments is disabled + if (!(Flags & parse_comment_nodes)) + { + // Skip until end of comment + while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>')) + { + if (!text[0]) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + text += 3; // Skip '-->' + return 0; // Do not produce comment node + } + + // Remember value start + Ch *value = text; + + // Skip until end of comment + while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>')) + { + if (!text[0]) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + + // Create comment node + xml_node<Ch> *comment = this->allocate_node(node_comment); + comment->value(value, text - value); + + // Place zero terminator after comment value + if (!(Flags & parse_no_string_terminators)) + *text = Ch('\0'); + + text += 3; // Skip '-->' + return comment; + } + + // Parse DOCTYPE + template<int Flags> + xml_node<Ch> *parse_doctype(Ch *&text) + { + // Remember value start + Ch *value = text; + + // Skip to > + while (*text != Ch('>')) + { + // Determine character type + switch (*text) + { + + // If '[' encountered, scan for matching ending ']' using naive algorithm with depth + // This works for all W3C test files except for 2 most wicked + case Ch('['): + { + ++text; // Skip '[' + int depth = 1; + while (depth > 0) + { + switch (*text) + { + case Ch('['): ++depth; break; + case Ch(']'): --depth; break; + case 0: RAPIDXML_PARSE_ERROR("unexpected end of data", text); + } + ++text; + } + break; + } + + // Error on end of text + case Ch('\0'): + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + + // Other character, skip it + default: + ++text; + + } + } + + // If DOCTYPE nodes enabled + if (Flags & parse_doctype_node) + { + // Create a new doctype node + xml_node<Ch> *doctype = this->allocate_node(node_doctype); + doctype->value(value, text - value); + + // Place zero terminator after value + if (!(Flags & parse_no_string_terminators)) + *text = Ch('\0'); + + text += 1; // skip '>' + return doctype; + } + else + { + text += 1; // skip '>' + return 0; + } + + } + + // Parse PI + template<int Flags> + xml_node<Ch> *parse_pi(Ch *&text) + { + // If creation of PI nodes is enabled + if (Flags & parse_pi_nodes) + { + // Create pi node + xml_node<Ch> *pi = this->allocate_node(node_pi); + + // Extract PI target name + Ch *name = text; + skip<node_name_pred, Flags>(text); + if (text == name) + RAPIDXML_PARSE_ERROR("expected PI target", text); + pi->name(name, text - name); + + // Skip whitespace between pi target and pi + skip<whitespace_pred, Flags>(text); + + // Remember start of pi + Ch *value = text; + + // Skip to '?>' + while (text[0] != Ch('?') || text[1] != Ch('>')) + { + if (*text == Ch('\0')) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + + // Set pi value (verbatim, no entity expansion or whitespace normalization) + pi->value(value, text - value); + + // Place zero terminator after name and value + if (!(Flags & parse_no_string_terminators)) + { + pi->name()[pi->name_size()] = Ch('\0'); + pi->value()[pi->value_size()] = Ch('\0'); + } + + text += 2; // Skip '?>' + return pi; + } + else + { + // Skip to '?>' + while (text[0] != Ch('?') || text[1] != Ch('>')) + { + if (*text == Ch('\0')) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + text += 2; // Skip '?>' + return 0; + } + } + + // Parse and append data + // Return character that ends data. + // This is necessary because this character might have been overwritten by a terminating 0 + template<int Flags> + Ch parse_and_append_data(xml_node<Ch> *node, Ch *&text, Ch *contents_start) + { + // Backup to contents start if whitespace trimming is disabled + if (!(Flags & parse_trim_whitespace)) + text = contents_start; + + // Skip until end of data + Ch *value = text, *end; + if (Flags & parse_normalize_whitespace) + end = skip_and_expand_character_refs<text_pred, text_pure_with_ws_pred, Flags>(text); + else + end = skip_and_expand_character_refs<text_pred, text_pure_no_ws_pred, Flags>(text); + + // Trim trailing whitespace if flag is set; leading was already trimmed by whitespace skip after > + if (Flags & parse_trim_whitespace) + { + if (Flags & parse_normalize_whitespace) + { + // Whitespace is already condensed to single space characters by skipping function, so just trim 1 char off the end + if (*(end - 1) == Ch(' ')) + --end; + } + else + { + // Backup until non-whitespace character is found + while (whitespace_pred::test(*(end - 1))) + --end; + } + } + + // If characters are still left between end and value (this test is only necessary if normalization is enabled) + // Create new data node + if (!(Flags & parse_no_data_nodes)) + { + xml_node<Ch> *data = this->allocate_node(node_data); + data->value(value, end - value); + node->append_node(data); + } + + // Add data to parent node if no data exists yet + if (!(Flags & parse_no_element_values)) + if (*node->value() == Ch('\0')) + node->value(value, end - value); + + // Place zero terminator after value + if (!(Flags & parse_no_string_terminators)) + { + Ch ch = *text; + *end = Ch('\0'); + return ch; // Return character that ends data; this is required because zero terminator overwritten it + } + + // Return character that ends data + return *text; + } + + // Parse CDATA + template<int Flags> + xml_node<Ch> *parse_cdata(Ch *&text) + { + // If CDATA is disabled + if (Flags & parse_no_data_nodes) + { + // Skip until end of cdata + while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>')) + { + if (!text[0]) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + text += 3; // Skip ]]> + return 0; // Do not produce CDATA node + } + + // Skip until end of cdata + Ch *value = text; + while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>')) + { + if (!text[0]) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + + // Create new cdata node + xml_node<Ch> *cdata = this->allocate_node(node_cdata); + cdata->value(value, text - value); + + // Place zero terminator after value + if (!(Flags & parse_no_string_terminators)) + *text = Ch('\0'); + + text += 3; // Skip ]]> + return cdata; + } + + // Parse element node + template<int Flags> + xml_node<Ch> *parse_element(Ch *&text) + { + // Create element node + xml_node<Ch> *element = this->allocate_node(node_element); + + // Extract element name + Ch *name = text; + skip<node_name_pred, Flags>(text); + if (text == name) + RAPIDXML_PARSE_ERROR("expected element name", text); + element->name(name, text - name); + + // Skip whitespace between element name and attributes or > + skip<whitespace_pred, Flags>(text); + + // Parse attributes, if any + parse_node_attributes<Flags>(text, element); + + // Determine ending type + if (*text == Ch('>')) + { + ++text; + parse_node_contents<Flags>(text, element); + } + else if (*text == Ch('/')) + { + ++text; + if (*text != Ch('>')) + RAPIDXML_PARSE_ERROR("expected >", text); + ++text; + } + else + RAPIDXML_PARSE_ERROR("expected >", text); + + // Place zero terminator after name + if (!(Flags & parse_no_string_terminators)) + element->name()[element->name_size()] = Ch('\0'); + + // Return parsed element + return element; + } + + // Determine node type, and parse it + template<int Flags> + xml_node<Ch> *parse_node(Ch *&text) + { + // Parse proper node type + switch (text[0]) + { + + // <... + default: + // Parse and append element node + return parse_element<Flags>(text); + + // <?... + case Ch('?'): + ++text; // Skip ? + if ((text[0] == Ch('x') || text[0] == Ch('X')) && + (text[1] == Ch('m') || text[1] == Ch('M')) && + (text[2] == Ch('l') || text[2] == Ch('L')) && + whitespace_pred::test(text[3])) + { + // '<?xml ' - xml declaration + text += 4; // Skip 'xml ' + return parse_xml_declaration<Flags>(text); + } + else + { + // Parse PI + return parse_pi<Flags>(text); + } + + // <!... + case Ch('!'): + + // Parse proper subset of <! node + switch (text[1]) + { + + // <!- + case Ch('-'): + if (text[2] == Ch('-')) + { + // '<!--' - xml comment + text += 3; // Skip '!--' + return parse_comment<Flags>(text); + } + break; + + // <![ + case Ch('['): + if (text[2] == Ch('C') && text[3] == Ch('D') && text[4] == Ch('A') && + text[5] == Ch('T') && text[6] == Ch('A') && text[7] == Ch('[')) + { + // '<![CDATA[' - cdata + text += 8; // Skip '![CDATA[' + return parse_cdata<Flags>(text); + } + break; + + // <!D + case Ch('D'): + if (text[2] == Ch('O') && text[3] == Ch('C') && text[4] == Ch('T') && + text[5] == Ch('Y') && text[6] == Ch('P') && text[7] == Ch('E') && + whitespace_pred::test(text[8])) + { + // '<!DOCTYPE ' - doctype + text += 9; // skip '!DOCTYPE ' + return parse_doctype<Flags>(text); + } + + } // switch + + // Attempt to skip other, unrecognized node types starting with <! + ++text; // Skip ! + while (*text != Ch('>')) + { + if (*text == 0) + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + ++text; + } + ++text; // Skip '>' + return 0; // No node recognized + + } + } + + // Parse contents of the node - children, data etc. + template<int Flags> + void parse_node_contents(Ch *&text, xml_node<Ch> *node) + { + // For all children and text + while (1) + { + // Skip whitespace between > and node contents + Ch *contents_start = text; // Store start of node contents before whitespace is skipped + skip<whitespace_pred, Flags>(text); + Ch next_char = *text; + + // After data nodes, instead of continuing the loop, control jumps here. + // This is because zero termination inside parse_and_append_data() function + // would wreak havoc with the above code. + // Also, skipping whitespace after data nodes is unnecessary. + after_data_node: + + // Determine what comes next: node closing, child node, data node, or 0? + switch (next_char) + { + + // Node closing or child node + case Ch('<'): + if (text[1] == Ch('/')) + { + // Node closing + text += 2; // Skip '</' + if (Flags & parse_validate_closing_tags) + { + // Skip and validate closing tag name + Ch *closing_name = text; + skip<node_name_pred, Flags>(text); + if (!internal::compare(node->name(), node->name_size(), closing_name, text - closing_name, true)) + RAPIDXML_PARSE_ERROR("invalid closing tag name", text); + } + else + { + // No validation, just skip name + skip<node_name_pred, Flags>(text); + } + // Skip remaining whitespace after node name + skip<whitespace_pred, Flags>(text); + if (*text != Ch('>')) + RAPIDXML_PARSE_ERROR("expected >", text); + ++text; // Skip '>' + return; // Node closed, finished parsing contents + } + else + { + // Child node + ++text; // Skip '<' + if (xml_node<Ch> *child = parse_node<Flags>(text)) + node->append_node(child); + } + break; + + // End of data - error + case Ch('\0'): + RAPIDXML_PARSE_ERROR("unexpected end of data", text); + + // Data node + default: + next_char = parse_and_append_data<Flags>(node, text, contents_start); + goto after_data_node; // Bypass regular processing after data nodes + + } + } + } + + // Parse XML attributes of the node + template<int Flags> + void parse_node_attributes(Ch *&text, xml_node<Ch> *node) + { + // For all attributes + while (attribute_name_pred::test(*text)) + { + // Extract attribute name + Ch *name = text; + ++text; // Skip first character of attribute name + skip<attribute_name_pred, Flags>(text); + if (text == name) + RAPIDXML_PARSE_ERROR("expected attribute name", name); + + // Create new attribute + xml_attribute<Ch> *attribute = this->allocate_attribute(); + attribute->name(name, text - name); + node->append_attribute(attribute); + + // Skip whitespace after attribute name + skip<whitespace_pred, Flags>(text); + + // Skip = + if (*text != Ch('=')) + RAPIDXML_PARSE_ERROR("expected =", text); + ++text; + + // Add terminating zero after name + if (!(Flags & parse_no_string_terminators)) + attribute->name()[attribute->name_size()] = 0; + + // Skip whitespace after = + skip<whitespace_pred, Flags>(text); + + // Skip quote and remember if it was ' or " + Ch quote = *text; + if (quote != Ch('\'') && quote != Ch('"')) + RAPIDXML_PARSE_ERROR("expected ' or \"", text); + ++text; + + // Extract attribute value and expand char refs in it + Ch *value = text, *end; + const int AttFlags = Flags & ~parse_normalize_whitespace; // No whitespace normalization in attributes + if (quote == Ch('\'')) + end = skip_and_expand_character_refs<attribute_value_pred<Ch('\'')>, attribute_value_pure_pred<Ch('\'')>, AttFlags>(text); + else + end = skip_and_expand_character_refs<attribute_value_pred<Ch('"')>, attribute_value_pure_pred<Ch('"')>, AttFlags>(text); + + // Set attribute value + attribute->value(value, end - value); + + // Make sure that end quote is present + if (*text != quote) + RAPIDXML_PARSE_ERROR("expected ' or \"", text); + ++text; // Skip quote + + // Add terminating zero after value + if (!(Flags & parse_no_string_terminators)) + attribute->value()[attribute->value_size()] = 0; + + // Skip whitespace after attribute value + skip<whitespace_pred, Flags>(text); + } + } + + }; + + //! \cond internal + namespace internal + { + + // Whitespace (space \n \r \t) + template<int Dummy> + const unsigned char lookup_tables<Dummy>::lookup_whitespace[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, // 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1 + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 5 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // F + }; + + // Node name (anything but space \n \r \t / > ? \0) + template<int Dummy> + const unsigned char lookup_tables<Dummy>::lookup_node_name[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + + // Text (i.e. PCDATA) (anything but < \0) + template<int Dummy> + const unsigned char lookup_tables<Dummy>::lookup_text[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + + // Text (i.e. PCDATA) that does not require processing when ws normalization is disabled + // (anything but < \0 &) + template<int Dummy> + const unsigned char lookup_tables<Dummy>::lookup_text_pure_no_ws[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + + // Text (i.e. PCDATA) that does not require processing when ws normalizationis is enabled + // (anything but < \0 & space \n \r \t) + template<int Dummy> + const unsigned char lookup_tables<Dummy>::lookup_text_pure_with_ws[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + + // Attribute name (anything but space \n \r \t / < > = ? ! \0) + template<int Dummy> + const unsigned char lookup_tables<Dummy>::lookup_attribute_name[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + + // Attribute data with single quote (anything but ' \0) + template<int Dummy> + const unsigned char lookup_tables<Dummy>::lookup_attribute_data_1[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + + // Attribute data with single quote that does not require processing (anything but ' \0 &) + template<int Dummy> + const unsigned char lookup_tables<Dummy>::lookup_attribute_data_1_pure[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + + // Attribute data with double quote (anything but " \0) + template<int Dummy> + const unsigned char lookup_tables<Dummy>::lookup_attribute_data_2[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + + // Attribute data with double quote that does not require processing (anything but " \0 &) + template<int Dummy> + const unsigned char lookup_tables<Dummy>::lookup_attribute_data_2_pure[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 + 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F + }; + + // Digits (dec and hex, 255 denotes end of numeric character reference) + template<int Dummy> + const unsigned char lookup_tables<Dummy>::lookup_digits[256] = + { + // 0 1 2 3 4 5 6 7 8 9 A B C D E F + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 0 + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 1 + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 2 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,255,255,255,255,255,255, // 3 + 255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255, // 4 + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 5 + 255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255, // 6 + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 7 + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 8 + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 9 + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // A + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // B + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // C + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // D + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // E + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255 // F + }; + + // Upper case conversion + template<int Dummy> + const unsigned char lookup_tables<Dummy>::lookup_upcase[256] = + { + // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A B C D E F + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, // 0 + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, // 1 + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, // 2 + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, // 3 + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, // 4 + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, // 5 + 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, // 6 + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123,124,125,126,127, // 7 + 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, // 8 + 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, // 9 + 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, // A + 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, // B + 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, // C + 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, // D + 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, // E + 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 // F + }; + } + //! \endcond + +} + +// Undefine internal macros +#undef RAPIDXML_PARSE_ERROR + +// On MSVC, restore warnings state +#ifdef _MSC_VER + #pragma warning(pop) +#endif + +#endif diff --git a/Project/rapidXML/rapidxml_iterators.hpp b/Project/rapidXML/rapidxml_iterators.hpp new file mode 100644 index 0000000..52ebc29 --- /dev/null +++ b/Project/rapidXML/rapidxml_iterators.hpp @@ -0,0 +1,174 @@ +#ifndef RAPIDXML_ITERATORS_HPP_INCLUDED +#define RAPIDXML_ITERATORS_HPP_INCLUDED + +// Copyright (C) 2006, 2009 Marcin Kalicinski +// Version 1.13 +// Revision $DateTime: 2009/05/13 01:46:17 $ +//! \file rapidxml_iterators.hpp This file contains rapidxml iterators + +#include "rapidxml.hpp" + +namespace rapidxml +{ + + //! Iterator of child nodes of xml_node + template<class Ch> + class node_iterator + { + + public: + + typedef typename xml_node<Ch> value_type; + typedef typename xml_node<Ch> &reference; + typedef typename xml_node<Ch> *pointer; + typedef std::ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + + node_iterator() + : m_node(0) + { + } + + node_iterator(xml_node<Ch> *node) + : m_node(node->first_node()) + { + } + + reference operator *() const + { + assert(m_node); + return *m_node; + } + + pointer operator->() const + { + assert(m_node); + return m_node; + } + + node_iterator& operator++() + { + assert(m_node); + m_node = m_node->next_sibling(); + return *this; + } + + node_iterator operator++(int) + { + node_iterator tmp = *this; + ++this; + return tmp; + } + + node_iterator& operator--() + { + assert(m_node && m_node->previous_sibling()); + m_node = m_node->previous_sibling(); + return *this; + } + + node_iterator operator--(int) + { + node_iterator tmp = *this; + ++this; + return tmp; + } + + bool operator ==(const node_iterator<Ch> &rhs) + { + return m_node == rhs.m_node; + } + + bool operator !=(const node_iterator<Ch> &rhs) + { + return m_node != rhs.m_node; + } + + private: + + xml_node<Ch> *m_node; + + }; + + //! Iterator of child attributes of xml_node + template<class Ch> + class attribute_iterator + { + + public: + + typedef typename xml_attribute<Ch> value_type; + typedef typename xml_attribute<Ch> &reference; + typedef typename xml_attribute<Ch> *pointer; + typedef std::ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + + attribute_iterator() + : m_attribute(0) + { + } + + attribute_iterator(xml_node<Ch> *node) + : m_attribute(node->first_attribute()) + { + } + + reference operator *() const + { + assert(m_attribute); + return *m_attribute; + } + + pointer operator->() const + { + assert(m_attribute); + return m_attribute; + } + + attribute_iterator& operator++() + { + assert(m_attribute); + m_attribute = m_attribute->next_attribute(); + return *this; + } + + attribute_iterator operator++(int) + { + attribute_iterator tmp = *this; + ++this; + return tmp; + } + + attribute_iterator& operator--() + { + assert(m_attribute && m_attribute->previous_attribute()); + m_attribute = m_attribute->previous_attribute(); + return *this; + } + + attribute_iterator operator--(int) + { + attribute_iterator tmp = *this; + ++this; + return tmp; + } + + bool operator ==(const attribute_iterator<Ch> &rhs) + { + return m_attribute == rhs.m_attribute; + } + + bool operator !=(const attribute_iterator<Ch> &rhs) + { + return m_attribute != rhs.m_attribute; + } + + private: + + xml_attribute<Ch> *m_attribute; + + }; + +} + +#endif diff --git a/Project/rapidXML/rapidxml_print.hpp b/Project/rapidXML/rapidxml_print.hpp new file mode 100644 index 0000000..ab76424 --- /dev/null +++ b/Project/rapidXML/rapidxml_print.hpp @@ -0,0 +1,447 @@ +#ifndef RAPIDXML_PRINT_HPP_INCLUDED +#define RAPIDXML_PRINT_HPP_INCLUDED + +// Copyright (C) 2006, 2009 Marcin Kalicinski +// Version 1.13 +// Revision $DateTime: 2009/05/13 01:46:17 $ +//! \file rapidxml_print.hpp This file contains rapidxml printer implementation + +#include "rapidxml.hpp" + +// Only include streams if not disabled +#ifndef RAPIDXML_NO_STREAMS + #include <ostream> + #include <iterator> +#endif + +namespace rapidxml +{ + + /////////////////////////////////////////////////////////////////////// + // Printing flags + + const int print_no_indenting = 0x1; //!< Printer flag instructing the printer to suppress indenting of XML. See print() function. + + /////////////////////////////////////////////////////////////////////// + // Internal + + //! \cond internal + namespace internal + { + + /////////////////////////////////////////////////////////////////////////// + // Internal character operations + + // Copy characters from given range to given output iterator + template<class OutIt, class Ch> + inline OutIt copy_chars(const Ch *begin, const Ch *end, OutIt out) + { + while (begin != end) + *out++ = *begin++; + return out; + } + + // Copy characters from given range to given output iterator and expand + // characters into references (< > ' " &) + template<class OutIt, class Ch> + inline OutIt copy_and_expand_chars(const Ch *begin, const Ch *end, Ch noexpand, OutIt out) + { + while (begin != end) + { + if (*begin == noexpand) + { + *out++ = *begin; // No expansion, copy character + } + else + { + switch (*begin) + { + case Ch('<'): + *out++ = Ch('&'); *out++ = Ch('l'); *out++ = Ch('t'); *out++ = Ch(';'); + break; + case Ch('>'): + *out++ = Ch('&'); *out++ = Ch('g'); *out++ = Ch('t'); *out++ = Ch(';'); + break; + case Ch('\''): + *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('p'); *out++ = Ch('o'); *out++ = Ch('s'); *out++ = Ch(';'); + break; + case Ch('"'): + *out++ = Ch('&'); *out++ = Ch('q'); *out++ = Ch('u'); *out++ = Ch('o'); *out++ = Ch('t'); *out++ = Ch(';'); + break; + case Ch('&'): + *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('m'); *out++ = Ch('p'); *out++ = Ch(';'); + break; + default: + *out++ = *begin; // No expansion, copy character + } + } + ++begin; // Step to next character + } + return out; + } + + // Fill given output iterator with repetitions of the same character + template<class OutIt, class Ch> + inline OutIt fill_chars(OutIt out, int n, Ch ch) + { + for (int i = 0; i < n; ++i) + *out++ = ch; + return out; + } + + // Find character + template<class Ch, Ch ch> + inline bool find_char(const Ch *begin, const Ch *end) + { + while (begin != end) + if (*begin++ == ch) + return true; + return false; + } + + /////////////////////////////////////////////////////////////////////////// + // Internal printing operations + template<class OutIt, class Ch> + inline OutIt print_children(OutIt out, const xml_node<Ch> *node, int flags, int indent); + + template<class OutIt, class Ch> + inline OutIt print_attributes(OutIt out, const xml_node<Ch> *node, int flags); + + template<class OutIt, class Ch> + inline OutIt print_data_node(OutIt out, const xml_node<Ch> *node, int flags, int indent); + + template<class OutIt, class Ch> + inline OutIt print_cdata_node(OutIt out, const xml_node<Ch> *node, int flags, int indent); + + template<class OutIt, class Ch> + inline OutIt print_element_node(OutIt out, const xml_node<Ch> *node, int flags, int indent); + + template<class OutIt, class Ch> + inline OutIt print_declaration_node(OutIt out, const xml_node<Ch> *node, int flags, int indent); + + template<class OutIt, class Ch> + inline OutIt print_comment_node(OutIt out, const xml_node<Ch> *node, int flags, int indent); + + template<class OutIt, class Ch> + inline OutIt print_doctype_node(OutIt out, const xml_node<Ch> *node, int flags, int indent); + + template<class OutIt, class Ch> + inline OutIt print_pi_node(OutIt out, const xml_node<Ch> *node, int flags, int indent); + + // Print node + template<class OutIt, class Ch> + inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent) + { + // Print proper node type + switch (node->type()) + { + + // Document + case node_document: + out = print_children(out, node, flags, indent); + break; + + // Element + case node_element: + out = print_element_node(out, node, flags, indent); + break; + + // Data + case node_data: + out = print_data_node(out, node, flags, indent); + break; + + // CDATA + case node_cdata: + out = print_cdata_node(out, node, flags, indent); + break; + + // Declaration + case node_declaration: + out = print_declaration_node(out, node, flags, indent); + break; + + // Comment + case node_comment: + out = print_comment_node(out, node, flags, indent); + break; + + // Doctype + case node_doctype: + out = print_doctype_node(out, node, flags, indent); + break; + + // Pi + case node_pi: + out = print_pi_node(out, node, flags, indent); + break; + + // Unknown + default: + assert(0); + break; + } + + // If indenting not disabled, add line break after node + if (!(flags & print_no_indenting)) + *out = Ch('\n'), ++out; + + // Return modified iterator + return out; + } + + // Print children of the node + template<class OutIt, class Ch> + inline OutIt print_children(OutIt out, const xml_node<Ch> *node, int flags, int indent) + { + for (xml_node<Ch> *child = node->first_node(); child; child = child->next_sibling()) + out = print_node(out, child, flags, indent); + return out; + } + + // Print attributes of the node + template<class OutIt, class Ch> + inline OutIt print_attributes(OutIt out, const xml_node<Ch> *node, int flags) + { + for (xml_attribute<Ch> *attribute = node->first_attribute(); attribute; attribute = attribute->next_attribute()) + { + if (attribute->name() && attribute->value()) + { + // Print attribute name + *out = Ch(' '), ++out; + out = copy_chars(attribute->name(), attribute->name() + attribute->name_size(), out); + *out = Ch('='), ++out; + // Print attribute value using appropriate quote type + if (find_char<Ch, Ch('"')>(attribute->value(), attribute->value() + attribute->value_size())) + { + *out = Ch('\''), ++out; + out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('"'), out); + *out = Ch('\''), ++out; + } + else + { + *out = Ch('"'), ++out; + out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('\''), out); + *out = Ch('"'), ++out; + } + } + } + return out; + } + + // Print data node + template<class OutIt, class Ch> + inline OutIt print_data_node(OutIt out, const xml_node<Ch> *node, int flags, int indent) + { + assert(node->type() == node_data); + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out); + return out; + } + + // Print data node + template<class OutIt, class Ch> + inline OutIt print_cdata_node(OutIt out, const xml_node<Ch> *node, int flags, int indent) + { + assert(node->type() == node_cdata); + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'); ++out; + *out = Ch('!'); ++out; + *out = Ch('['); ++out; + *out = Ch('C'); ++out; + *out = Ch('D'); ++out; + *out = Ch('A'); ++out; + *out = Ch('T'); ++out; + *out = Ch('A'); ++out; + *out = Ch('['); ++out; + out = copy_chars(node->value(), node->value() + node->value_size(), out); + *out = Ch(']'); ++out; + *out = Ch(']'); ++out; + *out = Ch('>'); ++out; + return out; + } + + // Print element node + template<class OutIt, class Ch> + inline OutIt print_element_node(OutIt out, const xml_node<Ch> *node, int flags, int indent) + { + assert(node->type() == node_element); + + // Print element name and attributes, if any + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'), ++out; + out = copy_chars(node->name(), node->name() + node->name_size(), out); + out = print_attributes(out, node, flags); + + // If node is childless + if (node->value_size() == 0 && !node->first_node()) + { + // Print childless node tag ending + *out = Ch('/'), ++out; + *out = Ch('>'), ++out; + } + else + { + // Print normal node tag ending + *out = Ch('>'), ++out; + + // Test if node contains a single data node only (and no other nodes) + xml_node<Ch> *child = node->first_node(); + if (!child) + { + // If node has no children, only print its value without indenting + out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out); + } + else if (child->next_sibling() == 0 && child->type() == node_data) + { + // If node has a sole data child, only print its value without indenting + out = copy_and_expand_chars(child->value(), child->value() + child->value_size(), Ch(0), out); + } + else + { + // Print all children with full indenting + if (!(flags & print_no_indenting)) + *out = Ch('\n'), ++out; + out = print_children(out, node, flags, indent + 1); + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + } + + // Print node end + *out = Ch('<'), ++out; + *out = Ch('/'), ++out; + out = copy_chars(node->name(), node->name() + node->name_size(), out); + *out = Ch('>'), ++out; + } + return out; + } + + // Print declaration node + template<class OutIt, class Ch> + inline OutIt print_declaration_node(OutIt out, const xml_node<Ch> *node, int flags, int indent) + { + // Print declaration start + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'), ++out; + *out = Ch('?'), ++out; + *out = Ch('x'), ++out; + *out = Ch('m'), ++out; + *out = Ch('l'), ++out; + + // Print attributes + out = print_attributes(out, node, flags); + + // Print declaration end + *out = Ch('?'), ++out; + *out = Ch('>'), ++out; + + return out; + } + + // Print comment node + template<class OutIt, class Ch> + inline OutIt print_comment_node(OutIt out, const xml_node<Ch> *node, int flags, int indent) + { + assert(node->type() == node_comment); + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'), ++out; + *out = Ch('!'), ++out; + *out = Ch('-'), ++out; + *out = Ch('-'), ++out; + out = copy_chars(node->value(), node->value() + node->value_size(), out); + *out = Ch('-'), ++out; + *out = Ch('-'), ++out; + *out = Ch('>'), ++out; + return out; + } + + // Print doctype node + template<class OutIt, class Ch> + inline OutIt print_doctype_node(OutIt out, const xml_node<Ch> *node, int flags, int indent) + { + assert(node->type() == node_doctype); + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'), ++out; + *out = Ch('!'), ++out; + *out = Ch('D'), ++out; + *out = Ch('O'), ++out; + *out = Ch('C'), ++out; + *out = Ch('T'), ++out; + *out = Ch('Y'), ++out; + *out = Ch('P'), ++out; + *out = Ch('E'), ++out; + *out = Ch(' '), ++out; + out = copy_chars(node->value(), node->value() + node->value_size(), out); + *out = Ch('>'), ++out; + return out; + } + + // Print pi node + template<class OutIt, class Ch> + inline OutIt print_pi_node(OutIt out, const xml_node<Ch> *node, int flags, int indent) + { + assert(node->type() == node_pi); + if (!(flags & print_no_indenting)) + out = fill_chars(out, indent, Ch('\t')); + *out = Ch('<'), ++out; + *out = Ch('?'), ++out; + out = copy_chars(node->name(), node->name() + node->name_size(), out); + *out = Ch(' '), ++out; + out = copy_chars(node->value(), node->value() + node->value_size(), out); + *out = Ch('?'), ++out; + *out = Ch('>'), ++out; + return out; + } + + } + //! \endcond + + /////////////////////////////////////////////////////////////////////////// + // Printing + + //! Prints XML to given output iterator. + //! \param out Output iterator to print to. + //! \param node Node to be printed. Pass xml_document to print entire document. + //! \param flags Flags controlling how XML is printed. + //! \return Output iterator pointing to position immediately after last character of printed text. + template<class OutIt, class Ch> + inline OutIt print(OutIt out, const xml_node<Ch> &node, int flags = 0) + { + return internal::print_node(out, &node, flags, 0); + } + +#ifndef RAPIDXML_NO_STREAMS + + //! Prints XML to given output stream. + //! \param out Output stream to print to. + //! \param node Node to be printed. Pass xml_document to print entire document. + //! \param flags Flags controlling how XML is printed. + //! \return Output stream. + template<class Ch> + inline std::basic_ostream<Ch> &print(std::basic_ostream<Ch> &out, const xml_node<Ch> &node, int flags = 0) + { + print(std::ostream_iterator<Ch>(out), node, flags); + return out; + } + + //! Prints formatted XML to given output stream. Uses default printing flags. Use print() function to customize printing process. + //! \param out Output stream to print to. + //! \param node Node to be printed. + //! \return Output stream. + template<class Ch> + inline std::basic_ostream<Ch> &operator <<(std::basic_ostream<Ch> &out, const xml_node<Ch> &node) + { + return print(out, node); + } + +#endif + +} + +#endif diff --git a/Project/rapidXML/rapidxml_utils.hpp b/Project/rapidXML/rapidxml_utils.hpp new file mode 100644 index 0000000..37c2953 --- /dev/null +++ b/Project/rapidXML/rapidxml_utils.hpp @@ -0,0 +1,122 @@ +#ifndef RAPIDXML_UTILS_HPP_INCLUDED +#define RAPIDXML_UTILS_HPP_INCLUDED + +// Copyright (C) 2006, 2009 Marcin Kalicinski +// Version 1.13 +// Revision $DateTime: 2009/05/13 01:46:17 $ +//! \file rapidxml_utils.hpp This file contains high-level rapidxml utilities that can be useful +//! in certain simple scenarios. They should probably not be used if maximizing performance is the main objective. + +#include "rapidxml.hpp" +#include <vector> +#include <string> +#include <fstream> +#include <stdexcept> + +namespace rapidxml +{ + + //! Represents data loaded from a file + template<class Ch = char> + class file + { + + public: + + //! Loads file into the memory. Data will be automatically destroyed by the destructor. + //! \param filename Filename to load. + file(const char *filename) + { + using namespace std; + + // Open stream + basic_ifstream<Ch> stream(filename, ios::binary); + if (!stream) + throw runtime_error(string("cannot open file ") + filename); + stream.unsetf(ios::skipws); + + // Determine stream size + stream.seekg(0, ios::end); + size_t size = stream.tellg(); + stream.seekg(0); + + // Load data and add terminating 0 + m_data.resize(size + 1); + stream.read(&m_data.front(), static_cast<streamsize>(size)); + m_data[size] = 0; + } + + //! Loads file into the memory. Data will be automatically destroyed by the destructor + //! \param stream Stream to load from + file(std::basic_istream<Ch> &stream) + { + using namespace std; + + // Load data and add terminating 0 + stream.unsetf(ios::skipws); + m_data.assign(istreambuf_iterator<Ch>(stream), istreambuf_iterator<Ch>()); + if (stream.fail() || stream.bad()) + throw runtime_error("error reading stream"); + m_data.push_back(0); + } + + //! Gets file data. + //! \return Pointer to data of file. + Ch *data() + { + return &m_data.front(); + } + + //! Gets file data. + //! \return Pointer to data of file. + const Ch *data() const + { + return &m_data.front(); + } + + //! Gets file data size. + //! \return Size of file data, in characters. + std::size_t size() const + { + return m_data.size(); + } + + private: + + std::vector<Ch> m_data; // File data + + }; + + //! Counts children of node. Time complexity is O(n). + //! \return Number of children of node + template<class Ch> + inline std::size_t count_children(xml_node<Ch> *node) + { + xml_node<Ch> *child = node->first_node(); + std::size_t count = 0; + while (child) + { + ++count; + child = child->next_sibling(); + } + return count; + } + + //! Counts attributes of node. Time complexity is O(n). + //! \return Number of attributes of node + template<class Ch> + inline std::size_t count_attributes(xml_node<Ch> *node) + { + xml_attribute<Ch> *attr = node->first_attribute(); + std::size_t count = 0; + while (attr) + { + ++count; + attr = attr->next_attribute(); + } + return count; + } + +} + +#endif |