stringService = $stringService ?? new StringService(); } public function getDeviceElement(DOMDocument $document): DOMElement { $deviceElement = $document->getElementsByTagName('device')->item(0); if (!$deviceElement instanceof DOMElement) { throw new XmlParsingException('Missing device element'); } return $deviceElement; } public function getNodeAttributesByName(DOMNode $node): array { $output = []; foreach ($node->attributes as $attribute) { /** @var \DOMAttr $attribute */ $output[$attribute->name] = $attribute->value; } return $output; } public function getDeviceElementsFromXPath(string $expression, DOMDocument $document): DOMNodeList { $elements = (new \DOMXPath($document))->query('/device/' . $expression); if ($elements === false) { throw new \Exception('Failed to evaluate XPath expression - malformed expression'); } return $elements; } public function propertyGroupFromElement(DOMElement $element): PropertyGroup { $attributes = $this->getNodeAttributesByName($element); $output = new PropertyGroup($attributes['key'] ?? null, [], []); foreach ($element->childNodes as $childNode) { if (!$childNode instanceof DOMElement) { continue; } if ($childNode->nodeName === 'property') { $output->properties[] = $this->propertyFromElement($childNode); continue; } if ($childNode->nodeName === 'property-group') { $output->subPropertyGroups[] = $this->propertyGroupFromElement($childNode); } } return $output; } public function propertyFromElement(DOMElement $element): Property { $attributes = $this->getNodeAttributesByName($element); return new Property( $attributes['key'] ?? null, $attributes['value'] ?? null, ); } public function addressSpaceFromElement(DOMElement $element): AddressSpace { $attributes = $this->getNodeAttributesByName($element); $output = new AddressSpace( $attributes['key'] ?? null, $this->stringService->tryStringToInt($attributes['start'] ?? null), $this->stringService->tryStringToInt($attributes['size'] ?? null), $attributes['endianness'] ?? null, ); foreach ($element->childNodes as $childNode) { if (!$childNode instanceof DOMElement) { continue; } if ($childNode->nodeName === 'memory-segment') { $output->memorySegments[] = $this->memorySegmentFromElement($childNode); } } return $output; } public function memorySegmentFromElement(DOMElement $element): MemorySegment { $attributes = $this->getNodeAttributesByName($element); $output = new MemorySegment( $attributes['key'] ?? null, $attributes['name'] ?? null, MemorySegmentType::tryFrom($attributes['type'] ?? null), $this->stringService->tryStringToInt($attributes['start'] ?? null), $this->stringService->tryStringToInt($attributes['size'] ?? null), $this->stringService->tryStringToInt($attributes['page-size'] ?? null), $attributes['rw'] ?? null, [] ); foreach ($element->childNodes as $childNode) { if (!$childNode instanceof DOMElement) { continue; } if ($childNode->nodeName === 'section') { $output->sections[] = $this->memorySegmentSectionFromElement($childNode); } } return $output; } public function memorySegmentSectionFromElement(DOMElement $element): MemorySegmentSection { $attributes = $this->getNodeAttributesByName($element); $output = new MemorySegmentSection( $attributes['key'] ?? null, $attributes['name'] ?? null, $this->stringService->tryStringToInt($attributes['start'] ?? null), $this->stringService->tryStringToInt($attributes['size'] ?? null), [] ); foreach ($element->childNodes as $childNode) { if (!$childNode instanceof DOMElement) { continue; } if ($childNode->nodeName === 'section') { $output->subSections[] = $this->memorySegmentSectionFromElement($childNode); } } return $output; } public function physicalInterfaceFromElement(DOMElement $element): PhysicalInterface { $attributes = $this->getNodeAttributesByName($element); return new PhysicalInterface( $attributes['name'] ?? null, $attributes['type'] ?? null, ); } public function moduleFromElement(DOMElement $element): Module { $attributes = $this->getNodeAttributesByName($element); $output = new Module( $attributes['key'] ?? null, $attributes['name'] ?? null, $attributes['description'] ?? null, [] ); foreach ($element->childNodes as $childNode) { if (!$childNode instanceof DOMElement) { continue; } if ($childNode->nodeName === 'register-group') { $output->registerGroups[] = $this->registerGroupFromElement($childNode); } } return $output; } public function registerGroupFromElement(DOMElement $element): RegisterGroup { $attributes = $this->getNodeAttributesByName($element); $output = new RegisterGroup( $attributes['key'] ?? null, $attributes['name'] ?? null, $this->stringService->tryStringToInt($attributes['offset'] ?? null), [], [], [] ); foreach ($element->childNodes as $childNode) { if (!$childNode instanceof DOMElement) { continue; } if ($childNode->nodeName === 'register') { $output->registers[] = $this->registerFromElement($childNode); continue; } if ($childNode->nodeName === 'register-group') { $output->subGroups[] = $this->registerGroupFromElement($childNode); continue; } if ($childNode->nodeName === 'register-group-reference') { $output->subGroupReferences[] = $this->registerGroupReferenceFromElement($childNode); } } return $output; } public function registerGroupReferenceFromElement(DOMElement $element): RegisterGroupReference { $attributes = $this->getNodeAttributesByName($element); return new RegisterGroupReference( $attributes['key'] ?? null, $attributes['name'] ?? null, $attributes['register-group-key'] ?? null, $this->stringService->tryStringToInt($attributes['offset'] ?? null), $attributes['description'] ?? null ); } public function registerFromElement(DOMElement $element): Register { $attributes = $this->getNodeAttributesByName($element); $output = new Register( $attributes['key'] ?? null, $attributes['name'] ?? null, $attributes['description'] ?? null, $this->stringService->tryStringToInt($attributes['offset'] ?? null), $this->stringService->tryStringToInt($attributes['size'] ?? null), $this->stringService->tryStringToInt($attributes['initial-value'] ?? null), $attributes['rw'] ?? null, isset($attributes['alternative']) ? trim($attributes['alternative']) === 'true' : null, [] ); foreach ($element->childNodes as $childNode) { if (!$childNode instanceof DOMElement) { continue; } if ($childNode->nodeName === 'bit-field') { $output->bitFields[] = $this->bitFieldFromElement($childNode); } } return $output; } public function bitFieldFromElement(DOMElement $element): BitField { $attributes = $this->getNodeAttributesByName($element); return new BitField( $attributes['key'] ?? null, $attributes['name'] ?? null, $attributes['description'] ?? null, $this->stringService->tryStringToInt($attributes['mask'] ?? null), $attributes['rw'] ?? null ); } public function peripheralFromElement(DOMElement $element): Peripheral { $attributes = $this->getNodeAttributesByName($element); $output = new Peripheral( $attributes['key'] ?? null, $attributes['name'] ?? null, $attributes['module-key'] ?? null, [], [] ); foreach ($element->childNodes as $childNode) { if (!$childNode instanceof DOMElement) { continue; } if ($childNode->nodeName === 'register-group-reference') { $output->registerGroupReferences[] = $this->registerGroupReferenceFromElement($childNode); continue; } if ($childNode->nodeName === 'signal') { $output->signals[] = $this->signalFromElement($childNode); } } $signalsElements = $element->getElementsByTagName('signals'); if ($signalsElements->count() > 1) { throw new XmlParsingException('Unexpected number of "signals" elements'); } $signalElement = $signalsElements->item(0); if ($signalElement instanceof DOMElement) { foreach ($signalElement->childNodes as $childNode) { if (!$childNode instanceof DOMElement) { continue; } if ($childNode->nodeName === 'signal') { $output->signals[] = $this->signalFromElement($childNode); } } } return $output; } public function signalFromElement(DOMElement $element): Signal { $attributes = $this->getNodeAttributesByName($element); return new Signal( $attributes['pad-id'] ?? null, $this->stringService->tryStringToInt($attributes['index'] ?? null), $attributes['function'] ?? null, $attributes['group'] ?? null, $attributes['field'] ?? null ); } public function pinoutFromElement(DOMElement $element): Pinout { $attributes = $this->getNodeAttributesByName($element); $output = new Pinout( $attributes['key'] ?? null, $attributes['name'] ?? null, PinoutType::tryFrom($attributes['type'] ?? null), $attributes['function'] ?? null, [] ); foreach ($element->childNodes as $childNode) { if (!$childNode instanceof DOMElement) { continue; } if ($childNode->nodeName === 'pin') { $output->pins[] = $this->pinFromElement($childNode); } } return $output; } public function pinFromElement(DOMElement $element): Pin { $attributes = $this->getNodeAttributesByName($element); return new Pin( $attributes['position'] ?? null, $attributes['pad'] ?? null ); } public function variantFromElement(DOMElement $element): Variant { $attributes = $this->getNodeAttributesByName($element); return new Variant( $attributes['name'] ?? null, $attributes['pinout-key'] ?? null, $attributes['package'] ?? null ); } }