/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

// When the platform supports STL, the functions are implemented using a
// templated spreadsort algorithm (http://sourceforge.net/projects/spreadsort/),
// part of the Boost C++ library collection. Otherwise, the C standard library's
// qsort() will be used.

#include "webrtc/system_wrappers/interface/sort.h"

#include <assert.h>
#include <string.h>  // memcpy

#include <new>      // nothrow new

#ifdef NO_STL
#include <stdlib.h>      // qsort
#else
#include <algorithm>    // std::sort
#include <vector>

// TODO(ajm) upgrade to spreadsort v2.
#include "webrtc/system_wrappers/source/spreadsortlib/spreadsort.hpp"
#endif

#ifdef NO_STL
#define COMPARE_DEREFERENCED(XT, YT)      \
  do {                                    \
    if ((XT) > (YT)) {                    \
      return 1;                           \
    }                                     \
    else if ((XT) < (YT)) {               \
      return -1;                          \
    }                                     \
    return 0;                             \
  } while(0)

#define COMPARE_FOR_QSORT(X, Y, TYPE)                           \
  do {                                                          \
    TYPE xT = static_cast<TYPE>(*static_cast<const TYPE*>(X));  \
    TYPE yT = static_cast<TYPE>(*static_cast<const TYPE*>(Y));  \
    COMPARE_DEREFERENCED(xT, yT);                               \
  } while(0)

#define COMPARE_KEY_FOR_QSORT(SORT_KEY_X, SORT_KEY_Y, TYPE)                   \
  do {                                                                        \
    TYPE xT = static_cast<TYPE>(                                              \
        *static_cast<TYPE*>(static_cast<const SortKey*>(SORT_KEY_X)->key_));  \
    TYPE yT = static_cast<TYPE>(                                              \
        *static_cast<TYPE*>(static_cast<const SortKey*>(SORT_KEY_Y)->key_));  \
    COMPARE_DEREFERENCED(xT, yT);                                             \
  } while(0)

#define KEY_QSORT(SORT_KEY, KEY, NUM_OF_ELEMENTS, KEY_TYPE, COMPARE_FUNC)     \
  do {                                                                        \
    KEY_TYPE* key_type = (KEY_TYPE*)(key);                                    \
    for (uint32_t i = 0; i < (NUM_OF_ELEMENTS); ++i) {                  \
      ptr_sort_key[i].key_ = &key_type[i];                                    \
      ptr_sort_key[i].index_ = i;                                             \
    }                                                                         \
    qsort((SORT_KEY), (NUM_OF_ELEMENTS), sizeof(SortKey), (COMPARE_FUNC));    \
  } while(0)
#endif

