Added iterator function which can work on all types of array objects
authorMatthew Mondor <mmondor@pulsar-zone.net>
Sun, 13 Feb 2005 05:43:36 +0000 (05:43 +0000)
committerMatthew Mondor <mmondor@pulsar-zone.net>
Sun, 13 Feb 2005 05:43:36 +0000 (05:43 +0000)
tests/js-test/src/classes/js_fd.c

index 1b4d24b..d372b8d 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: js_fd.c,v 1.9 2005/02/11 18:25:36 mmondor Exp $ */
+/* $Id: js_fd.c,v 1.10 2005/02/13 05:43:36 mmondor Exp $ */
 
 /*
  * Copyright (c) 2005, Matthew Mondor
@@ -127,7 +127,10 @@ static JSBool      fd_m_shutdown(JSContext *, JSObject *, uintN, jsval *,
  */
 
 static JSBool  fd_sm_poll(JSContext *, JSObject *, uintN, jsval *, jsval *);
+static JSBool  poll_iterator(JSContext *, jsval *, jsval *, void *);
 
+static JSBool  object_iterate(JSContext *, JSObject *, void *,
+                   JSBool (*)(JSContext *, jsval *, jsval *, void *));
 static int     fd_path_allow(const char *);
 static mode_t  fd_mode_allow(mode_t);
 static int     fd_flags_allow(int);
