Example #1
0
 void run() {
     StringBuilder sb;
     sb << "1" << "abc" << "5.17";
     ASSERT_EQUALS( "1abc5.17" , sb.str() );
     ASSERT_EQUALS( "1abc5.17" , sb.str() );
     sb.reset(1);
     ASSERT_EQUALS( "" , sb.str() );
     sb << "999";
     ASSERT_EQUALS( "999" , sb.str() );
 }
Example #2
0
TEST(Builder, StringBuilderAddress) {
    const void* longPtr = reinterpret_cast<const void*>(-1);
    const void* shortPtr = reinterpret_cast<const void*>(0xDEADBEEF);
    const void* nullPtr = NULL;

    StringBuilder sb;
    sb << longPtr;

    if (sizeof(longPtr) == 8) {
        ASSERT_EQUALS("0xFFFFFFFFFFFFFFFF", sb.str());
    } else {
        ASSERT_EQUALS("0xFFFFFFFF", sb.str());
    }

    sb.reset();
    sb << shortPtr;
    ASSERT_EQUALS("0xDEADBEEF", sb.str());

    sb.reset();
    sb << nullPtr;
    ASSERT_EQUALS("0x0", sb.str());
}
Example #3
0
std::string escape(StringData sd, bool escape_slash) {
    StringBuilder ret;
    ret.reset(sd.size());
    for (const auto& c : sd) {
        switch (c) {
            case '"':
                ret << "\\\"";
                break;
            case '\\':
                ret << "\\\\";
                break;
            case '/':
                ret << (escape_slash ? "\\/" : "/");
                break;
            case '\b':
                ret << "\\b";
                break;
            case '\f':
                ret << "\\f";
                break;
            case '\n':
                ret << "\\n";
                break;
            case '\r':
                ret << "\\r";
                break;
            case '\t':
                ret << "\\t";
                break;
            default:
                if (c >= 0 && c <= 0x1f) {
                    // For c < 0x7f, ASCII value == Unicode code point.
                    ret << "\\u00" << toHexLower(&c, 1);
                } else {
                    ret << c;
                }
        }
    }
    return ret.str();
}
Example #4
0
/**
 * Edit a variable or input buffer text in an external editor -- EDITOR must be defined
 *
 * @param whatToEdit Name of JavaScript variable to be edited, or any text string
 */