namespace webrtc {

#ifdef NO_STL
struct SortKey {
  void* key_;
  uint32_t index_;
};
#else
template<typename KeyType>
struct SortKey {
  KeyType key_;
  uint32_t index_;
};
#endif

namespace {  // Unnamed namespace provides internal linkage.

#ifdef NO_STL
int CompareWord8(const void* x, const void* y) {
  COMPARE_FOR_QSORT(x, y, int8_t);
}

int CompareUWord8(const void* x, const void* y) {
  COMPARE_FOR_QSORT(x, y, uint8_t);
}

int CompareWord16(const void* x, const void* y) {
  COMPARE_FOR_QSORT(x, y, int16_t);
}

int CompareUWord16(const void* x, const void* y) {
  COMPARE_FOR_QSORT(x, y, uint16_t);
}

int CompareWord32(const void* x, const void* y) {
  COMPARE_FOR_QSORT(x, y, int32_t);
}

int CompareUWord32(const void* x, const void* y) {
  COMPARE_FOR_QSORT(x, y, uint32_t);
}

int CompareWord64(const void* x, const void* y) {
  COMPARE_FOR_QSORT(x, y, int64_t);
}

int CompareUWord64(const void* x, const void* y) {
  COMPARE_FOR_QSORT(x, y, uint64_t);
}

int CompareFloat32(const void* x, const void* y) {
  COMPARE_FOR_QSORT(x, y, float);
}

int CompareFloat64(const void* x, const void* y) {
  COMPARE_FOR_QSORT(x, y, double);
}

int CompareKeyWord8(const void* sort_key_x, const void* sort_key_y) {
  COMPARE_KEY_FOR_QSORT(sort_key_x, sort_key_y, int8_t);
}

int CompareKeyUWord8(const void* sort_key_x, const void* sort_key_y) {
  COMPARE_KEY_FOR_QSORT(sort_key_x, sort_key_y, uint8_t);
}

int CompareKeyWord16(const void* sort_key_x, const void* sort_key_y) {
  COMPARE_KEY_FOR_QSORT(sort_key_x, sort_key_y, int16_t);
}

int CompareKeyUWord16(const void* sort_key_x, const void* sort_key_y) {
  COMPARE_KEY_FOR_QSORT(sort_key_x, sort_key_y, uint16_t);
}

int CompareKeyWord32(const void* sort_key_x, const void* sort_key_y) {
  COMPARE_KEY_FOR_QSORT(sort_key_x, sort_key_y, int32_t);
}

int CompareKeyUWord32(const void* sort_key_x, const void* sort_key_y) {
  COMPARE_KEY_FOR_QSORT(sort_key_x, sort_key_y, uint32_t);
}

int CompareKeyWord64(const void* sort_key_x, const void* sort_key_y) {
  COMPARE_KEY_FOR_QSORT(sort_key_x, sort_key_y, int64_t);
}

int CompareKeyUWord64(const void* sort_key_x, const void* sort_key_y) {
  COMPARE_KEY_FOR_QSORT(sort_key_x, sort_key_y, uint64_t);
}

int CompareKeyFloat32(const void* sort_key_x, const void* sort_key_y) {
  COMPARE_KEY_FOR_QSORT(sort_key_x, sort_key_y, float);
}

int CompareKeyFloat64(const void* sort_key_x, const void* sort_key_y) {
  COMPARE_KEY_FOR_QSORT(sort_key_x, sort_key_y, double);
}
#else
template <typename KeyType>
struct KeyLessThan {
  bool operator()(const SortKey<KeyType>& sort_key_x,
                  const SortKey<KeyType>& sort_key_y) const {
    return sort_key_x.key_ < sort_key_y.key_;
  }
};

template <typename KeyType>
struct KeyRightShift {
  KeyType operator()(const SortKey<KeyType>& sort_key,
                     const unsigned offset) const {
    return sort_key.key_ >> offset;
  }
};

template <typename DataType>
inline void IntegerSort(void* data, uint32_t num_of_elements) {
  DataType* data_type = static_cast<DataType*>(data);
  boost::integer_sort(data_type, data_type + num_of_elements);
}

template <typename DataType, typename IntegerType>
inline void FloatSort(void* data, uint32_t num_of_elements) {
  DataType* data_type = static_cast<DataType*>(data);
  IntegerType c_val = 0;
  boost::float_sort_cast(data_type, data_type + num_of_elements, c_val);
}

template <typename DataType>
inline void StdSort(void* data, uint32_t num_of_elements) {
  DataType* data_type = static_cast<DataType*>(data);
  std::sort(data_type, data_type + num_of_elements);
}

template<typename KeyType>
inline int32_t SetupKeySort(void* key,
                            SortKey<KeyType>*& ptr_sort_key,
                            uint32_t num_of_elements) {
  ptr_sort_key = new(std::nothrow) SortKey<KeyType>[num_of_elements];
  if (ptr_sort_key == NULL) {
    return -1;
  }

  KeyType* key_type = static_cast<KeyType*>(key);
  for (uint32_t i = 0; i < num_of_elements; i++) {
    ptr_sort_key[i].key_ = key_type[i];
    ptr_sort_key[i].index_ = i;
  }

  return 0;
}

template<typename KeyType>
inline int32_t TeardownKeySort(void* data,
                               SortKey<KeyType>* ptr_sort_key,
                               uint32_t num_of_elements,
                               uint32_t size_of_element) {
  uint8_t* ptr_data = static_cast<uint8_t*>(data);
  uint8_t* ptr_data_sorted =
      new(std::nothrow) uint8_t[num_of_elements * size_of_element];
  if (ptr_data_sorted == NULL) {
    return -1;
  }

  for (uint32_t i = 0; i < num_of_elements; i++) {
    memcpy(ptr_data_sorted + i * size_of_element, ptr_data +
           ptr_sort_key[i].index_ * size_of_element, size_of_element);
  }
  memcpy(ptr_data, ptr_data_sorted, num_of_elements * size_of_element);
  delete[] ptr_sort_key;
  delete[] ptr_data_sorted;
  return 0;
}

template<typename KeyType>
inline int32_t IntegerKeySort(void* data, void* key,
                              uint32_t num_of_elements,
                              uint32_t size_of_element) {
  SortKey<KeyType>* ptr_sort_key;
  if (SetupKeySort<KeyType>(key, ptr_sort_key, num_of_elements) != 0) {
    return -1;
  }

  boost::integer_sort(ptr_sort_key, ptr_sort_key + num_of_elements,
                      KeyRightShift<KeyType>(), KeyLessThan<KeyType>());

  if (TeardownKeySort<KeyType>(data, ptr_sort_key, num_of_elements,
                               size_of_element) != 0) {
    return -1;
  }

  return 0;
}

template<typename KeyType>
inline int32_t StdKeySort(void* data, void* key,
                          uint32_t num_of_elements,
                          uint32_t size_of_element) {
  SortKey<KeyType>* ptr_sort_key;
  if (SetupKeySort<KeyType>(key, ptr_sort_key, num_of_elements) != 0) {
    return -1;
  }

  std::sort(ptr_sort_key, ptr_sort_key + num_of_elements,
            KeyLessThan<KeyType>());

  if (TeardownKeySort<KeyType>(data, ptr_sort_key, num_of_elements,
                               size_of_element) != 0) {
    return -1;
  }

  return 0;
}
#endif
}

int32_t Sort(void* data, uint32_t num_of_elements, Type type) {
  if (data == NULL) {
    return -1;
  }

#ifdef NO_STL
  switch (type) {
    case TYPE_Word8:
      qsort(data, num_of_elements, sizeof(int8_t), CompareWord8);
      break;
    case TYPE_UWord8:
      qsort(data, num_of_elements, sizeof(uint8_t), CompareUWord8);
      break;
    case TYPE_Word16:
      qsort(data, num_of_elements, sizeof(int16_t), CompareWord16);
      break;
    case TYPE_UWord16:
      qsort(data, num_of_elements, sizeof(uint16_t), CompareUWord16);
      break;
    case TYPE_Word32:
      qsort(data, num_of_elements, sizeof(int32_t), CompareWord32);
      break;
    case TYPE_UWord32:
      qsort(data, num_of_elements, sizeof(uint32_t), CompareUWord32);
      break;
    case TYPE_Word64:
      qsort(data, num_of_elements, sizeof(int64_t), CompareWord64);
      break;
    case TYPE_UWord64:
      qsort(data, num_of_elements, sizeof(uint64_t), CompareUWord64);
      break;
    case TYPE_Float32:
      qsort(data, num_of_elements, sizeof(float), CompareFloat32);
      break;
    case TYPE_Float64:
      qsort(data, num_of_elements, sizeof(double), CompareFloat64);
      break;
    default:
      return -1;
  }
#else
  // Fall back to std::sort for 64-bit types and floats due to compiler
  // warnings and VS 2003 build crashes respectively with spreadsort.
  switch (type) {
    case TYPE_Word8:
      IntegerSort<int8_t>(data, num_of_elements);
      break;
    case TYPE_UWord8:
      IntegerSort<uint8_t>(data, num_of_elements);
      break;
    case TYPE_Word16:
      IntegerSort<int16_t>(data, num_of_elements);
      break;
    case TYPE_UWord16:
      IntegerSort<uint16_t>(data, num_of_elements);
      break;
    case TYPE_Word32:
      IntegerSort<int32_t>(data, num_of_elements);
      break;
    case TYPE_UWord32:
      IntegerSort<uint32_t>(data, num_of_elements);
      break;
    case TYPE_Word64:
      StdSort<int64_t>(data, num_of_elements);
      break;
    case TYPE_UWord64:
      StdSort<uint64_t>(data, num_of_elements);
      break;
    case TYPE_Float32:
      StdSort<float>(data, num_of_elements);
      break;
    case TYPE_Float64:
      StdSort<double>(data, num_of_elements);
      break;
  }
#endif
  return 0;
}

int32_t KeySort(void* data, void* key, uint32_t num_of_elements,
                uint32_t size_of_element, Type key_type) {
  if (data == NULL) {
    return -1;
  }

  if (key == NULL) {
    return -1;
  }

  if ((uint64_t)num_of_elements * size_of_element > 0xffffffff) {
    return -1;
  }

#ifdef NO_STL
  SortKey* ptr_sort_key = new(std::nothrow) SortKey[num_of_elements];
  if (ptr_sort_key == NULL) {
    return -1;
  }

  switch (key_type) {
    case TYPE_Word8:
      KEY_QSORT(ptr_sort_key, key, num_of_elements, int8_t,
                CompareKeyWord8);
      break;
    case TYPE_UWord8:
      KEY_QSORT(ptr_sort_key, key, num_of_elements, uint8_t,
                CompareKeyUWord8);
      break;
    case TYPE_Word16:
      KEY_QSORT(ptr_sort_key, key, num_of_elements, int16_t,
                CompareKeyWord16);
      break;
    case TYPE_UWord16:
      KEY_QSORT(ptr_sort_key, key, num_of_elements, uint16_t,
                CompareKeyUWord16);
      break;
    case TYPE_Word32:
      KEY_QSORT(ptr_sort_key, key, num_of_elements, int32_t,
                CompareKeyWord32);
      break;
    case TYPE_UWord32:
      KEY_QSORT(ptr_sort_key, key, num_of_elements, uint32_t,
                CompareKeyUWord32);
      break;
    case TYPE_Word64:
      KEY_QSORT(ptr_sort_key, key, num_of_elements, int64_t,
                CompareKeyWord64);
      break;
    case TYPE_UWord64:
      KEY_QSORT(ptr_sort_key, key, num_of_elements, uint64_t,
                CompareKeyUWord64);
      break;
    case TYPE_Float32:
      KEY_QSORT(ptr_sort_key, key, num_of_elements, float,
                CompareKeyFloat32);
      break;
    case TYPE_Float64:
      KEY_QSORT(ptr_sort_key, key, num_of_elements, double,
                CompareKeyFloat64);
      break;
    default:
      return -1;
  }

  // Shuffle into sorted position based on index map.
  uint8_t* ptr_data = static_cast<uint8_t*>(data);
  uint8_t* ptr_data_sorted =
      new(std::nothrow) uint8_t[num_of_elements * size_of_element];
  if (ptr_data_sorted == NULL) {
    return -1;
  }

  for (uint32_t i = 0; i < num_of_elements; i++) {
    memcpy(ptr_data_sorted + i * size_of_element, ptr_data +
           ptr_sort_key[i].index_ * size_of_element, size_of_element);
  }
  memcpy(ptr_data, ptr_data_sorted, num_of_elements * size_of_element);

  delete[] ptr_sort_key;
  delete[] ptr_data_sorted;

  return 0;
#else
  // Fall back to std::sort for 64-bit types and floats due to compiler
  // warnings and errors respectively with spreadsort.
  switch (key_type) {
    case TYPE_Word8:
      return IntegerKeySort<int8_t>(data, key, num_of_elements,
                                    size_of_element);
    case TYPE_UWord8:
      return IntegerKeySort<uint8_t>(data, key, num_of_elements,
                                     size_of_element);
    case TYPE_Word16:
      return IntegerKeySort<int16_t>(data, key, num_of_elements,
                                     size_of_element);
    case TYPE_UWord16:
      return IntegerKeySort<uint16_t>(data, key, num_of_elements,
                                      size_of_element);
    case TYPE_Word32:
      return IntegerKeySort<int32_t>(data, key, num_of_elements,
                                     size_of_element);
    case TYPE_UWord32:
      return IntegerKeySort<uint32_t>(data, key, num_of_elements,
                                      size_of_element);
    case TYPE_Word64:
      return StdKeySort<int64_t>(data, key, num_of_elements,
                                 size_of_element);
    case TYPE_UWord64:
      return StdKeySort<uint64_t>(data, key, num_of_elements,
                                  size_of_element);
    case TYPE_Float32:
      return StdKeySort<float>(data, key, num_of_elements, size_of_element);
    case TYPE_Float64:
      return StdKeySort<double>(data, key, num_of_elements, size_of_element);
  }
  assert(false);
  return -1;
#endif
}

}  // namespace webrtc
