#include "CachingHRCParser.h" #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #ifdef keyword #undef keyword #endif #define QUALIFY_SCHEME(name, scheme) \ {\ if ((name) && !(scheme))\ {\ String *schemeName = qualifyForeignName((name), QNT_SCHEME, true);\ if (schemeName != null)\ {\ (scheme) = schemeHash.get(schemeName);\ delete schemeName;\ }\ }\ } void CachingHRCParser::loadFileType(FileType *filetype) { if (buf) { FriendlyFileTypeImpl *f = (FriendlyFileTypeImpl*)filetype; if (!f->typeLoaded && f->baseScheme) { curFileType = f; int pos = (int)f->baseScheme; deserialize(pos, f->baseScheme); f->typeLoaded = TRUE; f->loadDone = TRUE; } } else HRCParserImpl::loadFileType(filetype); } void CachingHRCParser::serializeToFile(const char *filename) { schemesSerialized.clear(); regionsSerialized.clear(); curPos = 0; dryRun = TRUE; serializePrimitive('HRCC'); serializeVector(fileTypeVector); processQueue(); file = fopen(filename, "wb"); if (!file) croak("Couldn't open file %s for writing", filename); schemesSerialized.clear(); regionsSerialized.clear(); curPos = 0; dryRun = FALSE; serializePrimitive('HRCC'); serializeVector(fileTypeVector); processQueue(); fclose(file); } void CachingHRCParser::deserializeFromFile(const char *filename) { file = fopen(filename, "rb"); if (!file) croak("Couldn't open file %s for reading", filename); struct stat s; if (fstat(fileno(file), &s) < 0) { fclose(file); croak("Couldn't stat file %s", filename); } bufSize = s.st_size; buf = new char[bufSize]; fread(buf, sizeof(char), bufSize, file); fclose(file); int pos = 0; int magic; deserializePrimitive(pos, magic); if (magic != 'HRCC') croak("File %s has wrong format", filename); deserializeVector(pos, fileTypeVector); } void CachingHRCParser::serialize(const String *value) { if (!value) { serializePrimitive((char)0xFF); return; } int len = value->length(); if (len > 0xFFFF) { if (!dryRun) fclose(file); croak("Can't serialize a string that is longer than %i characters", 0xFFFF); } if (len <= 0xFD) serializePrimitive((char)len); else { serializePrimitive((char)0xFE); serializePrimitive((short)len); } if (!dryRun) fwrite(value->getChars(), sizeof(char), len, file); curPos += len; } void CachingHRCParser::deserialize(int &pos, String* &value) { int len = *(unsigned char*)(buf + pos); pos += sizeof(unsigned char); if (len == 0xFF) { value = NULL; return; } else if (len == 0xFE) { len = *(unsigned short*)(buf + pos); pos += sizeof(unsigned short); } value = new DString(buf + pos, 0, len); pos += len; } void CachingHRCParser::deserialize(int &pos, const SString* &value) { String* v; deserialize(pos, v); value = v ? new SString(v) : NULL; } void CachingHRCParser::serialize(const Vector &names, const Hashtable &values) { int len = names.size(); serializePrimitive(len); for (int i = 0; i < len; i++) { String *name = names.elementAt(i); serialize(name); serialize(values.get(name)); } } void CachingHRCParser::deserialize(int &pos, Vector &names, Hashtable &values) { int len; deserializePrimitive(pos, len); for (int i = 0; i < len; i++) { String *name, *value; deserialize(pos, name); deserialize(pos, value); names.addElement(name); values.put(name, value); } } void CachingHRCParser::serialize(const Region *value) { if (regionsSerialized.get(value->getName())) return; regions.put(value->getName(), curPos); regionsSerialized.put(value->getName(), true); serializePrimitive((Region*)NULL); serialize(value->getName()); serialize(value->getDescription()); serializeQueued((Region*)value->getParent()); } void CachingHRCParser::deserialize(int &pos, Region* &value) { int origPos = pos; deserializePrimitive(pos, value); if (value) return; String* regionName; deserialize(pos, regionName); String* regionDescr; deserialize(pos, regionDescr); FriendlyRegion* v = new FriendlyRegion(regionName, regionDescr, null, regionNamesVector.size()); value = v; *(Region**)(buf + origPos) = value; regionNamesVector.addElement(value); regionNamesHash.put(regionName, value); delete regionName; delete regionDescr; Region* parent; deserializePointer(pos, parent); v->parent = parent; } void CachingHRCParser::serialize(VirtualEntry *value) { QUALIFY_SCHEME(value->virtSchemeName, value->virtScheme); QUALIFY_SCHEME(value->substSchemeName, value->substScheme); serializeQueued(value->virtScheme); serializeQueued(value->substScheme); } void CachingHRCParser::deserialize(int &pos, VirtualEntry* &value) { DString s(""); value = new VirtualEntry(&s, &s); delete value->virtSchemeName; delete value->substSchemeName; value->virtSchemeName = null; value->substSchemeName = null; deserializePointer(pos, value->virtScheme); deserializePointer(pos, value->substScheme); } void CachingHRCParser::serialize(const KeywordInfo *value) { serialize((String*)value->keyword); serializePrimitive((char)(value->isSymbol ? 1 : 0)); serializeQueued((Region*)value->region); } void CachingHRCParser::deserialize(int &pos, KeywordInfo* value) { deserialize(pos, value->keyword); char isSymbol; deserializePrimitive(pos, isSymbol); value->isSymbol = isSymbol; Region* region; deserializePointer(pos, region); value->region = region; } void CachingHRCParser::serialize(const KeywordList *value) { if (!value || !value->num) { serializePrimitive((int)0); return; } serializePrimitive(value->num); serializePrimitive((char)(value->matchCase ? 1 : 0)); for (int i = 0; i < value->num; i++) serialize(value->kwList + i); } void CachingHRCParser::deserialize(int &pos, KeywordList* &value) { int num; deserializePrimitive(pos, num); if (!num) { value = NULL; return; } value = new KeywordList(); value->firstChar = new CharacterClass(); value->num = num; value->kwList = new KeywordInfo[num]; value->minKeywordLength = 0x10000; char matchCase; deserializePrimitive(pos, matchCase); value->matchCase = matchCase; for (int i = 0; i < num; i++) { deserialize(pos, value->kwList + i); if (value->kwList[i].keyword) { value->firstChar->addChar((*value->kwList[i].keyword)[0]); if (!value->matchCase) { value->firstChar->addChar(Character::toLowerCase((*value->kwList[i].keyword)[0])); value->firstChar->addChar(Character::toUpperCase((*value->kwList[i].keyword)[0])); value->firstChar->addChar(Character::toTitleCase((*value->kwList[i].keyword)[0])); } if (value->minKeywordLength > value->kwList[i].keyword->length()) value->minKeywordLength = value->kwList[i].keyword->length(); } } } void CachingHRCParser::serialize(SchemeNode *value) { serializePrimitive((char)value->type); if (value->type == SNT_SCHEME || value->type == SNT_INHERIT) { QUALIFY_SCHEME(value->schemeName, value->scheme); serializeQueued(value->scheme); } serializeVector(value->virtualEntryVector); if (value->type == SNT_KEYWORDS) { serialize(value->kwList); serialize(value->worddivString); } if (value->type == SNT_SCHEME || value->type == SNT_RE) { serializeQueued((Region*)value->region); for (int i = 0; i < REGIONS_NUM; i++) serializeQueued((Region*)value->regions[i]); for (int i = 0; i < NAMED_REGIONS_NUM; i++) serializeQueued((Region*)value->regionsn[i]); if (value->type == SNT_SCHEME) { for (int i = 0; i < REGIONS_NUM; i++) serializeQueued((Region*)value->regione[i]); for (int i = 0; i < NAMED_REGIONS_NUM; i++) serializeQueued((Region*)value->regionen[i]); } serialize(value->startString); if (value->type == SNT_SCHEME) serialize(value->endString); } serializePrimitive((char)(value->lowPriority ? 1 : 0)); serializePrimitive((char)(value->lowContentPriority ? 1 : 0)); } void CachingHRCParser::deserialize(int &pos, SchemeNode* &value) { value = new SchemeNode(); char type; deserializePrimitive(pos, type); value->type = (SchemeNodeType)type; if (value->type == SNT_SCHEME || value->type == SNT_INHERIT) { deserializePointer(pos, value->scheme); value->schemeName = NULL; } deserializeVector(pos, value->virtualEntryVector); if (value->type == SNT_KEYWORDS) { deserialize(pos, value->kwList); deserialize(pos, value->worddivString); value->worddiv = value->worddivString ? CharacterClass::createCharClass(*value->worddivString, 0, null) : null; } if (value->type == SNT_SCHEME || value->type == SNT_RE) { Region* region; deserializePointer(pos, region); value->region = region; for (int i = 0; i < REGIONS_NUM; i++) { deserializePointer(pos, region); value->regions[i] = region; } for (int i = 0; i < NAMED_REGIONS_NUM; i++) { deserializePointer(pos, region); value->regionsn[i] = region; } if (value->type == SNT_SCHEME) { for (int i = 0; i < REGIONS_NUM; i++) { deserializePointer(pos, region); value->regione[i] = region; } for (int i = 0; i < NAMED_REGIONS_NUM; i++) { deserializePointer(pos, region); value->regionen[i] = region; } } deserialize(pos, value->startString); value->start = value->startString ? new CRegExp(value->startString) : null; value->start->setPositionMoves(FALSE); if (value->type == SNT_SCHEME) { deserialize(pos, value->endString); if (value->endString) { value->end = new CRegExp(); value->end->setPositionMoves(TRUE); value->end->setBackRE(value->start); value->end->setRE(value->endString); } else value->end = null; } } char priority; deserializePrimitive(pos, priority); value->lowPriority = priority; deserializePrimitive(pos, priority); value->lowContentPriority = priority; } void CachingHRCParser::serialize(const SchemeImpl *value) { if (schemesSerialized.get(value->getName())) return; schemes.put(value->getName(), curPos); schemesSerialized.put(value->getName(), true); serializePrimitive((SchemeImpl*)NULL); FriendlySchemeImpl *v = (FriendlySchemeImpl*)value; serialize(v->schemeName); serializeVector(v->nodes); processQueue(); } void CachingHRCParser::deserialize(int &pos, SchemeImpl* &value) { int origPos = pos; deserializePrimitive(pos, value); if (value) return; String* schemeName; deserialize(pos, schemeName); FriendlySchemeImpl *v = new FriendlySchemeImpl(schemeName); v->fileType = curFileType; value = v; *(SchemeImpl**)(buf + origPos) = value; schemeHash.put(schemeName, value); delete schemeName; deserializeVector(pos, v->nodes); } void CachingHRCParser::serialize(const FileTypeImpl *value) { FriendlyFileTypeImpl *v = (FriendlyFileTypeImpl*) value; serialize(v->name); v->getBaseScheme(); serializeQueued(v->baseScheme); serialize(v->paramVector, v->paramDefaultHash); } void CachingHRCParser::deserialize(int &pos, FileTypeImpl* &value) { FriendlyFileTypeImpl *v = new FriendlyFileTypeImpl(this); deserialize(pos, v->name); int baseScheme; deserializePrimitive(pos, baseScheme); v->baseScheme = (SchemeImpl*)baseScheme; deserialize(pos, v->paramVector, v->paramDefaultHash); v->protoLoaded = TRUE; v->typeLoaded = FALSE; v->loadDone = FALSE; v->loadBroken = FALSE; value = v; fileTypeHash.put(v->name, value); } void CachingHRCParser::serializeQueued(SchemeImpl *value) { if (value) { if (!schemesSerialized.get(value->getName())) schemeQueue.addElement(value); serializePrimitive(schemes.get(value->getName())); } else serializePrimitive((int)0); } void CachingHRCParser::serializeQueued(Region *value) { if (value) { if (!regionsSerialized.get(value->getName())) regionQueue.addElement(value); serializePrimitive(regions.get(value->getName())); } else serializePrimitive((int)0); } void CachingHRCParser::processQueue() { while (regionQueue.size()) { int i = regionQueue.size() - 1; Region* region = regionQueue.elementAt(i); regionQueue.removeElementAt(i); serialize(region); } while (schemeQueue.size()) { int i = schemeQueue.size() - 1; SchemeImpl* scheme = schemeQueue.elementAt(i); schemeQueue.removeElementAt(i); serialize(scheme); } }