static void edit( const string& whatToEdit ) {

    // EDITOR may be defined in the JavaScript scope or in the environment
    string editor;
    if ( shellMainScope->type( "EDITOR" ) == String ) {
        editor = shellMainScope->getString( "EDITOR" );
    }
    else {
        static const char * editorFromEnv = getenv( "EDITOR" );
        if ( editorFromEnv ) {
            editor = editorFromEnv;
        }
    }
    if ( editor.empty() ) {
        cout << "please define EDITOR as a JavaScript string or as an environment variable" << endl;
        return;
    }

    // "whatToEdit" might look like a variable/property name
    bool editingVariable = true;
    for ( const char* p = whatToEdit.c_str(); *p; ++p ) {
        if ( ! ( isalnum( *p ) || *p == '_' || *p == '.' ) ) {
            editingVariable = false;
            break;
        }
    }

    string js;
    if ( editingVariable ) {
        // Convert "whatToEdit" to JavaScript (JSON) text
        if ( !shellMainScope->exec( "__jsout__ = tojson(" + whatToEdit + ")", "tojs", false, false, false ) )
            return; // Error already printed

        js = shellMainScope->getString( "__jsout__" );

        if ( strstr( js.c_str(), "[native code]" ) ) {
            cout << "can't edit native functions" << endl;
            return;
        }
    }
    else {
        js = whatToEdit;
    }

    // Pick a name to use for the temp file
    string filename;
    const int maxAttempts = 10;
    int i;
    for ( i = 0; i < maxAttempts; ++i ) {
        StringBuilder sb;
#ifdef _WIN32
        char tempFolder[MAX_PATH];
        GetTempPathA( sizeof tempFolder, tempFolder );
        sb << tempFolder << "mongo_edit" << time( 0 ) + i << ".js";
#else
        sb << "/tmp/mongo_edit" << time( 0 ) + i << ".js";
#endif
        filename = sb.str();
        if ( ! fileExists( filename ) )
            break;
    }
    if ( i == maxAttempts ) {
        cout << "couldn't create unique temp file after " << maxAttempts << " attempts" << endl;
        return;
    }

    // Create the temp file
    FILE * tempFileStream;
    tempFileStream = fopen( filename.c_str(), "wt" );
    if ( ! tempFileStream ) {
        cout << "couldn't create temp file (" << filename << "): " << errnoWithDescription() << endl;
        return;
    }

    // Write JSON into the temp file
    size_t fileSize = js.size();
    if ( fwrite( js.data(), sizeof( char ), fileSize, tempFileStream ) != fileSize ) {
        int systemErrno = errno;
        cout << "failed to write to temp file: " << errnoWithDescription( systemErrno ) << endl;
        fclose( tempFileStream );
        remove( filename.c_str() );
        return;
    }
    fclose( tempFileStream );

    // Pass file to editor
    StringBuilder sb;
    sb << editor << " " << filename;
    int ret = ::system( sb.str().c_str() );
    if ( ret ) {
        if ( ret == -1 ) {
            int systemErrno = errno;
            cout << "failed to launch $EDITOR (" << editor << "): " << errnoWithDescription( systemErrno ) << endl;
        }
        else
            cout << "editor exited with error (" << ret << "), not applying changes" << endl;
        remove( filename.c_str() );
        return;
    }

    // The editor gave return code zero, so read the file back in
    tempFileStream = fopen( filename.c_str(), "rt" );
    if ( ! tempFileStream ) {
        cout << "couldn't open temp file on return from editor: " << errnoWithDescription() << endl;
        remove( filename.c_str() );
        return;
    }
    sb.reset();
    int bytes;
    do {
        char buf[1024];
        bytes = fread( buf, sizeof( char ), sizeof buf, tempFileStream );
        if ( ferror( tempFileStream ) ) {
            cout << "failed to read temp file: " << errnoWithDescription() << endl;
            fclose( tempFileStream );
            remove( filename.c_str() );
            return;
        }
        sb.append( StringData( buf, bytes ) );
    } while ( bytes );

    // Done with temp file, close and delete it
    fclose( tempFileStream );
    remove( filename.c_str() );

    if ( editingVariable ) {
        // Try to execute assignment to copy edited value back into the variable
        const string code = whatToEdit + string( " = " ) + sb.str();
        if ( !shellMainScope->exec( code, "tojs", false, false, false ) )
            return; // Error already printed
    }
    else {
        linenoisePreloadBuffer( sb.str().c_str() );
    }
}
Example #5
0
static void edit(const string& var){
    static const char * editor = getenv("EDITOR");
    if (!editor) {
        cout << "please define the EDITOR environment variable" << endl;
        return;
    }

    for (const char* p=var.data(); *p ; p++){
        if (! (isalnum(*p) || *p == '_' || *p == '.')){
            cout << "can only edit variable or property" << endl;
            return;
        }
    }

    if (!shellMainScope->exec("__jsout__ = tojson("+var+")", "tojs", false, false, false))
        return; // Error already printed

    const string js = shellMainScope->getString("__jsout__");

    if (strstr(js.c_str(), "[native code]")) {
        cout << "Can't edit native functions" << endl;
        return;
    }

    string filename;
    int fd;
    for (int i=0; i < 10; i++){
        StringBuilder sb;
        sb << "/tmp/mongo_edit" << time(0)+i << ".js";
        filename = sb.str();
        fd = open(filename.c_str(), O_RDWR|O_CREAT|O_EXCL, 0600);
        if (fd > 0)
            break;

        if (errno != EEXIST) {
            cout << "couldn't open temp file: " << errnoWithDescription() << endl;
            return;
        }
    }

    if (fd == -1){
        cout << "couldn't create unique temp file after 10 attempts" << endl;
        return;
    }

    // just to make sure this gets closed no matter what
    File holder;
    holder.fd = fd;

    if (write(fd, js.data(), js.size()) != (int)js.size()){
        cout << "failed to write to temp file: " << errnoWithDescription() << endl;
        return;
    }

    StringBuilder sb;
    sb << editor << " " << filename;
    int ret = ::system(sb.str().c_str());
    int systemErrno = errno;
    remove(filename.c_str()); // file already open, deleted on close
    if (ret){
        if (ret == -1) {
            cout << "failed to launch $EDITOR (" << editor << "): " << errnoWithDescription(systemErrno) << endl;
            return;
        }

        cout << "editor exited with error, not applying changes" << endl;
        return;

    }

    lseek(fd, 0, SEEK_SET);

    sb.reset();
    sb << var << " = ";
    int bytes;
    do {
        char buf[1024];
        bytes = read(fd, buf, sizeof(buf));
        if (bytes < 0) {
            cout << "failed to read temp file: " << errnoWithDescription() << endl;
            return;
        }
        sb.append( StringData(buf, bytes) );
    }while (bytes);

    const string code = sb.str();
    if (!shellMainScope->exec(code, "tojs", false, false, false))
        return; // Error already printed

}
Example #6
0
/**
 * Reads the bytes in the buffer. Interprets messages as
 *  it detects them.
 *
 * Preconditions:
 * -serialInBox has been initialized.
 * -MAX_MESSAGE_SIZE number of bytes of memory availiable
 *   on the stack.
 * -Serial.begin() has been called successfully.
 * -serialInBox may need more memory on the heap.
 *
 * Post Conditions:
 * -serialInBox may have additional bytes from buffer if the proper
 *   begginning and ending chars are received and the message is
 *   properly formatted.

 * @param buffer is the array of characters to read.
 * @param numOfBytes is the length of the array.
 */
