예제 #1
0
파일: jslex.c 프로젝트: CWBudde/Espruino
JsVar *jslNewStringFromLexer(JslCharPos *charFrom, size_t charTo) {
  // Original method - just copy it verbatim
  size_t maxLength = charTo + 1 - jsvStringIteratorGetIndex(&charFrom->it);
  assert(maxLength>0); // will fail if 0
  // Try and create a flat string first
  JsVar *var = 0;
  if (maxLength > JSV_FLAT_STRING_BREAK_EVEN) {
    var = jsvNewFlatStringOfLength((unsigned int)maxLength);
    if (var) {
      // Flat string
      char *flatPtr = jsvGetFlatStringPointer(var);
      *(flatPtr++) = charFrom->currCh;
      JsvStringIterator it = jsvStringIteratorClone(&charFrom->it);
      while (jsvStringIteratorHasChar(&it) && (--maxLength>0)) {
        *(flatPtr++) = jsvStringIteratorGetChar(&it);
        jsvStringIteratorNext(&it);
      }
      jsvStringIteratorFree(&it);
      return var;
    }
  }
  // Non-flat string...
  var = jsvNewFromEmptyString();
  if (!var) { // out of memory
    return 0;
  }

  //jsvAppendStringVar(var, lex->sourceVar, charFrom->it->index, (int)(charTo-charFrom));
  JsVar *block = jsvLockAgain(var);
  block->varData.str[0] = charFrom->currCh;
  size_t blockChars = 1;

  size_t l = maxLength;
  // now start appending
  JsvStringIterator it = jsvStringIteratorClone(&charFrom->it);
  while (jsvStringIteratorHasChar(&it) && (--maxLength>0)) {
    char ch = jsvStringIteratorGetChar(&it);
    if (blockChars >= jsvGetMaxCharactersInVar(block)) {
      jsvSetCharactersInVar(block, blockChars);
      JsVar *next = jsvNewWithFlags(JSV_STRING_EXT_0);
      if (!next) break; // out of memory
      // we don't ref, because  StringExts are never reffed as they only have one owner (and ALWAYS have an owner)
      jsvSetLastChild(block, jsvGetRef(next));
      jsvUnLock(block);
      block = next;
      blockChars=0; // it's new, so empty
    }
    block->varData.str[blockChars++] = ch;
    jsvStringIteratorNext(&it);
  }
  jsvSetCharactersInVar(block, blockChars);
  jsvUnLock(block);
  // Just make sure we only assert if there's a bug here. If we just ran out of memory or at end of string it's ok
  assert((l == jsvGetStringLength(var)) || (jsErrorFlags&JSERR_MEMORY) || !jsvStringIteratorHasChar(&it));
  jsvStringIteratorFree(&it);


  return var;
}
예제 #2
0
/*JSON{
  "type" : "method",
  "class" : "String",
  "name" : "trim",
  "generate" : "jswrap_string_trim",
  "return" : ["JsVar","A String with Whitespace removed from the beginning and end"],
  "return_object" : "String"
}
Return a new string with any whitespace (tabs, space, form feed, newline,
carriage return, etc) removed from the beginning and end.
 */
JsVar *jswrap_string_trim(JsVar *parent) {
  JsVar *s = jsvAsString(parent);
  if (!s) return s;
  unsigned int start = 0;
  int end = -1;

  // work out beginning and end
  JsvStringIterator it;
  jsvStringIteratorNew(&it, s, 0);
  while (jsvStringIteratorHasChar(&it)) {
    bool ws = isWhitespace(jsvStringIteratorGetChar(&it));
    if (!ws) {
      if (end<0) start = (unsigned int)jsvStringIteratorGetIndex(&it);
      end = (int)jsvStringIteratorGetIndex(&it); // last
    }
    jsvStringIteratorNext(&it);
  }
  jsvStringIteratorFree(&it);
  // work out length
  unsigned int len = 0;
  if (end>=(int)start) len = 1+(unsigned int)end-start;
  JsVar *res = jsvNewFromStringVar(s, start, len);
  jsvUnLock(s);
  return res;
}
예제 #3
0
/* match: search for regexp anywhere in text */
static JsVar *match(char *regexp, JsVar *str, size_t startIndex, bool ignoreCase) {
  matchInfo info;
  info.sourceStr = str;
  info.startIndex = startIndex;
  info.ignoreCase = ignoreCase;
  info.rangeMatch = false;
  info.rangeFirstChar = NO_RANGE;
  info.groups = 0;

  JsVar *rmatch;
  JsvStringIterator txtIt, txtIt2;
  jsvStringIteratorNew(&txtIt, str, startIndex);
  /* must look even if string is empty */
  txtIt2 = jsvStringIteratorClone(&txtIt);
  rmatch = matchhere(regexp, &txtIt2, info);
  jsvStringIteratorFree(&txtIt2);
  jsvStringIteratorNext(&txtIt);
  while (!rmatch && jsvStringIteratorHasChar(&txtIt)) {
    info.startIndex++;
    txtIt2 = jsvStringIteratorClone(&txtIt);
    rmatch = matchhere(regexp, &txtIt2, info);
    jsvStringIteratorFree(&txtIt2);
    jsvStringIteratorNext(&txtIt);
  }
  jsvStringIteratorFree(&txtIt);
  return rmatch;
}
예제 #4
0
bool jsvIteratorHasElement(JsvIterator *it) {
  switch (it->type) {
  case JSVI_OBJECT : return jsvObjectIteratorHasValue(&it->it.obj);
  case JSVI_STRING : return jsvStringIteratorHasChar(&it->it.str);
  case JSVI_ARRAYBUFFER : return jsvArrayBufferIteratorHasElement(&it->it.buf);
  default: assert(0); return 0;
  }
}
예제 #5
0
void jsvStringIteratorAppendString(JsvStringIterator *it, JsVar *str, size_t startIdx) {
  JsvStringIterator sit;
  jsvStringIteratorNew(&sit, str, startIdx);
  while (jsvStringIteratorHasChar(&sit)) {
    jsvStringIteratorAppend(it, jsvStringIteratorGetChar(&sit));
    jsvStringIteratorNext(&sit);
  }
  jsvStringIteratorFree(&sit);
}
예제 #6
0
파일: jslex.c 프로젝트: CWBudde/Espruino
void jslPrintTokenLineMarker(vcbprintf_callback user_callback, void *user_data, size_t tokenPos, char *prefix) {
  size_t line = 1,col = 1;
  jsvGetLineAndCol(lex->sourceVar, tokenPos, &line, &col);
  size_t startOfLine = jsvGetIndexFromLineAndCol(lex->sourceVar, line, 1);
  size_t lineLength = jsvGetCharsOnLine(lex->sourceVar, line);
  size_t prefixLength = 0;

  if (prefix) {
    user_callback(prefix, user_data);
    prefixLength = strlen(prefix);
  }

  if (lineLength>60 && tokenPos-startOfLine>30) {
    cbprintf(user_callback, user_data, "...");
    size_t skipChars = tokenPos-30 - startOfLine;
    startOfLine += 3+skipChars;
    if (skipChars<=col)
      col -= skipChars;
    else
      col = 0;
    lineLength -= skipChars;
  }

  // print the string until the end of the line, or 60 chars (whichever is less)
  int chars = 0;
  JsvStringIterator it;
  jsvStringIteratorNew(&it, lex->sourceVar, startOfLine);
  unsigned char lastch = 0;
  while (jsvStringIteratorHasChar(&it) && chars<60) {
    unsigned char ch = (unsigned char)jsvStringIteratorGetChar(&it);
    if (ch == '\n') break;
    if (jslNeedSpaceBetween(lastch, ch)) {
      col++;
      user_callback(" ", user_data);
    }
    char buf[32];
    jslFunctionCharAsString(ch, buf, sizeof(buf));
    size_t len = strlen(buf);
    col += len-1;
    user_callback(buf, user_data);
    chars++;
    lastch = ch;
    jsvStringIteratorNext(&it);
  }
  jsvStringIteratorFree(&it);

  if (lineLength > 60)
    user_callback("...", user_data);
  user_callback("\n", user_data);
  col += prefixLength;
  while (col-- > 1) user_callback(" ", user_data);
  user_callback("^\n", user_data);
}
예제 #7
0
void jsfGetEscapedString(JsVar *var, vcbprintf_callback user_callback, void *user_data) {
  user_callback("\"",user_data);
  JsvStringIterator it;
  jsvStringIteratorNew(&it, var, 0);
  while (jsvStringIteratorHasChar(&it)) {
    char ch = jsvStringIteratorGetChar(&it);
    user_callback(escapeCharacter(ch), user_data);
    jsvStringIteratorNext(&it);
  }
  jsvStringIteratorFree(&it);
  user_callback("\"",user_data);
}
예제 #8
0
/*JSON{
  "type" : "method",
  "class" : "String",
  "name" : "charAt",
  "generate" : "jswrap_string_charAt",
  "params" : [
    ["pos","int","The character number in the string. Negative values return characters from end of string (-1 = last char)"]
  ],
  "return" : ["JsVar","The character in the string"]
}
Return a single character at the given position in the String.
*/
JsVar *jswrap_string_charAt(JsVar *parent, JsVarInt idx) {
  // We do this so we can handle '/0' in a string
  JsVar *r = jsvNewFromEmptyString();
  if (r && jsvIsString(parent) && idx>=0) {
    JsvStringIterator it;
    jsvStringIteratorNew(&it, parent, (size_t)idx);
    if (jsvStringIteratorHasChar(&it)) {
      char ch = jsvStringIteratorGetChar(&it);
      jsvAppendStringBuf(r, &ch, 1);
    }
    jsvStringIteratorFree(&it);
  }
  return r;
}
예제 #9
0
size_t httpStringGet(JsVar *v, char *str, size_t len) {
    size_t l = len;
    JsvStringIterator it;
    jsvStringIteratorNew(&it, v, 0);
    while (jsvStringIteratorHasChar(&it)) {
        if (l--==0) {
            jsvStringIteratorFree(&it);
            return len;
        }
        *(str++) = jsvStringIteratorGetChar(&it);
        jsvStringIteratorNext(&it);
    }
    jsvStringIteratorFree(&it);
    return len-l;
}
예제 #10
0
/// Does this regex have the given flag?
bool jswrap_regexp_hasFlag(JsVar *parent, char flag) {
  JsVar *flags = jsvObjectGetChild(parent, "flags", 0);
  bool has = false;
  if (jsvIsString(flags)) {
    JsvStringIterator it;
    jsvStringIteratorNew(&it, flags, 0);
    while (jsvStringIteratorHasChar(&it)) {
      has |= jsvStringIteratorGetChar(&it)==flag;
      jsvStringIteratorNext(&it);
    }
    jsvStringIteratorFree(&it);
  }
  jsvUnLock(flags);
  return has;
}
예제 #11
0
파일: jslex.c 프로젝트: 8bitgeek/Espruino
void jslPrintTokenLineMarker(vcbprintf_callback user_callback, void *user_data, size_t tokenPos, char *prefix) {
  size_t line = 1,col = 1;
  jsvGetLineAndCol(lex->sourceVar, tokenPos, &line, &col);
  size_t startOfLine = jsvGetIndexFromLineAndCol(lex->sourceVar, line, 1);
  size_t lineLength = jsvGetCharsOnLine(lex->sourceVar, line);
  size_t prefixLength = 0;

  if (prefix) {
    user_callback(prefix, user_data);
    prefixLength = strlen(prefix);
  }

  if (lineLength>60 && tokenPos-startOfLine>30) {
    cbprintf(user_callback, user_data, "...");
    size_t skipChars = tokenPos-30 - startOfLine;
    startOfLine += 3+skipChars;
    col -= skipChars;
    lineLength -= skipChars;
  }

  // print the string until the end of the line, or 60 chars (whichever is lesS)
  int chars = 0;
  JsvStringIterator it;
  jsvStringIteratorNew(&it, lex->sourceVar, startOfLine);
  while (jsvStringIteratorHasChar(&it) && chars<60) {
    char ch = jsvStringIteratorGetChar(&it);
    if (ch == '\n') break;
    char buf[2];
    buf[0] = ch;
    buf[1] = 0;
    user_callback(buf, user_data);
    chars++;
    jsvStringIteratorNext(&it);
  }
  jsvStringIteratorFree(&it);

  if (lineLength > 60)
    user_callback("...", user_data);
  user_callback("\n", user_data);
  col += prefixLength;
  while (col-- > 1) user_callback(" ", user_data);
  user_callback("^\n", user_data);
}
예제 #12
0
/** Iterate over the contents of var, calling callback for each. Contents may be:
 *   * numeric -> output
 *   * a string -> output each character
 *   * array/arraybuffer -> call itself on each element
 *   * object -> call itself object.count times, on object.data
 */
bool jsvIterateCallback(JsVar *data, void (*callback)(int item, void *callbackData), void *callbackData) {
  bool ok = true;
  if (jsvIsNumeric(data)) {
    callback((int)jsvGetInteger(data), callbackData);
  } else if (jsvIsObject(data)) {
    JsVar *countVar = jsvObjectGetChild(data, "count", 0);
    JsVar *dataVar = jsvObjectGetChild(data, "data", 0);
    if (countVar && dataVar && jsvIsNumeric(countVar)) {
      int n = (int)jsvGetInteger(countVar);
      while (ok && n-- > 0) {
        ok = jsvIterateCallback(dataVar, callback, callbackData);
      }
    } else {
      jsWarn("If specifying an object, it must be of the form {data : ..., count : N}");
    }
    jsvUnLock(countVar);
    jsvUnLock(dataVar);
  } else if (jsvIsString(data)) {
    JsvStringIterator it;
    jsvStringIteratorNew(&it, data, 0);
    while (jsvStringIteratorHasChar(&it) && ok) {
      char ch = jsvStringIteratorGetChar(&it);
      callback(ch, callbackData);
      jsvStringIteratorNext(&it);
    }
    jsvStringIteratorFree(&it);
  } else if (jsvIsIterable(data)) {
    JsvIterator it;
    jsvIteratorNew(&it, data);
    while (jsvIteratorHasElement(&it) && ok) {
      JsVar *el = jsvIteratorGetValue(&it);
      ok = jsvIterateCallback(el, callback, callbackData);
      jsvUnLock(el);
      jsvIteratorNext(&it);
    }
    jsvIteratorFree(&it);
  } else {
    jsWarn("Expecting a number or something iterable, got %t", data);
    ok = false;
  }
  return ok;
}
예제 #13
0
/*JSON{ "type":"function", "name" : "isNaN",
         "description" : "Whether the x is NaN (Not a Number) or not",
         "generate" : "jswrap_isNaN",
         "params" :  [ [ "x", "JsVar", ""] ],
         "return" : ["bool", "True is the value is NaN, false if not."]
}*/
bool jswrap_isNaN(JsVar *v) {
  if (jsvIsUndefined(v) ||
      jsvIsObject(v) ||
      (jsvIsFloat(v) && isnan(jsvGetFloat(v)))) return true;
  if (jsvIsString(v)) {
    // this is where is can get a bit crazy
    bool allWhiteSpace = true;
    JsvStringIterator it;
    jsvStringIteratorNew(&it,v,0);
    while (jsvStringIteratorHasChar(&it)) {
      if (!isWhitespace(jsvStringIteratorGetChar(&it))) {
        allWhiteSpace = false;
        break;
      }
      jsvStringIteratorNext(&it);
    }
    jsvStringIteratorFree(&it);
    if (allWhiteSpace) return false;
    return isnan(jsvGetFloat(v));
  }
  return false;
}
예제 #14
0
/*JSON{
  "type" : "method",
  "class" : "String",
  "name" : "toUpperCase",
  "generate_full" : "jswrap_string_toUpperLowerCase(parent, true)",
  "params" : [

  ],
  "return" : ["JsVar","The uppercase version of this string"]
}*/
JsVar *jswrap_string_toUpperLowerCase(JsVar *parent, bool upper) {
  JsVar *res = jsvNewFromEmptyString();
  if (!res) return 0; // out of memory
  JsVar *parentStr = jsvAsString(parent);

  JsvStringIterator itsrc, itdst;
  jsvStringIteratorNew(&itsrc, parentStr, 0);
  jsvStringIteratorNew(&itdst, res, 0);

  while (jsvStringIteratorHasChar(&itsrc)) {
    char ch = jsvStringIteratorGetChar(&itsrc);
    ch = upper ? jsvStringCharToUpper(ch) : jsvStringCharToLower(ch);
    jsvStringIteratorAppend(&itdst, ch);
    jsvStringIteratorNext(&itsrc);
  }

  jsvStringIteratorFree(&itsrc);
  jsvStringIteratorFree(&itdst);
  jsvUnLock(parentStr);

  return res;
}
예제 #15
0
JsVar *jslNewFromLexer(struct JsLex *lex, JslCharPos *charFrom, size_t charTo) {
  // Create a var
  JsVar *var = jsvNewFromEmptyString();
  if (!var) { // out of memory
    return 0;
  }

  //jsvAppendStringVar(var, lex->sourceVar, charFrom->it->index, (int)(charTo-charFrom));
  size_t maxLength = charTo - jsvStringIteratorGetIndex(&charFrom->it);
  JsVar *block = jsvLockAgain(var);
  block->varData.str[0] = charFrom->currCh;
  size_t blockChars = 1;

  // now start appending
  JsvStringIterator it = jsvStringIteratorClone(&charFrom->it);
  while (jsvStringIteratorHasChar(&it) && (maxLength-->0)) {
    char ch = jsvStringIteratorGetChar(&it);
    if (blockChars >= jsvGetMaxCharactersInVar(block)) {
      jsvSetCharactersInVar(block, blockChars);
      JsVar *next = jsvNewWithFlags(JSV_STRING_EXT);
      if (!next) break; // out of memory
      // we don't ref, because  StringExts are never reffed as they only have one owner (and ALWAYS have an owner)
      block->lastChild = jsvGetRef(next);
      jsvUnLock(block);
      block = next;
      blockChars=0; // it's new, so empty
    }
    block->varData.str[blockChars++] = ch;
    jsvStringIteratorNext(&it);
  }
  jsvStringIteratorFree(&it);
  jsvSetCharactersInVar(block, blockChars);
  jsvUnLock(block);

  return var;
}
예제 #16
0
/*JSON{
  "type" : "method",
  "class" : "String",
  "name" : "toUpperCase",
  "generate_full" : "jswrap_string_toUpperLowerCase(parent, true)",
  "params" : [
    
  ],
  "return" : ["JsVar","The uppercase version of this string"]
}*/
JsVar *jswrap_string_toUpperLowerCase(JsVar *parent, bool upper) {
  JsVar *res = jsvNewFromEmptyString();
  if (!res) return 0; // out of memory

  JsvStringIterator itsrc, itdst;
  jsvStringIteratorNew(&itsrc, parent, 0);
  jsvStringIteratorNew(&itdst, res, 0);

  while (jsvStringIteratorHasChar(&itsrc)) {
    char ch = jsvStringIteratorGetChar(&itsrc);
    if (upper) {
      if (ch >= 97 && ch <= 122) ch = (char)(ch - 32);
    } else {
      if (ch >= 65 && ch <= 90) ch = (char)(ch + 32); // A-Z
    }
    jsvStringIteratorAppend(&itdst, ch);
    jsvStringIteratorNext(&itsrc);
  }

  jsvStringIteratorFree(&itsrc);
  jsvStringIteratorFree(&itdst);

  return res;
}
예제 #17
0
// httpParseHeaders(&receiveData, reqVar, true) // server
// httpParseHeaders(&receiveData, resVar, false) // client
bool httpParseHeaders(JsVar **receiveData, JsVar *objectForData, bool isServer) {
    // find /r/n/r/n
    int newlineIdx = 0;
    int strIdx = 0;
    int headerEnd = -1;
    JsvStringIterator it;
    jsvStringIteratorNew(&it, *receiveData, 0);
    while (jsvStringIteratorHasChar(&it)) {
        char ch = jsvStringIteratorGetChar(&it);
        if (ch == '\r') {
            if (newlineIdx==0) newlineIdx=1;
            else if (newlineIdx==2) newlineIdx=3;
        } else if (ch == '\n') {
            if (newlineIdx==1) newlineIdx=2;
            else if (newlineIdx==3) {
                headerEnd = strIdx+1;
                break;
            }
        } else newlineIdx=0;
        jsvStringIteratorNext(&it);
        strIdx++;
    }
    jsvStringIteratorFree(&it);
    // skip if we have no header
    if (headerEnd<0) return false;
    // Now parse the header
    JsVar *vHeaders = jsvNewObject();
    if (!vHeaders) return true;
    jsvUnLock(jsvAddNamedChild(objectForData, vHeaders, "headers"));
    strIdx = 0;
    int firstSpace = -1;
    int secondSpace = -1;
    int firstEOL = -1;
    int lineNumber = 0;
    int lastLineStart = 0;
    int colonPos = 0;
    //jsiConsolePrintStringVar(receiveData);
    jsvStringIteratorNew(&it, *receiveData, 0);
    while (jsvStringIteratorHasChar(&it)) {
        char ch = jsvStringIteratorGetChar(&it);
        if (ch==' ' || ch=='\r') {
            if (firstSpace<0) firstSpace = strIdx;
            else if (secondSpace<0) secondSpace = strIdx;
        }
        if (ch == ':' && colonPos<0) colonPos = strIdx;
        if (ch == '\r') {
            if (firstEOL<0) firstEOL=strIdx;
            if (lineNumber>0 && colonPos>lastLineStart && lastLineStart<strIdx) {
                JsVar *hVal = jsvNewFromEmptyString();
                if (hVal)
                    jsvAppendStringVar(hVal, *receiveData, (size_t)colonPos+2, (size_t)(strIdx-(colonPos+2)));
                JsVar *hKey = jsvNewFromEmptyString();
                if (hKey) {
                    jsvMakeIntoVariableName(hKey, hVal);
                    jsvAppendStringVar(hKey, *receiveData, (size_t)lastLineStart, (size_t)(colonPos-lastLineStart));
                    jsvAddName(vHeaders, hKey);
                    jsvUnLock(hKey);
                }
                jsvUnLock(hVal);
            }
            lineNumber++;
            colonPos=-1;
        }
        if (ch == '\r' || ch == '\n') {
            lastLineStart = strIdx+1;
        }

        jsvStringIteratorNext(&it);
        strIdx++;
    }
    jsvStringIteratorFree(&it);
    jsvUnLock(vHeaders);
    // try and pull out methods/etc
    if (isServer) {
        jsvObjectSetChildAndUnLock(objectForData, "method", jsvNewFromStringVar(*receiveData, 0, (size_t)firstSpace));
        jsvObjectSetChildAndUnLock(objectForData, "url", jsvNewFromStringVar(*receiveData, (size_t)(firstSpace+1), (size_t)(secondSpace-(firstSpace+1))));
    } else {
        jsvObjectSetChildAndUnLock(objectForData, "httpVersion", jsvNewFromStringVar(*receiveData, 5, (size_t)firstSpace-5));
        jsvObjectSetChildAndUnLock(objectForData, "statusCode", jsvNewFromStringVar(*receiveData, (size_t)(firstSpace+1), (size_t)(secondSpace-(firstSpace+1))));
        jsvObjectSetChildAndUnLock(objectForData, "statusMessage", jsvNewFromStringVar(*receiveData, (size_t)(secondSpace+1), (size_t)(firstEOL-(secondSpace+1))));
    }
    // strip out the header
    JsVar *afterHeaders = jsvNewFromStringVar(*receiveData, (size_t)headerEnd, JSVAPPENDSTRINGVAR_MAXLENGTH);
    jsvUnLock(*receiveData);
    *receiveData = afterHeaders;
    return true;
}
예제 #18
0
/* This is like jsfGetJSONWithCallback, but handles ONLY functions (and does not print the initial 'function' text) */
void jsfGetJSONForFunctionWithCallback(JsVar *var, JSONFlags flags, vcbprintf_callback user_callback, void *user_data) {
  assert(jsvIsFunction(var));
  JsVar *codeVar = 0; // TODO: this should really be in jsvAsString

  JsvObjectIterator it;
  jsvObjectIteratorNew(&it, var);

  bool firstParm = true;
  cbprintf(user_callback, user_data, "(");
  while (jsvObjectIteratorHasValue(&it)) {
    JsVar *child = jsvObjectIteratorGetKey(&it);
    if (jsvIsFunctionParameter(child)) {
      if (firstParm)
        firstParm=false;
      else
        cbprintf(user_callback, user_data, ",");
      JsVar *name = jsvNewFromStringVar(child, 1, JSVAPPENDSTRINGVAR_MAXLENGTH);
      cbprintf(user_callback, user_data, "%v", name);
      jsvUnLock(name);
    } else if (jsvIsString(child) && jsvIsStringEqual(child, JSPARSE_FUNCTION_CODE_NAME)) {
      codeVar = jsvObjectIteratorGetValue(&it);
    }
    jsvUnLock(child);
    jsvObjectIteratorNext(&it);
  }
  jsvObjectIteratorFree(&it);
  cbprintf(user_callback, user_data, ") ");

  if (jsvIsNative(var)) {
    cbprintf(user_callback, user_data, "{ [native code] }");
  } else {
    if (codeVar) {
      if (flags & JSON_LIMIT) {
        cbprintf(user_callback, user_data, "{%s}", JSON_LIMIT_TEXT);
      } else {
        bool hasNewLine = jsvGetStringIndexOf(codeVar,'\n')>=0;
        user_callback(hasNewLine?"{\n  ":"{", user_data);
        if (jsvIsFunctionReturn(var))
          user_callback("return ", user_data);
        // reconstruct the tokenised output into something more readable
        char buf[32];
        unsigned char lastch = 0;
        JsvStringIterator it;
        jsvStringIteratorNew(&it, codeVar, 0);
        while (jsvStringIteratorHasChar(&it)) {
          unsigned char ch = (unsigned char)jsvStringIteratorGetChar(&it);
          if (jslNeedSpaceBetween(lastch, ch))
            user_callback(" ", user_data);
          jslFunctionCharAsString(ch, buf, sizeof(buf));
          user_callback(buf, user_data);
          jsvStringIteratorNext(&it);
          lastch = ch;
        }
        jsvStringIteratorFree(&it);

        user_callback(hasNewLine?"\n}":"}", user_data);
      }
    } else cbprintf(user_callback, user_data, "{}");
  }
  jsvUnLock(codeVar);
}
예제 #19
0
/*JSON{
  "type" : "method",
  "class" : "String",
  "name" : "replace",
  "generate" : "jswrap_string_replace",
  "params" : [
    ["subStr","JsVar","The string to search for"],
    ["newSubStr","JsVar","The string to replace it with"]
  ],
  "return" : ["JsVar","This string with `subStr` replaced"]
}
Search and replace ONE occurrance of `subStr` with `newSubStr` and return the result. This doesn't alter the original string. Regular expressions not supported.
 */
