/*	$OpenBSD: citrus_utf8.c,v 1.6 2012/12/05 23:19:59 deraadt Exp $ */

/*-
 * Copyright (c) 2002-2004 Tim J. Robbins
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <errno.h>
#include <sys/param.h>
#include <string.h>
#include <wchar.h>
#include <uchar.h>

#include "private/bionic_mbstate.h"

//
// This file is basically OpenBSD's citrus_utf8.c but rewritten to not require a
// 12-byte mbstate_t so we're backwards-compatible with our LP32 ABI where
// mbstate_t was only 4 bytes.
//
// The state is the UTF-8 sequence. We only support <= 4-bytes sequences so LP32
// mbstate_t already has enough space (out of the 4 available bytes we only
// need 3 since we should never need to store the entire sequence in the
// intermediary state).
//
// The C standard leaves the conversion state undefined after a bad conversion.
// To avoid unexpected failures due to the possible use of the internal private
// state we always reset the conversion state when encountering illegal
// sequences.
//
// We also implement the POSIX interface directly rather than being accessed via
// function pointers.
//

int mbsinit(const mbstate_t* ps) {
  return (ps == NULL || (*(reinterpret_cast<const uint32_t*>(ps->__seq)) == 0));
}

size_t mbrtowc(wchar_t* pwc, const char* s, size_t n, mbstate_t* ps) {
  static mbstate_t __private_state;
  mbstate_t* state = (ps == NULL) ? &__private_state : ps;

  // Our wchar_t is UTF-32
  return mbrtoc32(reinterpret_cast<char32_t*>(pwc), s, n, state);
}

size_t mbsnrtowcs(wchar_t* dst, const char** src, size_t nmc, size_t len, mbstate_t* ps) {
  static mbstate_t __private_state;
  mbstate_t* state = (ps == NULL) ? &__private_state : ps;
  size_t i, o, r;

  if (dst == NULL) {
    /*
     * The fast path in the loop below is not safe if an ASCII
     * character appears as anything but the first byte of a
     * multibyte sequence. Check now to avoid doing it in the loop.
     */
    if ((nmc > 0) && (mbstate_bytes_so_far(state) > 0)
        && (static_cast<uint8_t>((*src)[0]) < 0x80)) {
      return reset_and_return_illegal(EILSEQ, state);
    }
    for (i = o = 0; i < nmc; i += r, o++) {
      if (static_cast<uint8_t>((*src)[i]) < 0x80) {
        // Fast path for plain ASCII characters.
        if ((*src)[i] == '\0') {
          return reset_and_return(o, state);
        }
        r = 1;
      } else {
        r = mbrtowc(NULL, *src + i, nmc - i, state);
        if (r == __MB_ERR_ILLEGAL_SEQUENCE) {
          return reset_and_return_illegal(EILSEQ, state);
        }
        if (r == __MB_ERR_INCOMPLETE_SEQUENCE) {
          return reset_and_return_illegal(EILSEQ, state);
        }
        if (r == 0) {
          return reset_and_return(o, state);
        }
      }
    }
    return reset_and_return(o, state);
  }

  /*
   * The fast path in the loop below is not safe if an ASCII
   * character appears as anything but the first byte of a
   * multibyte sequence. Check now to avoid doing it in the loop.
   */
  if ((nmc > 0) && (mbstate_bytes_so_far(state) > 0)
      && (static_cast<uint8_t>((*src)[0]) < 0x80)) {
    return reset_and_return_illegal(EILSEQ, state);
  }
  for (i = o = 0; i < nmc && o < len; i += r, o++) {
    if (static_cast<uint8_t>((*src)[i]) < 0x80) {
      // Fast path for plain ASCII characters.
      dst[o] = (*src)[i];
      r = 1;
      if ((*src)[i] == '\0') {
        break;
      }
    } else {
      r = mbrtowc(dst + o, *src + i, nmc - i, state);
      if (r == __MB_ERR_ILLEGAL_SEQUENCE) {
        *src += i;
        return reset_and_return_illegal(EILSEQ, state);
      }
      if (r == __MB_ERR_INCOMPLETE_SEQUENCE) {
        *src += nmc;
        return reset_and_return(EILSEQ, state);
      }
      if (r == 0) {
        *src = NULL;
        return reset_and_return(o, state);
      }
    }
  }
  *src += i;
  return reset_and_return(o, state);
}

size_t mbsrtowcs(wchar_t* dst, const char** src, size_t len, mbstate_t* ps) {
  return mbsnrtowcs(dst, src, SIZE_MAX, len, ps);
}

size_t wcrtomb(char* s, wchar_t wc, mbstate_t* ps) {
  static mbstate_t __private_state;
  mbstate_t* state = (ps == NULL) ? &__private_state : ps;

  // Our wchar_t is UTF-32
  return c32rtomb(s, static_cast<char32_t>(wc), state);
}

size_t wcsnrtombs(char* dst, const wchar_t** src, size_t nwc, size_t len, mbstate_t* ps) {
  static mbstate_t __private_state;
  mbstate_t* state = (ps == NULL) ? &__private_state : ps;

  if (!mbsinit(state)) {
    return reset_and_return_illegal(EILSEQ, state);
  }

  char buf[MB_LEN_MAX];
  size_t i, o, r;
  if (dst == NULL) {
    for (i = o = 0; i < nwc; i++, o += r) {
      wchar_t wc = (*src)[i];
      if (static_cast<uint32_t>(wc) < 0x80) {
        // Fast path for plain ASCII characters.
        if (wc == 0) {
          return o;
        }
        r = 1;
      } else {
        r = wcrtomb(buf, wc, state);
        if (r == __MB_ERR_ILLEGAL_SEQUENCE) {
          return r;
        }
      }
    }
    return o;
  }

  for (i = o = 0; i < nwc && o < len; i++, o += r) {
    wchar_t wc = (*src)[i];
    if (static_cast<uint32_t>(wc) < 0x80) {
      // Fast path for plain ASCII characters.
      dst[o] = wc;
      if (wc == 0) {
        *src = NULL;
        return o;
      }
      r = 1;
    } else if (len - o >= sizeof(buf)) {
      // Enough space to translate in-place.
      r = wcrtomb(dst + o, wc, state);
      if (r == __MB_ERR_ILLEGAL_SEQUENCE) {
        *src += i;
        return r;
      }
    } else {
      // May not be enough space; use temp buffer.
      r = wcrtomb(buf, wc, state);
      if (r == __MB_ERR_ILLEGAL_SEQUENCE) {
        *src += i;
        return r;
      }
      if (r > len - o) {
        break;
      }
      memcpy(dst + o, buf, r);
    }
  }
  *src += i;
  return o;
}

size_t wcsrtombs(char* dst, const wchar_t** src, size_t len, mbstate_t* ps) {
  return wcsnrtombs(dst, src, SIZE_MAX, len, ps);
}

int wcscoll_l(const wchar_t *ws1, const wchar_t *ws2, locale_t) {
  return wcscoll(ws1, ws2);
}

size_t wcsxfrm_l(wchar_t *dest, const wchar_t *src, size_t n, locale_t) {
  return wcsxfrm(dest, src, n);
}

long long wcstoll_l(const wchar_t *nptr, wchar_t **endptr, size_t base,
                    locale_t) {
  return wcstoll(nptr, endptr, base);
}

unsigned long long wcstoull_l(const wchar_t *nptr, wchar_t **endptr,
                              size_t base, locale_t) {
  return wcstoull(nptr, endptr, base);
}

long double wcstold_l(const wchar_t *nptr, wchar_t **endptr, locale_t) {
  return wcstold(nptr, endptr);
}