void readBytes( char buffer[], int numOfBytes ) {
  static boolean foundMessage = false;
  // Discard any previous messages.
  serialInBox.reset();
  // Handle each byte.
    for( int i = 0; i < numOfBytes; ++i ) {
      char chr = buffer[ i ];
      switch( chr ) {
        case MSG_START:
        {
          foundMessage = true;
          //XXX Clear inbox.
        }
        break;
        case MSG_TERMINATOR:
        {
          if ( serialInBox.len() > 0 ) {
              // What to do once we have the message?
            int messageID;
            bool goodMessage = false;
            // Get message type.
            char messageType = *(const char*)serialInBox;
            serialOutBox.appends( "\"" );
            serialOutBox.appends( (const char*)serialInBox );
            serialOutBox.appends( "\"" );

            switch( messageType ) {
              case TIME_REQUEST:
              {
                int delayAmount;
                if ( sscanf( (const char*)serialInBox + 1, "%d/%d", &messageID, &delayAmount ) == 2 ) {
                  goodMessage = true;
                  timeRequestEndTime = millis() + delayAmount;
                }
              }
              break;
              default:
              {
                // Unknown request.
              }
            }
              // Read ID.
              // sscanf returns the number of variables read.
            if ( goodMessage ) {
              // Only new messages.
              if ( lastIDReceived < messageID ) {
                // Write confirmation message.`
                char tempOutString[MAX_MESSAGE_SIZE];
                sprintf( tempOutString, "%cC%d%c", MSG_START, messageID, MSG_TERMINATOR );
                Serial.write( tempOutString );
                serialOutBox.appends( tempOutString );
                lastIDReceived = messageID;
              }
            }
            else {
              char tempOutString[ MAX_MESSAGE_SIZE ];
              sprintf( tempOutString, "%cE%d\"%s\"Bad Message Format%c", MSG_START, messageID, (const char*)serialInBox, MSG_TERMINATOR );
              serialOutBox.appends( tempOutString );
            }
            foundMessage = false;
            serialInBox.reset();
          }
        }
        break;
        default:
        {
          if ( foundMessage )
            serialInBox.append( chr );
        }
        break;
      }
    }
}