JsVar *jswrap_string_replace(JsVar *parent, JsVar *subStr, JsVar *newSubStr) {
  JsVar *str = jsvAsString(parent);
#ifndef SAVE_ON_FLASH
  // Use RegExp if one is passed in
  if (jsvIsInstanceOf(subStr, "RegExp")) {
    JsVar *replace;
    if (jsvIsFunction(newSubStr) || jsvIsString(newSubStr))
      replace = jsvLockAgain(newSubStr);
    else
      replace = jsvAsString(newSubStr);
    jsvObjectSetChildAndUnLock(subStr, "lastIndex", jsvNewFromInteger(0));
    bool global = jswrap_regexp_hasFlag(subStr,'g');
    JsVar *match;
    match = jswrap_regexp_exec(subStr, str);
    while (match && !jsvIsNull(match) && !jspIsInterrupted()) {
      // get info about match
      JsVar *matchStr = jsvGetArrayItem(match,0);
      JsVarInt idx = jsvGetIntegerAndUnLock(jsvObjectGetChild(match,"index",0));
      JsVarInt len = (JsVarInt)jsvGetStringLength(matchStr);
      // do the replacement
      JsVar *newStr = jsvNewFromStringVar(str, 0, (size_t)idx);
      JsvStringIterator dst;
      jsvStringIteratorNew(&dst, newStr, 0);
      jsvStringIteratorGotoEnd(&dst);
      if (jsvIsFunction(replace)) {
        unsigned int argCount = 0;
        JsVar *args[13];
        args[argCount++] = jsvLockAgain(matchStr);
        JsVar *v;
        while ((v = jsvGetArrayItem(match, (JsVarInt)argCount)))
          args[argCount++] = v;
        args[argCount++] = jsvObjectGetChild(match,"index",0);
        args[argCount++] = jsvObjectGetChild(match,"input",0);
        JsVar *result = jsvAsStringAndUnLock(jspeFunctionCall(replace, 0, 0, false, (JsVarInt)argCount, args));
        jsvUnLockMany(argCount, args);
        jsvStringIteratorAppendString(&dst, result, 0);
        jsvUnLock(result);
      } else {
        JsvStringIterator src;
        jsvStringIteratorNew(&src, replace, 0);
        while (jsvStringIteratorHasChar(&src)) {
          char ch = jsvStringIteratorGetChar(&src);
          if (ch=='$') {
            jsvStringIteratorNext(&src);
            ch = jsvStringIteratorGetChar(&src);
            JsVar *group = 0;
            if (ch>'0' && ch<='9')
              group = jsvGetArrayItem(match, ch-'0');
            if (group) {
              jsvStringIteratorAppendString(&dst, group, 0);
              jsvUnLock(group);
            } else {
              jsvStringIteratorAppend(&dst, '$');
              jsvStringIteratorAppend(&dst, ch);
            }
          } else {
            jsvStringIteratorAppend(&dst, ch);
          }
          jsvStringIteratorNext(&src);
        }
        jsvStringIteratorFree(&src);
      }
      JsVarInt lastIndex = 1+(JsVarInt)jsvStringIteratorGetIndex(&dst);
      jsvStringIteratorAppendString(&dst, str, (size_t)(idx+len));
      jsvStringIteratorFree(&dst);
      jsvUnLock2(str,matchStr);
      str = newStr;
      // search again if global
      jsvUnLock(match);
      match = 0;
      if (global) {
        jsvObjectSetChildAndUnLock(subStr, "lastIndex", jsvNewFromInteger(lastIndex));
        match = jswrap_regexp_exec(subStr, str);
      }
    }
    jsvUnLock(match);
    jsvUnLock(replace);
    // reset lastIndex if global
    if (global)
      jsvObjectSetChildAndUnLock(subStr, "lastIndex", jsvNewFromInteger(0));
    return str;
  }
#endif

  newSubStr = jsvAsString(newSubStr);
  subStr = jsvAsString(subStr);


  int idx = jswrap_string_indexOf(parent, subStr, 0, false);
  if (idx>=0) {
    JsVar *newStr = jsvNewFromStringVar(str, 0, (size_t)idx);
    jsvAppendStringVar(newStr, newSubStr, 0, JSVAPPENDSTRINGVAR_MAXLENGTH);
    jsvAppendStringVar(newStr, str, (size_t)idx+jsvGetStringLength(subStr), JSVAPPENDSTRINGVAR_MAXLENGTH);
    jsvUnLock(str);
    str = newStr;
  }

  jsvUnLock2(subStr, newSubStr);
  return str;
}
예제 #20
0
/* matchhere: search for regexp at beginning of text. Only handles up to '|' character. Modifies txtIt */
static JsVar *matchhere(char *regexp, JsvStringIterator *txtIt, matchInfo info) {
  if (jspIsInterrupted()) return 0;
  if (regexp[0] == '\0' || // end of regex
      regexp[0] == '|') // end of this 'or' section of regex
    return matchfound(txtIt, info);
  if (regexp[0] == '^') { // must be beginning of String
    if (jsvStringIteratorGetIndex(txtIt)!=0)
      return 0; // no match
    if (!jspCheckStackPosition()) return 0;
    return matchhere(regexp+1, txtIt, info);
  }
  // Marker for end of String
  if (regexp[0] == '$') {
    if (!jsvStringIteratorHasChar(txtIt))
      return matchhere(regexp+1, txtIt, info);
    else
      return nomatchfound(regexp+1, info); // not the end, it's a fail
  }
  if (regexp[0] == '(') {
    info.groupStart[info.groups] = jsvStringIteratorGetIndex(txtIt);
    info.groupEnd[info.groups] = info.groupStart[info.groups];
    if (info.groups<MAX_GROUPS) info.groups++;
    if (!jspCheckStackPosition()) return 0;
    return matchhere(regexp+1, txtIt, info);
  }
  if (regexp[0] == ')') {
    if (info.groups>0)
      info.groupEnd[info.groups-1] = jsvStringIteratorGetIndex(txtIt);
    if (!jspCheckStackPosition()) return 0;
    return matchhere(regexp+1, txtIt, info);
  }
  int charLength;
  bool charMatched = matchcharacter(regexp, txtIt, &charLength, &info);
  if (regexp[charLength] == '*' || regexp[charLength] == '+') {
    char op = regexp[charLength];
    if (!charMatched && op=='+') {
      // with '+' operator it has to match at least once
      return nomatchfound(&regexp[charLength+1], info);
    }
    char *regexpAfterStar = regexp+charLength+1;
    JsvStringIterator txtIt2;
    // Try and match everything after right now
    txtIt2 = jsvStringIteratorClone(txtIt);
    JsVar *lastrmatch = matchhere(regexpAfterStar, &txtIt2, info);
    jsvStringIteratorFree(&txtIt2);
    // Otherwise try and match more than one
    while (jsvStringIteratorHasChar(txtIt) && charMatched) {
      // We had this character matched, so move on and see if we can match with the new one
      jsvStringIteratorNext(txtIt);
      charMatched = matchcharacter(regexp, txtIt, &charLength, &info);
      // See if we can match after the character...
      txtIt2 = jsvStringIteratorClone(txtIt);
      JsVar *rmatch = matchhere(regexpAfterStar, &txtIt2, info);
      jsvStringIteratorFree(&txtIt2);
      // can't match with this - use the last one
      if (rmatch) {
        jsvUnLock(lastrmatch);
        lastrmatch = rmatch;
      }
    }
    return lastrmatch;
  }

  // This character is matched
  if (jsvStringIteratorHasChar(txtIt) && charMatched) {
    jsvStringIteratorNext(txtIt);
    if (!jspCheckStackPosition()) return 0;
    return matchhere(regexp+charLength, txtIt, info);
  }
  // No match
  return nomatchfound(&regexp[charLength], info);
}
예제 #21
0
파일: jswrap_net.c 프로젝트: Yzzl/Espruino
/*JSON{
  "type" : "staticmethod",
  "class" : "url",
  "name" : "parse",
  "generate" : "jswrap_url_parse",
  "params" : [
    ["urlStr","JsVar","A URL to be parsed"],
    ["parseQuery","bool","Whether to parse the query string into an object not (default = false)"]
  ],
  "return" : ["JsVar","An object containing options for ```http.request``` or ```http.get```. Contains `method`, `host`, `path`, `pathname`, `search`, `port` and `query`"]
}
A utility function to split a URL into parts

This is useful in web servers for instance when handling a request.

For instance `url.parse("/a?b=c&d=e",true)` returns `{"method":"GET","host":"","path":"/a?b=c&d=e","pathname":"/a","search":"?b=c&d=e","port":80,"query":{"b":"c","d":"e"}}`
*/
JsVar *jswrap_url_parse(JsVar *url, bool parseQuery) {
  if (!jsvIsString(url)) return 0;
  JsVar *obj = jsvNewWithFlags(JSV_OBJECT);
  if (!obj) return 0; // out of memory

  // scan string to try and pick stuff out
  JsvStringIterator it;
  jsvStringIteratorNew(&it, url, 0);
  int slashes = 0;
  int colons = 0;
  int addrStart = -1;
  int portStart = -1;
  int pathStart = -1;
  int searchStart = -1;
  int charIdx = 0;
  int portNumber = 0;
  while (jsvStringIteratorHasChar(&it)) {
    char ch = jsvStringIteratorGetChar(&it);
    if (ch == '/') {
      slashes++;
      if (pathStart<0) pathStart = charIdx;
      if (colons==1 && slashes==2 && addrStart<0) {
        addrStart = charIdx;
        pathStart = -1;
        searchStart = -1;
      }
    }
    if (ch == ':') {
      colons++;
      if (addrStart>=0 && pathStart<0)
        portStart = charIdx;
    }

    if (portStart>=0 && charIdx>portStart && pathStart<0 && ch >= '0' && ch <= '9') {
      portNumber = portNumber*10 + (ch-'0');
    }

    if (ch == '?' && pathStart>=0) {
      searchStart = charIdx;
    }

    jsvStringIteratorNext(&it);
    charIdx++;
  }
  jsvStringIteratorFree(&it);
  // try and sort stuff out
  if (pathStart<0) pathStart = charIdx;
  if (pathStart<0) pathStart = charIdx;
  int addrEnd = (portStart>=0) ? portStart : pathStart;
  // pull out details
  if (addrStart>0)
    jsvObjectSetChildAndUnLock(obj, "protocol", jsvNewFromStringVar(url, 0, (size_t)addrStart-1));
  jsvObjectSetChildAndUnLock(obj, "method", jsvNewFromString("GET"));
  jsvObjectSetChildAndUnLock(obj, "host", jsvNewFromStringVar(url, (size_t)(addrStart+1), (size_t)(addrEnd-(addrStart+1))));

  JsVar *v;

  v = jsvNewFromStringVar(url, (size_t)pathStart, JSVAPPENDSTRINGVAR_MAXLENGTH);
  if (jsvGetStringLength(v)==0) jsvAppendString(v, "/");
  jsvObjectSetChildAndUnLock(obj, "path", v);

  v = jsvNewFromStringVar(url, (size_t)pathStart, (size_t)((searchStart>=0)?(searchStart-pathStart):JSVAPPENDSTRINGVAR_MAXLENGTH));
  if (jsvGetStringLength(v)==0) jsvAppendString(v, "/");
  jsvObjectSetChildAndUnLock(obj, "pathname", v);

  jsvObjectSetChildAndUnLock(obj, "search", (searchStart>=0)?jsvNewFromStringVar(url, (size_t)searchStart, JSVAPPENDSTRINGVAR_MAXLENGTH):jsvNewNull());

  jsvObjectSetChildAndUnLock(obj, "port", (portNumber<=0 || portNumber>65535) ? jsvNewWithFlags(JSV_NULL) : jsvNewFromInteger(portNumber));

  JsVar *query = (searchStart>=0)?jsvNewFromStringVar(url, (size_t)(searchStart+1), JSVAPPENDSTRINGVAR_MAXLENGTH):jsvNewNull();
  if (parseQuery && !jsvIsNull(query)) {
    JsVar *queryStr = query;
    jsvStringIteratorNew(&it, query, 0);
    query = jsvNewWithFlags(JSV_OBJECT);

    JsVar *key = jsvNewFromEmptyString();
    JsVar *val = jsvNewFromEmptyString();
    bool hadEquals = false;

    while (jsvStringIteratorHasChar(&it)) {
      char ch = jsvStringIteratorGetChar(&it);
      if (ch=='&') {
        if (jsvGetStringLength(key)>0 || jsvGetStringLength(val)>0) {
          key = jsvAsArrayIndexAndUnLock(key); // make sure "0" gets made into 0
          jsvMakeIntoVariableName(key, val);
          jsvAddName(query, key);
          jsvUnLock2(key, val);
          key = jsvNewFromEmptyString();
          val = jsvNewFromEmptyString();
          hadEquals = false;
        }
      } else if (!hadEquals && ch=='=') {
        hadEquals = true;
      } else {
        // decode percent escape chars
        if (ch=='%') {
          jsvStringIteratorNext(&it);
          ch = jsvStringIteratorGetChar(&it);
          jsvStringIteratorNext(&it);
          ch = (char)((chtod(ch)<<4) | chtod(jsvStringIteratorGetChar(&it)));
        }

        if (hadEquals) jsvAppendCharacter(val, ch);
        else jsvAppendCharacter(key, ch);
      }
      jsvStringIteratorNext(&it);
      charIdx++;
    }
    jsvStringIteratorFree(&it);
    jsvUnLock(queryStr);

    if (jsvGetStringLength(key)>0 || jsvGetStringLength(val)>0) {
      key = jsvAsArrayIndexAndUnLock(key); // make sure "0" gets made into 0
      jsvMakeIntoVariableName(key, val);
      jsvAddName(query, key);
    }
    jsvUnLock2(key, val);
  }
  jsvObjectSetChildAndUnLock(obj, "query", query);

  return obj;
}
예제 #22
0
파일: jswrap_fat.c 프로젝트: jbkim/Espruino
JsVar *wrap_fat_readdir(JsVar *path) {
  JsVar *arr = 0; // undefined unless we can open card

  char pathStr[JS_DIR_BUF_SIZE] = "";
  if (!jsvIsUndefined(path))
    jsvGetString(path, pathStr, JS_DIR_BUF_SIZE);
#ifdef LINUX
  if (!pathStr[0]) strcpy(pathStr, "."); // deal with empty readdir
#endif

  FRESULT res = 0;
  if (jsfsInit()) {
#ifndef LINUX
    DIR dirs;
    if ((res=f_opendir(&dirs, pathStr)) == FR_OK) {
      char lfnBuf[_MAX_LFN+1];
      FILINFO Finfo;
      Finfo.lfname = lfnBuf;
      Finfo.lfsize = sizeof(lfnBuf);
#else
    DIR *dir = opendir(pathStr);
    if(dir) {
#endif
      arr = jsvNewWithFlags(JSV_ARRAY);
      if (arr) { // could be out of memory
#ifndef LINUX
        while (((res=f_readdir(&dirs, &Finfo)) == FR_OK) && Finfo.fname[0]) {
          char *fn = GET_FILENAME(Finfo);
#else
        struct dirent *pDir=NULL;
        while((pDir = readdir(dir)) != NULL) {
          char *fn = (*pDir).d_name;
#endif
          JsVar *fnVar = jsvNewFromString(fn);
          if (fnVar) // out of memory?
            jsvArrayPush(arr, fnVar);
        }
      }
#ifdef LINUX
      closedir(dir);
#endif
    }
  }
  if (res) jsfsReportError("Unable to list files", res);
  return arr;
}

/*JSON{  "type" : "staticmethod", "class" : "fs", "name" : "writeFile",
         "generate" : "wrap_fat_writeFile",
         "description" : [ "Write the data to the given file", "NOTE: Espruino does not yet support Async file IO, so this function behaves like the 'Sync' version." ],
         "params" : [ [ "path", "JsVar", "The path of the file to write" ],
                      [ "data", "JsVar", "The data to write to the file" ] ]
}*/
/*JSON{  "type" : "staticmethod", "class" : "fs", "name" : "writeFileSync", "ifndef" : "SAVE_ON_FLASH",
         "generate" : "wrap_fat_writeFile",
         "description" : [ "Write the data to the given file" ],
         "params" : [ [ "path", "JsVar", "The path of the file to write" ],
                      [ "data", "JsVar", "The data to write to the file" ] ]
}*/
/*JSON{  "type" : "staticmethod", "class" : "fs", "name" : "appendFile",
         "generate" : "wrap_fat_appendFile",
         "description" : [ "Append the data to the given file, created a new file if it doesn't exist", "NOTE: Espruino does not yet support Async file IO, so this function behaves like the 'Sync' version." ],
         "params" : [ [ "path", "JsVar", "The path of the file to write" ],
                      [ "data", "JsVar", "The data to write to the file" ] ]
}*/
/*JSON{  "type" : "staticmethod", "class" : "fs", "name" : "appendFileSync", "ifndef" : "SAVE_ON_FLASH",
         "generate" : "wrap_fat_appendFile",
         "description" : [ "Append the data to the given file, created a new file if it doesn't exist" ],
         "params" : [ [ "path", "JsVar", "The path of the file to write" ],
                      [ "data", "JsVar", "The data to write to the file" ] ]
}*/
void wrap_fat_writeOrAppendFile(JsVar *path, JsVar *data, bool append) {
  char pathStr[JS_DIR_BUF_SIZE] = "";
  if (!jsvIsUndefined(path))
    jsvGetString(path, pathStr, JS_DIR_BUF_SIZE);

  FRESULT res = 0;
  if (jsfsInit()) {
#ifndef LINUX
    FIL file;

    if ((res=f_open(&file, pathStr, FA_WRITE|(append ? FA_OPEN_ALWAYS : FA_CREATE_ALWAYS))) == FR_OK) {

      if (append) {
        // move to end of file to append data
        f_lseek(&file, file.fsize);
//        if (res != FR_OK) jsfsReportError("Unable to move to end of file", res);
      }
#else
      FILE *file = fopen(pathStr, append?"a":"w");
      if (file) {
#endif

      JsvStringIterator it;
      JsVar *dataString = jsvAsString(data, false);
      jsvStringIteratorNew(&it, dataString, 0);
      size_t toWrite = 0;
      size_t written = 0;

      while (jsvStringIteratorHasChar(&it) && res==FR_OK && written==toWrite) {

        // re-use pathStr buffer
        toWrite = 0;
        while (jsvStringIteratorHasChar(&it) && toWrite < JS_DIR_BUF_SIZE) {
          pathStr[toWrite++] = jsvStringIteratorGetChar(&it);
          jsvStringIteratorNext(&it);
        }
#ifndef LINUX
        res = f_write(&file, pathStr, toWrite, &written);
#else
        written = fwrite(pathStr, 1, toWrite, file);
#endif
      }
      jsvStringIteratorFree(&it);
      jsvUnLock(dataString);
#ifndef LINUX
      f_close(&file);
#else
      fclose(file);
#endif
    }
  }
  if (res) jsfsReportError("Unable to write file", res);
}
void wrap_fat_writeFile(JsVar *path, JsVar *data) {
  wrap_fat_writeOrAppendFile(path, data, false);
}
void wrap_fat_appendFile(JsVar *path, JsVar *data) {
  wrap_fat_writeOrAppendFile(path, data, true);
}
예제 #23
0
bool httpParseHeaders(JsVar **receiveData, JsVar *objectForData, bool isServer) {
  // find /r/n/r/n
  int newlineIdx = 0;
  int strIdx = 0;
  int headerEnd = -1;
  JsvStringIterator it;
  jsvStringIteratorNew(&it, *receiveData, 0);
  while (jsvStringIteratorHasChar(&it)) {
    char ch = jsvStringIteratorGetChar(&it);
    if (ch == '\r') {
      if (newlineIdx==0) newlineIdx=1;
      else if (newlineIdx==2) newlineIdx=3;
    } else if (ch == '\n') {
      if (newlineIdx==1) newlineIdx=2;
      else if (newlineIdx==3) {
        headerEnd = strIdx+1;
      }
    } else newlineIdx=0;
    jsvStringIteratorNext(&it);
    strIdx++;
  }
  jsvStringIteratorFree(&it);
  // skip if we have no header
  if (headerEnd<0) return false;
  // Now parse the header
  JsVar *vHeaders = jsvNewWithFlags(JSV_OBJECT);
  if (!vHeaders) return true;
  jsvUnLock(jsvAddNamedChild(objectForData, vHeaders, "headers"));
  strIdx = 0;
  int firstSpace = -1;
  int secondSpace = -1;
  int lineNumber = 0;
  int lastLineStart = 0;
  int colonPos = 0;
  //jsiConsolePrintStringVar(receiveData);
  jsvStringIteratorNew(&it, *receiveData, 0);
    while (jsvStringIteratorHasChar(&it)) {
      char ch = jsvStringIteratorGetChar(&it);
      if (ch==' ' || ch=='\r') {
        if (firstSpace<0) firstSpace = strIdx;
        else if (secondSpace<0) secondSpace = strIdx;
      }
      if (ch == ':' && colonPos<0) colonPos = strIdx;
      if (ch == '\r') {
        if (lineNumber>0 && colonPos>lastLineStart && lastLineStart<strIdx) {
          JsVar *hVal = jsvNewFromEmptyString();
          if (hVal)
            jsvAppendStringVar(hVal, *receiveData, colonPos+2, strIdx-(colonPos+2));
          JsVar *hKey = jsvNewFromEmptyString();
          if (hKey) {
            jsvMakeIntoVariableName(hKey, hVal);
            jsvAppendStringVar(hKey, *receiveData, lastLineStart, colonPos-lastLineStart);
            jsvAddName(vHeaders, hKey);
            jsvUnLock(hKey);
          }
          jsvUnLock(hVal);
        }
        lineNumber++;
        colonPos=-1;
      }
      if (ch == '\r' || ch == '\n') {
        lastLineStart = strIdx+1;
      }

      jsvStringIteratorNext(&it);
      strIdx++;
    }
    jsvStringIteratorFree(&it);
  jsvUnLock(vHeaders);
  // try and pull out methods/etc
  if (isServer) {
    JsVar *vMethod = jsvNewFromEmptyString();
    if (vMethod) {
      jsvAppendStringVar(vMethod, *receiveData, 0, firstSpace);
      jsvUnLock(jsvAddNamedChild(objectForData, vMethod, "method"));
      jsvUnLock(vMethod);
    }
    JsVar *vUrl = jsvNewFromEmptyString();
    if (vUrl) {
      jsvAppendStringVar(vUrl, *receiveData, firstSpace+1, secondSpace-(firstSpace+1));
      jsvUnLock(jsvAddNamedChild(objectForData, vUrl, "url"));
      jsvUnLock(vUrl);
    }
  }
  // strip out the header
  JsVar *afterHeaders = jsvNewFromEmptyString();
  if (!afterHeaders) return true;
  jsvAppendStringVar(afterHeaders, *receiveData, headerEnd, JSVAPPENDSTRINGVAR_MAXLENGTH);
  jsvUnLock(*receiveData);
  *receiveData = afterHeaders;
  return true;
}
예제 #24
0
void jsvStringIteratorSetChar(JsvStringIterator *it, char c) {
  if (jsvStringIteratorHasChar(it))
    it->ptr[it->charIdx] = c;
}
예제 #25
0
void jsvStringIteratorSetCharAndNext(JsvStringIterator *it, char c) {
  if (jsvStringIteratorHasChar(it))
    it->ptr[it->charIdx] = c;
  jsvStringIteratorNextInline(it);
}
예제 #26
0
/**
 * \brief Iterate over the contents of the content of a variable, calling callback for each.
 * Contents may be:
 * * numeric -> output
 * * a string -> output each character
 * * array/arraybuffer -> call itself on each element
 * object -> call itself object.count times, on object.data
 */
bool jsvIterateCallback(
    JsVar *data,                                    // The data to iterate over.
	void (*callback)(int item, void *callbackData), // The callback function invoke.
	void *callbackData                              // Data to be passed to the callback function
  ) {
  bool ok = true;
  // Handle the data being a single numeric.
  if (jsvIsNumeric(data)) {
    callback((int)jsvGetInteger(data), callbackData);
  }
  // Handle the data being an object.
  else if (jsvIsObject(data)) {
    JsVar *countVar = jsvObjectGetChild(data, "count", 0);
    JsVar *dataVar = jsvObjectGetChild(data, "data", 0);
    if (countVar && dataVar && jsvIsNumeric(countVar)) {
      int n = (int)jsvGetInteger(countVar);
      while (ok && n-- > 0) {
        ok = jsvIterateCallback(dataVar, callback, callbackData);
      }
    } else {
      jsWarn("If specifying an object, it must be of the form {data : ..., count : N}");
    }
    jsvUnLock2(countVar, dataVar);
  }
  // Handle the data being a string
  else if (jsvIsString(data)) {
    JsvStringIterator it;
    jsvStringIteratorNew(&it, data, 0);
    while (jsvStringIteratorHasChar(&it) && ok) {
      char ch = jsvStringIteratorGetChar(&it);
      callback(ch, callbackData);
      jsvStringIteratorNext(&it);
    }
    jsvStringIteratorFree(&it);
  }
  // Handle the data being an array buffer
  else if (jsvIsArrayBuffer(data)) {
    JsvArrayBufferIterator it;
    jsvArrayBufferIteratorNew(&it, data, 0);
    if (JSV_ARRAYBUFFER_GET_SIZE(it.type) == 1 && !JSV_ARRAYBUFFER_IS_SIGNED(it.type)) {
      // faster for single byte arrays.
      while (jsvArrayBufferIteratorHasElement(&it)) {
        callback((int)(unsigned char)jsvStringIteratorGetChar(&it.it), callbackData);
        jsvArrayBufferIteratorNext(&it);
      }
    } else {
      while (jsvArrayBufferIteratorHasElement(&it)) {
        callback((int)jsvArrayBufferIteratorGetIntegerValue(&it), callbackData);
        jsvArrayBufferIteratorNext(&it);
      }
    }
    jsvArrayBufferIteratorFree(&it);
  }
  // Handle the data being iterable
  else if (jsvIsIterable(data)) {
    JsvIterator it;
    jsvIteratorNew(&it, data);
    while (jsvIteratorHasElement(&it) && ok) {
      JsVar *el = jsvIteratorGetValue(&it);
      ok = jsvIterateCallback(el, callback, callbackData);
      jsvUnLock(el);
      jsvIteratorNext(&it);
    }
    jsvIteratorFree(&it);
  } else {
    jsWarn("Expecting a number or something iterable, got %t", data);
    ok = false;
  }
  return ok;
}
예제 #27
0
JsVar *jswrap_spi_send(JsVar *parent, JsVar *srcdata, Pin nss_pin) {
  NOT_USED(parent);
  IOEventFlags device = jsiGetDeviceFromClass(parent);

  jswrap_spi_send_data data;
  if (!jsspiGetSendFunction(parent, &data.spiSend, &data.spiSendData))
    return 0;

  JsVar *dst = 0;

  // we're sending and receiving
  if (DEVICE_IS_SPI(device)) jshSPISetReceive(device, true);

  // assert NSS
  if (nss_pin!=PIN_UNDEFINED) jshPinOutput(nss_pin, false);

  // send data
  if (jsvIsNumeric(srcdata)) {
    int r = data.spiSend((unsigned char)jsvGetInteger(srcdata), &data.spiSendData);
    if (r<0) r = data.spiSend(-1, &data.spiSendData);
    dst = jsvNewFromInteger(r); // retrieve the byte (no send!)
  } else if (jsvIsString(srcdata)) {
    dst = jsvNewFromEmptyString();
    JsvStringIterator it;
    jsvStringIteratorNew(&it, srcdata, 0);
    int incount = 0, outcount = 0;
    while (jsvStringIteratorHasChar(&it) && !jspIsInterrupted()) {
      unsigned char in = (unsigned char)jsvStringIteratorGetChar(&it);
      incount++;
      int out = data.spiSend(in, &data.spiSendData);
      if (out>=0) {
        outcount++;
        char outc = (char)out;
        jsvAppendStringBuf(dst, (char*)&outc, 1);
      }
      jsvStringIteratorNext(&it);
    }
    jsvStringIteratorFree(&it);
    // finally add the remaining bytes  (no send!)
    while (outcount < incount && !jspIsInterrupted()) {
      outcount++;
      unsigned char out = (unsigned char)data.spiSend(-1, &data.spiSendData);
      jsvAppendStringBuf(dst, (char*)&out, 1);
    }
  } else {
    int nBytes = jsvIterateCallbackCount(srcdata);
    dst = jsvNewTypedArray(ARRAYBUFFERVIEW_UINT8, nBytes);
    if (dst) {
      data.rxAmt = data.txAmt = 0;
      jsvArrayBufferIteratorNew(&data.it, dst, 0);
      // Write data
      jsvIterateCallback(srcdata, (void (*)(int,  void *))jswrap_spi_send_cb, &data);
      // Wait until SPI send is finished, and flush data
      while (data.rxAmt < data.txAmt && !jspIsInterrupted())
        jswrap_spi_send_cb(-1, &data);
      jsvArrayBufferIteratorFree(&data.it);
    }
  }

  // de-assert NSS
  if (nss_pin!=PIN_UNDEFINED) jshPinOutput(nss_pin, true);
  return dst;
}
예제 #28
0
/**
 * Send data through SPI.
 * The data can be in a variety of formats including:
 * * `numeric` - A single byte is transmitted.
 * * `string` - Each character in the string is transmitted.
 * * `iterable` - An iterable object is transmitted.
 * \return the Received bytes (MISO).  This is byte array.
 */
JsVar *jswrap_spi_send(
    JsVar *parent,  //!< A description of the SPI device to send data through.
    JsVar *srcdata, //!< The data to send through SPI.
    Pin    nss_pin  //!< The pin to toggle low then high (CS)
  ) {
  // Debug
  // jsiConsolePrintf("jswrap_spi_send called: parent=%j, srcdata=%j, nss_pin=%p\n", parent, srcdata, nss_pin);
  NOT_USED(parent);
  IOEventFlags device = jsiGetDeviceFromClass(parent);

  jswrap_spi_send_data data;
  if (!jsspiGetSendFunction(parent, &data.spiSend, &data.spiSendData))
    return 0;

  JsVar *dst = 0;

  // we're sending and receiving
  if (DEVICE_IS_SPI(device)) jshSPISetReceive(device, true);

  // assert NSS
  if (nss_pin!=PIN_UNDEFINED) jshPinOutput(nss_pin, false);

  // Now that we are setup, we can send the data.

  // Handle the data being a single byte value
  if (jsvIsNumeric(srcdata)) {
    int r = data.spiSend((unsigned char)jsvGetInteger(srcdata), &data.spiSendData);
    if (r<0) r = data.spiSend(-1, &data.spiSendData);
    dst = jsvNewFromInteger(r); // retrieve the byte (no send!)
  }
  // Handle the data being a string
  else if (jsvIsString(srcdata)) {
    dst = jsvNewFromEmptyString();
    JsvStringIterator it;
    jsvStringIteratorNew(&it, srcdata, 0);
    int incount = 0, outcount = 0;
    while (jsvStringIteratorHasChar(&it) && !jspIsInterrupted()) {
      unsigned char in = (unsigned char)jsvStringIteratorGetChar(&it);
      incount++;
      int out = data.spiSend(in, &data.spiSendData);
      if (out>=0) {
        outcount++;
        char outc = (char)out;
        jsvAppendStringBuf(dst, (char*)&outc, 1);
      }
      jsvStringIteratorNext(&it);
    }
    jsvStringIteratorFree(&it);
    // finally add the remaining bytes  (no send!)
    while (outcount < incount && !jspIsInterrupted()) {
      outcount++;
      unsigned char out = (unsigned char)data.spiSend(-1, &data.spiSendData);
      jsvAppendStringBuf(dst, (char*)&out, 1);
    }
  }
  // Handle the data being an iterable.
  else {
    int nBytes = jsvIterateCallbackCount(srcdata);
    dst = jsvNewTypedArray(ARRAYBUFFERVIEW_UINT8, nBytes);
    if (dst) {
      data.rxAmt = data.txAmt = 0;
      jsvArrayBufferIteratorNew(&data.it, dst, 0);
      // Write data
      jsvIterateCallback(srcdata, (void (*)(int,  void *))jswrap_spi_send_cb, &data);
      // Wait until SPI send is finished, and flush data
      while (data.rxAmt < data.txAmt && !jspIsInterrupted())
        jswrap_spi_send_cb(-1, &data);
      jsvArrayBufferIteratorFree(&data.it);
    }
  }

  // de-assert NSS
  if (nss_pin!=PIN_UNDEFINED) jshPinOutput(nss_pin, true);
  return dst;
}
예제 #29
0
/**
 Iterate over the contents of the content of a variable, calling callback for each.
 Contents may be:
 * numeric -> output
 * a string -> output each character
 * array/arraybuffer -> call itself on each element
 * {data:..., count:...} -> call itself object.count times, on object.data
 * {callback:...} -> call the given function, call itself on return value
 */
bool jsvIterateCallback(
    JsVar *data,
    jsvIterateCallbackFn callback,
    void *callbackData
  ) {
  bool ok = true;
  // Handle the data being a single numeric.
  if (jsvIsNumeric(data)) {
    callback((int)jsvGetInteger(data), callbackData);
  }
  // Handle the data being an object.
  else if (jsvIsObject(data)) {
    JsVar *callbackVar = jsvObjectGetChild(data, "callback", 0);
    if (jsvIsFunction(callbackVar)) {
      JsVar *result = jspExecuteFunction(callbackVar,0,0,NULL);
      jsvUnLock(callbackVar);
      if (result) {
        bool r = jsvIterateCallback(result, callback, callbackData);
        jsvUnLock(result);
        return r;
      }
      return true;
    }
    jsvUnLock(callbackVar);
    JsVar *countVar = jsvObjectGetChild(data, "count", 0);
    JsVar *dataVar = jsvObjectGetChild(data, "data", 0);
    if (countVar && dataVar && jsvIsNumeric(countVar)) {
      int n = (int)jsvGetInteger(countVar);
      while (ok && n-- > 0) {
        ok = jsvIterateCallback(dataVar, callback, callbackData);
      }
    } else {
      jsExceptionHere(JSET_TYPEERROR, "If specifying an object, it must be of the form {data : ..., count : N} or {callback : fn} - got %j", data);
      ok = false;
    }
    jsvUnLock2(countVar, dataVar);
  }
  // Handle the data being a string
  else if (jsvIsString(data)) {
    JsvStringIterator it;
    jsvStringIteratorNew(&it, data, 0);
    while (jsvStringIteratorHasChar(&it) && ok) {
      char ch = jsvStringIteratorGetChar(&it);
      callback(ch, callbackData);
      jsvStringIteratorNext(&it);
    }
    jsvStringIteratorFree(&it);
  }
  // Handle the data being an array buffer
  else if (jsvIsArrayBuffer(data)) {
    JsvArrayBufferIterator it;
    jsvArrayBufferIteratorNew(&it, data, 0);
    if (JSV_ARRAYBUFFER_GET_SIZE(it.type) == 1 && !JSV_ARRAYBUFFER_IS_SIGNED(it.type)) {
      JsvStringIterator *sit = &it.it;
      // faster for single byte arrays - read using the string iterator.
      while (jsvStringIteratorHasChar(sit)) {
        callback((int)(unsigned char)jsvStringIteratorGetChar(sit), callbackData);
        jsvStringIteratorNextInline(sit);
      }
    } else {
      while (jsvArrayBufferIteratorHasElement(&it)) {
        callback((int)jsvArrayBufferIteratorGetIntegerValue(&it), callbackData);
        jsvArrayBufferIteratorNext(&it);
      }
    }
    jsvArrayBufferIteratorFree(&it);
  }
  // Handle the data being iterable
  else if (jsvIsIterable(data)) {
    JsvIterator it;
    jsvIteratorNew(&it, data, JSIF_EVERY_ARRAY_ELEMENT);
    while (jsvIteratorHasElement(&it) && ok) {
      JsVar *el = jsvIteratorGetValue(&it);
      ok = jsvIterateCallback(el, callback, callbackData);
      jsvUnLock(el);
      jsvIteratorNext(&it);
    }
    jsvIteratorFree(&it);
  } else {
    jsExceptionHere(JSET_TYPEERROR, "Expecting a number or something iterable, got %t", data);
    ok = false;
  }
  return ok;
}