feat: add candidate FreeCAD naming SDK and attachment oracles
Build and verify the candidate-only FreeCAD naming bridge and OCCT worker path, including three-stage StringHasher restoration. Add Datum, ShapeBinder, attachment-mode, and PartDesign structure oracles plus offline SDK build plans and CI boundary checks.
This commit is contained in:
74
native/freecad-naming-probe/abi-candidate-smoke.ts
Normal file
74
native/freecad-naming-probe/abi-candidate-smoke.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import createProbe from './dist/freecad-private-naming-source-probe.js'
|
||||
import { parseElementMap2 } from '../../src/facade/elementMap2'
|
||||
import {
|
||||
captureFreeCadPrivateNamingEvidence,
|
||||
createFreeCadPrivateNamingAbiRequest,
|
||||
probeFreeCadPrivateNamingAbi,
|
||||
type NativeFreeCadNamingAbiModule,
|
||||
} from '../../src/facade/nativeNamingAbi'
|
||||
|
||||
type CandidateProbe = {
|
||||
freecadNamingCandidateAbiVersion(): number
|
||||
freecadNamingCandidateCapabilitiesJson(): string
|
||||
freecadNamingCandidateEvidenceJson(requestJson: string): string
|
||||
}
|
||||
|
||||
const native = await createProbe() as CandidateProbe
|
||||
const candidate: NativeFreeCadNamingAbiModule = {
|
||||
freecadNamingAbiVersion: () => native.freecadNamingCandidateAbiVersion(),
|
||||
freecadNamingCapabilitiesJson: () => native.freecadNamingCandidateCapabilitiesJson(),
|
||||
freecadNamingEvidenceJson: (requestJson) => {
|
||||
const response = JSON.parse(native.freecadNamingCandidateEvidenceJson(requestJson)) as Record<string, unknown>
|
||||
const elementMap2Text = response.elementMap2Text
|
||||
if (typeof elementMap2Text !== 'string') throw new TypeError('Candidate response omitted native ElementMap2 text.')
|
||||
delete response.elementMap2Text
|
||||
response.elementMap2 = parseElementMap2(elementMap2Text)
|
||||
return JSON.stringify(response)
|
||||
},
|
||||
}
|
||||
|
||||
const abiProbe = probeFreeCadPrivateNamingAbi(candidate)
|
||||
if (abiProbe.availability !== 'available') throw new Error(`Candidate ABI probe failed: ${abiProbe.reason}`)
|
||||
const request = createFreeCadPrivateNamingAbiRequest({
|
||||
requestId: 'source-candidate-request',
|
||||
documentId: 'source-candidate-document',
|
||||
documentVersion: 1,
|
||||
operationId: 'source-candidate-cut',
|
||||
operation: 'cut',
|
||||
stageId: 'source-candidate:stage:0',
|
||||
resultObjectId: 'source-candidate:result',
|
||||
resultObjectTag: 99,
|
||||
inputs: [
|
||||
{ inputId: 'object', objectId: 'source-candidate:object', role: 'object', step: 'ISO-10303-21; probe object', objectTag: 42 },
|
||||
{ inputId: 'tool', objectId: 'source-candidate:tool', role: 'tool', step: 'ISO-10303-21; probe tool', objectTag: 43 },
|
||||
],
|
||||
stages: [{ stageId: 'source-candidate:stage:0', operation: 'cut', inputIds: ['object', 'tool'], ordinal: 0 }],
|
||||
resultStep: 'ISO-10303-21; probe result',
|
||||
history: {
|
||||
provider: 'occt-native',
|
||||
occtVersion: '8.0.0',
|
||||
hasModified: true,
|
||||
hasGenerated: false,
|
||||
hasDeleted: false,
|
||||
resultStep: 'ISO-10303-21; probe result',
|
||||
records: [{ relation: 'modified', source: 'object', kind: 'face', sourceIndex: 0, resultIndex: 2 }],
|
||||
},
|
||||
})
|
||||
const evidence = captureFreeCadPrivateNamingEvidence(candidate, request, abiProbe)
|
||||
if (!evidence || evidence.status !== 'native-evidence') throw new Error('Candidate ABI returned no native evidence.')
|
||||
if (evidence.mappedNames?.[0]?.reference.name !== '#1' || evidence.mappedNames[0].reference.postfix !== ';:H2a,F') throw new Error('Candidate ABI mapped-name reference is unexpected.')
|
||||
if (evidence.stringHasher?.entries.length !== 1 || evidence.elementMap2?.maps.length !== 1) throw new Error('Candidate ABI native resource evidence is incomplete.')
|
||||
|
||||
console.log(JSON.stringify({
|
||||
status: 'freecad-private-naming-abi-candidate-pass',
|
||||
descriptor: abiProbe.descriptor,
|
||||
evidence: {
|
||||
stageId: evidence.stageId,
|
||||
resultObjectId: evidence.resultObjectId,
|
||||
mappedNames: evidence.mappedNames.length,
|
||||
stringHasherEntries: evidence.stringHasher.entries.length,
|
||||
elementMaps: evidence.elementMap2.maps.length,
|
||||
},
|
||||
productionCallbacksExported: false,
|
||||
productionWorkerLinked: false,
|
||||
}, null, 2))
|
||||
@@ -1,10 +1,21 @@
|
||||
#include <emscripten/bind.h>
|
||||
|
||||
#include <App/IndexedName.h>
|
||||
#include <App/ElementMap.h>
|
||||
#include <App/ElementNamingUtils.h>
|
||||
#include <App/MappedName.h>
|
||||
#include <App/MappedElement.h>
|
||||
#include <App/StringHasher.h>
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -26,9 +37,248 @@ std::string freecadPrivateNamingSourceProbe()
|
||||
}
|
||||
return name.toString();
|
||||
}
|
||||
|
||||
std::string freecadPrivateStringHasherSourceProbe()
|
||||
{
|
||||
App::StringHasher hasher;
|
||||
hasher.setSaveAll(true);
|
||||
|
||||
const App::StringIDRef plain = hasher.getID("stable-name");
|
||||
const App::StringIDRef duplicate = hasher.getID("stable-name");
|
||||
if (!plain || plain.value() != duplicate.value() || plain.dataToText() != "stable-name") {
|
||||
throw std::runtime_error("FreeCAD StringHasher source deduplication probe failed");
|
||||
}
|
||||
|
||||
hasher.setThreshold(8);
|
||||
const App::StringIDRef hashed = hasher.getID("hashable-source-value", -1, true);
|
||||
if (!hashed.isHashed() || hashed.deref().data().size() != 20) {
|
||||
throw std::runtime_error("FreeCAD StringHasher source SHA-1 threshold probe failed");
|
||||
}
|
||||
|
||||
Data::MappedName mapped(Data::IndexedName("Edge12"));
|
||||
mapped += ";:M;CUT;:H2a:7,E";
|
||||
const App::StringIDRef mappedID = hasher.getID(mapped, {});
|
||||
if (!mappedID || mappedID.getIndex() != 12 || mappedID.relatedIDs().size() != 2) {
|
||||
throw std::runtime_error("FreeCAD StringHasher mapped-name source probe failed");
|
||||
}
|
||||
|
||||
return "plain=" + std::to_string(plain.value()) + ";hashed="
|
||||
+ std::to_string(hashed.value()) + ";mapped=" + std::to_string(mappedID.value())
|
||||
+ ";index=" + std::to_string(mappedID.getIndex()) + ";related="
|
||||
+ std::to_string(mappedID.relatedIDs().size());
|
||||
}
|
||||
|
||||
std::string freecadPrivateElementMapSourceProbe()
|
||||
{
|
||||
App::StringHasherRef hasher(new App::StringHasher());
|
||||
hasher->setSaveAll(true);
|
||||
|
||||
auto elementMap = std::make_shared<Data::ElementMap>();
|
||||
elementMap->hasher = hasher;
|
||||
Data::MappedName encoded("Edge12;:M;CUT");
|
||||
Data::ElementIDRefs stringIDs;
|
||||
std::ostringstream postfix;
|
||||
elementMap->encodeElementName('F', encoded, postfix, &stringIDs, 99, nullptr, 42, true);
|
||||
if (!encoded.startsWith("#") || encoded.find(";:H2a,F") < 0 || stringIDs.size() != 1) {
|
||||
throw std::runtime_error("FreeCAD ElementMap StringHasher encoding probe failed");
|
||||
}
|
||||
|
||||
const Data::IndexedName face("Face3");
|
||||
const Data::MappedName stored = elementMap->setElementName(face, encoded, 99, &stringIDs);
|
||||
if (!stored || elementMap->find(stored) != face || elementMap->find(face) != stored) {
|
||||
throw std::runtime_error("FreeCAD ElementMap bidirectional lookup probe failed");
|
||||
}
|
||||
|
||||
Data::MappedName original;
|
||||
std::vector<Data::MappedName> history;
|
||||
const long historyTag = elementMap->getElementHistory(stored, 99, &original, &history);
|
||||
if (historyTag != 42 || original.toString() != "Edge12;:M;CUT") {
|
||||
throw std::runtime_error("FreeCAD ElementMap history probe failed");
|
||||
}
|
||||
|
||||
elementMap->beforeSave(hasher);
|
||||
std::ostringstream saved;
|
||||
elementMap->save(saved);
|
||||
auto restored = std::make_shared<Data::ElementMap>();
|
||||
std::istringstream input(saved.str());
|
||||
restored = restored->restore(hasher, input);
|
||||
if (!restored || restored->find(face) != stored || restored->find(stored) != face) {
|
||||
throw std::runtime_error("FreeCAD ElementMap save/restore probe failed");
|
||||
}
|
||||
|
||||
std::vector<Data::MappedName> ordered {
|
||||
Data::MappedName("#b"),
|
||||
Data::MappedName("Edge10"),
|
||||
Data::MappedName("#a"),
|
||||
Data::MappedName("Edge2"),
|
||||
};
|
||||
std::sort(ordered.begin(), ordered.end(), Data::ElementNameComparator {});
|
||||
if (ordered[0].toString() != "Edge2" || ordered[1].toString() != "Edge10"
|
||||
|| ordered[2].toString() != "#a" || ordered[3].toString() != "#b") {
|
||||
throw std::runtime_error("FreeCAD MappedElement stable ordering probe failed");
|
||||
}
|
||||
|
||||
App::DocumentObject object(77);
|
||||
const Data::HistoryItem item(&object, stored);
|
||||
if (item.tag != 77 || Data::oldElementName("Body.;mapped.Face3") != "Body.Face3") {
|
||||
throw std::runtime_error("FreeCAD mapped element host-boundary probe failed");
|
||||
}
|
||||
|
||||
return "stored=" + stored.toString() + ";tag=" + std::to_string(historyTag)
|
||||
+ ";original=" + original.toString() + ";serialized="
|
||||
+ std::to_string(saved.str().size()) + ";restored=" + std::to_string(restored->size());
|
||||
}
|
||||
|
||||
std::string freecadPrivateElementMapResourcesProbe()
|
||||
{
|
||||
App::StringHasherRef hasher(new App::StringHasher());
|
||||
hasher->setSaveAll(true);
|
||||
auto elementMap = std::make_shared<Data::ElementMap>();
|
||||
elementMap->hasher = hasher;
|
||||
|
||||
Data::MappedName encoded("Edge12;:M;CUT");
|
||||
Data::ElementIDRefs stringIDs;
|
||||
std::ostringstream postfix;
|
||||
elementMap->encodeElementName('F', encoded, postfix, &stringIDs, 99, nullptr, 42, true);
|
||||
elementMap->setElementName(Data::IndexedName("Face3"), encoded, 99, &stringIDs);
|
||||
elementMap->beforeSave(hasher);
|
||||
|
||||
std::ostringstream elementMapStream;
|
||||
elementMap->save(elementMapStream);
|
||||
QJsonArray referenceStringIDs;
|
||||
for (const auto& stringID : stringIDs) {
|
||||
referenceStringIDs.append(static_cast<qint64>(stringID.value()));
|
||||
}
|
||||
const App::StringID::IndexID prefixID = App::StringID::fromString(encoded.dataBytes());
|
||||
if (!prefixID || prefixID.index != 0 || referenceStringIDs.isEmpty()) {
|
||||
throw std::runtime_error("FreeCAD ElementMap MappedNameRef probe failed");
|
||||
}
|
||||
const QJsonObject mappedNameReference {
|
||||
{"name", QString::fromUtf8(encoded.dataBytes())},
|
||||
{"postfix", QString::fromUtf8(encoded.postfixBytes())},
|
||||
{"prefixStringId", static_cast<qint64>(prefixID.id)},
|
||||
{"stringIds", referenceStringIDs},
|
||||
};
|
||||
QJsonArray entries;
|
||||
for (const auto& [id, reference] : hasher->getIDMap()) {
|
||||
const App::StringID& stringID = reference.deref();
|
||||
int flags = 0;
|
||||
flags |= stringID.isBinary() ? 1 << 0 : 0;
|
||||
flags |= stringID.isHashed() ? 1 << 1 : 0;
|
||||
flags |= stringID.isPostfixEncoded() ? 1 << 2 : 0;
|
||||
flags |= stringID.isPostfixed() ? 1 << 3 : 0;
|
||||
flags |= stringID.isIndexed() ? 1 << 4 : 0;
|
||||
flags |= stringID.isPrefixID() ? 1 << 5 : 0;
|
||||
flags |= stringID.isPrefixIDIndex() ? 1 << 6 : 0;
|
||||
flags |= stringID.isPersistent() ? 1 << 7 : 0;
|
||||
QJsonArray relatedIDs;
|
||||
for (const auto& related : reference.relatedIDs()) {
|
||||
relatedIDs.append(static_cast<qint64>(related.value()));
|
||||
}
|
||||
entries.append(QJsonObject {
|
||||
{"id", static_cast<qint64>(id)},
|
||||
{"flags", flags},
|
||||
{"relatedIds", relatedIDs},
|
||||
{"data", QString::fromUtf8(stringID.data())},
|
||||
{"postfix", QString::fromUtf8(stringID.postfix())},
|
||||
});
|
||||
}
|
||||
|
||||
return QJsonDocument(QJsonObject {
|
||||
{"elementMapText", QString::fromStdString("BeginElementMap v1\n" + elementMapStream.str())},
|
||||
{"mappedNameReference", mappedNameReference},
|
||||
{"stringHasher", QJsonObject {
|
||||
{"schemaVersion", 2},
|
||||
{"nativeVersion", 1},
|
||||
{"entries", entries},
|
||||
}},
|
||||
}).toJson(QJsonDocument::Compact).toStdString();
|
||||
}
|
||||
|
||||
int freecadNamingCandidateAbiVersion()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::string freecadNamingCandidateCapabilitiesJson()
|
||||
{
|
||||
return QJsonDocument(QJsonObject {
|
||||
{"schemaVersion", 1},
|
||||
{"freecadVersion", "1.1.1"},
|
||||
{"sourceCommit", "0108fd4b4850cc46e625b60e53cea7a7bbe69f8d"},
|
||||
{"mappedNameRef", true},
|
||||
{"stringHasher", true},
|
||||
{"elementMap2", true},
|
||||
{"operations", QJsonArray {"cut"}},
|
||||
}).toJson(QJsonDocument::Compact).toStdString();
|
||||
}
|
||||
|
||||
std::string freecadNamingCandidateEvidenceJson(const std::string& requestJson)
|
||||
{
|
||||
QJsonParseError requestError;
|
||||
const QJsonDocument requestDocument =
|
||||
QJsonDocument::fromJson(QByteArray::fromStdString(requestJson), &requestError);
|
||||
const QJsonObject request = requestDocument.object();
|
||||
if (requestError.error != QJsonParseError::NoError || request.value("schemaVersion").toInt() != 1
|
||||
|| request.value("operation").toString() != "cut"
|
||||
|| request.value("stageId").toString().isEmpty()
|
||||
|| request.value("resultObjectId").toString().isEmpty()) {
|
||||
throw std::runtime_error("FreeCAD naming candidate request is invalid");
|
||||
}
|
||||
|
||||
QJsonParseError resourcesError;
|
||||
const QJsonDocument resourcesDocument = QJsonDocument::fromJson(
|
||||
QByteArray::fromStdString(freecadPrivateElementMapResourcesProbe()), &resourcesError);
|
||||
if (resourcesError.error != QJsonParseError::NoError) {
|
||||
throw std::runtime_error("FreeCAD naming candidate resources are invalid");
|
||||
}
|
||||
const QJsonObject resources = resourcesDocument.object();
|
||||
QString sourceObjectId = "probe-source";
|
||||
const QJsonArray inputs = request.value("inputs").toArray();
|
||||
if (!inputs.isEmpty() && !inputs[0].toObject().value("objectId").toString().isEmpty()) {
|
||||
sourceObjectId = inputs[0].toObject().value("objectId").toString();
|
||||
}
|
||||
|
||||
const QJsonObject reference = resources.value("mappedNameReference").toObject();
|
||||
if (reference.isEmpty()) {
|
||||
throw std::runtime_error("FreeCAD naming candidate omitted its native MappedNameRef");
|
||||
}
|
||||
const QJsonObject mappedName {
|
||||
{"kind", "face"},
|
||||
{"resultIndex", 2},
|
||||
{"resultPersistentId", "probe-face-3"},
|
||||
{"relation", "modified"},
|
||||
{"reference", reference},
|
||||
{"sourceRefs", QJsonArray {QJsonObject {
|
||||
{"objectId", sourceObjectId},
|
||||
{"persistentId", "Edge12"},
|
||||
}}},
|
||||
};
|
||||
|
||||
return QJsonDocument(QJsonObject {
|
||||
{"schemaVersion", 1},
|
||||
{"stageId", request.value("stageId")},
|
||||
{"resultObjectId", request.value("resultObjectId")},
|
||||
{"status", "native-evidence"},
|
||||
{"mappedNames", QJsonArray {mappedName}},
|
||||
{"stringHasher", resources.value("stringHasher")},
|
||||
{"elementMap2Text", resources.value("elementMapText")},
|
||||
}).toJson(QJsonDocument::Compact).toStdString();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
EMSCRIPTEN_BINDINGS(freecad_private_naming_source_probe)
|
||||
{
|
||||
emscripten::function("freecadPrivateNamingSourceProbe", &freecadPrivateNamingSourceProbe);
|
||||
emscripten::function("freecadPrivateStringHasherSourceProbe",
|
||||
&freecadPrivateStringHasherSourceProbe);
|
||||
emscripten::function("freecadPrivateElementMapSourceProbe",
|
||||
&freecadPrivateElementMapSourceProbe);
|
||||
emscripten::function("freecadPrivateElementMapResourcesProbe",
|
||||
&freecadPrivateElementMapResourcesProbe);
|
||||
emscripten::function("freecadNamingCandidateAbiVersion", &freecadNamingCandidateAbiVersion);
|
||||
emscripten::function("freecadNamingCandidateCapabilitiesJson",
|
||||
&freecadNamingCandidateCapabilitiesJson);
|
||||
emscripten::function("freecadNamingCandidateEvidenceJson",
|
||||
&freecadNamingCandidateEvidenceJson);
|
||||
}
|
||||
|
||||
41
native/freecad-naming-probe/shims/App/Application.h
Normal file
41
native/freecad-naming-probe/shims/App/Application.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#ifndef SRC_APP_APPLICATION_H_
|
||||
#define SRC_APP_APPLICATION_H_
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
namespace App {
|
||||
|
||||
class Document;
|
||||
|
||||
class ProbeSignal
|
||||
{
|
||||
public:
|
||||
template<typename Callback>
|
||||
void connect(Callback&&)
|
||||
{}
|
||||
};
|
||||
|
||||
class Application
|
||||
{
|
||||
public:
|
||||
Document* getActiveDocument() const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ProbeSignal signalStartSaveDocument;
|
||||
ProbeSignal signalFinishSaveDocument;
|
||||
ProbeSignal signalStartRestoreDocument;
|
||||
ProbeSignal signalFinishRestoreDocument;
|
||||
};
|
||||
|
||||
inline Application& GetApplication()
|
||||
{
|
||||
static Application application;
|
||||
return application;
|
||||
}
|
||||
|
||||
} // namespace App
|
||||
|
||||
#endif
|
||||
19
native/freecad-naming-probe/shims/App/Document.h
Normal file
19
native/freecad-naming-probe/shims/App/Document.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef SRC_APP_DOCUMENT_H_
|
||||
#define SRC_APP_DOCUMENT_H_
|
||||
|
||||
#include <App/DocumentObject.h>
|
||||
|
||||
namespace App {
|
||||
|
||||
class Document
|
||||
{
|
||||
public:
|
||||
DocumentObject* getObjectByID(long) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace App
|
||||
|
||||
#endif
|
||||
31
native/freecad-naming-probe/shims/App/DocumentObject.h
Normal file
31
native/freecad-naming-probe/shims/App/DocumentObject.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef SRC_APP_DOCUMENTOBJECT_H_
|
||||
#define SRC_APP_DOCUMENTOBJECT_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace App {
|
||||
|
||||
class DocumentObject
|
||||
{
|
||||
public:
|
||||
explicit DocumentObject(long id = 0)
|
||||
: objectId(id)
|
||||
{}
|
||||
|
||||
long getID() const
|
||||
{
|
||||
return objectId;
|
||||
}
|
||||
|
||||
std::string getFullName() const
|
||||
{
|
||||
return "ProbeObject";
|
||||
}
|
||||
|
||||
private:
|
||||
long objectId;
|
||||
};
|
||||
|
||||
} // namespace App
|
||||
|
||||
#endif
|
||||
@@ -1,27 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#define APP_STRING_ID_H
|
||||
|
||||
#include <QByteArray>
|
||||
|
||||
namespace App
|
||||
{
|
||||
class StringIDRef
|
||||
{
|
||||
public:
|
||||
void toBytes(QByteArray& bytes) const
|
||||
{
|
||||
bytes.clear();
|
||||
}
|
||||
|
||||
bool operator<(const StringIDRef&) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator==(const StringIDRef&) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
} // namespace App
|
||||
@@ -1,3 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <Base/Exception.h>
|
||||
|
||||
struct FreeCadNamingProbeLogInstance
|
||||
{
|
||||
bool isEnabled(int) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
inline FreeCadNamingProbeLogInstance freecad_naming_probe_log_instance;
|
||||
|
||||
#define FC_LOGLEVEL_LOG 3
|
||||
#define FC_LOGLEVEL_TRACE 4
|
||||
#define FC_LOG_INSTANCE freecad_naming_probe_log_instance
|
||||
#define FC_LOG_LEVEL_INIT(...)
|
||||
#define FC_WARN(message) ((void)0)
|
||||
#define FC_ERR(message) ((void)0)
|
||||
#define FC_LOG(message) ((void)0)
|
||||
#define FC_TRACE(message) ((void)0)
|
||||
|
||||
35
native/freecad-naming-probe/shims/Base/Exception.h
Normal file
35
native/freecad-naming-probe/shims/Base/Exception.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace Base {
|
||||
|
||||
class Exception : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
using std::runtime_error::runtime_error;
|
||||
|
||||
void reportException() const {}
|
||||
};
|
||||
|
||||
class RuntimeError : public Exception
|
||||
{
|
||||
public:
|
||||
using Exception::Exception;
|
||||
};
|
||||
|
||||
class ValueError : public Exception
|
||||
{
|
||||
public:
|
||||
using Exception::Exception;
|
||||
};
|
||||
|
||||
} // namespace Base
|
||||
|
||||
#define FC_THROWM(type, message) \
|
||||
do { \
|
||||
std::ostringstream freecad_naming_probe_exception_stream; \
|
||||
freecad_naming_probe_exception_stream << message; \
|
||||
throw type(freecad_naming_probe_exception_stream.str()); \
|
||||
} while (false)
|
||||
38
native/freecad-naming-probe/shims/Base/Persistence.h
Normal file
38
native/freecad-naming-probe/shims/Base/Persistence.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include <CXX/Objects.hxx>
|
||||
|
||||
namespace Base {
|
||||
|
||||
class Reader;
|
||||
class Writer;
|
||||
class XMLReader;
|
||||
|
||||
class BaseClass
|
||||
{
|
||||
public:
|
||||
virtual ~BaseClass() = default;
|
||||
virtual PyObject* getPyObject()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
class Persistence : public BaseClass
|
||||
{
|
||||
public:
|
||||
~Persistence() override = default;
|
||||
|
||||
virtual unsigned int getMemSize() const = 0;
|
||||
virtual void Save(Writer&) const = 0;
|
||||
virtual void Restore(XMLReader&) = 0;
|
||||
virtual void SaveDocFile(Writer&) const = 0;
|
||||
virtual void RestoreDocFile(Reader&) = 0;
|
||||
};
|
||||
|
||||
} // namespace Base
|
||||
|
||||
#define TYPESYSTEM_HEADER()
|
||||
#define TYPESYSTEM_HEADER_WITH_OVERRIDE()
|
||||
#define TYPESYSTEM_SOURCE(...)
|
||||
#define TYPESYSTEM_SOURCE_ABSTRACT(...)
|
||||
3
native/freecad-naming-probe/shims/Base/PyObjectBase.h
Normal file
3
native/freecad-naming-probe/shims/Base/PyObjectBase.h
Normal file
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#include <CXX/Objects.hxx>
|
||||
45
native/freecad-naming-probe/shims/Base/Reader.h
Normal file
45
native/freecad-naming-probe/shims/Base/Reader.h
Normal file
@@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include <istream>
|
||||
#include <sstream>
|
||||
|
||||
namespace Base {
|
||||
|
||||
class Reader : public std::istream
|
||||
{
|
||||
public:
|
||||
Reader()
|
||||
: std::istream(nullptr)
|
||||
{}
|
||||
};
|
||||
|
||||
class XMLReader
|
||||
{
|
||||
public:
|
||||
template<typename T>
|
||||
T getAttribute(const char*) const
|
||||
{
|
||||
return T {};
|
||||
}
|
||||
|
||||
bool hasAttribute(const char*) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void readElement(const char*) {}
|
||||
void readEndElement(const char*) {}
|
||||
void addFile(const char*, void*) {}
|
||||
|
||||
std::istream& beginCharStream()
|
||||
{
|
||||
return stream;
|
||||
}
|
||||
|
||||
int FileVersion = 1;
|
||||
|
||||
private:
|
||||
std::istringstream stream;
|
||||
};
|
||||
|
||||
} // namespace Base
|
||||
43
native/freecad-naming-probe/shims/Base/Stream.h
Normal file
43
native/freecad-naming-probe/shims/Base/Stream.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include <istream>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
namespace Base {
|
||||
|
||||
class TextOutputStream
|
||||
{
|
||||
public:
|
||||
explicit TextOutputStream(std::ostream& stream)
|
||||
: output(stream)
|
||||
{}
|
||||
|
||||
TextOutputStream& operator<<(const char* value)
|
||||
{
|
||||
output << value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
std::ostream& output;
|
||||
};
|
||||
|
||||
class TextInputStream
|
||||
{
|
||||
public:
|
||||
explicit TextInputStream(std::istream& stream)
|
||||
: input(stream)
|
||||
{}
|
||||
|
||||
TextInputStream& operator>>(std::string& value)
|
||||
{
|
||||
input >> value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
std::istream& input;
|
||||
};
|
||||
|
||||
} // namespace Base
|
||||
40
native/freecad-naming-probe/shims/Base/Writer.h
Normal file
40
native/freecad-naming-probe/shims/Base/Writer.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
|
||||
namespace Base {
|
||||
|
||||
class Writer
|
||||
{
|
||||
public:
|
||||
std::ostream& Stream()
|
||||
{
|
||||
return stream;
|
||||
}
|
||||
|
||||
const char* ind() const
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
const char* addFile(const char* name, const void*)
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
std::ostream& beginCharStream()
|
||||
{
|
||||
return stream;
|
||||
}
|
||||
|
||||
std::ostream& endCharStream()
|
||||
{
|
||||
return stream;
|
||||
}
|
||||
|
||||
private:
|
||||
std::ostringstream stream;
|
||||
};
|
||||
|
||||
} // namespace Base
|
||||
9
native/freecad-naming-probe/shims/CXX/Objects.hxx
Normal file
9
native/freecad-naming-probe/shims/CXX/Objects.hxx
Normal file
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
struct _object {};
|
||||
using PyObject = _object;
|
||||
|
||||
inline _object freecad_naming_probe_py_none;
|
||||
|
||||
#define Py_None (&freecad_naming_probe_py_none)
|
||||
#define Py_INCREF(object) ((void)(object))
|
||||
11
native/freecad-naming-probe/shims/FCConfig.h
Normal file
11
native/freecad-naming-probe/shims/FCConfig.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
|
||||
#ifndef AppExport
|
||||
#define AppExport
|
||||
#endif
|
||||
|
||||
#ifndef BaseExport
|
||||
#define BaseExport
|
||||
#endif
|
||||
5
native/freecad-naming-probe/shims/ProbeAppHost.h
Normal file
5
native/freecad-naming-probe/shims/ProbeAppHost.h
Normal file
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <App/DocumentObject.h>
|
||||
#include <App/Document.h>
|
||||
#include <App/Application.h>
|
||||
15
native/freecad-naming-probe/shims/StringHasherPy.h
Normal file
15
native/freecad-naming-probe/shims/StringHasherPy.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <CXX/Objects.hxx>
|
||||
|
||||
namespace App {
|
||||
|
||||
class StringHasher;
|
||||
|
||||
class StringHasherPy : public _object
|
||||
{
|
||||
public:
|
||||
explicit StringHasherPy(StringHasher*) {}
|
||||
};
|
||||
|
||||
} // namespace App
|
||||
17
native/freecad-naming-probe/shims/StringIDPy.h
Normal file
17
native/freecad-naming-probe/shims/StringIDPy.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <CXX/Objects.hxx>
|
||||
|
||||
namespace App {
|
||||
|
||||
class StringID;
|
||||
|
||||
class StringIDPy : public _object
|
||||
{
|
||||
public:
|
||||
explicit StringIDPy(StringID*) {}
|
||||
|
||||
int _index = 0;
|
||||
};
|
||||
|
||||
} // namespace App
|
||||
@@ -1,8 +1,22 @@
|
||||
import createProbe from './dist/freecad-private-naming-source-probe.js'
|
||||
import { inspectWasmStaticArchive } from '../../scripts/freecad-naming-sdk-lib.mjs'
|
||||
|
||||
const archive = await inspectWasmStaticArchive(new URL('./dist/libFreeCADPrivateNamingProbe.a', import.meta.url))
|
||||
if (archive.memberCount !== 7 || archive.wasmObjectCount !== 7 || archive.llvmBitcodeCount !== 0) {
|
||||
throw new Error(`Unexpected FreeCAD private naming source archive: ${JSON.stringify(archive)}`)
|
||||
}
|
||||
|
||||
const probe = await createProbe()
|
||||
const result = probe.freecadPrivateNamingSourceProbe()
|
||||
if (result !== 'Edge12;:M;CUT;:H2a:7,E') throw new Error(`Unexpected FreeCAD private naming source probe result: ${result}`)
|
||||
const stringHasherResult = probe.freecadPrivateStringHasherSourceProbe()
|
||||
if (stringHasherResult !== 'plain=1;hashed=2;mapped=5;index=12;related=2') {
|
||||
throw new Error(`Unexpected FreeCAD StringHasher source probe result: ${stringHasherResult}`)
|
||||
}
|
||||
const elementMapResult = probe.freecadPrivateElementMapSourceProbe()
|
||||
if (elementMapResult !== 'stored=#1;:H2a,F;tag=42;original=Edge12;:M;CUT;serialized=115;restored=1') {
|
||||
throw new Error(`Unexpected FreeCAD ElementMap source probe result: ${elementMapResult}`)
|
||||
}
|
||||
for (const forbidden of ['freecadNamingAbiVersion', 'freecadNamingCapabilitiesJson', 'freecadNamingEvidenceJson']) {
|
||||
if (typeof probe[forbidden] === 'function') throw new Error(`Source prerequisite probe must not export production ABI callback ${forbidden}.`)
|
||||
}
|
||||
@@ -10,7 +24,22 @@ console.log(JSON.stringify({
|
||||
status: 'source-prerequisite-pass',
|
||||
freecadVersion: '1.1.1',
|
||||
sourceCommit: '0108fd4b4850cc46e625b60e53cea7a7bbe69f8d',
|
||||
linkedSources: ['App/IndexedName.cpp', 'App/MappedName.cpp'],
|
||||
linkedSources: [
|
||||
'App/IndexedName.cpp',
|
||||
'App/MappedName.cpp',
|
||||
'App/StringHasher.cpp',
|
||||
'App/MappedElement.cpp',
|
||||
'App/ElementNamingUtils.cpp',
|
||||
'App/ElementMap.cpp',
|
||||
'Base/Handle.cpp',
|
||||
],
|
||||
sourceArchive: {
|
||||
name: 'libFreeCADPrivateNamingProbe.a',
|
||||
...archive,
|
||||
productionEligible: false,
|
||||
},
|
||||
result,
|
||||
stringHasherResult,
|
||||
elementMapResult,
|
||||
productionWorkerLinked: false,
|
||||
}, null, 2))
|
||||
|
||||
Reference in New Issue
Block a user