Esempio n. 1
0
/*JSON{
  "type" : "staticmethod",
  "class" : "Trig",
  "name" : "setTrigger",
  "generate" : "jswrap_trig_setTrigger",
  "params" : [
    ["num","int","The trigger number (0..7)"],
    ["pos","float","The position (in degrees) to fire the trigger at"],
    ["pins","JsVar","An array of pins to pulse (max 4)"],
    ["pulseLength","float","The time (in msec) to pulse for"]
  ]
}
Set a trigger for a certain point in the cycle
*/
void jswrap_trig_setTrigger(JsVarInt num, JsVarFloat position, JsVar *pins, JsVarFloat pulseLength) {
  TriggerStruct *trig = &mainTrigger;
  if (num<0 || num>=TRIGGER_TRIGGERS_COUNT) {
     jsWarn("Invalid trigger number\n");
     return;
   }
  if (!jsvIsArray(pins)) {
    jsWarn("Second argument must be an array of pins\n");
    return;
  }
  if (jsvGetArrayLength(pins) > TRIGGERPOINT_TRIGGERS_COUNT) {
    jsWarn("Too many pins in array\n");
    return;
  }

  // convert from degrees to teeth
  position = wrapAround(((position - trig->keyPosition) * trig->teethTotal / 360), trig->teethTotal);

  TriggerPointStruct *tp = &trig->triggers[num];
  tp->newTooth = (unsigned char)position;
  tp->newToothFraction = (unsigned char)((position - tp->tooth)*256);
  tp->pulseLength = jshGetTimeFromMilliseconds(pulseLength);
  int i, l=(int)jsvGetArrayLength(pins);
  for (i=0;i<TRIGGERPOINT_TRIGGERS_COUNT;i++) {
    tp->pins[i] = (Pin)((i<l) ? jshGetPinFromVarAndUnLock(jsvGetArrayItem(pins, i)) : PIN_UNDEFINED);
  }
  // now copy over data if we need to do it immediately
  if (tp->tooth==TRIGGERPOINT_TOOTH_DISABLE || tp->newTooth==TRIGGERPOINT_TOOTH_DISABLE) {
    tp->tooth = tp->newTooth;
    tp->toothFraction = tp->newToothFraction;
  }
  // all done!
}
Esempio n. 2
0
/*JSON{
  "type" : "constructor",
  "class" : "Date",
  "name" : "Date",
  "generate" : "jswrap_date_constructor",
  "params" : [
    ["args","JsVarArray","Either nothing (current time), one numeric argument (milliseconds since 1970), a date string (see `Date.parse`), or [year, month, day, hour, minute, second, millisecond] "]
  ],
  "return" : ["JsVar","A Date object"],
  "return_object" : "Date"
}
Creates a date object
*/
JsVar *jswrap_date_constructor(JsVar *args) {
  JsVarFloat time = 0;

  if (jsvGetArrayLength(args)==0) {
    time = jswrap_date_now();
  } else if (jsvGetArrayLength(args)==1) {
    JsVar *arg = jsvGetArrayItem(args, 0);
    if (jsvIsNumeric(arg))
      time = jsvGetFloat(arg);
    else if (jsvIsString(arg))
      time = jswrap_date_parse(arg);
    else
      jsWarn("Variables of type %t are not supported in date constructor", arg);
    jsvUnLock(arg);
  } else {
    CalendarDate date;
    date.year = (int)jsvGetIntegerAndUnLock(jsvGetArrayItem(args, 0));
    date.month = (int)jsvGetIntegerAndUnLock(jsvGetArrayItem(args, 1));
    date.day = (int)jsvGetIntegerAndUnLock(jsvGetArrayItem(args, 2));
    TimeInDay td;
    td.daysSinceEpoch = fromCalenderDate(&date);
    td.hour = (int)jsvGetIntegerAndUnLock(jsvGetArrayItem(args, 3));
    td.min = (int)jsvGetIntegerAndUnLock(jsvGetArrayItem(args, 4));
    td.sec = (int)jsvGetIntegerAndUnLock(jsvGetArrayItem(args, 5));
    td.ms = (int)jsvGetIntegerAndUnLock(jsvGetArrayItem(args, 6));
    td.zone = 0;
    time = fromTimeInDay(&td);
  }

  return jswrap_date_from_milliseconds(time);
}
Esempio n. 3
0
/*JSON{
  "type" : "constructor",
  "class" : "Number",
  "name" : "Number",
  "generate" : "jswrap_number_constructor",
  "params" : [
    ["value","JsVarArray","A single value to be converted to a number"]
  ],
  "return" : ["JsVar","A Number object"]
}
Creates a number
 */
