// This file is a part of Framsticks SDK. http://www.framsticks.com/ // Copyright (C) 1999-2015 Maciej Komosinski and Szymon Ulatowski. // See LICENSE.txt for details. #include #include #include static const char* maybedup(bool dup, const char* src) { return dup ? (src ? strdup(src) : 0) : src; } static void maybefree(void* mem) { if (mem) free(mem); } int ParamObject::firstFieldOffset() { static ParamObject dummy(0, NULL); return ((char*)&dummy.fields[0]) - (char*)&dummy; } ParamEntry* ParamObject::makeParamTab(ParamInterface *pi, bool stripgroups, bool stripproc, int firstprop, int maxprops, bool dupentries, int flagsexclude, bool addnew, const char* rename) { ParamEntry *tab, *t; int i, n, offset; static ExtValue ex; int count = 0, gcount = 1; if (!stripgroups) gcount = pi->getGroupCount(); if (stripproc || flagsexclude) for (int i = firstprop; i < pi->getPropCount(); i++) { const char*t = pi->type(i); if ((!stripproc) || (strchr("dfsox", *t))) if ((!flagsexclude) || (!(pi->flags(i)&flagsexclude))) if (++count >= maxprops) break; } else count = pi->getPropCount() - firstprop; if (addnew) count++; t = tab = (ParamEntry*)malloc(sizeof(ParamEntry)*(count + gcount + 1)); t->group = (short)gcount; t->flags = (short)count; t->name = maybedup(dupentries, rename ? rename : pi->getName()); t->type = maybedup(dupentries, pi->getDescription()); for (i = 0; i < gcount; i++) { t->id = maybedup(dupentries, pi->grname(i)); t->offset = 0; t++; } n = 1; offset = firstFieldOffset(); if (addnew) { t->id = maybedup(dupentries, "new"); t->name = maybedup(dupentries, "create new object"); SString tmp = SString::sprintf("p o%s()", pi->getName()); t->type = maybedup(dupentries, (const char*)tmp); t->help = maybedup(dupentries, pi->help(i)); t->flags = 0; t->group = 0; t->offset = PARAM_ILLEGAL_OFFSET; t->fun1 = (void*)p_new; t->fun2 = 0; t++; } for (i = firstprop; i < pi->getPropCount(); i++) { if ((!stripproc) || (strchr("dfsox", *pi->type(i)))) { if ((!flagsexclude) || (!(pi->flags(i)&flagsexclude))) { t->offset = offset; if (*pi->type(i) != 'x') t->offset += (((char*)&ex.data[0]) - ((char*)&ex)); t->group = (short)(stripgroups ? 0 : pi->group(i)); t->flags = (short)pi->flags(i); t->fun1 = 0; t->fun2 = 0; t->id = maybedup(dupentries, pi->id(i)); t->name = maybedup(dupentries, pi->name(i)); t->type = maybedup(dupentries, pi->type(i)); t->help = maybedup(dupentries, pi->help(i)); t++; n++; offset += sizeof(ExtValue); if (n > count) break; } } } t->id = 0; t->group = 0; t->flags = dupentries ? MUTPARAM_ALLOCENTRY : 0; return tab; } void ParamObject::setParamTabText(ParamEntry *pe, const char* &ptr, const char* txt) { if (!paramTabAllocatedString(pe)) return; maybefree((char*)ptr); ptr = maybedup(true, txt); } bool ParamObject::paramTabAllocatedString(ParamEntry *pe) { return (pe[pe->flags + pe->group].flags & MUTPARAM_ALLOCENTRY) ? true : false; } void ParamObject::freeParamTab(ParamEntry *pe) { if (paramTabAllocatedString(pe)) { int i; ParamEntry *e; maybefree((void*)pe->name); maybefree((void*)pe->type); for (i = 0, e = pe; i < pe->group; i++, e++) maybefree((void*)e->id); for (i = pe->group, e = pe + i; i < pe->group + pe->flags; i++, e++) { maybefree((void*)e->id); maybefree((void*)e->name); maybefree((void*)e->type); maybefree((void*)e->help); } } free(pe); } bool ParamObject::paramTabEqual(ParamEntry *pe1, ParamEntry *pe2) { if (pe1->flags != pe2->flags) return false; ParamEntry *e1 = pe1 + pe1->group, *e2 = pe2 + pe2->group; for (int i = 0; i < pe1->flags; i++, e1++, e2++) { if (strcmp(e1->id, e2->id)) return false; if (strcmp(e1->name, e2->name)) return false; if (strcmp(e1->type, e2->type)) return false; if (e1->offset != e2->offset) return false; } return true; } void ParamObject::p_new(void* obj, ExtValue *args, ExtValue *ret) { ParamObject *this_obj = (ParamObject*)obj; ParamObject *po = makeObject(this_obj->par.getParamTab()); ret->setObject(ExtObject(&this_obj->par, po)); po->par.setDefault(); } ParamObject::ParamObject(int _numfields, ParamEntry *_tab) { numfields = _numfields; par.setParamTab(_tab); par.select(this); for (int i = 0; i < numfields; i++) new(&fields[i])ExtValue(); } ParamObject::~ParamObject() { for (int i = 0; i < numfields; i++) fields[i].~ExtValue(); } ParamObject* ParamObject::makeObject(ParamEntry *tab) { if (!tab) return 0; int n = tab->flags; if (!n) return 0; ParamObject *obj = new(n)ParamObject(n, tab); // new(n): allocate n fields ; ParamObject(n,...): tell the object it has n fields ExtValue *v = &obj->fields[0]; tab += tab->group; for (; n > 0; n--, tab++) switch (*tab->type) { case 'd': v->setInt(0); v++; break; case 'f': v->setDouble(0); v++; break; case 's': v->setString(SString::empty()); v++; break; case 'o': v->setObject(ExtObject()); v++; break; case 'x': v++; break; } return obj; } void ParamObject::operator=(const ParamObject& src) { const ExtValue *s = &src.fields[0]; ExtValue *d = &fields[0]; int n = min(numfields, src.numfields); for (int i = 0; i < n; i++, d++, s++) *d = *s; } ParamObject* ParamObject::clone() { ParamObject *c = new(numfields)ParamObject(numfields, par.getParamTab()); *c = *this; return c; } void ParamObject::copyObject(void* dst, void* src) { if ((!dst) || (!src)) return; ParamObject *s = (ParamObject*)src; ParamObject *d = (ParamObject*)dst; *d = *s; } void* ParamObject::dupObject(void* src) { if (!src) return NULL; ParamObject *s = (ParamObject*)src; return s->clone(); } void ParamObject::freeObject(void* obj) { if (!obj) return; ParamObject *o = (ParamObject*)obj; delete o; }