/***********************************************************************/ /* Open Visualization Data Explorer */ /* (C) Copyright IBM Corp. 1989,1999 */ /* ALL RIGHTS RESERVED */ /* This code licensed under the */ /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */ /***********************************************************************/ #include #include #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif struct NextNState { int start; int end; int delta; int direction; int next; }; struct NextGroupState { int next; int end; }; struct NextArrayState { int next; ArrayHandle ahandle; Object in_obj; Type type; Category category; int items, rank, shape[50], isize; Pointer buf; }; Error NextArrState_delete(Pointer in) { struct NextArrayState *astate; if(in) astate = (struct NextArrayState *)in; if(astate->buf) DXFree(astate->buf); if(astate->ahandle) DXFreeArrayHandle(astate->ahandle); if(astate->in_obj) DXDelete(astate->in_obj); DXFree(in); return OK; } Error NextState_delete(Pointer in) { if(in) DXFree(in); return OK; } m_First(Object *in, Object *out) { int first; out[0] = NULL; first = DXLoopFirst(); out[0] = (Object)DXMakeInteger(first); return OK; } m_Done(Object *in, Object *out) { int done; if(!in[0]) { DXSetError(ERROR_BAD_PARAMETER, "Done value must be set"); return ERROR; } if(!DXExtractInteger(in[0], &done)) { DXSetError(ERROR_BAD_PARAMETER, "#10010", "Done value"); return ERROR; } DXLoopDone(done); return OK; } m_ForEachN(Object *in, Object *out) { struct NextNState *state = NULL; Object obj; char *modid; int first; out[0] = NULL; out[1] = NULL; modid = DXGetModuleId(); first = DXLoopFirst(); if(first) { if(!in[0]) { DXSetError(ERROR_MISSING_DATA,"start must be specified"); goto error_return; } if(!in[1]) { DXSetError(ERROR_MISSING_DATA,"end must be specified"); goto error_return; } state = DXAllocateZero(sizeof(struct NextNState)); if(state == NULL) goto error_return; if(!DXExtractInteger(in[0], &state->start)) { DXSetError(ERROR_BAD_PARAMETER, "#10010", "start value"); goto error_return; } if(!DXExtractInteger(in[1], &state->end)) { DXSetError(ERROR_BAD_PARAMETER, "#10010", "end value"); goto error_return; } if(!in[2]) state->delta = 1; else if(!DXExtractInteger(in[2], &state->delta)) { DXSetError(ERROR_BAD_PARAMETER, "#10010", "delta value"); goto error_return; } DXLoopDone(FALSE); state->next = state->start; if(state->delta < 0) state->direction = -1; else state->direction = 1; if((state->start*state->direction) > (state->end*state->direction)) { DXLoopDone(TRUE); DXFreeModuleId(modid); DXFree(state); return; } /* cache the state information */ obj = (Object) DXNewPrivate((Pointer)state, NextState_delete); DXSetCacheEntryV(obj, CACHE_PERMANENT, modid, 0, 0, NULL); } else { obj = DXGetCacheEntryV(modid, 0, 0, NULL); DXDelete(obj); if(obj == NULL) { DXSetError(ERROR_INTERNAL, "Lost state information for loop"); goto error_return; } state = (struct NextNState *) DXGetPrivateData ((Private) obj); state->next += state->delta; } out[0] = (Object)DXMakeInteger(state->next); if(state->next*state->direction>(state->end-state->delta)*state->direction) { #if 0 /* This will be taken care of by ExCleanupForState */ DXSetCacheEntryV(NULL, 0, modid, 0, 0, NULL); #endif DXLoopDone(TRUE); out[1] = (Object)DXMakeInteger(1); } else out[1] = (Object)DXMakeInteger(0); /* if it's the first time we save the modid so that the program */ /* can clean up the state information when it terminates */ if(first) DXSaveForId(modid); else DXFreeModuleId(modid); return OK; error_return: out[0] = NULL; out[1] = NULL; if(state) DXFree(state); DXFreeModuleId(modid); DXLoopDone(TRUE); return ERROR; } m_ForEachMember(Object *in, Object *out) { Group group; struct NextGroupState *gstate = NULL; struct NextArrayState *astate = NULL; Array array, retarray; Pointer nextitem; char *modid; Object obj; int first; modid = DXGetModuleId(); if(!in[0]) { DXSetError(ERROR_BAD_PARAMETER, "#10000", "group or list"); goto error_return; } out[0] = out[1] = out[2] = NULL; first = DXLoopFirst(); switch(DXGetObjectClass(in[0])) { case CLASS_MULTIGRID: case CLASS_COMPOSITEFIELD: case CLASS_SERIES: case CLASS_GROUP: group = (Group)(in[0]); if(first) { DXLoopDone(FALSE); gstate = DXAllocateZero(sizeof(struct NextGroupState)); if(gstate == NULL) goto error_return; gstate->next = 0; DXGetMemberCount(group, &gstate->end); gstate->end--; obj = (Object)DXNewPrivate((Pointer)gstate, NextState_delete); DXSetCacheEntryV((Object)obj, CACHE_PERMANENT, modid, 0, 0, NULL); } else { obj = DXGetCacheEntryV(modid, 0, 0, NULL); DXDelete(obj); if(obj == NULL) { DXSetError(ERROR_INTERNAL, "Lost state information for loop"); goto error_return; } gstate = (struct NextGroupState *) DXGetPrivateData((Private)obj); gstate->next++; } if(gstate->end >= 0) { out[0] = (Object)DXGetEnumeratedMember(group, gstate->next, NULL); out[1] = (Object)DXMakeInteger(gstate->next); if(gstate->next == gstate->end) { DXLoopDone(TRUE); out[2] = (Object)DXMakeInteger(1); } else out[2] = (Object)DXMakeInteger(0); } else { /* we have an empty group */ out[0] = NULL; out[1] = (Object)DXMakeInteger(0); out[2] = (Object)DXMakeInteger(1); DXLoopDone(TRUE); } break; case CLASS_ARRAY: case CLASS_REGULARARRAY: case CLASS_PATHARRAY: case CLASS_PRODUCTARRAY: case CLASS_MESHARRAY: array = (Array)in[0]; if(first) { DXLoopDone(FALSE); astate = DXAllocateZero(sizeof(struct NextArrayState)); if(astate == NULL) goto error_return; DXGetArrayInfo(array, &astate->items, &astate->type, &astate->category, &astate->rank, astate->shape); astate->isize = DXGetItemSize(array); astate->buf = DXAllocate(astate->isize); if(astate->buf == NULL) goto error_return; astate->ahandle = DXCreateArrayHandle(array); if(!astate->ahandle) goto error_return; DXReference(in[0]); astate->in_obj = in[0]; astate->next = 0; astate->items--; obj = (Object)DXNewPrivate((Pointer)astate, NextArrState_delete); DXSetCacheEntryV((Object)obj, CACHE_PERMANENT, modid, 0, 0, NULL); } else { obj = DXGetCacheEntryV(modid, 0, 0, NULL); DXDelete(obj); if(obj == NULL) { DXSetError(ERROR_INTERNAL, "Lost state information for loop"); goto error_return; } astate = (struct NextArrayState *) DXGetPrivateData((Private)obj); astate->next++; } if(astate->items >= 0) { nextitem = DXGetArrayEntry(astate->ahandle, astate->next, astate->buf); retarray = DXNewArrayV(astate->type, astate->category, astate->rank, astate->shape); retarray = DXAddArrayData(retarray, 0, 1, nextitem); out[0] = (Object)retarray; out[1] = (Object)DXMakeInteger(astate->next); if(astate->next == astate->items) { DXLoopDone(TRUE); out[2] = (Object)DXMakeInteger(1); } else out[2] = (Object)DXMakeInteger(0); } else { /* empty array */ out[0] = NULL; out[1] = (Object)DXMakeInteger(0); out[2] = (Object)DXMakeInteger(1); DXLoopDone(TRUE); } break; default: DXSetError(ERROR_BAD_PARAMETER, "input must be group or list"); goto error_return; } /* if it's the first time we save the modid so that the program */ /* can clean up the state information when it terminates */ if(first) DXSaveForId(modid); else DXFreeModuleId(modid); return OK; error_return: out[0] = NULL; out[1] = NULL; out[2] = NULL; if(astate) DXFree(astate); if(gstate) DXFree(gstate); DXFreeModuleId(modid); DXLoopDone(TRUE); return ERROR; }