JsVar *jswrap_number_constructor(JsVar *args) {
  if (jsvGetArrayLength(args)==0) return jsvNewFromInteger(0);
  JsVar *val = jsvGetArrayItem(args, 0);
  JsVar *result = 0;

  if (jsvIsArray(val)) {
    JsVarInt l = jsvGetArrayLength(val);
    if (l==0) result = jsvNewFromInteger(0);
    else if (l==1) {
      JsVar *n = jsvGetArrayItem(val, 0);
      if (jsvIsString(n) && jsvIsEmptyString(n)) result = jsvNewFromInteger(0);
      else if (!jsvIsBoolean(n)) result=jsvAsNumber(n);
      jsvUnLock(n);
    } // else NaN
  } else if (jsvIsUndefined(val) || jsvIsObject(val))
    result = 0;
  else {
    if (jsvIsString(val) && jsvIsEmptyString(val)) {
      result = jsvNewFromInteger(0);
    } else
      result = jsvAsNumber(val);
  }
  jsvUnLock(val);
  if (result) return result;
  return jsvNewFromFloat(NAN);
}
Esempio n. 4
0
/*JSON{ "type":"method", "class": "Function", "name" : "apply",
         "description" : ["This executes the function with the supplied 'this' argument and parameters"],
         "generate" : "jswrap_function_apply",
         "params" : [ [ "this", "JsVar", "The value to use as the 'this' argument when executing the function"],
                      [ "args", "JsVar", "Optional Array of Aruments"]
                    ],
         "return" : [ "JsVar", "The return value of executing this function" ]
}*/
JsVar *jswrap_function_apply(JsVar *parent, JsVar *thisArg, JsVar *argsArray) {
  unsigned int i;
  JsVar **args = 0;
  size_t argC = 0;

  if (jsvIsArray(argsArray)) {
    argC = (size_t)jsvGetArrayLength(argsArray);
    if (argC>64) argC=64; // sanity
    args = (JsVar**)alloca((size_t)argC * sizeof(JsVar*));


    for (i=0;i<argC;i++) args[i] = 0;
    JsvArrayIterator it;
    jsvArrayIteratorNew(&it, argsArray);
    while (jsvArrayIteratorHasElement(&it)) {
      JsVarInt idx = jsvGetIntegerAndUnLock(jsvArrayIteratorGetIndex(&it));
      if (idx>=0 && idx<(int)argC) {
        assert(!args[idx]); // just in case there were dups
        args[idx] = jsvArrayIteratorGetElement(&it);
      }
      jsvArrayIteratorNext(&it);
    }
    jsvArrayIteratorFree(&it);
  } else if (!jsvIsUndefined(argsArray)) {
    jsWarn("Second argument to Function.apply must be an array");
  }

  JsVar *r = jspeFunctionCall(parent, 0, thisArg, false, (int)argC, args);
  for (i=0;i<argC;i++) jsvUnLock(args[i]);
  return r;
}
Esempio n. 5
0
/*JSON{
  "type" : "function",
  "name" : "setTimeout",
  "generate" : "jswrap_interface_setTimeout",
  "params" : [
    ["function","JsVar","A Function or String to be executed"],
    ["timeout","float","The time until the function will be executed"],
    ["args","JsVarArray","Optional arguments to pass to the function when executed"]
  ],
  "return" : ["JsVar","An ID that can be passed to clearTimeout"]
}
Call the function (or evaluate the string) specified ONCE after the timeout in milliseconds.

For instance:

```
setTimeout(function () {
  console.log("Hello World");
}, 1000);
// or
setTimeout('console.log("Hello World");', 1000);
// both print 'Hello World' after a second
```

You can also specify extra arguments that will be sent to the function when it is executed. For example:

```
setTimeout(function (a,b) {
  console.log(a+" "+b);
}, 1000, "Hello", "World");
// prints 'Hello World' after 1 second
```

If you want to stop the function from being called, pass the number that
was returned by `setTimeout` into the `clearInterval` function.

 **Note:** If `setDeepSleep(true)` has been called and the interval is greater than 5 seconds, Espruino may execute the interval up to 1 second late. This is because Espruino can only wake from deep sleep every second - and waking early would cause Espruino to waste power while it waited for the correct time.
 */
JsVar *_jswrap_interface_setTimeoutOrInterval(JsVar *func, JsVarFloat interval, JsVar *args, bool isTimeout) {
  // NOTE: The 5 sec delay mentioned in the description is handled by jshSleep
  JsVar *itemIndex = 0;
  if (!jsvIsFunction(func) && !jsvIsString(func)) {
    jsExceptionHere(JSET_ERROR, "Function or String not supplied!");
  } else {
    // Create a new timer
    JsVar *timerPtr = jsvNewWithFlags(JSV_OBJECT);
    if (interval<TIMER_MIN_INTERVAL) interval=TIMER_MIN_INTERVAL;
    JsSysTime intervalInt = jshGetTimeFromMilliseconds(interval);
    jsvObjectSetChildAndUnLock(timerPtr, "time", jsvNewFromLongInteger((jshGetSystemTime() - jsiLastIdleTime) + intervalInt));
    if (!isTimeout) {
      jsvObjectSetChildAndUnLock(timerPtr, "interval", jsvNewFromLongInteger(intervalInt));
    }
    jsvObjectSetChild(timerPtr, "callback", func); // intentionally no unlock
    if (jsvGetArrayLength(args))
      jsvObjectSetChild(timerPtr, "args", args); // intentionally no unlock

    // Add to array
    itemIndex = jsvNewFromInteger(jsiTimerAdd(timerPtr));
    jsvUnLock(timerPtr);
    jsiTimersChanged(); // mark timers as changed
  }
  return itemIndex;
}
Esempio n. 6
0
/*JSON{
  "type" : "method",
  "class" : "SPI",
  "name" : "write",
  "generate" : "jswrap_spi_write",
  "params" : [
    ["data","JsVarArray",["One or more items to write. May be ints, strings, arrays, or objects of the form `{data: ..., count:#}`.","If the last argument is a pin, it is taken to be the NSS pin"]]
  ]
}
Write a character or array of characters to SPI - without reading the result back.

For maximum speeds, please pass either Strings or Typed Arrays as arguments.
*/
void jswrap_spi_write(JsVar *parent, JsVar *args) {
  NOT_USED(parent);
  IOEventFlags device = jsiGetDeviceFromClass(parent);

  spi_sender spiSend;
  spi_sender_data spiSendData;
  if (!jsspiGetSendFunction(parent, &spiSend, &spiSendData))
    return;


  Pin nss_pin = PIN_UNDEFINED;
  // If the last value is a pin, use it as the NSS pin
  JsVarInt len = jsvGetArrayLength(args);
  if (len>0) {    
    JsVar *last = jsvGetArrayItem(args, len-1); // look at the last value
    if (jsvIsPin(last)) {
      nss_pin = jshGetPinFromVar(last);    
      jsvUnLock(jsvArrayPop(args));
    }
    jsvUnLock(last);
  }

  // we're only sending (no receive)
  if (DEVICE_IS_SPI(device)) jshSPISetReceive(device, false);

  // assert NSS
  if (nss_pin!=PIN_UNDEFINED) jshPinOutput(nss_pin, false);
  // Write data
  jsvIterateCallback(args, (void (*)(int,  void *))spiSend, &spiSendData);
  // Wait until SPI send is finished, and flush data
  if (DEVICE_IS_SPI(device))
    jshSPIWait(device);
  // de-assert NSS
  if (nss_pin!=PIN_UNDEFINED) jshPinOutput(nss_pin, true);
}
Esempio n. 7
0
/*JSON{
  "type" : "property",
  "class" : "Object",
  "name" : "length",
  "generate" : "jswrap_object_length",
  "return" : ["JsVar","The length of the object"]
}
Find the length of the object
 */
