⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dvgenerate.c

📁 DataDraw is an ultra-fast persistent database for high performance programs written in C. It s so fa
💻 C
字号:
/* * Copyright(C) 2006 Bill Cox * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or *(at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License  * along with this program; if not, write to the Free Software  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA */#include "dv.h"/*--------------------------------------------------------------------------------------------------  Create new classes that are just useful for holding dynamic arrays of objects.--------------------------------------------------------------------------------------------------*/static void createClassDynamicArrayClasses(    dvModule module){    dvClass theClass, dynarrayClass;    dvClass lastClass = dvModuleGetLastClass(module);    dvRelationship rel;    utSym sym;    dvForeachModuleClass(module, theClass) {        if(dvClassGenerateArrayClass(theClass)) {            sym = utSymCreateFormatted("%sArray", utCopyString(dvClassGetName(theClass)));            dynarrayClass = dvClassCreate(module, dvSchemaNull, sym, dvClassNull);            rel = dvRelationshipCreate(dynarrayClass, theClass, REL_ARRAY, utSymNull, utSymNull);            dvRelationshipSetAccessParent(rel, false);        }        if(theClass == lastClass) {            return; /* Don't build array classes for themselves! */        }    } dvEndForeachModuleClass;}/*--------------------------------------------------------------------------------------------------  Create fields used by the relationship.  Note that we copy the label strings because we are  creating new symbols in this fuction, which could cause them to move in memory.--------------------------------------------------------------------------------------------------*/static void generateRelationshipFields(    dvRelationship relationship){    dvClass parent = dvRelationshipGetParentClass(relationship);    dvClass child = dvRelationshipGetChildClass(relationship);    dvProperty prop;    utSym sym;    char *parentName = utCopyString(dvClassGetName(parent));    char *childName = utCopyString(dvClassGetName(child));    char *parentLabel = utCopyString(dvRelationshipGetParentLabel(relationship));    char *childLabel = utCopyString(dvRelationshipGetChildLabel(relationship));    dvRelationshipType type = dvRelationshipGetType(relationship);    if(dvRelationshipAccessParent(relationship)) {        /* Owner pointer */        sym = utSymCreateFormatted("%s%s", parentLabel, parentName);        prop = dvClassFindProperty(child, sym);        if(prop != dvPropertyNull) {            if(dvPropertyGetClass(prop) != child ||                    dvPropertyGetUnion(prop) != dvUnionNull ||                    dvPropertyGetType(prop) != PROP_POINTER) {                utExit("Property %s defined differently the second time", utSymGetName(sym));            }            /* Must be a duplicated relationship */            dvRelationshipSetSharedParent(relationship, true);        } else {            prop = dvPropertyCreate(child, dvUnionNull, PROP_POINTER, sym);            dvPropertySetClassProp(prop, parent);        }    }    if(!dvRelationshipAccessChild(relationship)) {        return;    }    if(type == REL_POINTER) {        /* Child pointer */        sym = utSymCreateFormatted("%s%s", childLabel, childName);        prop = dvPropertyCreate(parent, dvUnionNull, PROP_POINTER, sym);        dvPropertySetClassProp(prop, child);    }    if(type == REL_LINKED_LIST || type == REL_TAIL_LINKED || type == REL_DOUBLY_LINKED ||            type == REL_HASHED) {        /* First pointer */        sym = utSymCreateFormatted("First%s%s", childLabel, childName);        prop = dvPropertyCreate(parent, dvUnionNull, PROP_POINTER, sym);        dvPropertySetClassProp(prop, child);        /* Next child pointer */        sym = utSymCreateFormatted("Next%s%s%s", parentName, childLabel, childName);        prop = dvPropertyCreate(child, dvUnionNull, PROP_POINTER, sym);        dvPropertySetClassProp(prop, child);    }    if(type == REL_TAIL_LINKED || type == REL_DOUBLY_LINKED || type == REL_HASHED) {        /* Last pointer */        sym = utSymCreateFormatted("Last%s%s", childLabel, childName);        prop = dvPropertyCreate(parent, dvUnionNull, PROP_POINTER, sym);        dvPropertySetClassProp(prop, child);    }    if(type == REL_DOUBLY_LINKED || type == REL_HASHED) {        /* Previous child pointer */        sym = utSymCreateFormatted("Prev%s%s%s", parentName, childLabel, childName);        prop = dvPropertyCreate(child, dvUnionNull, PROP_POINTER, sym);        dvPropertySetClassProp(prop, child);    }    if(type == REL_ARRAY) {        /* Array of children */        sym = utSymCreateFormatted("%s%s", childLabel, childName);        prop = dvPropertyCreate(parent, dvUnionNull, PROP_POINTER, sym);        dvPropertySetClassProp(prop, child);        dvPropertySetArray(prop, true);        /* Index on parent */        sym = utSymCreateFormatted("%s%sIndex", parentName, childLabel);        prop = dvPropertyCreate(child, dvUnionNull, PROP_UINT, sym);        dvPropertySetWidth(prop, 32);        /* Used children on parent */        sym = utSymCreateFormatted("Used%s%s", childLabel, childName);        prop = dvPropertyCreate(parent, dvUnionNull, PROP_UINT, sym);        dvPropertySetWidth(prop, 32);    }    if(type == REL_HASHED) {        /* Hash table */        sym = utSymCreateFormatted("%s%sTable", childLabel, childName);        prop = dvPropertyCreate(parent, dvUnionNull, PROP_POINTER, sym);        dvPropertySetClassProp(prop, child);        dvPropertySetArray(prop, true);        /* Number of entries in table */        sym = utSymCreateFormatted("Num%s%s", childLabel, childName);        prop = dvPropertyCreate(parent, dvUnionNull, PROP_UINT, sym);        dvPropertySetWidth(prop, 32);        /* Symbol on child */        sym = utSymCreateFormatted("%sSym", childLabel);        prop = dvPropertyCreate(child, dvUnionNull, PROP_SYM, sym);        /* Move symbol to front, just to improve reading fields */        dvClassRemoveProperty(child, prop);        dvClassInsertProperty(child, prop);        /* Next child in table */        sym = utSymCreateFormatted("NextTable%s%s%s", parentName, childLabel, childName);        prop = dvPropertyCreate(child, dvUnionNull, PROP_POINTER, sym);        dvPropertySetClassProp(prop, child);    }}/*--------------------------------------------------------------------------------------------------  Create all the module's fields used by relationships.--------------------------------------------------------------------------------------------------*/static void createModuleRelationshipFields(    dvModule module){    dvRelationship relationship;    dvClass theClass;    dvForeachModuleClass(module, theClass) {        dvForeachClassChildRelationship(theClass, relationship) {            generateRelationshipFields(relationship);        } dvEndForeachClassChildRelationship;    } dvEndForeachModuleClass;}/*--------------------------------------------------------------------------------------------------  Move the new property in front of the old property in the list of properties on a class.--------------------------------------------------------------------------------------------------*/static void movePropInFront(    dvProperty newProp,    dvProperty oldProp){    dvClass theClass = dvPropertyGetClass(newProp);    dvClassRemoveProperty(theClass, newProp);    if(dvClassGetFirstProperty(theClass) == oldProp) {        dvClassInsertProperty(theClass, newProp);    } else {        dvClassInsertAfterProperty(theClass, dvPropertyGetPrevClassProperty(oldProp), newProp);    }}/*--------------------------------------------------------------------------------------------------  Generate array fields.  Move them in front of their array properties so when we read them from  a backup file, they already have been defined.--------------------------------------------------------------------------------------------------*/static void createArrayFields(    dvModule module){    dvClass theClass;    dvProperty property, newProp;    utSym sym;    dvForeachModuleClass(module, theClass) {        dvForeachClassProperty(theClass, property) {            if(dvPropertyArray(property)) {                /* Index into heap for first element */                sym = utSymCreateFormatted("%sIndex", utCopyString(dvPropertyGetName(property)));                newProp = dvPropertyCreate(theClass, dvUnionNull, PROP_UINT, sym);                dvPropertySetWidth(newProp, 32);                dvPropertySetFirstElementProp(property, newProp);                movePropInFront(newProp, property);                dvPropertySetHidden(newProp, true);                /* Number of elements allocated in array */                sym = utSymCreateFormatted("Num%s", utCopyString(dvPropertyGetName(property)));                newProp = dvPropertyCreate(theClass, dvUnionNull, PROP_UINT, sym);                dvPropertySetWidth(newProp, 32);                dvPropertySetNumElementsProp(property, newProp);                movePropInFront(newProp, property);                dvPropertySetHidden(newProp, true);            }        } dvEndForeachClassProperty;    } dvEndForeachModuleClass;}/*--------------------------------------------------------------------------------------------------  Find the size of a property element in bits.  For typedef properties, we return 0.--------------------------------------------------------------------------------------------------*/uint8 dvFindPropertySize(    dvProperty property){    switch(dvPropertyGetType(property)) {    case PROP_INT:    case PROP_UINT:        return dvPropertyGetWidth(property);    case PROP_FLOAT:        return sizeof(float) << 3;    case PROP_DOUBLE:        return sizeof(double) << 3;    case PROP_BOOL:        return sizeof(bool) << 3;    case PROP_CHAR:        return sizeof(char) << 3;    case PROP_ENUM:        return sizeof(int) << 3;    case PROP_TYPEDEF:        return 0; /* We don't really know */    case PROP_POINTER:        return dvClassGetReferenceSize(dvPropertyGetClassProp(property));    case PROP_SYM:        return sizeof(utSym) << 3;    case PROP_BIT:        return 1;    default:        utExit("Unknown property type");    }    return 0; /* Dummy return */}/*--------------------------------------------------------------------------------------------------  Find a field on the class for use as a next pointer on a free list.--------------------------------------------------------------------------------------------------*/static dvProperty findFieldForNextFreePointer(    dvClass theClass){    dvProperty property;    uint32 refSize = dvClassGetReferenceSize(theClass);    dvForeachClassProperty(theClass, property) {        if(dvFindPropertySize(property) == refSize && dvPropertyGetUnion(property) == dvUnionNull) {            return property;        }    } dvEndForeachClassProperty;    return dvPropertyNull;}/*--------------------------------------------------------------------------------------------------  Find a field on the class large enough to hold the next pointer.  If none exist, allocate it.--------------------------------------------------------------------------------------------------*/static void setFreeListFields(    dvModule module){    dvClass theClass;    dvProperty property;    utSym sym;    dvForeachModuleClass(module, theClass) {        property = findFieldForNextFreePointer(theClass);        if(property == dvPropertyNull) {            sym = utSymCreate("FreeList");            property = dvPropertyCreate(theClass, dvUnionNull, PROP_POINTER, sym);            dvPropertySetClassProp(property, theClass);            dvPropertySetHidden(property, true);        }        dvClassSetFreeListProperty(theClass, property);    } dvEndForeachModuleClass;}/*--------------------------------------------------------------------------------------------------  Just count the number fields that we will need to track.  Set the total number of fields on  dvTheRoot.--------------------------------------------------------------------------------------------------*/static void setPropertyFieldNumbers(    dvModule module){    dvClass theClass;    dvUnion theUnion;    dvCase theCase;    dvEnum theEnum;    dvEntry entry;    dvProperty property;    uint16 classNumber = 0;    uint16 fieldNumber = 0;    uint16 enumNumber = 0;    uint16 entryNumber;    uint16 unionCaseNumber;    uint16 xField;    dvForeachModuleClass(module, theClass) {        xField = 0;        dvForeachClassProperty(theClass, property) {            if(dvPropertyGetUnion(property) == dvUnionNull) {                dvPropertySetFieldNumber(property, fieldNumber);                fieldNumber++;                xField++;            }        } dvEndForeachClassProperty;        dvForeachClassUnion(theClass, theUnion) {            dvUnionSetFieldNumber(theUnion, fieldNumber);            unionCaseNumber = 0;            dvForeachUnionProperty(theUnion, property) {                dvForeachPropertyCase(property, theCase) {                    unionCaseNumber++;                } dvEndForeachPropertyCase;            } dvEndForeachUnionProperty;            dvUnionSetNumCases(theUnion, unionCaseNumber);            fieldNumber++;            xField++;        } dvEndForeachClassUnion;        dvClassSetNumFields(theClass, xField);        classNumber++;    } dvEndForeachModuleClass;    dvModuleSetNumFields(module, fieldNumber);    dvModuleSetNumClasses(module, classNumber);    dvForeachModuleEnum(module, theEnum) {        enumNumber++;        entryNumber = 0;        dvForeachEnumEntry(theEnum, entry) {            entryNumber++;        } dvEndForeachEnumEntry;        dvEnumSetNumEntries(theEnum, entryNumber);    } dvEndForeachModuleEnum;    dvModuleSetNumEnums(module, enumNumber);}/*--------------------------------------------------------------------------------------------------  Generate code from the file.--------------------------------------------------------------------------------------------------*/bool dvGenerateCode(    dvModule module,    char *includeFile,    char *sourceFile){    createClassDynamicArrayClasses(module);    createModuleRelationshipFields(module);    createArrayFields(module);    setFreeListFields(module);    setPropertyFieldNumbers(module);    dvWriteHeaderFile(module, includeFile);    dvWriteCFile(module, sourceFile);    return true;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -