/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdlib.h>
#include "utf16char.h"

namespace ime_pinyin {

#ifdef __cplusplus
extern "C" {
#endif

  char16* utf16_strtok(char16 *utf16_str, size_t *token_size,
                       char16 **utf16_str_next) {
    if (NULL == utf16_str || NULL == token_size || NULL == utf16_str_next) {
      return NULL;
    }

    // Skip the splitters
    size_t pos = 0;
    while ((char16)' ' == utf16_str[pos] || (char16)'\n' == utf16_str[pos]
           || (char16)'\t' == utf16_str[pos])
      pos++;

    utf16_str += pos;
    pos = 0;

    while ((char16)'\0' != utf16_str[pos] && (char16)' ' != utf16_str[pos]
           && (char16)'\n' != utf16_str[pos]
           && (char16)'\t' != utf16_str[pos]) {
      pos++;
    }

    char16 *ret_val = utf16_str;
    if ((char16)'\0' == utf16_str[pos]) {
      *utf16_str_next = NULL;
      if (0 == pos)
        return NULL;
    } else {
      *utf16_str_next = utf16_str + pos + 1;
    }

    utf16_str[pos] = (char16)'\0';
    *token_size = pos;

    return ret_val;
  }

  int utf16_atoi(const char16 *utf16_str) {
    if (NULL == utf16_str)
      return 0;

    int value = 0;
    int sign = 1;
    size_t pos = 0;

    if ((char16)'-' == utf16_str[pos]) {
      sign = -1;
      pos++;
    }

    while ((char16)'0' <=  utf16_str[pos] &&
           (char16)'9' >= utf16_str[pos]) {
      value = value * 10 + static_cast<int>(utf16_str[pos] - (char16)'0');
      pos++;
    }

    return value*sign;
  }

  float utf16_atof(const char16 *utf16_str) {
    // A temporary implemetation.
    char char8[256];
    if (utf16_strlen(utf16_str) >= 256) return 0;

    utf16_strcpy_tochar(char8, utf16_str);
    return atof(char8);
  }

  size_t utf16_strlen(const char16 *utf16_str) {
    if (NULL == utf16_str)
      return 0;

    size_t size = 0;
    while ((char16)'\0' != utf16_str[size])
      size++;
    return size;
  }

  int utf16_strcmp(const char16* str1, const char16* str2) {
    size_t pos = 0;
    while (str1[pos] == str2[pos] && (char16)'\0' != str1[pos])
      pos++;

    return static_cast<int>(str1[pos]) - static_cast<int>(str2[pos]);
  }

  int utf16_strncmp(const char16 *str1, const char16 *str2, size_t size) {
    size_t pos = 0;
    while (pos < size && str1[pos] == str2[pos] && (char16)'\0' != str1[pos])
      pos++;

    if (pos == size)
      return 0;

    return static_cast<int>(str1[pos]) - static_cast<int>(str2[pos]);
  }

  // we do not consider overlapping
  char16* utf16_strcpy(char16 *dst, const char16 *src) {
    if (NULL == src || NULL == dst)
      return NULL;

    char16* cp = dst;

    while ((char16)'\0' != *src) {
      *cp = *src;
      cp++;
      src++;
    }

    *cp = *src;

    return dst;
  }

  char16* utf16_strncpy(char16 *dst, const char16 *src, size_t size) {
    if (NULL == src || NULL == dst || 0 == size)
      return NULL;

    if (src == dst)
      return dst;

    char16* cp = dst;

    if (dst < src || (dst > src && dst >= src + size)) {
      while (size-- && (*cp++ = *src++))
        ;
    } else {
      cp += size - 1;
      src += size - 1;
      while (size-- && (*cp-- == *src--))
        ;
    }
    return dst;
  }

  // We do not handle complicated cases like overlapping, because in this
  // codebase, it is not necessary.
  char* utf16_strcpy_tochar(char *dst, const char16 *src) {
    if (NULL == src || NULL == dst)
      return NULL;

    char* cp = dst;

    while ((char16)'\0' != *src) {
      *cp = static_cast<char>(*src);
      cp++;
      src++;
    }
    *cp = *src;

    return dst;
  }

#ifdef __cplusplus
}
#endif
}  // namespace ime_pinyin