JsVar *jswrap_object_length(JsVar *parent) {
  JsVarInt l;
  if (jsvIsArray(parent)) {
    l = jsvGetArrayLength(parent);
  } else if (jsvIsArrayBuffer(parent)) {
    l = (JsVarInt)jsvGetArrayBufferLength(parent);
  } else if (jsvIsString(parent)) {
    l = (JsVarInt)jsvGetStringLength(parent);
  } else if (jsvIsFunction(parent)) {
    JsVar *args = jsvGetFunctionArgumentLength(parent);
    l = jsvGetArrayLength(args);
    jsvUnLock(args);
  } else
    return 0;
  return jsvNewFromInteger(l);
}
Esempio n. 8
0
bool jsvIteratorHasElement(JsvIterator *it) {
  switch (it->type) {
  case JSVI_FULLARRAY: return it->it.obj.index < jsvGetArrayLength(it->it.obj.var);
  case JSVI_OBJECT : return jsvObjectIteratorHasValue(&it->it.obj.it);
  case JSVI_STRING : return jsvStringIteratorHasChar(&it->it.str);
  case JSVI_ARRAYBUFFER : return jsvArrayBufferIteratorHasElement(&it->it.buf);
  default: assert(0); return 0;
  }
}
/*JSON{ "type":"property", "class": "Object", "name" : "length",
         "description" : "Find the length of the object",
         "generate" : "jswrap_object_length",
         "return" : ["JsVar", "The value of the string"]
}*/
JsVar *jswrap_object_length(JsVar *parent) {
  if (jsvIsArray(parent)) {
    return jsvNewFromInteger(jsvGetArrayLength(parent));
  } else if (jsvIsArrayBuffer(parent)) {
      return jsvNewFromInteger((JsVarInt)jsvGetArrayBufferLength(parent));
  } else if (jsvIsString(parent)) {
    return jsvNewFromInteger((JsVarInt)jsvGetStringLength(parent));
  }
  return 0;
}
Esempio n. 10
0
/*JSON{
  "type" : "method",
  "class" : "Array",
  "name" : "push",
  "generate" : "jswrap_array_push",
  "params" : [
    ["arguments","JsVarArray","One or more arguments to add"]
  ],
  "return" : ["int","The new size of the array"]
}
Push a new value onto the end of this array'

This is the opposite of `[1,2,3].unshift(0)`, which adds one or more elements to the beginning of the array.
 */
