Beispiel #1
0
/* Implements svn_stream_seek_fn_t */
static svn_error_t *
seek_handler_lazyopen(void *baton,
                      const svn_stream_mark_t *mark)
{
  lazyopen_baton_t *b = baton;

  SVN_ERR(lazyopen_if_unopened(b));
  SVN_ERR(svn_stream_seek(b->real_stream, mark));

  return SVN_NO_ERROR;
}
Beispiel #2
0
static svn_error_t *
test_stream_seek_stringbuf(apr_pool_t *pool)
{
  svn_stream_t *stream;
  svn_stringbuf_t *stringbuf;
  char buf[4];
  apr_size_t len;
  svn_stream_mark_t *mark;

  stringbuf = svn_stringbuf_create("OneTwo", pool);
  stream = svn_stream_from_stringbuf(stringbuf, pool);
  len = 3;
  SVN_ERR(svn_stream_read_full(stream, buf, &len));
  buf[3] = '\0';
  SVN_TEST_STRING_ASSERT(buf, "One");
  SVN_ERR(svn_stream_mark(stream, &mark, pool));
  len = 3;
  SVN_ERR(svn_stream_read_full(stream, buf, &len));
  buf[3] = '\0';
  SVN_TEST_STRING_ASSERT(buf, "Two");
  SVN_ERR(svn_stream_seek(stream, mark));
  len = 3;
  SVN_ERR(svn_stream_read_full(stream, buf, &len));
  buf[3] = '\0';
  SVN_TEST_STRING_ASSERT(buf, "Two");

  /* Go back to the begin of last word and try to skip some of it */
  SVN_ERR(svn_stream_seek(stream, mark));
  SVN_ERR(svn_stream_skip(stream, 2));
  /* The remaining line should be empty */
  len = 3;
  SVN_ERR(svn_stream_read_full(stream, buf, &len));
  buf[len] = '\0';
  SVN_TEST_ASSERT(len == 1);
  SVN_TEST_STRING_ASSERT(buf, "o");

  SVN_ERR(svn_stream_close(stream));

  return SVN_NO_ERROR;
}
Beispiel #3
0
static svn_error_t *
test_stream_seek_translated(apr_pool_t *pool)
{
  svn_stream_t *stream, *translated_stream;
  svn_stringbuf_t *stringbuf;
  char buf[44]; /* strlen("One$MyKeyword: my keyword was expanded $Two") + \0 */
  apr_size_t len;
  svn_stream_mark_t *mark;
  apr_hash_t *keywords;
  svn_string_t *keyword_val;

  keywords = apr_hash_make(pool);
  keyword_val = svn_string_create("my keyword was expanded", pool);
  apr_hash_set(keywords, "MyKeyword", APR_HASH_KEY_STRING, keyword_val);
  stringbuf = svn_stringbuf_create("One$MyKeyword$Two", pool);
  stream = svn_stream_from_stringbuf(stringbuf, pool);
  translated_stream = svn_subst_stream_translated(stream, APR_EOL_STR,
                                                  FALSE, keywords, TRUE, pool);
  /* Seek from outside of keyword to inside of keyword. */
  len = 25;
  SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
  SVN_TEST_ASSERT(len == 25);
  buf[25] = '\0';
  SVN_TEST_STRING_ASSERT(buf, "One$MyKeyword: my keyword");
  SVN_ERR(svn_stream_mark(translated_stream, &mark, pool));
  SVN_ERR(svn_stream_reset(translated_stream));
  SVN_ERR(svn_stream_seek(translated_stream, mark));
  len = 4;
  SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
  SVN_TEST_ASSERT(len == 4);
  buf[4] = '\0';
  SVN_TEST_STRING_ASSERT(buf, " was");

  SVN_ERR(svn_stream_seek(translated_stream, mark));
  SVN_ERR(svn_stream_skip(translated_stream, 2));
  len = 2;
  SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
  SVN_TEST_ASSERT(len == 2);
  buf[len] = '\0';
  SVN_TEST_STRING_ASSERT(buf, "as");

  /* Seek from inside of keyword to inside of keyword. */
  SVN_ERR(svn_stream_mark(translated_stream, &mark, pool));
  len = 9;
  SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
  SVN_TEST_ASSERT(len == 9);
  buf[9] = '\0';
  SVN_TEST_STRING_ASSERT(buf, " expanded");
  SVN_ERR(svn_stream_seek(translated_stream, mark));
  len = 9;
  SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
  SVN_TEST_ASSERT(len == 9);
  buf[9] = '\0';
  SVN_TEST_STRING_ASSERT(buf, " expanded");

  SVN_ERR(svn_stream_seek(translated_stream, mark));
  SVN_ERR(svn_stream_skip(translated_stream, 6));
  len = 3;
  SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
  SVN_TEST_ASSERT(len == 3);
  buf[len] = '\0';
  SVN_TEST_STRING_ASSERT(buf, "ded");

  /* Seek from inside of keyword to outside of keyword. */
  SVN_ERR(svn_stream_mark(translated_stream, &mark, pool));
  len = 4;
  SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
  SVN_TEST_ASSERT(len == 4);
  buf[4] = '\0';
  SVN_TEST_STRING_ASSERT(buf, " $Tw");
  SVN_ERR(svn_stream_seek(translated_stream, mark));
  len = 4;
  SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
  SVN_TEST_ASSERT(len == 4);
  buf[4] = '\0';
  SVN_TEST_STRING_ASSERT(buf, " $Tw");

  SVN_ERR(svn_stream_seek(translated_stream, mark));
  SVN_ERR(svn_stream_skip(translated_stream, 2));
  len = 2;
  SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
  SVN_TEST_ASSERT(len == 2);
  buf[len] = '\0';
  SVN_TEST_STRING_ASSERT(buf, "Tw");

  /* Seek from outside of keyword to outside of keyword. */
  SVN_ERR(svn_stream_mark(translated_stream, &mark, pool));
  len = 1;
  SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
  SVN_TEST_ASSERT(len == 1);
  buf[1] = '\0';
  SVN_TEST_STRING_ASSERT(buf, "o");
  SVN_ERR(svn_stream_seek(translated_stream, mark));
  len = 1;
  SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
  SVN_TEST_ASSERT(len == 1);
  buf[1] = '\0';
  SVN_TEST_STRING_ASSERT(buf, "o");

  SVN_ERR(svn_stream_seek(translated_stream, mark));
  SVN_ERR(svn_stream_skip(translated_stream, 2));
  len = 1;
  SVN_ERR(svn_stream_read_full(translated_stream, buf, &len));
  SVN_TEST_ASSERT(len == 0);
  buf[len] = '\0';
  SVN_TEST_STRING_ASSERT(buf, "");

  SVN_ERR(svn_stream_close(stream));

  return SVN_NO_ERROR;
}
Beispiel #4
0
static svn_error_t *
test_stream_seek_file(apr_pool_t *pool)
{
  static const char *file_data[2] = {"One", "Two"};
  svn_stream_t *stream;
  svn_stringbuf_t *line;
  svn_boolean_t eof;
  apr_file_t *f;
  static const char *fname = "test_stream_seek.txt";
  int j;
  apr_status_t status;
  static const char *NL = APR_EOL_STR;
  svn_stream_mark_t *mark;

  status = apr_file_open(&f, fname, (APR_READ | APR_WRITE | APR_CREATE |
                         APR_TRUNCATE | APR_DELONCLOSE), APR_OS_DEFAULT, pool);
  if (status != APR_SUCCESS)
    return svn_error_createf(SVN_ERR_TEST_FAILED, NULL, "Cannot open '%s'",
                             fname);

  /* Create the file. */
  for (j = 0; j < 2; j++)
    {
      apr_size_t len;

      len = strlen(file_data[j]);
      status = apr_file_write(f, file_data[j], &len);
      if (status || len != strlen(file_data[j]))
        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
                                 "Cannot write to '%s'", fname);
      len = strlen(NL);
      status = apr_file_write(f, NL, &len);
      if (status || len != strlen(NL))
        return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
                                 "Cannot write to '%s'", fname);
    }

  /* Create a stream to read from the file. */
  stream = svn_stream_from_aprfile2(f, FALSE, pool);
  SVN_ERR(svn_stream_reset(stream));
  SVN_ERR(svn_stream_readline(stream, &line, NL, &eof, pool));
  SVN_TEST_ASSERT(! eof && strcmp(line->data, file_data[0]) == 0);
  /* Set a mark at the beginning of the second line of the file. */
  SVN_ERR(svn_stream_mark(stream, &mark, pool));
  /* Read the second line and then seek back to the mark. */
  SVN_ERR(svn_stream_readline(stream, &line, NL, &eof, pool));
  SVN_TEST_ASSERT(! eof && strcmp(line->data, file_data[1]) == 0);
  SVN_ERR(svn_stream_seek(stream, mark));
  /* The next read should return the second line again. */
  SVN_ERR(svn_stream_readline(stream, &line, NL, &eof, pool));
  SVN_TEST_ASSERT(! eof && strcmp(line->data, file_data[1]) == 0);
  /* The next read should return EOF. */
  SVN_ERR(svn_stream_readline(stream, &line, NL, &eof, pool));
  SVN_TEST_ASSERT(eof);

  /* Go back to the beginning of the last line and try to skip it
   * NOT including the EOL. */
  SVN_ERR(svn_stream_seek(stream, mark));
  SVN_ERR(svn_stream_skip(stream, strlen(file_data[1])));
  /* The remaining line should be empty */
  SVN_ERR(svn_stream_readline(stream, &line, NL, &eof, pool));
  SVN_TEST_ASSERT(! eof && strcmp(line->data, "") == 0);
  /* The next read should return EOF. */
  SVN_ERR(svn_stream_readline(stream, &line, NL, &eof, pool));
  SVN_TEST_ASSERT(eof);

  SVN_ERR(svn_stream_close(stream));

  return SVN_NO_ERROR;
}
/* Writes out a git-like literal output of the compressed data in
   COMPRESSED_DATA to OUTPUT_STREAM, describing that its normal length is
   UNCOMPRESSED_SIZE. */
