/*
 * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

#ifndef SHARE_RUNTIME_FLAGS_JVMFLAGACCESS_HPP
#define SHARE_RUNTIME_FLAGS_JVMFLAGACCESS_HPP

#include "memory/allStatic.hpp"
#include "runtime/flags/jvmFlag.hpp"
#include "utilities/vmEnums.hpp"

class FlagAccessImpl;
class JVMFlagLimit;
class outputStream;

// Use this macro in combination with JVMFlag::{read, write} and JVMFlagAccess::{get, set}
// to safely access the underlying variable of a JVMFlag:
//
//  JVMFlag* flag = JVMFlag::flag_from_enum(FLAG_MEMBER_ENUM(ObjectAlignmentInBytes));
//
//  /* If you use a wrong type, a run-time assertion will happen */
//  intx v = flag->read<intx>();
//
//  /* If you use a wrong type, or a null flag, an error code is returned */
//  JVMFlag::Error err = JVMFlagAccess::get<JVM_FLAG_TYPE(intx)>(flag, &v, origin);

#define JVM_FLAG_TYPE(t) \
  t, JVMFlag::TYPE_ ## t

// This class provides a unified interface for getting/setting the JVM flags, with support
// for (1) type correctness checks, (2) range checks, (3) constraint checks. Two main types
// of setters are provided. See notes below on which one to use.
class JVMFlagAccess : AllStatic {
  inline static const FlagAccessImpl* access_impl(const JVMFlag* flag);
  static JVMFlag::Error set_impl(JVMFlag* flag, void* value, JVMFlagOrigin origin);
  static JVMFlag::Error set_or_assert(JVMFlagsEnum flag_enum, int type_enum, void* value, JVMFlagOrigin origin);

  static bool is_correct_type(const JVMFlag* flag, int type_enum) {
    if (type_enum == JVMFlag::TYPE_ccstr) {
      if (!flag->is_ccstr()) { // ccstr or ccstrlist
        return false;
      }
    } else {
      if (flag->type() != type_enum) {
        return false;
      }
    }
    return true;
  }

public:
  static JVMFlag::Error check_range(const JVMFlag* flag, bool verbose);
  static JVMFlag::Error check_constraint(const JVMFlag* flag, void * func, bool verbose);
  static void print_range(outputStream* st, const JVMFlag* flag, const JVMFlagLimit* range);
  static void print_range(outputStream* st, const JVMFlag* flag);

  template <typename T, int type_enum>
  static JVMFlag::Error get(const JVMFlag* flag, T* value) {
    // The caller must not not mix incompatible types such as
    // set<double, JVMFlag::TYPE_int>(flag, double_ptr);
    assert(JVMFlag::is_compatible_type<T>(type_enum), "must be");

    if (flag == nullptr) {
      return JVMFlag::INVALID_FLAG;
    }
    if (!is_correct_type(flag, type_enum)) {
      return JVMFlag::WRONG_FORMAT;
    }

    *value = flag->read<T>();
    return JVMFlag::SUCCESS;
  }

  // This is a *flag specific* setter. It should be used only via by the
  // FLAG_SET_{DEFAULT, CMDLINE, ERGO, MGMT} macros.
  // It's used to set a specific flag whose type is statically known. A mismatched
  // type_enum will result in an assert.
  template <typename T, int type_enum>
  static JVMFlag::Error set(JVMFlagsEnum flag_enum, T value, JVMFlagOrigin origin) {
    return set_or_assert(flag_enum, type_enum, &value, origin);
  }

  // This is a *generic* setter. It should be used by code that can set a number of different
  // flags, often according to external input that may contain errors.
  // Examples callers are arguments.cpp, writeableFlags.cpp, and WB_SetXxxVMFlag functions.
  // A mismatched type_enum would result in a JVMFlag::WRONG_FORMAT code.
  template <typename T, int type_enum>
  static JVMFlag::Error set(JVMFlag* flag, T* value, JVMFlagOrigin origin) {
    // The caller must not not mix incompatible types such as
    // set<double, JVMFlag::TYPE_int>(flag, double_ptr);
    assert(JVMFlag::is_compatible_type<T>(type_enum), "must be");

    if (flag == nullptr) {
      return JVMFlag::INVALID_FLAG;
    }
    if (!is_correct_type(flag, type_enum)) {
      return JVMFlag::WRONG_FORMAT;
    }

    return set_impl(flag, (void*)value, origin);
  }

  // Special handling needed for ccstr
  // Contract:  JVMFlag will make private copy of the incoming value.
  // Outgoing value is always malloc-ed, and caller MUST call free.
  static JVMFlag::Error set_ccstr(JVMFlag* flag, ccstr* value, JVMFlagOrigin origin);

  // Handy aliases
  static JVMFlag::Error get_ccstr(const JVMFlag* flag, ccstr* value) {
    return get<JVM_FLAG_TYPE(ccstr)>(flag, value);
  }

  static JVMFlag::Error set_bool    (JVMFlag* f, bool*     v, JVMFlagOrigin origin) { return set<JVM_FLAG_TYPE(bool)>    (f, v, origin); }
  static JVMFlag::Error set_int     (JVMFlag* f, int*      v, JVMFlagOrigin origin) { return set<JVM_FLAG_TYPE(int)>     (f, v, origin); }
  static JVMFlag::Error set_uint    (JVMFlag* f, uint*     v, JVMFlagOrigin origin) { return set<JVM_FLAG_TYPE(uint)>    (f, v, origin); }
  static JVMFlag::Error set_intx    (JVMFlag* f, intx*     v, JVMFlagOrigin origin) { return set<JVM_FLAG_TYPE(intx)>    (f, v, origin); }
  static JVMFlag::Error set_uintx   (JVMFlag* f, uintx*    v, JVMFlagOrigin origin) { return set<JVM_FLAG_TYPE(uintx)>   (f, v, origin); }
  static JVMFlag::Error set_uint64_t(JVMFlag* f, uint64_t* v, JVMFlagOrigin origin) { return set<JVM_FLAG_TYPE(uint64_t)>(f, v, origin); }
  static JVMFlag::Error set_size_t  (JVMFlag* f, size_t*   v, JVMFlagOrigin origin) { return set<JVM_FLAG_TYPE(size_t)>  (f, v, origin); }
  static JVMFlag::Error set_double  (JVMFlag* f, double*   v, JVMFlagOrigin origin) { return set<JVM_FLAG_TYPE(double)>  (f, v, origin); }
};

#endif // SHARE_RUNTIME_FLAGS_JVMFLAGACCESS_HPP
