// Copyright 2018 the V8 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.

#ifndef V8_OBJECTS_SMI_H_
#define V8_OBJECTS_SMI_H_

#include "src/globals.h"
#include "src/objects/heap-object.h"

// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"

namespace v8 {
namespace internal {

// Smi represents integer Numbers that can be stored in 31 bits.
// Smis are immediate which means they are NOT allocated in the heap.
// The ptr_ value has the following format: [31 bit signed int] 0
// For long smis it has the following format:
//     [32 bit signed int] [31 bits zero padding] 0
// Smi stands for small integer.
class Smi : public ObjectPtr {
 public:
  // This replaces the OBJECT_CONSTRUCTORS macro, because Smis are special
  // in that we want them to be constexprs.
  constexpr Smi() : ObjectPtr() {}
  explicit constexpr Smi(Address ptr) : ObjectPtr(ptr) {
#if V8_CAN_HAVE_DCHECK_IN_CONSTEXPR
    DCHECK(HAS_SMI_TAG(ptr));
#endif
  }
  Smi* operator->() { return this; }
  const Smi* operator->() const { return this; }

  // Returns the integer value.
  inline int value() const { return Internals::SmiValue(ptr()); }
  inline Smi ToUint32Smi() {
    if (value() <= 0) return Smi::FromInt(0);
    return Smi::FromInt(static_cast<uint32_t>(value()));
  }

  // Convert a Smi object to an int.
  static inline int ToInt(const Object object);

  // TODO(3770): Drop this when merging Object and ObjectPtr.
  bool ToInt32(int32_t* value) {
    *value = this->value();
    return true;
  }

  // Convert a value to a Smi object.
  static inline constexpr Smi FromInt(int value) {
#if V8_CAN_HAVE_DCHECK_IN_CONSTEXPR
    DCHECK(Smi::IsValid(value));
#endif
    return Smi(Internals::IntToSmi(value));
  }

  static inline Smi FromIntptr(intptr_t value) {
    DCHECK(Smi::IsValid(value));
    int smi_shift_bits = kSmiTagSize + kSmiShiftSize;
    return Smi((value << smi_shift_bits) | kSmiTag);
  }

  template <typename E,
            typename = typename std::enable_if<std::is_enum<E>::value>::type>
  static inline Smi FromEnum(E value) {
    STATIC_ASSERT(sizeof(E) <= sizeof(int));
    return FromInt(static_cast<int>(value));
  }

  // Returns whether value can be represented in a Smi.
  static inline bool constexpr IsValid(intptr_t value) {
#if V8_CAN_HAVE_DCHECK_IN_CONSTEXPR
    DCHECK(Internals::IsValidSmi(value) ==
           (value >= kMinValue && value <= kMaxValue));
#endif
    return Internals::IsValidSmi(value);
  }

  // Compare two Smis x, y as if they were converted to strings and then
  // compared lexicographically. Returns:
  // -1 if x < y.
  //  0 if x == y.
  //  1 if x > y.
  // Returns the result (a tagged Smi) as a raw Address for ExternalReference
  // usage.
  static Address LexicographicCompare(Isolate* isolate, Smi x, Smi y);

  DECL_CAST2(Smi)

  // Dispatched behavior.
  V8_EXPORT_PRIVATE void SmiPrint(std::ostream& os) const;  // NOLINT
  DECL_VERIFIER(Smi)

  // C++ does not allow us to have an object of type Smi within class Smi,
  // so the kZero value has type ObjectPtr. Consider it deprecated; new code
  // should use zero() instead.
  V8_EXPORT_PRIVATE static constexpr ObjectPtr kZero = ObjectPtr(0);
  // If you need something with type Smi, call zero() instead. Since it is
  // a constexpr, "calling" it is just as efficient as reading kZero.
  static inline constexpr Smi zero() { return Smi::FromInt(0); }
  static constexpr int kMinValue = kSmiMinValue;
  static constexpr int kMaxValue = kSmiMaxValue;
};

}  // namespace internal
}  // namespace v8

#include "src/objects/object-macros-undef.h"

#endif  // V8_OBJECTS_SMI_H_
