Пример #1
0
static value_t read_string(void)
{
    char *buf, *temp;
    char eseq[10];
    size_t i=0, j, sz = 64, ndig;
    int c;
    value_t s;
    u_int32_t wc=0;

    buf = malloc(sz);
    while (1) {
        if (i >= sz-4) {  // -4: leaves room for longest utf8 sequence
            sz *= 2;
            temp = realloc(buf, sz);
            if (temp == NULL) {
                free(buf);
                lerror(ParseError, "read: out of memory reading string");
            }
            buf = temp;
        }
        c = ios_getc(F);
        if (c == IOS_EOF) {
            free(buf);
            lerror(ParseError, "read: unexpected end of input in string");
        }
        if (c == '"')
            break;
        else if (c == '\\') {
            c = ios_getc(F);
            if (c == IOS_EOF) {
                free(buf);
                lerror(ParseError, "read: end of input in escape sequence");
            }
            j=0;
            if (octal_digit(c)) {
                do {
                    eseq[j++] = c;
                    c = ios_getc(F);
                } while (octal_digit(c) && j<3 && (c!=IOS_EOF));
                if (c!=IOS_EOF) ios_ungetc(c, F);
                eseq[j] = '\0';
                wc = strtol(eseq, NULL, 8);
                // \DDD and \xXX read bytes, not characters
                buf[i++] = ((char)wc);
            }
            else if ((c=='x' && (ndig=2)) ||
                     (c=='u' && (ndig=4)) ||
                     (c=='U' && (ndig=8))) {
                c = ios_getc(F);
                while (hex_digit(c) && j<ndig && (c!=IOS_EOF)) {
                    eseq[j++] = c;
                    c = ios_getc(F);
                }
                if (c!=IOS_EOF) ios_ungetc(c, F);
                eseq[j] = '\0';
                if (j) wc = strtol(eseq, NULL, 16);
                if (!j || wc > 0x10ffff) {
                    free(buf);
                    lerror(ParseError, "read: invalid escape sequence");
                }
                if (ndig == 2)
                    buf[i++] = ((char)wc);
                else
                    i += u8_wc_toutf8(&buf[i], wc);
            }
            else {
                buf[i++] = read_escape_control_char((char)c);
            }
        }
        else {
            buf[i++] = c;
        }
    }
    s = cvalue_string(i);
    memcpy(cvalue_data(s), buf, i);
    free(buf);
    return s;
}
Пример #2
0
std::shared_ptr<Object> read_string(std::istream &in) {
  std::stringstream buf;
  // lambda to get the next char, or throw EOF exception
  std::function<int ()> getc = [&in] () -> int { 
    int c = in.get();
    if (in.eof()) {
      throw "EOF while reading string";
    }
    return c;
  };
  while (1) {
    int c = getc();
    if (c == '"') {
      return std::make_shared<String>(buf.str());
    }
    if (c == '\\') {
      c = getc();
      if (octal_digit(c)) {
        int j = 0;
        char eseq[4] = { 0, 0, 0, 0 } ;
        do {
          eseq[j++] = c;
          c = getc();
        } while (octal_digit(c) && j < 3);
        in.unget();
        if (!octal_digit(c) && j < 3) {
          if (c == '\\') {
          } else {
            buf.str("Invalid digit: ");
            buf.put(c);
            throw buf.str();
          }
        }
        u8_wc_toutf8(buf, std::strtol(eseq, 0, 8));
      } else if (c == 'u') {
        int j = 0;
        char eseq[5] = { 0, 0, 0, 0, 0 };
        c = getc();
        while (hex_digit(c) && j < 4) {
          eseq[j++] = c;
          c = getc();
        }
        if (j != 4) {
          buf.str("Invalid character length: ");
          buf << j << ", should be: 4";
          throw buf.str();
        }
        in.unget();
        long uni = std::strtol(eseq, 0, 16);
        u8_wc_toutf8(buf, uni);
      } else {
        if (c == 'b') {
          buf.put('\b');
        } else if (c == 'n') {
          buf.put('\n');
        } else if (c == 't') {
          buf.put('\t');
        } else if (c == 'f') {
          buf.put('\f');
        } else if (c == 'r') {
          buf.put('\r');
        } else if (c == '"') {
          buf.put('\'');
        } else if (c == '\\') {
          buf.put('\\');
        } else {
          buf.str("Unsupported escape character: \\");
          buf.put(c);
          throw buf.str();
        }
      }
    } else {
      buf.put(c);
    }
  }
  return Object::nil;
}