JsVarInt jswrap_array_push(JsVar *parent, JsVar *args) {
  if (!jsvIsArray(parent)) return -1;
  JsVarInt len = -1;
  JsvObjectIterator it;
  jsvObjectIteratorNew(&it, args);
  while (jsvObjectIteratorHasValue(&it)) {
    JsVar *el = jsvObjectIteratorGetValue(&it);
    len = jsvArrayPush(parent, el);
    jsvUnLock(el);
    jsvObjectIteratorNext(&it);
  }
  jsvObjectIteratorFree(&it);
  if (len<0) 
    len = jsvGetArrayLength(parent);
  return len;
}
Esempio n. 11
0
JsVar *jswrap_typedarray_constructor(JsVarDataArrayBufferViewType type, JsVar *arr, JsVarInt byteOffset, JsVarInt length) {
  JsVar *arrayBuffer = 0;
  if (jsvIsArrayBuffer(arr)) {
    arrayBuffer = jsvLockAgain(arr);
  } else if (jsvIsInt(arr)) {
    length = jsvGetInteger(arr);
    byteOffset = 0;
    arrayBuffer = jswrap_arraybuffer_constructor(JSV_ARRAYBUFFER_GET_SIZE(type)*length);
  } else if (jsvIsArray(arr)) {
    length = jsvGetArrayLength(arr);
    byteOffset = 0;
    arrayBuffer = jswrap_arraybuffer_constructor(JSV_ARRAYBUFFER_GET_SIZE(type)*length);
    // later on we'll populate this
  }
  if (!arrayBuffer) {
    jsError("Unsupported first argument\n");
    return 0;
  }
  if (length<=0) length = (JsVarInt)jsvGetArrayBufferLength(arrayBuffer) / JSV_ARRAYBUFFER_GET_SIZE(type);
  JsVar *typedArr = jsvNewWithFlags(JSV_ARRAYBUFFER);
  if (typedArr) {
    typedArr->varData.arraybuffer.type = type;
    typedArr->varData.arraybuffer.byteOffset = (unsigned short)byteOffset;
    typedArr->varData.arraybuffer.length = (unsigned short)length;
    typedArr->firstChild = jsvGetRef(jsvRef(arrayBuffer));

    if (jsvIsArray(arr)) {
      // if we were given an array, populate this ArrayBuffer
      JsvArrayIterator it;
      jsvArrayIteratorNew(&it, arr);
      while (jsvArrayIteratorHasElement(&it)) {
        JsVar *idx = jsvArrayIteratorGetIndex(&it);
        if (jsvIsInt(idx)) {
          JsVar *val = jsvArrayIteratorGetElement(&it);
          jsvArrayBufferSet(typedArr, jsvGetInteger(idx), val);
          jsvUnLock(val);
        }
        jsvUnLock(idx);
        jsvArrayIteratorNext(&it);
      }
      jsvArrayIteratorFree(&it);
    }
  }
  jsvUnLock(arrayBuffer);
  return typedArr;
}
Esempio n. 12
0
/*JSON{
  "type" : "constructor",
  "class" : "Array",
  "name" : "Array",
  "generate" : "jswrap_array_constructor",
  "params" : [
    ["args","JsVarArray","The length of the array OR any number of items to add to the array"]
  ],
  "return" : ["JsVar","An Array"]
}
Create an Array. Either give it one integer argument (>=0) which is the length of the array, or any number of arguments 
*/
JsVar *jswrap_array_constructor(JsVar *args) {
  assert(args);
  if (jsvGetArrayLength(args)==1) {
    JsVar *firstArg = jsvSkipNameAndUnLock(jsvGetArrayItem(args,0));
    if (jsvIsInt(firstArg) && jsvGetInteger(firstArg)>=0) {
      JsVarInt count = jsvGetInteger(firstArg);
      if (count>0) {
        JsVar *arr = jsvNewWithFlags(JSV_ARRAY);
        if (!arr) return 0; // out of memory
        jsvSetArrayLength(arr, count, false);
        jsvUnLock(firstArg);
        return arr;
      }
    }
    jsvUnLock(firstArg);
  }
  // Otherwise, we just return the array!
  return jsvLockAgain(args);
}
Esempio n. 13
0
/*JSON{ "type":"constructor", "class": "Array",  "name": "Array",
         "description" : "Create an Array. Either give it one integer argument (>=0) which is the length of the array, or any number of arguments ",
         "generate" : "jswrap_array_constructor",
         "params" : [ [ "args", "JsVarArray", "The length of the array OR any number of items to add to the array" ] ],
         "return" : [ "JsVar", "An Array" ]

}*/
JsVar *jswrap_array_constructor(JsVar *args) {
  assert(args);
  if (jsvGetArrayLength(args)==1) {
    JsVar *firstArg = jsvSkipNameAndUnLock(jsvArrayGetLast(args)); // also the first!
    if (jsvIsInt(firstArg) && jsvGetInteger(firstArg)>=0) {
      JsVarInt count = jsvGetInteger(firstArg);
      // we cheat - no need to fill the array - just the last element
      if (count>0) {
        JsVar *arr = jsvNewWithFlags(JSV_ARRAY);
        if (!arr) return 0; // out of memory
        JsVar *idx = jsvMakeIntoVariableName(jsvNewFromInteger(count-1), 0);
        if (idx) { // could be out of memory
          jsvAddName(arr, idx);
          jsvUnLock(idx);
        }
        jsvUnLock(firstArg);
        return arr;
      }
    }
    jsvUnLock(firstArg);
  }
  // Otherwise, we just return the array!
  return jsvLockAgain(args);
}
Esempio n. 14
0
/*JSON{
  "type" : "constructor",
  "class" : "Array",
  "name" : "Array",
  "generate" : "jswrap_array_constructor",
  "params" : [
    ["args","JsVarArray","The length of the array OR any number of items to add to the array"]
  ],
  "return" : ["JsVar","An Array"]
}
Create an Array. Either give it one integer argument (>=0) which is the length of the array, or any number of arguments 
 */
