/* Lookup a property by name. There are 7 kinds of lookups: prop, @att, [prop], *, @*, .name, .@name */ static EjsObj *getXmlListPropertyByName(Ejs *ejs, EjsXML *list, EjsName qname) { EjsXML *result, *subList, *item; int nextItem; /* Get the n'th item in the list */ if (isdigit((uchar) qname.name->value[0]) && allDigitsForXmlList(qname.name)) { return mprGetItem(list->elements, ejsAtoi(ejs, qname.name, 10)); } result = ejsCreateXMLList(ejs, list, qname); /* Build a list of all the elements that themselves have a property qname */ for (nextItem = 0; (item = mprGetNextItem(list->elements, &nextItem)) != 0; ) { if (item->kind == EJS_XML_ELEMENT) { subList = ejsGetPropertyByName(ejs, (EjsObj*) item, qname); assure(ejsIsXML(ejs, subList)); ejsAppendToXML(ejs, result, subList); } else { // TODO - do we ever get a list in a list? assure(0); } } return (EjsObj*) result; }
static int deleteXmlListPropertyByName(Ejs *ejs, EjsXML *list, EjsName qname) { EjsXML *elt; int index, next; if (isdigit((uchar) qname.name->value[0]) && allDigitsForXmlList(qname.name)) { index = ejsAtoi(ejs, qname.name, 10); elt = (EjsXML*) mprGetItem(list->elements, index); if (elt) { if (elt->parent) { if (elt->kind == EJS_XML_ATTRIBUTE) { ejsDeletePropertyByName(ejs, (EjsObj*) elt->parent, elt->qname); } else { // TODO - let q be the property of parent where parent[q] == x[i] mprRemoveItem(elt->parent->elements, elt); elt->parent = 0; } } } // Spec says return true even if index is out of range. We return 0 for true and < 0 for false. // TODO - should ejs throw? return 0; } for (next = 0; (elt = mprGetNextItem(list->elements, &next)) != 0; ) { if (elt->kind == EJS_XML_ELEMENT /* && elt->parent */) { ejsDeletePropertyByName(ejs, (EjsObj*) elt /* TODO was elt->parent */, qname); } } return 0; }
static int setArrayPropertyByName(Ejs *ejs, EjsArray *ap, EjsName qname, EjsObj *value) { int slotNum; if (!isdigit((uchar) qname.name->value[0])) { /* The "length" property is a method getter */ if (qname.name == ESV(length)) { setArrayLength(ejs, ap, 1, &value); return ES_Array_length; } slotNum = (ejs->service->potHelpers.lookupProperty)(ejs, ap, qname); if (slotNum < 0) { slotNum = (ejs->service->potHelpers.setProperty)(ejs, ap, slotNum, value); if (slotNum < 0) { return EJS_ERR; } if ((ejs->service->potHelpers.setPropertyName)(ejs, ap, slotNum, qname) < 0) { return EJS_ERR; } return slotNum; } else { return (ejs->service->potHelpers.setProperty)(ejs, ap, slotNum, value); } } if ((slotNum = checkSlot(ejs, ap, ejsAtoi(ejs, qname.name, 10))) < 0) { return EJS_ERR; } ap->data[slotNum] = value; return slotNum; }
/* Lookup an array index. */ static int lookupArrayProperty(Ejs *ejs, EjsArray *ap, EjsName qname) { int index; if (qname.name == 0 || !isdigit((uchar) qname.name->value[0])) { return EJS_ERR; } index = ejsAtoi(ejs, qname.name, 10); if (index < ap->length) { return index; } return EJS_ERR; }
static int lookupFileProperty(Ejs *ejs, EjsFile *fp, EjsName qname) { int index; if (qname.name == 0 || !isdigit((uchar) qname.name->value[0])) { return EJS_ERR; } if (!(fp->mode & EJS_FILE_OPEN)) { ejsThrowIOError(ejs, "File is not open"); return 0; } index = ejsAtoi(ejs, qname.name, 10); if (index < mprGetFileSize(fp->file)) { return index; } return EJS_ERR; }
/* Set a property by name. */ static int setXmlListPropertyByName(Ejs *ejs, EjsXML *list, EjsName qname, EjsObj *value) { EjsXML *elt, *targetObject; int index; if (!isdigit((uchar) qname.name->value[0])) { return setAlphaPropertyByName(ejs, list, qname, value); } /* Numeric property */ targetObject = 0; if (list->targetObject) { /* Find the real underlying target object. May be an XML object or XMLList if it contains multiple elements. */ targetObject = resolve(ejs, list->targetObject); if (targetObject == 0) { /* Spec says so - TODO why no error? */ return 0; } } index = ejsAtoi(ejs, qname.name, 10); if (index >= mprGetListLength(list->elements)) { /* Create, then fall through to update */ elt = createElement(ejs, list, targetObject, qname, value); if (elt == 0) { return 0; } } else { elt = mprGetItem(list->elements, index); } assure(elt); updateElement(ejs, list, elt, index, value); return index; }
static EjsObj *getArrayPropertyByName(Ejs *ejs, EjsArray *ap, EjsName qname) { int slotNum; if (isdigit((uchar) qname.name->value[0])) { slotNum = ejsAtoi(ejs, qname.name, 10); if (slotNum < 0 || slotNum >= ap->length) { return 0; } return getArrayProperty(ejs, ap, slotNum); } /* The "length" property is a method getter */ if (qname.name == ESV(length)) { return 0; } slotNum = (ejs->service->potHelpers.lookupProperty)(ejs, ap, qname); if (slotNum < 0) { return 0; } return (ejs->service->potHelpers.getProperty)(ejs, ap, slotNum); }