Task 697: .STP File Format
Task 697: .STP File Format
.STP File Format Specifications
The .STP file format refers to the STEP (Standard for the Exchange of Product Model Data) format, defined by ISO 10303-21. It is a text-based (ASCII or UTF-8) format for representing and exchanging 3D product data, commonly used in CAD, engineering, and manufacturing. The file structure is sequential, starting with the magic string ISO-10303-21;, followed by a mandatory HEADER section, optional ANCHOR and REFERENCE sections, one or more DATA sections containing entity instances, and ending with END-ISO-10303-21;. Optional SIGNATURE sections can follow. Sections are delimited by ENDSEC;. The format supports conformance classes (1-3) for features like external references and signatures. Data is encoded using EXPRESS schema mappings, with entities like #ID=ENTITY_NAME(attributes);.
- List of all the properties of this file format intrinsic to its file system:
- Description: A list of strings describing the file's content (from FILE_DESCRIPTION).
- Implementation Level: A string indicating the ISO 10303-21 version and conformance class (e.g., '4;1') (from FILE_DESCRIPTION).
- Name: The file's name or identifier (from FILE_NAME).
- Time Stamp: An ISO 8601-formatted date-time string of creation (from FILE_NAME).
- Author: A list of strings with author names/addresses (from FILE_NAME).
- Organization: A list of strings with organization names (from FILE_NAME).
- Preprocessor Version: A string with the tool/version used to create the file (from FILE_NAME).
- Originating System: A string identifying the source system (from FILE_NAME).
- Authorization: A string with the authorizer's name/address (from FILE_NAME).
- Schema Identifiers: A list of schema names (e.g., 'CONFIG_CONTROL_DESIGN') (from FILE_SCHEMA).
- Schema Population (optional): A list of external file identifications (URIs, timestamps, digests) for referenced files (from SCHEMA_POPULATION).
- File Population (optional): Details on governing schema, determination method, and governed sections (from FILE_POPULATION).
- Default Language (optional): A language code (e.g., 'eng') for strings in data sections (from SECTION_LANGUAGE).
- Context Identifiers (optional): A list of strings for contextual tags (e.g., conformance classes) (from SECTION_CONTEXT).
These properties are primarily in the HEADER section and are intrinsic as they define the file's metadata, schema conformance, and exchange context.
Two direct download links for files of format .STP:
- https://www.steptools.com/docs/stpfiles/ap203/1797609in.stp
- https://www.steptools.com/docs/stpfiles/ap203/2827056.stp
Ghost blog embedded HTML JavaScript for drag-and-drop .STP file to dump properties to screen:
This can be embedded in a Ghost blog post. It allows drag-and-drop of a .STP file, parses the HEADER, and displays the properties as JSON. Note: This is a basic parser; for production, use a robust library like stepcode to handle escapes, complex structures, and errors.
- Python class for .STP handling:
import re
import json
class StpHandler:
def __init__(self, file_path):
self.file_path = file_path
self.properties = {}
self.content = ''
self._read_and_decode()
def _read_and_decode(self):
with open(self.file_path, 'r', encoding='utf-8') as f:
self.content = f.read()
lines = self.content.split('\n')
in_header = False
header_content = ''
for line in lines:
line = line.strip()
if line.startswith('HEADER;'):
in_header = True
continue
if line.startswith('ENDSEC;') and in_header:
in_header = False
break
if in_header:
header_content += line
self.properties = {
'description': [],
'implementation_level': '',
'name': '',
'time_stamp': '',
'author': [],
'organization': [],
'preprocessor_version': '',
'originating_system': '',
'authorization': '',
'schema_identifiers': [],
'schema_population': [],
'file_population': {'governing_schema': '', 'determination_method': '', 'governed_sections': []},
'default_language': '',
'context_identifiers': []
}
# Basic regex-based parsing (assumes no deep nesting/escapes)
entities = re.split(r';(?![^(]*\))', header_content)
for entity in entities:
entity = entity.strip()
if not entity:
continue
if 'FILE_DESCRIPTION' in entity:
params = re.search(r'\((.*)\)', entity).group(1).split(',(?![^(]*\))', maxsplit=1)
self.properties['description'] = self._parse_list(params[0])
self.properties['implementation_level'] = params[1].strip("'") if len(params) > 1 else ''
elif 'FILE_NAME' in entity:
params = re.search(r'\((.*)\)', entity).group(1).split(',(?![^(]*\))', maxsplit=6)
self.properties['name'] = params[0].strip("'")
self.properties['time_stamp'] = params[1].strip("'")
self.properties['author'] = self._parse_list(params[2])
self.properties['organization'] = self._parse_list(params[3])
self.properties['preprocessor_version'] = params[4].strip("'")
self.properties['originating_system'] = params[5].strip("'")
self.properties['authorization'] = params[6].strip("'") if len(params) > 6 else ''
elif 'FILE_SCHEMA' in entity:
params = re.search(r'\((.*)\)', entity).group(1)
self.properties['schema_identifiers'] = self._parse_list(params)
elif 'SCHEMA_POPULATION' in entity:
params = re.search(r'\((.*)\)', entity).group(1)
self.properties['schema_population'] = self._parse_list(params)
elif 'FILE_POPULATION' in entity:
params = re.search(r'\((.*)\)', entity).group(1).split(',(?![^(]*\))', maxsplit=2)
self.properties['file_population']['governing_schema'] = params[0].strip("'")
self.properties['file_population']['determination_method'] = params[1].strip("'")
self.properties['file_population']['governed_sections'] = self._parse_list(params[2]) if len(params) > 2 else []
elif 'SECTION_LANGUAGE' in entity:
params = re.search(r'\((.*)\)', entity).group(1).split(',')
self.properties['default_language'] = params[1].strip("'") if len(params) > 1 else ''
elif 'SECTION_CONTEXT' in entity:
params = re.search(r'\((.*)\)', entity).group(1).split(',(?![^(]*\))', maxsplit=1)
self.properties['context_identifiers'] = self._parse_list(params[1]) if len(params) > 1 else []
def _parse_list(self, s):
s = s.strip('()')
if not s:
return []
items = re.split(r',(?!(?:[^()]*\([^()]*\))*[^()]*$)', s)
return [item.strip("'").strip() for item in items if item.strip()]
def print_properties(self):
print(json.dumps(self.properties, indent=2))
def write(self, new_file_path, modified_properties=None):
if modified_properties:
self.properties.update(modified_properties)
# Rebuild header (basic; preserves data sections)
new_header = 'HEADER;\n'
new_header += f"FILE_DESCRIPTION({self._format_list(self.properties['description'])},'{self.properties['implementation_level']}');\n"
new_header += f"FILE_NAME('{self.properties['name']}','{self.properties['time_stamp']}',{self._format_list(self.properties['author'])},{self._format_list(self.properties['organization'])},'{self.properties['preprocessor_version']}','{self.properties['originating_system']}','{self.properties['authorization']}');\n"
new_header += f"FILE_SCHEMA({self._format_list(self.properties['schema_identifiers'])});\n"
if self.properties['schema_population']:
new_header += f"SCHEMA_POPULATION({self._format_list(self.properties['schema_population'])});\n"
if self.properties['file_population']['governing_schema']:
fp = self.properties['file_population']
new_header += f"FILE_POPULATION('{fp['governing_schema']}','{fp['determination_method']}',{self._format_list(fp['governed_sections'])});\n"
if self.properties['default_language']:
new_header += f"SECTION_LANGUAGE($,'{self.properties['default_language']}');\n"
if self.properties['context_identifiers']:
new_header += f"SECTION_CONTEXT($,{self._format_list(self.properties['context_identifiers'])});\n"
new_header += 'ENDSEC;\n'
# Replace original header in content
content_without_header = re.sub(r'HEADER;.*?ENDSEC;', new_header, self.content, flags=re.DOTALL)
with open(new_file_path, 'w', encoding='utf-8') as f:
f.write(content_without_header)
def _format_list(self, lst):
if not lst:
return '()'
return '(' + ','.join(f"'{item}'" if isinstance(item, str) else str(item) for item in lst) + ')'
# Example usage:
# handler = StpHandler('example.stp')
# handler.print_properties()
# handler.write('modified.stp', {'name': 'new_name'})
- Java class for .STP handling:
import java.io.*;
import java.util.*;
import java.util.regex.*;
public class StpHandler {
private String filePath;
private Map<String, Object> properties;
private String content;
public StpHandler(String filePath) {
this.filePath = filePath;
this.properties = new HashMap<>();
this.content = "";
readAndDecode();
}
private void readAndDecode() {
try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
content = new String(Files.readAllBytes(new File(filePath).toPath()));
} catch (IOException e) {
e.printStackTrace();
}
Pattern headerPattern = Pattern.compile("HEADER;(.*?)ENDSEC;", Pattern.DOTALL);
Matcher matcher = headerPattern.matcher(content);
String headerContent = "";
if (matcher.find()) {
headerContent = matcher.group(1);
}
properties.put("description", new ArrayList<String>());
properties.put("implementation_level", "");
properties.put("name", "");
properties.put("time_stamp", "");
properties.put("author", new ArrayList<String>());
properties.put("organization", new ArrayList<String>());
properties.put("preprocessor_version", "");
properties.put("originating_system", "");
properties.put("authorization", "");
properties.put("schema_identifiers", new ArrayList<String>());
properties.put("schema_population", new ArrayList<String>());
Map<String, Object> filePopulation = new HashMap<>();
filePopulation.put("governing_schema", "");
filePopulation.put("determination_method", "");
filePopulation.put("governed_sections", new ArrayList<String>());
properties.put("file_population", filePopulation);
properties.put("default_language", "");
properties.put("context_identifiers", new ArrayList<String>());
String[] entities = headerContent.split(";");
for (String entity : entities) {
entity = entity.trim();
if (entity.isEmpty()) continue;
if (entity.contains("FILE_DESCRIPTION")) {
String params = entity.substring(entity.indexOf("(") + 1, entity.lastIndexOf(")"));
String[] split = params.split(",(?![^(]*\\))", 2);
((List<String>) properties.get("description")).addAll(parseList(split[0]));
properties.put("implementation_level", split[1].replace("'", "").trim());
} else if (entity.contains("FILE_NAME")) {
String params = entity.substring(entity.indexOf("(") + 1, entity.lastIndexOf(")"));
String[] split = params.split(",(?![^(]*\\))", 7);
properties.put("name", split[0].replace("'", "").trim());
properties.put("time_stamp", split[1].replace("'", "").trim());
((List<String>) properties.get("author")).addAll(parseList(split[2]));
((List<String>) properties.get("organization")).addAll(parseList(split[3]));
properties.put("preprocessor_version", split[4].replace("'", "").trim());
properties.put("originating_system", split[5].replace("'", "").trim());
properties.put("authorization", split.length > 6 ? split[6].replace("'", "").trim() : "");
} else if (entity.contains("FILE_SCHEMA")) {
String params = entity.substring(entity.indexOf("(") + 1, entity.lastIndexOf(")"));
((List<String>) properties.get("schema_identifiers")).addAll(parseList(params));
} else if (entity.contains("SCHEMA_POPULATION")) {
String params = entity.substring(entity.indexOf("(") + 1, entity.lastIndexOf(")"));
((List<String>) properties.get("schema_population")).addAll(parseList(params));
} else if (entity.contains("FILE_POPULATION")) {
String params = entity.substring(entity.indexOf("(") + 1, entity.lastIndexOf(")"));
String[] split = params.split(",(?![^(]*\\))", 3);
((Map<String, Object>) properties.get("file_population")).put("governing_schema", split[0].replace("'", "").trim());
((Map<String, Object>) properties.get("file_population")).put("determination_method", split[1].replace("'", "").trim());
if (split.length > 2) {
((Map<String, Object>) properties.get("file_population")).put("governed_sections", parseList(split[2]));
}
} else if (entity.contains("SECTION_LANGUAGE")) {
String params = entity.substring(entity.indexOf("(") + 1, entity.lastIndexOf(")"));
String[] split = params.split(",");
properties.put("default_language", split.length > 1 ? split[1].replace("'", "").trim() : "");
} else if (entity.contains("SECTION_CONTEXT")) {
String params = entity.substring(entity.indexOf("(") + 1, entity.lastIndexOf(")"));
String[] split = params.split(",(?![^(]*\\))", 2);
if (split.length > 1) {
((List<String>) properties.get("context_identifiers")).addAll(parseList(split[1]));
}
}
}
}
private List<String> parseList(String s) {
s = s.trim().replaceAll("^\\(|\\)$", "");
if (s.isEmpty()) return new ArrayList<>();
String[] items = s.split(",(?!(?:[^()]*\\([^()]*\\))*[^()]*$)");
List<String> list = new ArrayList<>();
for (String item : items) {
list.add(item.replace("'", "").trim());
}
return list;
}
public void printProperties() {
System.out.println(properties);
}
public void write(String newFilePath, Map<String, Object> modifiedProperties) {
if (modifiedProperties != null) {
for (Map.Entry<String, Object> entry : modifiedProperties.entrySet()) {
if (entry.getKey().equals("file_population") && entry.getValue() instanceof Map) {
((Map<String, Object>) properties.get("file_population")).putAll((Map<String, Object>) entry.getValue());
} else {
properties.put(entry.getKey(), entry.getValue());
}
}
}
// Rebuild header
StringBuilder newHeader = new StringBuilder("HEADER;\n");
newHeader.append("FILE_DESCRIPTION(").append(formatList((List<String>) properties.get("description"))).append(",'").append(properties.get("implementation_level")).append("');\n");
newHeader.append("FILE_NAME('").append(properties.get("name")).append("','").append(properties.get("time_stamp")).append("',")
.append(formatList((List<String>) properties.get("author"))).append(",")
.append(formatList((List<String>) properties.get("organization"))).append(",'")
.append(properties.get("preprocessor_version")).append("','").append(properties.get("originating_system")).append("','")
.append(properties.get("authorization")).append("');\n");
newHeader.append("FILE_SCHEMA(").append(formatList((List<String>) properties.get("schema_identifiers"))).append(");\n");
List<String> schemaPop = (List<String>) properties.get("schema_population");
if (!schemaPop.isEmpty()) {
newHeader.append("SCHEMA_POPULATION(").append(formatList(schemaPop)).append(");\n");
}
Map<String, Object> fp = (Map<String, Object>) properties.get("file_population");
if (!fp.get("governing_schema").equals("")) {
newHeader.append("FILE_POPULATION('").append(fp.get("governing_schema")).append("','").append(fp.get("determination_method")).append("',")
.append(formatList((List<String>) fp.get("governed_sections"))).append(");\n");
}
if (!properties.get("default_language").equals("")) {
newHeader.append("SECTION_LANGUAGE($,'").append(properties.get("default_language")).append("');\n");
}
List<String> contextIds = (List<String>) properties.get("context_identifiers");
if (!contextIds.isEmpty()) {
newHeader.append("SECTION_CONTEXT($,").append(formatList(contextIds)).append(");\n");
}
newHeader.append("ENDSEC;\n");
// Replace in content
String newContent = content.replaceAll("HEADER;.*?ENDSEC;", newHeader.toString());
try (FileWriter writer = new FileWriter(newFilePath)) {
writer.write(newContent);
} catch (IOException e) {
e.printStackTrace();
}
}
private String formatList(List<String> list) {
if (list.isEmpty()) return "()";
StringBuilder sb = new StringBuilder("(");
for (String item : list) {
sb.append("'").append(item).append("',");
}
return sb.substring(0, sb.length() - 1) + ")";
}
// Example usage:
// public static void main(String[] args) {
// StpHandler handler = new StpHandler("example.stp");
// handler.printProperties();
// handler.write("modified.stp", null);
// }
}
- JavaScript class for .STP handling (Node.js compatible; for browser, adapt with FileReader):
const fs = require('fs');
class StpHandler {
constructor(filePath) {
this.filePath = filePath;
this.properties = {};
this.content = '';
this.readAndDecode();
}
readAndDecode() {
this.content = fs.readFileSync(this.filePath, 'utf-8');
const lines = this.content.split('\n');
let inHeader = false;
let headerContent = '';
for (let line of lines) {
line = line.trim();
if (line.startsWith('HEADER;')) {
inHeader = true;
continue;
}
if (line.startsWith('ENDSEC;') && inHeader) {
inHeader = false;
break;
}
if (inHeader) {
headerContent += line;
}
}
this.properties = {
description: [],
implementation_level: '',
name: '',
time_stamp: '',
author: [],
organization: [],
preprocessor_version: '',
originating_system: '',
authorization: '',
schema_identifiers: [],
schema_population: [],
file_population: { governing_schema: '', determination_method: '', governed_sections: [] },
default_language: '',
context_identifiers: []
};
const entities = headerContent.split(';').filter(e => e.trim());
entities.forEach(entity => {
if (entity.includes('FILE_DESCRIPTION')) {
const params = entity.match(/\((.*)\)/)[1].split(/,(?![^(]*\))/);
this.properties.description = this.parseList(params[0]);
this.properties.implementation_level = params[1].replace(/'/g, '');
} else if (entity.includes('FILE_NAME')) {
const params = entity.match(/\((.*)\)/)[1].split(/,(?![^(]*\))/);
this.properties.name = params[0].replace(/'/g, '');
this.properties.time_stamp = params[1].replace(/'/g, '');
this.properties.author = this.parseList(params[2]);
this.properties.organization = this.parseList(params[3]);
this.properties.preprocessor_version = params[4].replace(/'/g, '');
this.properties.originating_system = params[5].replace(/'/g, '');
this.properties.authorization = params[6].replace(/'/g, '');
} else if (entity.includes('FILE_SCHEMA')) {
const params = entity.match(/\((.*)\)/)[1];
this.properties.schema_identifiers = this.parseList(params);
} else if (entity.includes('SCHEMA_POPULATION')) {
const params = entity.match(/\((.*)\)/)[1];
this.properties.schema_population = this.parseList(params);
} else if (entity.includes('FILE_POPULATION')) {
const params = entity.match(/\((.*)\)/)[1].split(/,(?![^(]*\))/);
this.properties.file_population.governing_schema = params[0].replace(/'/g, '');
this.properties.file_population.determination_method = params[1].replace(/'/g, '');
this.properties.file_population.governed_sections = this.parseList(params[2] || '()');
} else if (entity.includes('SECTION_LANGUAGE')) {
const params = entity.match(/\((.*)\)/)[1].split(',');
this.properties.default_language = (params[1] || '').replace(/'/g, '');
} else if (entity.includes('SECTION_CONTEXT')) {
const params = entity.match(/\((.*)\)/)[1].split(/,(?![^(]*\))/);
this.properties.context_identifiers = this.parseList(params[1] || '()');
}
});
}
parseList(s) {
s = s.trim().replace(/^\(|\)$/g, '');
if (!s) return [];
const items = s.split(/,(?!(?:[^()]*\([^()]*\))*[^()]*$)/);
return items.map(item => item.replace(/'/g, '').trim());
}
printProperties() {
console.log(JSON.stringify(this.properties, null, 2));
}
write(newFilePath, modifiedProperties) {
if (modifiedProperties) {
Object.assign(this.properties, modifiedProperties);
if (modifiedProperties.file_population) {
Object.assign(this.properties.file_population, modifiedProperties.file_population);
}
}
let newHeader = 'HEADER;\n';
newHeader += `FILE_DESCRIPTION(${this.formatList(this.properties.description)},'${this.properties.implementation_level}');\n`;
newHeader += `FILE_NAME('${this.properties.name}','${this.properties.time_stamp}',${this.formatList(this.properties.author)},${this.formatList(this.properties.organization)},'${this.properties.preprocessor_version}','${this.properties.originating_system}','${this.properties.authorization}');\n`;
newHeader += `FILE_SCHEMA(${this.formatList(this.properties.schema_identifiers)});\n`;
if (this.properties.schema_population.length) {
newHeader += `SCHEMA_POPULATION(${this.formatList(this.properties.schema_population)});\n`;
}
const fp = this.properties.file_population;
if (fp.governing_schema) {
newHeader += `FILE_POPULATION('${fp.governing_schema}','${fp.determination_method}',${this.formatList(fp.governed_sections)});\n`;
}
if (this.properties.default_language) {
newHeader += `SECTION_LANGUAGE($,'${this.properties.default_language}');\n`;
}
if (this.properties.context_identifiers.length) {
newHeader += `SECTION_CONTEXT($,${this.formatList(this.properties.context_identifiers)});\n`;
}
newHeader += 'ENDSEC;\n';
const newContent = this.content.replace(/HEADER;.*?ENDSEC;/s, newHeader);
fs.writeFileSync(newFilePath, newContent, 'utf-8');
}
formatList(lst) {
if (!lst.length) return '()';
return '(' + lst.map(item => `'${item}'`).join(',') + ')';
}
}
// Example usage:
// const handler = new StpHandler('example.stp');
// handler.printProperties();
// handler.write('modified.stp', { name: 'new_name' });
- C class (using C++ for class support):
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <map>
#include <regex>
#include <string>
class StpHandler {
private:
std::string filePath;
std::map<std::string, std::string> simpleProperties;
std::map<std::string, std::vector<std::string>> listProperties;
std::map<std::string, std::string> filePopulation;
std::string content;
std::vector<std::string> parseList(const std::string& s) {
std::string cleaned = s;
cleaned.erase(std::remove(cleaned.begin(), cleaned.end(), '('), cleaned.end());
cleaned.erase(std::remove(cleaned.begin(), cleaned.end(), ')'), cleaned.end());
if (cleaned.empty()) return {};
std::vector<std::string> list;
std::regex itemRegex(R"(([^,]+(?!(?:[^()]*\([^()]*\))*[^()]*$)))");
std::sregex_iterator iter(cleaned.begin(), cleaned.end(), itemRegex);
std::sregex_iterator end;
for (; iter != end; ++iter) {
std::string item = iter->str();
item.erase(std::remove(item.begin(), item.end(), '\''), item.end());
list.push_back(item);
}
return list;
}
std::string formatList(const std::vector<std::string>& lst) {
if (lst.empty()) return "()";
std::string res = "(";
for (const auto& item : lst) {
res += "'" + item + "',";
}
res.back() = ')';
return res;
}
public:
StpHandler(const std::string& path) : filePath(path) {
std::ifstream file(filePath);
std::stringstream buffer;
buffer << file.rdbuf();
content = buffer.str();
std::regex headerRegex(R"(HEADER;(.*?)ENDSEC;)", std::regex::dotall);
std::smatch match;
std::string headerContent;
if (std::regex_search(content, match, headerRegex)) {
headerContent = match[1].str();
}
listProperties["description"] = {};
simpleProperties["implementation_level"] = "";
simpleProperties["name"] = "";
simpleProperties["time_stamp"] = "";
listProperties["author"] = {};
listProperties["organization"] = {};
simpleProperties["preprocessor_version"] = "";
simpleProperties["originating_system"] = "";
simpleProperties["authorization"] = "";
listProperties["schema_identifiers"] = {};
listProperties["schema_population"] = {};
filePopulation["governing_schema"] = "";
filePopulation["determination_method"] = "";
listProperties["governed_sections"] = {};
simpleProperties["default_language"] = "";
listProperties["context_identifiers"] = {};
std::regex entityRegex(R"(([^;]+);)");
std::sregex_iterator entityIter(headerContent.begin(), headerContent.end(), entityRegex);
std::sregex_iterator entityEnd;
for (; entityIter != entityEnd; ++entityIter) {
std::string entity = entityIter->str(1);
if (entity.find("FILE_DESCRIPTION") != std::string::npos) {
std::regex paramsRegex(R"\((.*)\)");
std::smatch paramsMatch;
if (std::regex_search(entity, paramsMatch, paramsRegex)) {
std::string params = paramsMatch[1].str();
size_t splitPos = params.find_last_of(',');
listProperties["description"] = parseList(params.substr(0, splitPos));
simpleProperties["implementation_level"] = params.substr(splitPos + 1);
simpleProperties["implementation_level"].erase(std::remove(simpleProperties["implementation_level"].begin(), simpleProperties["implementation_level"].end(), '\''), simpleProperties["implementation_level"].end());
}
} else if (entity.find("FILE_NAME") != std::string::npos) {
std::regex paramsRegex(R"\((.*)\)");
std::smatch paramsMatch;
if (std::regex_search(entity, paramsMatch, paramsRegex)) {
std::string params = paramsMatch[1].str();
std::vector<std::string> split; // Manual split for simplicity
std::stringstream ss(params);
std::string token;
while (std::getline(ss, token, ',')) {
if (token.find('(') != std::string::npos && token.find(')') == std::string::npos) {
std::string nested;
nested += token + ",";
while (std::getline(ss, token, ',')) {
nested += token + ",";
if (token.find(')') != std::string::npos) break;
}
split.push_back(nested.substr(0, nested.size() - 1));
} else {
split.push_back(token);
}
}
simpleProperties["name"] = split[0]; simpleProperties["name"].erase(std::remove(simpleProperties["name"].begin(), simpleProperties["name"].end(), '\''), simpleProperties["name"].end());
simpleProperties["time_stamp"] = split[1]; simpleProperties["time_stamp"].erase(std::remove(simpleProperties["time_stamp"].begin(), simpleProperties["time_stamp"].end(), '\''), simpleProperties["time_stamp"].end());
listProperties["author"] = parseList(split[2]);
listProperties["organization"] = parseList(split[3]);
simpleProperties["preprocessor_version"] = split[4]; simpleProperties["preprocessor_version"].erase(std::remove(simpleProperties["preprocessor_version"].begin(), simpleProperties["preprocessor_version"].end(), '\''), simpleProperties["preprocessor_version"].end());
simpleProperties["originating_system"] = split[5]; simpleProperties["originating_system"].erase(std::remove(simpleProperties["originating_system"].begin(), simpleProperties["originating_system"].end(), '\''), simpleProperties["originating_system"].end());
simpleProperties["authorization"] = split.size() > 6 ? split[6] : ""; simpleProperties["authorization"].erase(std::remove(simpleProperties["authorization"].begin(), simpleProperties["authorization"].end(), '\''), simpleProperties["authorization"].end());
}
} else if (entity.find("FILE_SCHEMA") != std::string::npos) {
std::regex paramsRegex(R"\((.*)\)");
std::smatch paramsMatch;
if (std::regex_search(entity, paramsMatch, paramsRegex)) {
listProperties["schema_identifiers"] = parseList(paramsMatch[1].str());
}
} else if (entity.find("SCHEMA_POPULATION") != std::string::npos) {
std::regex paramsRegex(R"\((.*)\)");
std::smatch paramsMatch;
if (std::regex_search(entity, paramsMatch, paramsRegex)) {
listProperties["schema_population"] = parseList(paramsMatch[1].str());
}
} else if (entity.find("FILE_POPULATION") != std::string::npos) {
std::regex paramsRegex(R"\((.*)\)");
std::smatch paramsMatch;
if (std::regex_search(entity, paramsMatch, paramsRegex)) {
std::string params = paramsMatch[1].str();
size_t pos1 = params.find(',');
size_t pos2 = params.find(',', pos1 + 1);
filePopulation["governing_schema"] = params.substr(0, pos1); filePopulation["governing_schema"].erase(std::remove(filePopulation["governing_schema"].begin(), filePopulation["governing_schema"].end(), '\''), filePopulation["governing_schema"].end());
filePopulation["determination_method"] = params.substr(pos1 + 1, pos2 - pos1 - 1); filePopulation["determination_method"].erase(std::remove(filePopulation["determination_method"].begin(), filePopulation["determination_method"].end(), '\''), filePopulation["determination_method"].end());
if (pos2 != std::string::npos) {
listProperties["governed_sections"] = parseList(params.substr(pos2 + 1));
}
}
} else if (entity.find("SECTION_LANGUAGE") != std::string::npos) {
std::regex paramsRegex(R"\((.*)\)");
std::smatch paramsMatch;
if (std::regex_search(entity, paramsMatch, paramsRegex)) {
std::string params = paramsMatch[1].str();
size_t pos = params.find(',');
simpleProperties["default_language"] = (pos != std::string::npos) ? params.substr(pos + 1) : "";
simpleProperties["default_language"].erase(std::remove(simpleProperties["default_language"].begin(), simpleProperties["default_language"].end(), '\''), simpleProperties["default_language"].end());
}
} else if (entity.find("SECTION_CONTEXT") != std::string::npos) {
std::regex paramsRegex(R"\((.*)\)");
std::smatch paramsMatch;
if (std::regex_search(entity, paramsMatch, paramsRegex)) {
std::string params = paramsMatch[1].str();
size_t pos = params.find(',');
if (pos != std::string::npos) {
listProperties["context_identifiers"] = parseList(params.substr(pos + 1));
}
}
}
}
}
void printProperties() {
std::cout << "{\n";
std::cout << " \"description\": [" << std::endl;
for (const auto& item : listProperties["description"]) std::cout << " \"" << item << "\"," << std::endl;
std::cout << " ],\n";
std::cout << " \"implementation_level\": \"" << simpleProperties["implementation_level"] << "\",\n";
std::cout << " \"name\": \"" << simpleProperties["name"] << "\",\n";
std::cout << " \"time_stamp\": \"" << simpleProperties["time_stamp"] << "\",\n";
std::cout << " \"author\": [" << std::endl;
for (const auto& item : listProperties["author"]) std::cout << " \"" << item << "\"," << std::endl;
std::cout << " ],\n";
std::cout << " \"organization\": [" << std::endl;
for (const auto& item : listProperties["organization"]) std::cout << " \"" << item << "\"," << std::endl;
std::cout << " ],\n";
std::cout << " \"preprocessor_version\": \"" << simpleProperties["preprocessor_version"] << "\",\n";
std::cout << " \"originating_system\": \"" << simpleProperties["originating_system"] << "\",\n";
std::cout << " \"authorization\": \"" << simpleProperties["authorization"] << "\",\n";
std::cout << " \"schema_identifiers\": [" << std::endl;
for (const auto& item : listProperties["schema_identifiers"]) std::cout << " \"" << item << "\"," << std::endl;
std::cout << " ],\n";
std::cout << " \"schema_population\": [" << std::endl;
for (const auto& item : listProperties["schema_population"]) std::cout << " \"" << item << "\"," << std::endl;
std::cout << " ],\n";
std::cout << " \"file_population\": {\n";
std::cout << " \"governing_schema\": \"" << filePopulation["governing_schema"] << "\",\n";
std::cout << " \"determination_method\": \"" << filePopulation["determination_method"] << "\",\n";
std::cout << " \"governed_sections\": [" << std::endl;
for (const auto& item : listProperties["governed_sections"]) std::cout << " \"" << item << "\"," << std::endl;
std::cout << " ]\n";
std::cout << " },\n";
std::cout << " \"default_language\": \"" << simpleProperties["default_language"] << "\",\n";
std::cout << " \"context_identifiers\": [" << std::endl;
for (const auto& item : listProperties["context_identifiers"]) std::cout << " \"" << item << "\"," << std::endl;
std::cout << " ]\n";
std::cout << "}" << std::endl;
}
void write(const std::string& newFilePath) {
std::string newHeader = "HEADER;\n";
newHeader += "FILE_DESCRIPTION(" + formatList(listProperties["description"]) + ",'" + simpleProperties["implementation_level"] + "');\n";
newHeader += "FILE_NAME('" + simpleProperties["name"] + "','" + simpleProperties["time_stamp"] + "'," + formatList(listProperties["author"]) + "," + formatList(listProperties["organization"]) + ",'" + simpleProperties["preprocessor_version"] + "','" + simpleProperties["originating_system"] + "','" + simpleProperties["authorization"] + "');\n";
newHeader += "FILE_SCHEMA(" + formatList(listProperties["schema_identifiers"]) + ");\n";
if (!listProperties["schema_population"].empty()) {
newHeader += "SCHEMA_POPULATION(" + formatList(listProperties["schema_population"]) + ");\n";
}
if (!filePopulation["governing_schema"].empty()) {
newHeader += "FILE_POPULATION('" + filePopulation["governing_schema"] + "','" + filePopulation["determination_method"] + "'," + formatList(listProperties["governed_sections"]) + ");\n";
}
if (!simpleProperties["default_language"].empty()) {
newHeader += "SECTION_LANGUAGE($,'" + simpleProperties["default_language"] + "');\n";
}
if (!listProperties["context_identifiers"].empty()) {
newHeader += "SECTION_CONTEXT($," + formatList(listProperties["context_identifiers"]) + ");\n";
}
newHeader += "ENDSEC;\n";
std::regex headerRegex(R"(HEADER;(.*?)ENDSEC;)", std::regex::dotall);
std::string newContent = std::regex_replace(content, headerRegex, newHeader);
std::ofstream outFile(newFilePath);
outFile << newContent;
}
};
// Example usage:
// int main() {
// StpHandler handler("example.stp");
// handler.printProperties();
// handler.write("modified.stp");
// return 0;
// }