JsVar *jswrap_array_constructor(JsVar *args) {
  assert(args);
  if (jsvGetArrayLength(args)==1) {
    JsVar *firstArg = jsvSkipNameAndUnLock(jsvGetArrayItem(args,0));
    if (jsvIsNumeric(firstArg)) {
      JsVarFloat f = jsvGetFloat(firstArg);
      JsVarInt count = jsvGetInteger(firstArg);
      jsvUnLock(firstArg);
      if (f!=count || count<0) {
        jsExceptionHere(JSET_ERROR, "Invalid array length");
        return 0;
      } else {
        JsVar *arr = jsvNewEmptyArray();
        if (!arr) return 0; // out of memory
        jsvSetArrayLength(arr, count, false);
        return arr;
      } 
    } else {
      jsvUnLock(firstArg); 
    }
  }
  // Otherwise, we just return the array!
  return jsvLockAgain(args);
}
Esempio n. 15
0
void jsfGetJSONWithCallback(JsVar *var, JSONFlags flags, const char *whitespace, vcbprintf_callback user_callback, void *user_data) {
  JSONFlags nflags = flags + JSON_INDENT; // if we add a newline, make sure we indent any subsequent JSON more
  if (!whitespace) whitespace="  ";

  if (jsvIsUndefined(var)) {
    cbprintf(user_callback, user_data, "undefined");
  } else {
    // Use IS_RECURSING  flag to stop recursion
    if (var->flags & JSV_IS_RECURSING) {
      cbprintf(user_callback, user_data, " ... ");
      return;
    }
    var->flags |= JSV_IS_RECURSING;

    if (jsvIsArray(var)) {
      JsVarInt length = jsvGetArrayLength(var);
      bool limited = (flags&JSON_LIMIT) && (length>(JsVarInt)JSON_LIMIT_AMOUNT);
      bool needNewLine = false;
      cbprintf(user_callback, user_data, (flags&JSON_PRETTY)?"[ ":"[");
      JsVarInt lastIndex = -1;
      bool numeric = true;
      bool first = true;
      JsvObjectIterator it;
      jsvObjectIteratorNew(&it, var);
      while (lastIndex+1<length && numeric && !jspIsInterrupted()) {
        JsVar *key = jsvObjectIteratorGetKey(&it);
        if (!jsvObjectIteratorHasValue(&it) || jsvIsNumeric(key)) {
          JsVarInt index = jsvObjectIteratorHasValue(&it) ? jsvGetInteger(key) : length-1;
          JsVar *item = jsvObjectIteratorGetValue(&it);
          while (lastIndex < index) {
            lastIndex++;
            if (!limited || lastIndex<(JsVarInt)JSON_LIMITED_AMOUNT || lastIndex>=length-(JsVarInt)JSON_LIMITED_AMOUNT) {
              if (!first) cbprintf(user_callback, user_data, (flags&JSON_PRETTY)?", ":",");
              first = false;
              if (limited && lastIndex==length-(JsVarInt)JSON_LIMITED_AMOUNT) cbprintf(user_callback, user_data, JSON_LIMIT_TEXT);
              bool newNeedsNewLine = ((flags&JSON_SOME_NEWLINES) && jsonNeedsNewLine(item));
              if (flags&JSON_ALL_NEWLINES) {
                needNewLine = true;
                newNeedsNewLine = true;
              }
              if (needNewLine || newNeedsNewLine) {
                jsonNewLine(nflags, whitespace, user_callback, user_data);
                needNewLine = false;
              }
              if (lastIndex == index)
                jsfGetJSONWithCallback(item, nflags, whitespace, user_callback, user_data);
              else
                cbprintf(user_callback, user_data, (flags&JSON_NO_UNDEFINED)?"null":"undefined");
              needNewLine = newNeedsNewLine;
            }
          }
          jsvUnLock(item);
          jsvObjectIteratorNext(&it);
        } else {
          numeric = false;
        }
        jsvUnLock(key);
      }

      // non-numeric  - but NOT for standard JSON
      if ((flags&JSON_PRETTY))
        jsfGetJSONForObjectItWithCallback(&it, flags, whitespace, nflags, user_callback, user_data, first);
      jsvObjectIteratorFree(&it);
      if (needNewLine) jsonNewLine(flags, whitespace, user_callback, user_data);
      cbprintf(user_callback, user_data, (flags&JSON_PRETTY)?" ]":"]");
    } else if (jsvIsArrayBuffer(var)) {
      JsvArrayBufferIterator it;
      bool allZero = true;
      jsvArrayBufferIteratorNew(&it, var, 0);
      while (jsvArrayBufferIteratorHasElement(&it)) {
        if (jsvArrayBufferIteratorGetFloatValue(&it)!=0)
          allZero = false;
        jsvArrayBufferIteratorNext(&it);
      }
      jsvArrayBufferIteratorFree(&it);
      bool asArray = flags&JSON_ARRAYBUFFER_AS_ARRAY;

      if (allZero && !asArray) {
        cbprintf(user_callback, user_data, "new %s(%d)", jswGetBasicObjectName(var), jsvGetArrayBufferLength(var));
      } else {
        const char *aname = jswGetBasicObjectName(var);
        /* You can't do `new ArrayBuffer([1,2,3])` so we have to output
         * `new Uint8Array([1,2,3]).buffer`! */
        bool isBasicArrayBuffer = strcmp(aname,"ArrayBuffer")==0;
        if (isBasicArrayBuffer) {
          aname="Uint8Array";
        }
        cbprintf(user_callback, user_data, asArray?"[":"new %s([", aname);
        if (flags&JSON_ALL_NEWLINES) jsonNewLine(nflags, whitespace, user_callback, user_data);
        size_t length = jsvGetArrayBufferLength(var);
        bool limited = (flags&JSON_LIMIT) && (length>JSON_LIMIT_AMOUNT);
        // no newlines needed for array buffers as they only contain simple stuff

        jsvArrayBufferIteratorNew(&it, var, 0);
        while (jsvArrayBufferIteratorHasElement(&it) && !jspIsInterrupted()) {
          if (!limited || it.index<JSON_LIMITED_AMOUNT || it.index>=length-JSON_LIMITED_AMOUNT) {
            if (it.index>0) cbprintf(user_callback, user_data, (flags&JSON_PRETTY)?", ":",");
            if (flags&JSON_ALL_NEWLINES) jsonNewLine(nflags, whitespace, user_callback, user_data);
            if (limited && it.index==length-JSON_LIMITED_AMOUNT) cbprintf(user_callback, user_data, JSON_LIMIT_TEXT);
            JsVar *item = jsvArrayBufferIteratorGetValue(&it);
            jsfGetJSONWithCallback(item, nflags, whitespace, user_callback, user_data);
            jsvUnLock(item);
          }
          jsvArrayBufferIteratorNext(&it);
        }
        if (flags&JSON_ALL_NEWLINES) jsonNewLine(flags, whitespace, user_callback, user_data);
        jsvArrayBufferIteratorFree(&it);
        cbprintf(user_callback, user_data, asArray?"]":"])");
        if (isBasicArrayBuffer && !asArray) cbprintf(user_callback, user_data, ".buffer");
      }
    } else if (jsvIsObject(var)) {
      IOEventFlags device = (flags & JSON_SHOW_DEVICES) ? jsiGetDeviceFromClass(var) : EV_NONE;
      if (device!=EV_NONE) {
        cbprintf(user_callback, user_data, "%s", jshGetDeviceString(device));
      } else {
        bool showContents = true;
        if (flags & JSON_SHOW_OBJECT_NAMES) {
          JsVar *proto = jsvObjectGetChild(var, JSPARSE_INHERITS_VAR, 0);
          if (jsvHasChildren(proto)) {
            JsVar *constr = jsvObjectGetChild(proto, JSPARSE_CONSTRUCTOR_VAR, 0);
            if (constr) {
              JsVar *p = jsvGetIndexOf(execInfo.root, constr, true);
              if (p) cbprintf(user_callback, user_data, "%v: ", p);
              jsvUnLock2(p,constr);
              /* We had the constructor - now if there was a non-default toString function
               * we'll execute it and print the result */
              JsVar *toStringFn = jspGetNamedField(var, "toString", false);
              if (toStringFn && toStringFn->varData.native.ptr != (void (*)(void))jswrap_object_toString) {
                // Function found and it's not the default one - execute it
                JsVar *result = jspExecuteFunction(toStringFn,var,0,0);
                cbprintf(user_callback, user_data, "%v", result);
                jsvUnLock(result);
                showContents = false; // we already printed something
              }
              jsvUnLock(toStringFn);
            }
          }
          jsvUnLock(proto);
        }
        if (showContents) {
          JsvObjectIterator it;
          jsvObjectIteratorNew(&it, var);
          cbprintf(user_callback, user_data, (flags&JSON_PRETTY)?"{ ":"{");
          bool needNewLine = jsfGetJSONForObjectItWithCallback(&it, flags, whitespace, nflags, user_callback, user_data, true);
          jsvObjectIteratorFree(&it);
          if (needNewLine) jsonNewLine(flags, whitespace, user_callback, user_data);
          cbprintf(user_callback, user_data, (flags&JSON_PRETTY)?" }":"}");
        }
      }
    } else if (jsvIsFunction(var)) {
      if (flags & JSON_IGNORE_FUNCTIONS) {
        cbprintf(user_callback, user_data, "undefined");
      } else {
        cbprintf(user_callback, user_data, "function ");
        jsfGetJSONForFunctionWithCallback(var, nflags, user_callback, user_data);
      }
    } else if (jsvIsString(var) && !jsvIsName(var)) {
      if ((flags&JSON_LIMIT) && jsvGetStringLength(var)>JSON_LIMIT_STRING_AMOUNT) {
        // if the string is too big, split it and put dots in the middle
        JsVar *var1 = jsvNewFromStringVar(var, 0, JSON_LIMITED_STRING_AMOUNT);
        JsVar *var2 = jsvNewFromStringVar(var, jsvGetStringLength(var)-JSON_LIMITED_STRING_AMOUNT, JSON_LIMITED_STRING_AMOUNT);
        cbprintf(user_callback, user_data, "%q%s%q", var1, JSON_LIMIT_TEXT, var2);
        jsvUnLock2(var1, var2);
      } else {
        cbprintf(user_callback, user_data, "%q", var);
      }
    } else {
      cbprintf(user_callback, user_data, "%v", var);
    }

    var->flags &= ~JSV_IS_RECURSING;
  }
}
Esempio n. 16
0
void jsfGetJSONWithCallback(JsVar *var, JSONFlags flags, vcbprintf_callback user_callback, void *user_data) {
  JSONFlags nflags = flags + JSON_INDENT; // if we add a newline, make sure we indent any subsequent JSON more

  if (jsvIsUndefined(var)) {
    cbprintf(user_callback, user_data, "undefined");
  } else {
    // Use IS_RECURSING  flag to stop recursion
    if (var->flags & JSV_IS_RECURSING) {
      cbprintf(user_callback, user_data, " ... ");
      return;
    }
    var->flags |= JSV_IS_RECURSING;

    if (jsvIsArray(var)) {
      size_t length = (size_t)jsvGetArrayLength(var);
      bool limited = (flags&JSON_LIMIT) && (length>JSON_LIMIT_AMOUNT);
      bool needNewLine = false;
      size_t i;
      cbprintf(user_callback, user_data, (flags&JSON_PRETTY)?"[ ":"[");
      for (i=0;i<length && !jspIsInterrupted();i++) {
        if (!limited || i<JSON_LIMITED_AMOUNT || i>=length-JSON_LIMITED_AMOUNT) {
          if (i>0) cbprintf(user_callback, user_data, (flags&JSON_PRETTY)?", ":",");
          if (limited && i==length-JSON_LIMITED_AMOUNT) {
            if (needNewLine) jsonNewLine(nflags, user_callback, user_data);
            cbprintf(user_callback, user_data, JSON_LIMIT_TEXT);
          }
          JsVar *item = jsvGetArrayItem(var, (JsVarInt)i);
          if (jsvIsUndefined(item) && (flags&JSON_NO_UNDEFINED))
              item = jsvNewWithFlags(JSV_NULL);
          bool newNeedsNewLine = (flags&JSON_NEWLINES) && jsonNeedsNewLine(item);
          if (needNewLine || newNeedsNewLine) {
            jsonNewLine(nflags, user_callback, user_data);
            needNewLine = false;
          }
          jsfGetJSONWithCallback(item, nflags, user_callback, user_data);
          needNewLine = newNeedsNewLine;
          jsvUnLock(item);
        }
      }
      if (needNewLine) jsonNewLine(flags, user_callback, user_data);
      cbprintf(user_callback, user_data, (flags&JSON_PRETTY)?" ]":"]");
    } else if (jsvIsArrayBuffer(var)) {
      JsvArrayBufferIterator it;
      bool allZero = true;
      jsvArrayBufferIteratorNew(&it, var, 0);
      while (jsvArrayBufferIteratorHasElement(&it)) {
        if (jsvArrayBufferIteratorGetFloatValue(&it)!=0)
          allZero = false;
        jsvArrayBufferIteratorNext(&it);
      }
      jsvArrayBufferIteratorFree(&it);

      if (allZero) {
        cbprintf(user_callback, user_data, "new %s(%d)", jswGetBasicObjectName(var), jsvGetArrayBufferLength(var));
      } else {
        cbprintf(user_callback, user_data, "new %s([", jswGetBasicObjectName(var));
        size_t length = jsvGetArrayBufferLength(var);
        bool limited = (flags&JSON_LIMIT) && (length>JSON_LIMIT_AMOUNT);
        // no newlines needed for array buffers as they only contain simple stuff

        jsvArrayBufferIteratorNew(&it, var, 0);
        while (jsvArrayBufferIteratorHasElement(&it) && !jspIsInterrupted()) {
          if (!limited || it.index<JSON_LIMITED_AMOUNT || it.index>=length-JSON_LIMITED_AMOUNT) {
            if (it.index>0) cbprintf(user_callback, user_data, (flags&JSON_PRETTY)?", ":",");
            if (limited && it.index==length-JSON_LIMITED_AMOUNT) cbprintf(user_callback, user_data, JSON_LIMIT_TEXT);
            JsVar *item = jsvArrayBufferIteratorGetValue(&it);
            jsfGetJSONWithCallback(item, nflags, user_callback, user_data);
            jsvUnLock(item);
          }
          jsvArrayBufferIteratorNext(&it);
        }
        jsvArrayBufferIteratorFree(&it);
        cbprintf(user_callback, user_data, "])");
      }
    } else if (jsvIsObject(var)) {
      IOEventFlags device = (flags & JSON_SHOW_DEVICES) ? jsiGetDeviceFromClass(var) : EV_NONE;
      if (device!=EV_NONE) {
        cbprintf(user_callback, user_data, "%s", jshGetDeviceString(device));
      } else {
        bool first = true;
        bool needNewLine = false;
        size_t sinceNewLine = 0;
        JsvObjectIterator it;
        jsvObjectIteratorNew(&it, var);
        cbprintf(user_callback, user_data, (flags&JSON_PRETTY)?"{ ":"{");
        while (jsvObjectIteratorHasValue(&it) && !jspIsInterrupted()) {
          JsVar *index = jsvObjectIteratorGetKey(&it);
          JsVar *item = jsvObjectIteratorGetValue(&it);
          bool hidden = jsvIsInternalObjectKey(index) ||
                        ((flags & JSON_IGNORE_FUNCTIONS) && jsvIsFunction(item)) ||
                        ((flags&JSON_NO_UNDEFINED) && jsvIsUndefined(item));
          if (!hidden) {
            sinceNewLine++;
            if (!first) cbprintf(user_callback, user_data, (flags&JSON_PRETTY)?", ":",");
            bool newNeedsNewLine = (flags&JSON_NEWLINES) && jsonNeedsNewLine(item);
            if ((flags&JSON_NEWLINES) && sinceNewLine>JSON_ITEMS_ON_LINE_OBJECT)
              needNewLine = true;
            if (needNewLine || newNeedsNewLine) {
              jsonNewLine(nflags, user_callback, user_data);
              needNewLine = false;
              sinceNewLine = 0;
            }
            cbprintf(user_callback, user_data, (flags&JSON_PRETTY)?"%q: ":"%q:", index);
            if (first)
              first = false;
            jsfGetJSONWithCallback(item, nflags, user_callback, user_data);
            needNewLine = newNeedsNewLine;
          }
          jsvUnLock(index);
          jsvUnLock(item);
          jsvObjectIteratorNext(&it);
        }
        jsvObjectIteratorFree(&it);
        if (needNewLine) jsonNewLine(flags, user_callback, user_data);
        cbprintf(user_callback, user_data, (flags&JSON_PRETTY)?" }":"}");
      }
    } else if (jsvIsFunction(var)) {
      if (flags & JSON_IGNORE_FUNCTIONS) {
        cbprintf(user_callback, user_data, "undefined");
      } else {
        cbprintf(user_callback, user_data, "function ");
        jsfGetJSONForFunctionWithCallback(var, nflags, user_callback, user_data);
      }
    } else if (jsvIsString(var) && !jsvIsName(var)) {
      if ((flags&JSON_LIMIT) && jsvGetStringLength(var)>JSON_LIMIT_STRING_AMOUNT) {
        // if the string is too big, split it and put dots in the middle
        JsVar *var1 = jsvNewFromStringVar(var, 0, JSON_LIMITED_STRING_AMOUNT);
        JsVar *var2 = jsvNewFromStringVar(var, jsvGetStringLength(var)-JSON_LIMITED_STRING_AMOUNT, JSON_LIMITED_STRING_AMOUNT);
        cbprintf(user_callback, user_data, "%q%s%q", var1, JSON_LIMIT_TEXT, var2);
        jsvUnLock(var1);
        jsvUnLock(var2);
      } else {
        cbprintf(user_callback, user_data, "%q", var);
      }
    } else {
      cbprintf(user_callback, user_data, "%v", var);
    }

    var->flags &= ~JSV_IS_RECURSING;
  }
}
Esempio n. 17
0
/*JSON{ "type":"method", "class": "Array", "name" : "splice",
         "description" : "Both remove and add items to an array",
         "generate" : "jswrap_array_splice",
         "params" : [ [ "index", "int", "Index at which to start changing the array. If negative, will begin that many elements from the end"],
                      [ "howMany", "JsVar", "An integer indicating the number of old array elements to remove. If howMany is 0, no elements are removed."],
                      [ "element1", "JsVar", "A new item to add (optional)" ],
                      [ "element2", "JsVar", "A new item to add (optional)" ],
                      [ "element3", "JsVar", "A new item to add (optional)" ],
                      [ "element4", "JsVar", "A new item to add (optional)" ],
                      [ "element5", "JsVar", "A new item to add (optional)" ],
                      [ "element6", "JsVar", "A new item to add (optional)" ] ],
         "return" : ["JsVar", "An array containing the removed elements. If only one element is removed, an array of one element is returned."]
}*/
JsVar *jswrap_array_splice(JsVar *parent, JsVarInt index, JsVar *howManyVar, JsVar *element1, JsVar *element2, JsVar *element3, JsVar *element4, JsVar *element5, JsVar *element6) {
  JsVarInt len = jsvGetArrayLength(parent);
  if (index<0) index+=len;
  if (index<0) index=0;
  if (index>len) index=len;
  JsVarInt howMany = len; // how many to delete!
  if (jsvIsInt(howManyVar)) howMany = jsvGetInteger(howManyVar);
  if (howMany > len-index) howMany = len-index;
  JsVarInt newItems = 0;
  if (element1) newItems++;
  if (element2) newItems++;
  if (element3) newItems++;
  if (element4) newItems++;
  if (element5) newItems++;
  if (element6) newItems++;
  JsVarInt shift = newItems-howMany;

  bool needToAdd = false;
  JsVar *result = jsvNewWithFlags(JSV_ARRAY);

  JsArrayIterator it;
  jsvArrayIteratorNew(&it, parent);
  while (jsvArrayIteratorHasElement(&it) && !needToAdd) {
    bool goToNext = true;
    JsVar *idxVar = jsvArrayIteratorGetIndex(&it);
    if (idxVar && jsvIsInt(idxVar)) {
      JsVarInt idx = jsvGetInteger(idxVar);
      if (idx<index) {
        // do nothing...
      } else if (idx<index+howMany) { // must delete
        if (result) { // append to result array
          JsVar *el = jsvArrayIteratorGetElement(&it);
          jsvArrayPush(result, el);
          jsvUnLock(el);
        }
        // delete
        goToNext = false;
        JsVar *toRemove = jsvArrayIteratorGetIndex(&it);
        jsvArrayIteratorNext(&it);
        jsvRemoveChild(parent, toRemove);
        jsvUnLock(toRemove);
      } else { // we're greater than the amount we need to remove now
        needToAdd = true;
        goToNext = false;
      }
    }
    jsvUnLock(idxVar);
    if (goToNext) jsvArrayIteratorNext(&it);
  }
  // now we add everything
  JsVar *beforeIndex = jsvArrayIteratorGetIndex(&it);
  if (element1) jsvArrayInsertBefore(parent, beforeIndex, element1);
  if (element2) jsvArrayInsertBefore(parent, beforeIndex, element2);
  if (element3) jsvArrayInsertBefore(parent, beforeIndex, element3);
  if (element4) jsvArrayInsertBefore(parent, beforeIndex, element4);
  if (element5) jsvArrayInsertBefore(parent, beforeIndex, element5);
  if (element6) jsvArrayInsertBefore(parent, beforeIndex, element6);
  jsvUnLock(beforeIndex);
  // And finally renumber
  while (jsvArrayIteratorHasElement(&it)) {
      JsVar *idxVar = jsvArrayIteratorGetIndex(&it);
      if (idxVar && jsvIsInt(idxVar)) {
        jsvSetInteger(idxVar, jsvGetInteger(idxVar)+shift);
      }
      jsvUnLock(idxVar);
      jsvArrayIteratorNext(&it);
    }
  // free
  jsvArrayIteratorFree(&it);

  return result;
}
Esempio n. 18
0
/*JSON{
  "type" : "method",
  "class" : "Array",
  "name" : "splice",
  "generate" : "jswrap_array_splice",
  "params" : [
    ["index","int","Index at which to start changing the array. If negative, will begin that many elements from the end"],
    ["howMany","JsVar","An integer indicating the number of old array elements to remove. If howMany is 0, no elements are removed."],
    ["elements","JsVarArray","One or more items to add to the array"]
  ],
  "return" : ["JsVar","An array containing the removed elements. If only one element is removed, an array of one element is returned."]
}
Both remove and add items to an array
 */
