예제 #1
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);
}
예제 #2
0
파일: jslex.c 프로젝트: CWBudde/Espruino
static void jslLexRegex() {
  lex->tokenValue = jsvNewFromEmptyString();
  if (!lex->tokenValue) {
    lex->tk = LEX_EOF;
    return;
  }
  JsvStringIterator it;
  jsvStringIteratorNew(&it, lex->tokenValue, 0);
  jsvStringIteratorAppend(&it, '/');
  // strings...
  jslGetNextCh();
  while (lex->currCh && lex->currCh!='/') {
    if (lex->currCh == '\\') {
      jsvStringIteratorAppend(&it, lex->currCh);
      jslGetNextCh();
    } else if (lex->currCh=='\n') {
      /* Was a newline - this is now allowed
       * unless we're a template string */
      break;
    }
    jsvStringIteratorAppend(&it, lex->currCh);
    jslGetNextCh();
  }
  lex->tk = LEX_REGEX;
  if (lex->currCh!='/') {
    lex->tk++; // +1 gets you to 'unfinished X'
  } else {
    jsvStringIteratorAppend(&it, '/');
    jslGetNextCh();
    // regex modifiers
    while (lex->currCh=='g' ||
        lex->currCh=='i' ||
        lex->currCh=='m' ||
        lex->currCh=='y' ||
        lex->currCh=='u') {
      jslTokenAppendChar(lex->currCh);
      jsvStringIteratorAppend(&it, lex->currCh);
      jslGetNextCh();
    }
  }
  jsvStringIteratorFree(&it);
}
예제 #3
0
/*JSON{  "type" : "method", "class" : "File", "name" : "read",
         "generate" : "jswrap_file_read",
         "description" : [ "Read data in a file in byte size chunks"],
         "params" : [ ["length", "int32", "is an integer specifying the number of bytes to read."] ],
         "return" : [ "JsVar", "A string containing the characters that were read" ]
}*/
JsVar *jswrap_file_read(JsVar* parent, int length) {
  JsVar *buffer = 0;
  JsvStringIterator it;
  FRESULT res = 0;
  size_t bytesRead = 0;
  if (jsfsInit()) {
    JsFile file;
    if (fileGetFromVar(&file, parent)) {
      if(file.data.mode == FM_READ || file.data.mode == FM_READ_WRITE) {
        char buf[32];
        size_t actual = 0;

        while (bytesRead < (size_t)length) {
          size_t requested = (size_t)length - bytesRead;
          if (requested > sizeof( buf ))
            requested = sizeof( buf );
          actual = 0;
    #ifndef LINUX
          res = f_read(&file.data.handle, buf, requested, &actual);
          if(res) break;
    #else
          actual = fread(buf, 1, requested, file.data.handle);
    #endif
          if (actual>0) {
            if (!buffer) {
              buffer = jsvNewFromEmptyString();
              if (!buffer) return 0; // out of memory
              jsvStringIteratorNew(&it, buffer, 0);
            }
            size_t i;
            for (i=0;i<actual;i++)
              jsvStringIteratorAppend(&it, buf[i]);
          }
          bytesRead += actual;
          if(actual != requested) break;
        }
        fileSetVar(&file);
      }
    }
  }
  if (res) jsfsReportError("Unable to read file", res);

  if (buffer)
    jsvStringIteratorFree(&it);

  // automatically close this file if we're at the end of it
  if (bytesRead!=(size_t)length)
    jswrap_file_close(parent);

  return buffer;
}
예제 #4
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;
}
예제 #5
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;
}
예제 #6
0
/*JSON{
  "type" : "method",
  "class" : "File",
  "name" : "read",
  "generate" : "jswrap_file_read",
  "params" : [
    ["length","int32","is an integer specifying the number of bytes to read."]
  ],
  "return" : ["JsVar","A string containing the characters that were read"]
}
Read data in a file in byte size chunks
*/
JsVar *jswrap_file_read(JsVar* parent, int length) {
  if (length<0) length=0;
  JsVar *buffer = 0;
  JsvStringIterator it;
  FRESULT res = 0;
  size_t bytesRead = 0;
  if (jsfsInit()) {
    JsFile file;
    if (fileGetFromVar(&file, parent)) {
      if(file.data->mode == FM_READ || file.data->mode == FM_READ_WRITE) {
        size_t actual = 0;
#ifndef LINUX
        // if we're able to load this into a flat string, do it!
        size_t len = f_size(&file.data->handle)-f_tell(&file.data->handle);
        if ( len == 0 ) { // file all read
          return 0; // if called from a pipe signal end callback
        }
        if (len > (size_t)length) len = (size_t)length;
        buffer = jsvNewFlatStringOfLength(len);
        if (buffer) {
          res = f_read(&file.data->handle, jsvGetFlatStringPointer(buffer), len, &actual);
          if (res) jsfsReportError("Unable to read file", res);
          return buffer;
        }
#endif
        char buf[32];

        while (bytesRead < (size_t)length) {
          size_t requested = (size_t)length - bytesRead;
          if (requested > sizeof( buf ))
            requested = sizeof( buf );
          actual = 0;
    #ifndef LINUX
          res = f_read(&file.data->handle, buf, requested, &actual);
          if(res) break;
    #else
          actual = fread(buf, 1, requested, file.data->handle);
    #endif
          if (actual>0) {
            if (!buffer) {
              buffer = jsvNewFromEmptyString();
              if (!buffer) return 0; // out of memory
              jsvStringIteratorNew(&it, buffer, 0);
            }
            size_t i;
            for (i=0;i<actual;i++)
              jsvStringIteratorAppend(&it, buf[i]);
          }
          bytesRead += actual;
          if(actual != requested) break;
        }
      }
    }
  }
  if (res) jsfsReportError("Unable to read file", res);

  if (buffer)
    jsvStringIteratorFree(&it);

  return buffer;
}
예제 #7
0
파일: jslex.c 프로젝트: 8bitgeek/Espruino
void jslGetNextToken() {
  jslGetNextToken_start:
  // Skip whitespace
  while (isWhitespace(lex->currCh))
    jslGetNextCh();
  // Search for comments
  if (lex->currCh=='/') {
    // newline comments
    if (jslNextCh()=='/') {
      while (lex->currCh && lex->currCh!='\n') jslGetNextCh();
      jslGetNextCh();
      goto jslGetNextToken_start;
    }
    // block comments
    if (jslNextCh()=='*') {
      while (lex->currCh && !(lex->currCh=='*' && jslNextCh()=='/'))
        jslGetNextCh();
      if (!lex->currCh) {
        lex->tk = LEX_UNFINISHED_COMMENT;
        return; /* an unfinished multi-line comment. When in interactive console,
                   detect this and make sure we accept new lines */
      }
      jslGetNextCh();
      jslGetNextCh();
      goto jslGetNextToken_start;
    }
  }
  lex->tk = LEX_EOF;
  lex->tokenl = 0; // clear token string
  if (lex->tokenValue) {
    jsvUnLock(lex->tokenValue);
    lex->tokenValue = 0;
  }
  // record beginning of this token
  lex->tokenLastStart = jsvStringIteratorGetIndex(&lex->tokenStart.it) - 1;
  /* we don't lock here, because we know that the string itself will be locked
   * because of lex->sourceVar */
  lex->tokenStart.it = lex->it;
  lex->tokenStart.currCh = lex->currCh;
  // tokens
  if (((unsigned char)lex->currCh) < jslJumpTableStart ||
      ((unsigned char)lex->currCh) > jslJumpTableEnd) {
    // if unhandled by the jump table, just pass it through as a single character
    jslSingleChar();
  } else {
    switch(jslJumpTable[((unsigned char)lex->currCh) - jslJumpTableStart]) {
    case JSLJT_ID: {
      while (isAlpha(lex->currCh) || isNumeric(lex->currCh) || lex->currCh=='$') {
        jslTokenAppendChar(lex->currCh);
        jslGetNextCh();
      }
      lex->tk = LEX_ID;
      // We do fancy stuff here to reduce number of compares (hopefully GCC creates a jump table)
      switch (lex->token[0]) {
      case 'b': if (jslIsToken("break", 1)) lex->tk = LEX_R_BREAK;
      break;
      case 'c': if (jslIsToken("case", 1)) lex->tk = LEX_R_CASE;
      else if (jslIsToken("catch", 1)) lex->tk = LEX_R_CATCH;
      else if (jslIsToken("continue", 1)) lex->tk = LEX_R_CONTINUE;
      break;
      case 'd': if (jslIsToken("default", 1)) lex->tk = LEX_R_DEFAULT;
      else if (jslIsToken("delete", 1)) lex->tk = LEX_R_DELETE;
      else if (jslIsToken("do", 1)) lex->tk = LEX_R_DO;
      else if (jslIsToken("debugger", 1)) lex->tk = LEX_R_DEBUGGER;
      break;
      case 'e': if (jslIsToken("else", 1)) lex->tk = LEX_R_ELSE;
      break;
      case 'f': if (jslIsToken("false", 1)) lex->tk = LEX_R_FALSE;
      else if (jslIsToken("finally", 1)) lex->tk = LEX_R_FINALLY;
      else if (jslIsToken("for", 1)) lex->tk = LEX_R_FOR;
      else if (jslIsToken("function", 1)) lex->tk = LEX_R_FUNCTION;
      break;
      case 'i': if (jslIsToken("if", 1)) lex->tk = LEX_R_IF;
      else if (jslIsToken("in", 1)) lex->tk = LEX_R_IN;
      else if (jslIsToken("instanceof", 1)) lex->tk = LEX_R_INSTANCEOF;
      break;
      case 'n': if (jslIsToken("new", 1)) lex->tk = LEX_R_NEW;
      else if (jslIsToken("null", 1)) lex->tk = LEX_R_NULL;
      break;
      case 'r': if (jslIsToken("return", 1)) lex->tk = LEX_R_RETURN;
      break;
      case 's': if (jslIsToken("switch", 1)) lex->tk = LEX_R_SWITCH;
      break;
      case 't': if (jslIsToken("this", 1)) lex->tk = LEX_R_THIS;
      else if (jslIsToken("throw", 1)) lex->tk = LEX_R_THROW;
      else if (jslIsToken("true", 1)) lex->tk = LEX_R_TRUE;
      else if (jslIsToken("try", 1)) lex->tk = LEX_R_TRY;
      else if (jslIsToken("typeof", 1)) lex->tk = LEX_R_TYPEOF;
      break;
      case 'u': if (jslIsToken("undefined", 1)) lex->tk = LEX_R_UNDEFINED;
      break;
      case 'w': if (jslIsToken("while", 1)) lex->tk = LEX_R_WHILE;
      break;
      case 'v': if (jslIsToken("var", 1)) lex->tk = LEX_R_VAR;
      else if (jslIsToken("void", 1)) lex->tk = LEX_R_VOID;
      break;
      default: break;
      } break;
      case JSLJT_NUMBER: {
        // TODO: check numbers aren't the wrong format
        bool canBeFloating = true;
        if (lex->currCh=='.') {
          jslGetNextCh();
          if (isNumeric(lex->currCh)) {
            // it is a float
            lex->tk = LEX_FLOAT;
            jslTokenAppendChar('.');
          } else {
            // it wasn't a number after all
            lex->tk = '.';
            break;
          }
        } else {
          if (lex->currCh=='0') {
            jslTokenAppendChar(lex->currCh);
            jslGetNextCh();
            if ((lex->currCh=='x' || lex->currCh=='X') ||
                (lex->currCh=='b' || lex->currCh=='B') ||
                (lex->currCh=='o' || lex->currCh=='O')) {
              canBeFloating = false;
              jslTokenAppendChar(lex->currCh); jslGetNextCh();
            }
          }
          lex->tk = LEX_INT;
          while (isNumeric(lex->currCh) || (!canBeFloating && isHexadecimal(lex->currCh))) {
            jslTokenAppendChar(lex->currCh);
            jslGetNextCh();
          }
          if (canBeFloating && lex->currCh=='.') {
            lex->tk = LEX_FLOAT;
            jslTokenAppendChar('.');
            jslGetNextCh();
          }
        }
        // parse fractional part
        if (lex->tk == LEX_FLOAT) {
          while (isNumeric(lex->currCh)) {
            jslTokenAppendChar(lex->currCh);
            jslGetNextCh();
          }
        }
        // do fancy e-style floating point
        if (canBeFloating && (lex->currCh=='e'||lex->currCh=='E')) {
          lex->tk = LEX_FLOAT;
          jslTokenAppendChar(lex->currCh); jslGetNextCh();
          if (lex->currCh=='-' || lex->currCh=='+') { jslTokenAppendChar(lex->currCh); jslGetNextCh(); }
          while (isNumeric(lex->currCh)) {
            jslTokenAppendChar(lex->currCh); jslGetNextCh();
          }
        }
      } break;
      case JSLJT_STRING:
      {
        char delim = lex->currCh;
        lex->tokenValue = jsvNewFromEmptyString();
        if (!lex->tokenValue) {
          lex->tk = LEX_EOF;
          return;
        }
        JsvStringIterator it;
        jsvStringIteratorNew(&it, lex->tokenValue, 0);
        // strings...
        jslGetNextCh();
        while (lex->currCh && lex->currCh!=delim) {
          if (lex->currCh == '\\') {
            jslGetNextCh();
            char ch = lex->currCh;
            switch (lex->currCh) {
            case 'n'  : ch = 0x0A; jslGetNextCh(); break;
            case 'b'  : ch = 0x08; jslGetNextCh(); break;
            case 'f'  : ch = 0x0C; jslGetNextCh(); break;
            case 'r'  : ch = 0x0D; jslGetNextCh(); break;
            case 't'  : ch = 0x09; jslGetNextCh(); break;
            case 'v'  : ch = 0x0B; jslGetNextCh(); break;
            case 'u' :
            case 'x' : { // hex digits
              char buf[5] = "0x??";
              if (lex->currCh == 'u') {
                // We don't support unicode, so we just take the bottom 8 bits
                // of the unicode character
                jslGetNextCh();
                jslGetNextCh();
              }
              jslGetNextCh();
              buf[2] = lex->currCh; jslGetNextCh();
              buf[3] = lex->currCh; jslGetNextCh();
              ch = (char)stringToInt(buf);
            } break;
            default:
              if (lex->currCh>='0' && lex->currCh<='7') {
                // octal digits
                char buf[5] = "0";
                buf[1] = lex->currCh;
                int n=2;
                jslGetNextCh();
                if (lex->currCh>='0' && lex->currCh<='7') {
                  buf[n++] = lex->currCh; jslGetNextCh();
                  if (lex->currCh>='0' && lex->currCh<='7') {
                    buf[n++] = lex->currCh; jslGetNextCh();
                  }
                }
                buf[n]=0;
                ch = (char)stringToInt(buf);
              } else {
                // for anything else, just push the character through
                jslGetNextCh();
              }
              break;
            }
            jslTokenAppendChar(ch);
            jsvStringIteratorAppend(&it, ch);
          } else {
            jslTokenAppendChar(lex->currCh);
            jsvStringIteratorAppend(&it, lex->currCh);
            jslGetNextCh();
          }
        }
        jsvStringIteratorFree(&it);
        lex->tk = lex->currCh==delim ? LEX_STR : LEX_UNFINISHED_STR;
        jslGetNextCh();
      } break;
      case JSLJT_EXCLAMATION: jslSingleChar();
      if (lex->currCh=='=') { // !=
        lex->tk = LEX_NEQUAL;
        jslGetNextCh();
        if (lex->currCh=='=') { // !==
          lex->tk = LEX_NTYPEEQUAL;
          jslGetNextCh();
        }
      } break;
      case JSLJT_PLUS: jslSingleChar();
      if (lex->currCh=='=') {
        lex->tk = LEX_PLUSEQUAL;
        jslGetNextCh();
      } else if (lex->currCh=='+') {
        lex->tk = LEX_PLUSPLUS;
        jslGetNextCh();
      } break;
      case JSLJT_MINUS: jslSingleChar();
      if (lex->currCh=='=') {
        lex->tk = LEX_MINUSEQUAL;
        jslGetNextCh();
      } else if (lex->currCh=='-') {
        lex->tk = LEX_MINUSMINUS;
        jslGetNextCh();
      } break;
      case JSLJT_AND: jslSingleChar();
      if (lex->currCh=='=') {
        lex->tk = LEX_ANDEQUAL;
        jslGetNextCh();
      } else if (lex->currCh=='&') {
        lex->tk = LEX_ANDAND;
        jslGetNextCh();
      } break;
      case JSLJT_OR: jslSingleChar();
      if (lex->currCh=='=') {
        lex->tk = LEX_OREQUAL;
        jslGetNextCh();
      } else if (lex->currCh=='|') {
        lex->tk = LEX_OROR;
        jslGetNextCh();
      } break;
      case JSLJT_TOPHAT: jslSingleChar();
      if (lex->currCh=='=') {
        lex->tk = LEX_XOREQUAL;
        jslGetNextCh();
      } break;
      case JSLJT_STAR: jslSingleChar();
      if (lex->currCh=='=') {
        lex->tk = LEX_MULEQUAL;
        jslGetNextCh();
      } break;
      case JSLJT_FORWARDSLASH: jslSingleChar();
      if (lex->currCh=='=') {
        lex->tk = LEX_DIVEQUAL;
        jslGetNextCh();
      } break;
      case JSLJT_PERCENT: jslSingleChar();
      if (lex->currCh=='=') {
        lex->tk = LEX_MODEQUAL;
        jslGetNextCh();
      } break;
      case JSLJT_EQUAL: jslSingleChar();
      if (lex->currCh=='=') { // ==
        lex->tk = LEX_EQUAL;
        jslGetNextCh();
        if (lex->currCh=='=') { // ===
          lex->tk = LEX_TYPEEQUAL;
          jslGetNextCh();
        }
      } break;
      case JSLJT_LESSTHAN: jslSingleChar();
      if (lex->currCh=='=') { // <=
        lex->tk = LEX_LEQUAL;
        jslGetNextCh();
      } else if (lex->currCh=='<') { // <<
        lex->tk = LEX_LSHIFT;
        jslGetNextCh();
        if (lex->currCh=='=') { // <<=
          lex->tk = LEX_LSHIFTEQUAL;
          jslGetNextCh();
        }
      } break;
      case JSLJT_GREATERTHAN: jslSingleChar();
      if (lex->currCh=='=') { // >=
        lex->tk = LEX_GEQUAL;
        jslGetNextCh();
      } else if (lex->currCh=='>') { // >>
        lex->tk = LEX_RSHIFT;
        jslGetNextCh();
        if (lex->currCh=='=') { // >>=
          lex->tk = LEX_RSHIFTEQUAL;
          jslGetNextCh();
        } else if (lex->currCh=='>') { // >>>
          jslGetNextCh();
          if (lex->currCh=='=') { // >>>=
            lex->tk = LEX_RSHIFTUNSIGNEDEQUAL;
            jslGetNextCh();
          } else {
            lex->tk = LEX_RSHIFTUNSIGNED;
          }
        }
      } break;

      case JSLJT_SINGLECHAR: jslSingleChar(); break;
      default: assert(0);break;
    }
    }
  }
}
예제 #8
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;
}
예제 #9
0
파일: jslex.c 프로젝트: CWBudde/Espruino
static void jslLexString() {
  char delim = lex->currCh;
  lex->tokenValue = jsvNewFromEmptyString();
  if (!lex->tokenValue) {
    lex->tk = LEX_EOF;
    return;
  }
  JsvStringIterator it;
  jsvStringIteratorNew(&it, lex->tokenValue, 0);
  // strings...
  jslGetNextCh();
  while (lex->currCh && lex->currCh!=delim) {
    if (lex->currCh == '\\') {
      jslGetNextCh();
      char ch = lex->currCh;
      switch (lex->currCh) {
      case 'n'  : ch = 0x0A; jslGetNextCh(); break;
      case 'b'  : ch = 0x08; jslGetNextCh(); break;
      case 'f'  : ch = 0x0C; jslGetNextCh(); break;
      case 'r'  : ch = 0x0D; jslGetNextCh(); break;
      case 't'  : ch = 0x09; jslGetNextCh(); break;
      case 'v'  : ch = 0x0B; jslGetNextCh(); break;
      case 'u' :
      case 'x' : { // hex digits
        char buf[5] = "0x??";
        if (lex->currCh == 'u') {
          // We don't support unicode, so we just take the bottom 8 bits
          // of the unicode character
          jslGetNextCh();
          jslGetNextCh();
        }
        jslGetNextCh();
        buf[2] = lex->currCh; jslGetNextCh();
        buf[3] = lex->currCh; jslGetNextCh();
        ch = (char)stringToInt(buf);
      } break;
      default:
        if (lex->currCh>='0' && lex->currCh<='7') {
          // octal digits
          char buf[5] = "0";
          buf[1] = lex->currCh;
          int n=2;
          jslGetNextCh();
          if (lex->currCh>='0' && lex->currCh<='7') {
            buf[n++] = lex->currCh; jslGetNextCh();
            if (lex->currCh>='0' && lex->currCh<='7') {
              buf[n++] = lex->currCh; jslGetNextCh();
            }
          }
          buf[n]=0;
          ch = (char)stringToInt(buf);
        } else {
          // for anything else, just push the character through
          jslGetNextCh();
        }
        break;
      }
      jslTokenAppendChar(ch);
      jsvStringIteratorAppend(&it, ch);
    } else if (lex->currCh=='\n' && delim!='`') {
      /* Was a newline - this is now allowed
       * unless we're a template string */
      break;
    } else {
      jslTokenAppendChar(lex->currCh);
      jsvStringIteratorAppend(&it, lex->currCh);
      jslGetNextCh();
    }
  }
  jsvStringIteratorFree(&it);
  if (delim=='`')
    lex->tk = LEX_TEMPLATE_LITERAL;
  else lex->tk = LEX_STR;
  // unfinished strings
  if (lex->currCh!=delim)
    lex->tk++; // +1 gets you to 'unfinished X'
  jslGetNextCh();
}