106 default:
return std::nullopt;
119 THROW_IO_ERROR( wxS(
"OrCAD structure: missing structure type" ) );
121 if( aExpectedType >= 0 && typeId != aExpectedType )
122 THROW_IO_ERRORF( wxS(
"OrCAD structure: expected type %d, got %d" ), aExpectedType, typeId );
126 : std::optional<size_t>( aLongPrefixCount );
129 THROW_IO_ERRORF( wxS(
"OrCAD structure: unregistered structure type %d" ), typeId );
131 if( *longCount == 0 )
132 THROW_IO_ERROR( wxS(
"OrCAD structure: long prefix count is zero" ) );
137 THROW_IO_ERROR( wxS(
"OrCAD structure: enclosing bound exceeds stream" ) );
139 for(
size_t i = 0; i < *longCount; ++i )
143 if( prefixType != typeId )
144 THROW_IO_ERRORF( wxS(
"OrCAD structure: prefix type mismatch %d != %d" ), prefixType, typeId );
149 THROW_IO_ERROR( wxS(
"OrCAD structure: long prefix pad not zero" ) );
153 THROW_IO_ERROR( wxS(
"OrCAD structure: short prefix type mismatch" ) );
156 int16_t propertyCount =
m_stream.ReadI16();
158 for(
int i = 0; i < propertyCount; ++i )
160 uint32_t nameIdx =
m_stream.ReadU32();
161 uint32_t valueIdx =
m_stream.ReadU32();
162 pfx.
props.emplace_back( nameIdx, valueIdx );
165 m_stream.ExpectPreamble( wxS(
"structure preamble" ) );
166 uint32_t trail =
m_stream.ReadU32();
171 for(
size_t i = 0; i < pfx.
bodyLens.size(); ++i )
174 size_t headerEnd = pfx.
start + 9 * i + 9;
176 if( pfx.
bodyLens[i] > std::numeric_limits<size_t>::max() - headerEnd )
177 THROW_IO_ERROR( wxS(
"OrCAD structure: structure stop overflow" ) );
179 size_t stop = headerEnd + pfx.
bodyLens[i];
181 if( stop < pfx.bodyStart || stop > bound )
182 THROW_IO_ERRORF( wxS(
"OrCAD structure: stop 0x%zx outside the enclosing bound" ), stop );
184 pfx.
stops.push_back( stop );
195 if(
m_strings && aIndex < m_strings->size() )
198 return std::string();
204 std::map<std::string, std::string> out;
206 for(
const std::pair<uint32_t, uint32_t>& prop : aPrefixes.
props )
226 THROW_IO_ERRORF( wxS(
"OrCAD structure: cannot skip structure %s" ), aWhat );
235 size_t start =
m_stream.GetOffset();
290 if( pfx.
end != 0 && pfx.
end > start )
292 Warn( wxString::Format( wxS(
"OrCAD structure type %d at 0x%zx: %s; skipped" ), pfx.
typeId, start,
295 result.record = std::monostate();
320 uint16_t rotFont = ds.
ReadU16();
321 prop.
fontIdx = rotFont & 0x3FFF;
322 prop.
rotation = ( rotFont >> 14 ) & 0x3;
326 ds.
ExpectByte( 0x00, wxS(
"display prop tail" ) );
362 uint16_t aliasCount = ds.
ReadU16();
364 for(
int i = 0; i < aliasCount; i++ )
369 wire.
aliases.push_back( std::move( *alias ) );
372 uint16_t propCount = ds.
ReadU16();
374 for(
int i = 0; i < propCount; i++ )
392 uint32_t headerWordB = ds.
ReadU32();
412 uint8_t orientation = ds.
ReadU8();
414 inst.
mirror = ( orientation & 0x4 ) != 0;
425 uint32_t valueIdx = ds.
ReadU32();
429 uint16_t pinCount = ds.
ReadU16();
431 for(
int i = 0; i < pinCount; i++ )
436 inst.
pins.push_back( std::move( *
pin ) );
453 uint32_t nameIdx = ds.
ReadU32();
473 uint8_t orientation = ds.
ReadU8();
475 inst.
mirror = ( orientation & 0x4 ) != 0;
489 inst.
nested = std::make_unique<ORCAD_SYMBOL_DEF>( std::move( *def ) );
573 std::vector<ORCAD_DISPLAY_PROP> out;
577 for(
int i = 0; i < count; i++ )
582 out.push_back( std::move( *prop ) );
609 uint16_t count = aStream.
ReadU16();
611 for( uint16_t i = 0; i < count; ++i )
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
Limit reads to one record so a malformed body cannot consume the next record.
Bound shared parser recursion; entering a level above MAX_NESTING throws IO_ERROR.
The caller owns the buffer.
uint8_t ReadU8()
– scalars (little-endian, bounds-checked, throw IO_ERROR on overrun) ----—
static constexpr size_t npos
Generic invalid offset sentinel.
void Skip(size_t aCount)
Advance the cursor; throws IO_ERROR when aCount exceeds the remaining bytes.
std::string ReadLzt()
– strings ----------------------------------------------------------------—
void Seek(size_t aOffset)
Set the absolute cursor position; throws IO_ERROR when aOffset exceeds Size().
void ExpectByte(uint8_t aValue, const wxString &aWhat)
Consume one byte and require the given value.
ReadStructure can recover from a body error when the prefix supplies a valid end offset.
std::map< std::string, std::string > PropsDict(const ORCAD_PREFIXES &aPrefixes) const
Resolve the short-prefix (nameIdx, valueIdx) pairs; empty names are dropped.
void SkipStructure(const ORCAD_PREFIXES &aPrefixes, const wxString &aWhat)
Throws IO_ERROR if the end is unknown or behind the cursor.
ORCAD_PREFIXES ReadPrefixes(int aExpectedType=-1, size_t aEnclosingEnd=ORCAD_STREAM::npos, size_t aLongPrefixCount=ORCAD_STREAM::npos)
aLongPrefixCount overrides the type depth; aEnclosingEnd bounds all stops.
void Warn(const wxString &aMsg) const
Report a recoverable problem to the warning sink (no-op when none was given).
std::string Resolve(uint32_t aIndex) const
String-table lookup; returns "" for out-of-range indices.
ORCAD_STRUCT_READER(ORCAD_STREAM &aStream, const std::vector< std::string > *aStrings=nullptr, ORCAD_WARN_FN aWarn=nullptr)
ORCAD_READ_RESULT ReadStructure()
Skip unknown bodies.
const std::vector< std::string > * m_strings
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
#define THROW_IO_ERRORF(msg,...)
ORCAD_DRAWN_INSTANCE OrcadReadDrawnInstance(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
ORCAD_SYMBOL_DEF OrcadReadSthInPages0(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
std::function< void(const wxString &aMsg)> ORCAD_WARN_FN
Coordinates use DBU with Y down.
@ ORCAD_ST_STH_IN_PAGES0
nested symbol body inside Graphic*Inst
@ ORCAD_ST_T0X10
scalar pin instance (absolute pos)
@ ORCAD_ST_PLACED_INSTANCE
@ ORCAD_ST_GRAPHIC_ARC_INST
@ ORCAD_ST_DRAWN_INSTANCE
hierarchical block instance
@ ORCAD_ST_GLOBAL
placed power symbol
@ ORCAD_ST_GRAPHIC_BITMAP_INST
@ ORCAD_ST_OFFPAGE_CONNECTOR
@ ORCAD_ST_GRAPHIC_LINE_INST
@ ORCAD_ST_GRAPHIC_COMMENT_TEXT_INST
@ ORCAD_ST_GRAPHIC_ELLIPSE_INST
@ ORCAD_ST_GRAPHIC_BOX_INST
@ ORCAD_ST_ERC_OBJECT
saved design-rule-check marker
@ ORCAD_ST_GRAPHIC_POLYLINE_INST
@ ORCAD_ST_GRAPHIC_BEZIER_INST
@ ORCAD_ST_GRAPHIC_POLYGON_INST
@ ORCAD_ST_ALIAS
net alias attached to a wire
@ ORCAD_ST_SYMBOL_DISPLAY_PROP
@ ORCAD_ST_T0X11
bus pin instance (absolute pos)
@ ORCAD_ST_GRAPHIC_OLE_INST
ORCAD_WIRE OrcadReadWire(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
Types 20 (wire) and 21 (bus); isBus is set from the prefix type.
ORCAD_PLACED_INSTANCE OrcadReadPlacedInstance(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
ORCAD_GRAPHIC_INST OrcadReadPort(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
GraphicInst body followed by a 9-byte trailer.
std::vector< ORCAD_DISPLAY_PROP > OrcadReadDisplayPropList(ORCAD_STRUCT_READER &aReader)
Keep only display properties that ReadStructure decodes.
ORCAD_NET_GROUP OrcadReadT0x34Raw(ORCAD_STREAM &aStream)
T0x34 records have no prefixes; consume their fixed layout to preserve alignment.
ORCAD_PIN_INST OrcadReadPinInst(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
ORCAD_DISPLAY_PROP OrcadReadDisplayProp(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &)
Body readers start after the prefixes.
ORCAD_BUS_ENTRY OrcadReadBusEntryBody(ORCAD_STREAM &aStream)
ORCAD_GRAPHIC_INST OrcadReadErcObject(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
GraphicInst body followed by 3 lzt strings.
ORCAD_ALIAS OrcadReadAlias(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &)
ORCAD_GRAPHIC_INST OrcadReadTitleBlock(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
GraphicInst body followed by a 12-byte trailer.
ORCAD_BUS_ENTRY OrcadReadBusEntry(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &)
ORCAD_GRAPHIC_INST OrcadReadGraphicInst(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
Common body of Port/Global/OffPageConnector/TitleBlock/ERCObject/Graphic*Inst.
std::optional< size_t > OrcadLongPrefixCount(int aTypeId)
Registered number of long prefixes for a modern framed structure type.
ORCAD_NET_GROUP OrcadReadT0x35Raw(ORCAD_STREAM &aStream)
T0x35 = the T0x34 raw layout followed by u16 n and 4 * n bytes.
ORCAD_WIRE OrcadReadWire(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
Types 20 (wire) and 21 (bus); isBus is set from the prefix type.
ORCAD_PLACED_INSTANCE OrcadReadPlacedInstance(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
ORCAD_GRAPHIC_INST OrcadReadPort(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
GraphicInst body followed by a 9-byte trailer.
ORCAD_PIN_INST OrcadReadPinInst(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
ORCAD_DISPLAY_PROP OrcadReadDisplayProp(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
Body readers start after the prefixes.
ORCAD_GRAPHIC_INST OrcadReadErcObject(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
GraphicInst body followed by 3 lzt strings.
ORCAD_GRAPHIC_INST OrcadReadTitleBlock(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
GraphicInst body followed by a 12-byte trailer.
ORCAD_GRAPHIC_INST OrcadReadGraphicInst(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
Common body of Port/Global/OffPageConnector/TitleBlock/ERCObject/Graphic*Inst.
ORCAD_BUS_ENTRY OrcadReadBusEntry(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
ORCAD_ALIAS OrcadReadAlias(ORCAD_STRUCT_READER &aReader, const ORCAD_PREFIXES &aPrefixes)
std::optional< size_t > OrcadLongPrefixCount(int aTypeId)
Registered number of long prefixes for a modern framed structure type.
The owning wire defines the connection.
int rotation
0..3 quarter turns
Display positions use symbol coordinates; rotFont combines the font index and quarter turns.
int fontIdx
1-based into ORCAD_LIBRARY_INFO::fonts; 0 = default
int rotation
0..3 quarter turns
std::string name
resolved property name (empty when index invalid)
Free graphics use nested primitive coordinates.
std::unique_ptr< ORCAD_SYMBOL_DEF > nested
SthInPages0 body, else nullptr.
std::map< std::string, std::string > props
int rotation
0..3 quarter turns
std::string name
cache symbol name
std::vector< ORCAD_DISPLAY_PROP > displayProps
std::string logicalName
ports: resolved net/port name
int typeId
ORCAD_ST value.
std::vector< uint32_t > members
Pin positions are absolute page connection points.
The placed box includes displayed text.
std::string sourcePackage
package base name
std::vector< ORCAD_DISPLAY_PROP > displayProps
ORCAD_BBOX bbox
placed box, page DBU
int rotation
0..3 quarter turns
uint16_t unitIndex
zero-based package device index
std::map< std::string, std::string > props
short-prefix property pairs
bool mirror
orientation bit 2
std::string sourceLibrary
source library path from the placed-instance header
std::string value
resolved Part Value
std::vector< ORCAD_PIN_INST > pins
successfully parsed T0x10 records
Prefix lengths supply structure bounds.
std::vector< size_t > stops
< (from the outermost long prefix); < 0 when unknown
int typeId
ORCAD_ST value (u8 in the stream)
size_t bodyStart
offset right after the preamble trail
std::vector< std::pair< uint32_t, uint32_t > > props
short prefix (nameIdx, valueIdx) pairs
std::vector< uint32_t > bodyLens
one per long prefix, outermost first
size_t end
offset right after the whole structure
size_t start
stream offset where the chain began
ORCAD_RECORD_VARIANT record
The bounding box occupies the final eight bytes before the next prefix stop.
The wire ID refers to the page net table.
bool isBus
true for structure type 21
std::vector< ORCAD_ALIAS > aliases
wxString result
Test unit parsing edge cases and error handling.