JsVar *jswrap_array_splice(JsVar *parent, JsVarInt index, JsVar *howManyVar, JsVar *elements) {
  if (!jsvIsArray(parent)) return 0;
  JsVarInt len = jsvGetArrayLength(parent);
  if (index<0) index+=len;
  if (index<0) index=0;
  if (index>len) index=len;
  JsVarInt howMany = len; // how many to delete!
  if (jsvIsInt(howManyVar)) howMany = jsvGetInteger(howManyVar);
  if (howMany > len-index) howMany = len-index;
  JsVarInt newItems = jsvGetArrayLength(elements);
  JsVarInt shift = newItems-howMany;

  bool needToAdd = false;
  JsVar *result = jsvNewEmptyArray();

  JsvObjectIterator it;
  jsvObjectIteratorNew(&it, parent);
  while (jsvObjectIteratorHasValue(&it) && !needToAdd) {
    bool goToNext = true;
    JsVar *idxVar = jsvObjectIteratorGetKey(&it);
    if (idxVar && jsvIsInt(idxVar)) {
      JsVarInt idx = jsvGetInteger(idxVar);
      if (idx<index) {
        // do nothing...
      } else if (idx<index+howMany) { // must delete
        if (result) { // append to result array
          JsVar *el = jsvObjectIteratorGetValue(&it);
          jsvArrayPushAndUnLock(result, el);
        }
        // delete
        goToNext = false;
        JsVar *toRemove = jsvObjectIteratorGetKey(&it);
        jsvObjectIteratorNext(&it);
        jsvRemoveChild(parent, toRemove);
        jsvUnLock(toRemove);
      } else { // we're greater than the amount we need to remove now
        needToAdd = true;
        goToNext = false;
      }
    }
    jsvUnLock(idxVar);
    if (goToNext) jsvObjectIteratorNext(&it);
  }
  // now we add everything
  JsVar *beforeIndex = jsvObjectIteratorGetKey(&it);
  JsvObjectIterator itElement;
  jsvObjectIteratorNew(&itElement, elements);
  while (jsvObjectIteratorHasValue(&itElement)) {
    JsVar *element = jsvObjectIteratorGetValue(&itElement);
    jsvArrayInsertBefore(parent, beforeIndex, element);
    jsvUnLock(element);
    jsvObjectIteratorNext(&itElement);
  }
  jsvObjectIteratorFree(&itElement);
  jsvUnLock(beforeIndex);
  // And finally renumber
  while (jsvObjectIteratorHasValue(&it)) {
    JsVar *idxVar = jsvObjectIteratorGetKey(&it);
    if (idxVar && jsvIsInt(idxVar)) {
      jsvSetInteger(idxVar, jsvGetInteger(idxVar)+shift);
    }
    jsvUnLock(idxVar);
    jsvObjectIteratorNext(&it);
  }
  // free
  jsvObjectIteratorFree(&it);

  // and reset array size
  jsvSetArrayLength(parent, len + shift, false);

  return result;
}
Esempio n. 19
0
/*JSON{
  "type" : "constructor",
  "class" : "String",
  "name" : "String",
  "generate" : "jswrap_string_constructor",
  "params" : [
    ["str","JsVarArray","A value to turn into a string. If undefined or not supplied, an empty String is created."]
  ],
  "return" : ["JsVar","A String"]
}
Create a new String
*/
JsVar *jswrap_string_constructor(JsVar *args) {
  if (jsvGetArrayLength(args)==0)
    return jsvNewFromEmptyString(); // no argument - return an empty string
  return jsvAsString(jsvGetArrayItem(args, 0), true);
}