static svn_error_t *
write_literal(svn_filesize_t uncompressed_size,
              svn_stream_t *compressed_data,
              svn_stream_t *output_stream,
              svn_cancel_func_t cancel_func,
              void *cancel_baton,
              apr_pool_t *scratch_pool)
{
  apr_size_t rd;
  SVN_ERR(svn_stream_seek(compressed_data, NULL)); /* Seek to start */

  SVN_ERR(svn_stream_printf(output_stream, scratch_pool,
                            "literal %" SVN_FILESIZE_T_FMT APR_EOL_STR,
                            uncompressed_size));

  do
    {
      char chunk[GIT_BASE85_CHUNKSIZE];
      const unsigned char *next;
      apr_size_t left;

      rd = sizeof(chunk);

      if (cancel_func)
        SVN_ERR(cancel_func(cancel_baton));

      SVN_ERR(svn_stream_read_full(compressed_data, chunk, &rd));

      {
        apr_size_t one = 1;
        SVN_ERR(svn_stream_write(output_stream, &b85lenstr[rd-1], &one));
      }

      left = rd;
      next = (void*)chunk;
      while (left)
      {
        char five[5];
        unsigned info = 0;
        int n;
        apr_size_t five_sz;

        /* Push 4 bytes into the 32 bit info, when available */
        for (n = 24; n >= 0 && left; n -= 8, next++, left--)
        {
            info |= (*next) << n;
        }

        /* Write out info as base85 */
        for (n = 4; n >= 0; n--)
        {
            five[n] = b85str[info % 85];
            info /= 85;
        }

        five_sz = 5;
        SVN_ERR(svn_stream_write(output_stream, five, &five_sz));
      }

      SVN_ERR(svn_stream_puts(output_stream, APR_EOL_STR));
    }
  while (rd == GIT_BASE85_CHUNKSIZE);

  return SVN_NO_ERROR;
}
Beispiel #6
0
static svn_error_t *
seek_handler_disown(void *baton, const svn_stream_mark_t *mark)
{
  return svn_error_trace(svn_stream_seek(baton, mark));
}
Beispiel #7
0
static svn_error_t *
stream_readline_chunky(svn_stringbuf_t **stringbuf,
                       svn_boolean_t *eof,
                       const char *eol,
                       svn_stream_t *stream,
                       apr_pool_t *pool)
{
  /* Read larger chunks of data at once into this buffer and scan
   * that for EOL. A good chunk size should be about 80 chars since
   * most text lines will be shorter. However, don't use a much
   * larger value because filling the buffer from the stream takes
   * time as well.
   */
  char buffer[LINE_CHUNK_SIZE+1];

  /* variables */
  svn_stream_mark_t *mark;
  apr_size_t numbytes;
  const char *eol_pos;
  apr_size_t total_parsed = 0;

  /* invariant for this call */
  const size_t eol_len = strlen(eol);

  /* Remember the line start so this plus the line length will be
   * the position to move to at the end of this function.
   */
  SVN_ERR(svn_stream_mark(stream, &mark, pool));

  /* Read the first chunk. */
  numbytes = LINE_CHUNK_SIZE;
  SVN_ERR(svn_stream_read(stream, buffer, &numbytes));
  buffer[numbytes] = '\0';

  /* Look for the EOL in this first chunk. If we find it, we are done here.
   */
  eol_pos = strstr(buffer, eol);
  if (eol_pos != NULL)
    {
      *stringbuf = svn_stringbuf_ncreate(buffer, eol_pos - buffer, pool);
      total_parsed = eol_pos - buffer + eol_len;
    }
  else if (numbytes < LINE_CHUNK_SIZE)
    {
      /* We hit EOF but not EOL.
       */
      *stringbuf = svn_stringbuf_ncreate(buffer, numbytes, pool);
      *eof = TRUE;
      return SVN_NO_ERROR;
     }
  else
    {
      /* A larger buffer for the string is needed. */
      svn_stringbuf_t *str;
      str = svn_stringbuf_create_ensure(2*LINE_CHUNK_SIZE, pool);
      svn_stringbuf_appendbytes(str, buffer, numbytes);
      *stringbuf = str;

      /* Loop reading chunks until an EOL was found. If we hit EOF, fall
       * back to the standard implementation. */
      do
      {
        /* Append the next chunk to the string read so far.
         */
        svn_stringbuf_ensure(str, str->len + LINE_CHUNK_SIZE);
        numbytes = LINE_CHUNK_SIZE;
        SVN_ERR(svn_stream_read(stream, str->data + str->len, &numbytes));
        str->len += numbytes;
        str->data[str->len] = '\0';

        /* Look for the EOL in the new data plus the last part of the
         * previous chunk because the EOL may span over the boundary
         * between both chunks.
         */
        eol_pos = strstr(str->data + str->len - numbytes - (eol_len-1), eol);

        if ((numbytes < LINE_CHUNK_SIZE) && (eol_pos == NULL))
        {
          /* We hit EOF instead of EOL. */
          *eof = TRUE;
          return SVN_NO_ERROR;
        }
      }
      while (eol_pos == NULL);

      /* Number of bytes we actually consumed (i.e. line + EOF).
       * We need to "return" the rest to the stream by moving its
       * read pointer.
       */
      total_parsed = eol_pos - str->data + eol_len;

      /* Terminate the string at the EOL postion and return it. */
      str->len = eol_pos - str->data;
      str->data[str->len] = 0;
    }

  /* Move the stream read pointer to the first position behind the EOL.
   */
  SVN_ERR(svn_stream_seek(stream, mark));
  return svn_error_trace(svn_stream_skip(stream, total_parsed));
}
Beispiel #8
0
svn_error_t *
svn_stream_reset(svn_stream_t *stream)
{
  return svn_error_trace(
            svn_stream_seek(stream, NULL));
}