Esempio n. 1
0
static bool
open_mixed (struct mixed *mixed, RECODE_TASK task)
{
  mixed->input_name = task->input.name;
  mixed->output_name = task->output.name;
  task->strategy = RECODE_SEQUENCE_IN_MEMORY;
  task->byte_order_mark = false;

  /* Open both files ourselves.  */

  if (!*(task->input.name))
    task->input.file = stdin;
  else if (task->input.file = fopen (mixed->input_name, "r"),
	   !task->input.file)
    {
      recode_perror (NULL, "fopen (%s)", task->input.name);
      return false;
    }
  task->input.name = NULL;

  if (!*(task->output.name))
    task->output.file = stdout;
  else if (task->output.file = fopen (mixed->output_name, "w"),
	   !task->output.file)
    {
      recode_perror (NULL, "fopen (%s)", task->output.name);
      if (*(task->input.name))
	fclose (task->input.file);
      return false;
    }
  task->output.name = NULL;

  /* Prepare for dynamic plumbing copy.  */

  memset (&mixed->subtask, 0, sizeof (struct recode_subtask));
  mixed->subtask.task = task;
  mixed->subtask.input = task->input;
  mixed->subtask.output = task->output;
  memset (&mixed->buffer, 0, sizeof (struct recode_read_write_text));

  return true;
}
Esempio n. 2
0
static bool
wrapped_transform (iconv_t conversion, RECODE_SUBTASK subtask)
{
  char output_buffer[BUFFER_SIZE];
  char input_buffer[BUFFER_SIZE];
  int input_char = get_byte (subtask);
  char *cursor = input_buffer;
  bool drain_first = false;

  while (true)
    {
      /* The output buffer is fully avaible at this point.  */

      char *input = input_buffer;
      char *output = output_buffer;
      size_t input_left = 0;
      size_t output_left = BUFFER_SIZE;
      int saved_errno = 0;
      size_t converted;

      if (drain_first)
        {
          /* Drain all accumulated partial state and emit output
             to return to the initial shift state.  */
          converted = iconv (conversion, NULL, NULL, &output, &output_left);
          if (converted == (size_t) -1)
            saved_errno = errno;
        }

      if (saved_errno == 0)
        {
          /* Continue filling the input buffer.  */
          while (input_char != EOF && cursor < input_buffer + BUFFER_SIZE)
            {
              *cursor++ = input_char;
              input_char = get_byte (subtask);
            }

          if (cursor == input_buffer)
            {
              if (output == output_buffer)
                {
                  /* All work has been done, just make sure we drained.  */
                  if (drain_first)
                    break;
                  drain_first = true;
                  continue;
                }
            }
          else
            {
              /* Convert accumulated input and add it to the output buffer.  */
              input = input_buffer;
              input_left = cursor - input_buffer;
              converted = iconv (conversion,
                                 &input, &input_left,
                                 &output, &output_left);
              if (converted == (size_t) -1)
                saved_errno = errno;
            }
        }

      /* Send the converted result, so freeing the output buffer.  */
      for (cursor = output_buffer; cursor < output; cursor++)
        put_byte (*cursor, subtask);

      /* Act according to the outcome of the iconv call.  */

      drain_first = false;
      if (saved_errno != 0 && saved_errno != E2BIG)
	{
	  if (saved_errno == EILSEQ)
	    {
	      /* Invalid input.  Skip one byte.  */
	      RETURN_IF_NOGO (RECODE_INVALID_INPUT, subtask);
	      assert (input_left > 0);
	      input++;
	      input_left--;
	      /* Why is draining required?  */
	      drain_first = true;
	    }
	  else if (saved_errno == EINVAL)
	    {
	      if (input + input_left < input_buffer + BUFFER_SIZE
		  && input_char == EOF)
		/* Incomplete multibyte sequence at end of input.  */
		RETURN_IF_NOGO (RECODE_INVALID_INPUT, subtask);
	    }
	  else
	    {
	      recode_perror (subtask->task->request->outer, "iconv ()");
	      RETURN_IF_NOGO (RECODE_SYSTEM_ERROR, subtask);
	    }
	}

      /* Move back any unprocessed part of the input buffer.  */
      for (cursor = input_buffer; input_left != 0; input_left--)
        *cursor++ = *input++;
    }

  SUBTASK_RETURN (subtask);
}