@@ -796,7 +799,6 @@ fd_m_get(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 static JSBool
 fd_sm_poll(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 {
-       jsint           i, l;
        JSObject        *array;
 
        if (argc != 2) {
@@ -814,81 +816,13 @@ fd_sm_poll(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                return JS_FALSE;
        }
 
-       {
-               JSIdArray       *a;
-               jsval           v;
-               jsid            id;
-
-               if ((a = JS_Enumerate(cx, JSVAL_TO_OBJECT(argv[0])))
-                   != NULL) {
-                       for (i = 0; i < a->length; i++) {
-                               printf("i=%d, id=%ld, ", i, a->vector[i]);
-                               JS_IdToValue(cx, a->vector[i], &v);
-                               printf("vtype=%s, v=",
-                                   JS_GetTypeName(cx, JS_TypeOfValue(cx, v)));
-                               if (JSVAL_IS_STRING(v))
-                                       printf("'%s'\n", JS_GetStringBytes(
-                                           JSVAL_TO_STRING(v)));
-                               else
-                                       printf("%d\n", JSVAL_TO_INT(v));
-                               JS_ValueToId(cx, v, &id);
-                               printf("ValueToId = %ld\n", id);
-                       }
-                       JS_DestroyIdArray(cx, a);
-               }
-       }
-
        /*
         * Now run though the array as a test and make sure that all elements
         * are actual FD objects.
         */
        array = JSVAL_TO_OBJECT(argv[0]);
-       if (!JS_GetArrayLength(cx, array, &l)) {
-               QUEUE_EXCEPTION("Internal error! (1)");
+       if (!object_iterate(cx, array, NULL, poll_iterator))
                return JS_FALSE;
-       }
-       /* XXX */printf("length=%d\n", l);
-       for (i = 0; i < l; i++) {
-               JSObject        *o;
-               jsval           v;
-               jsfd_t          *jsfd;
-
-               /*
-                * XXX Noncontiguous or associative arrays do not seem to work
-                * using this technique.  It appears that the IDs would then
-                * be non-contiguous as well, so decreasing <l> instead of
-                * running <i> to <l> seems more appropriate, while skipping
-                * IDs without entries.  However, this is both suboptimal, and
-                * strangely enough, an endless loop occurs since we do not
-                * detect which is the last entry.  Why? Since we do have the
-                * number of elements...
-                */
-               if (!JS_LookupElement(cx, array, i, &v)) {
-                       QUEUE_EXCEPTION("Internal error! (2)");
-                       return JS_FALSE;
-               }
-               if (JSVAL_IS_VOID(v)) {
-                       /* XXX */ printf("id: %d, void\n", i);
-                       continue;
-               }
-               /*
-                  if (!JS_GetElement(cx, array, i, &v)) {
-                  QUEUE_EXCEPTION("Internal error! (2)");
-                  return JS_FALSE;
-                  }
-                */
-               if (!JSVAL_IS_OBJECT(v) || !JS_InstanceOf(cx,
-                   (o = JSVAL_TO_OBJECT(v)), &fd_class, NULL)) {
-                       QUEUE_EXCEPTION("Array elements not FD object");
-                       return JS_FALSE;
-               }
-               if ((jsfd = JS_GetInstancePrivate(cx, o, &fd_class, NULL))
-                   == NULL) {
-                       QUEUE_EXCEPTION("Null private data!");
-                       return JS_FALSE;
-               }
-               printf("id: %d, fd=%d\n", i, jsfd->fd);
-       }
 
        /*
         * XXX First learn how to walk through user-supplied array.
@@ -906,12 +840,82 @@ fd_sm_poll(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
        return JS_TRUE;
 }
 
+static JSBool
+poll_iterator(JSContext *cx, jsval *id, jsval *val, void *udata)
+{
+       JSObject        *o;
+       jsfd_t          *jsfd;
+
+       if (!JSVAL_IS_OBJECT(*val) ||
+           !JS_InstanceOf(cx, (o = JSVAL_TO_OBJECT(*val)), &fd_class, NULL)) {
+               QUEUE_EXCEPTION("Not FD object");
+               return JS_FALSE;
+       }
+       if ((jsfd = JS_GetInstancePrivate(cx, o, &fd_class, NULL)) == NULL) {
+               QUEUE_EXCEPTION("Null private data!");
+               return JS_FALSE;
+       }
+       if (JSVAL_IS_STRING(*id)) {
+               char    *bytes;
+
+               bytes = JS_GetStringBytes(JSVAL_TO_STRING(*id));
+               printf("id: '%s', fd: %d\n", bytes, jsfd->fd);
+       } else
+               printf("id: %d, fd: %d\n", JSVAL_TO_INT(*id), jsfd->fd);
+
+       return JS_TRUE;
+}
+
 
 /*
  * Utility functions
  */
 
 /*
+ * Was written to be able to iterate over all elements of an array object,
+ * despite being an associated array or not, or a mix of both.  Unfortunately
+ * uses marked as private JSIdArray structure.
+ */
+static JSBool
+object_iterate(JSContext *cx, JSObject *obj, void *udata,
+    JSBool (*func)(JSContext *, jsval *, jsval *, void *))
+{
+       JSIdArray       *a;
+       jsval           id, val;
+       char            *name;
+       jsint           i;
+       JSBool          ret = JS_FALSE;
+
+       if ((a = JS_Enumerate(cx, obj)) != NULL) {
+               for (i = 0; i < a->length; i++) {
+                       JS_IdToValue(cx, a->vector[i], &id);
+                       if (JSVAL_IS_STRING(id)) {
+                               /*
+                                * Property id is a string, attempt to
+                                * lookup its value by name.
+                                */
+                               name = JS_GetStringBytes(JSVAL_TO_STRING(id));
+                               if (!JS_LookupProperty(cx, obj, name, &val))
+                                       continue;
+                       } else {
+                               /*
+                                * Property id is a number, attempt to
+                                * lookup its array element by index.
+                                */
+                               if (!JS_LookupElement(cx, obj,
+                                   JSVAL_TO_INT(id), &val))
+                                               continue;
+                       }
+                       if (!(ret = func(cx, &id, &val, udata)))
+                               break;
+               }
+               JS_DestroyIdArray(cx, a);
+       }
+
+       return ret;
+}
+
+/*
  * Utility function return 0 if user supplied path should be allowed, or -1 if
  * it should be rejected (invalid, or permission denied).  This can for
  * instance be used to restrict the program in a virtual chroot(2)-like jail.