// Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=95cf5f4a9561fd25c98ef424df8a9d6047c24cc8$
//

#include "libcef_dll/cpptoc/v8stack_frame_cpptoc.h"

namespace {

// MEMBER FUNCTIONS - Body may be edited by hand.

int CEF_CALLBACK v8stack_frame_is_valid(struct _cef_v8stack_frame_t* self) {
  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING

  DCHECK(self);
  if (!self)
    return 0;

  // Execute
  bool _retval = CefV8StackFrameCppToC::Get(self)->IsValid();

  // Return type: bool
  return _retval;
}

cef_string_userfree_t CEF_CALLBACK
v8stack_frame_get_script_name(struct _cef_v8stack_frame_t* self) {
  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING

  DCHECK(self);
  if (!self)
    return NULL;

  // Execute
  CefString _retval = CefV8StackFrameCppToC::Get(self)->GetScriptName();

  // Return type: string
  return _retval.DetachToUserFree();
}

cef_string_userfree_t CEF_CALLBACK
v8stack_frame_get_script_name_or_source_url(struct _cef_v8stack_frame_t* self) {
  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING

  DCHECK(self);
  if (!self)
    return NULL;

  // Execute
  CefString _retval =
      CefV8StackFrameCppToC::Get(self)->GetScriptNameOrSourceURL();

  // Return type: string
  return _retval.DetachToUserFree();
}

cef_string_userfree_t CEF_CALLBACK
v8stack_frame_get_function_name(struct _cef_v8stack_frame_t* self) {
  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING

  DCHECK(self);
  if (!self)
    return NULL;

  // Execute
  CefString _retval = CefV8StackFrameCppToC::Get(self)->GetFunctionName();

  // Return type: string
  return _retval.DetachToUserFree();
}

int CEF_CALLBACK
v8stack_frame_get_line_number(struct _cef_v8stack_frame_t* self) {
  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING

  DCHECK(self);
  if (!self)
    return 0;

  // Execute
  int _retval = CefV8StackFrameCppToC::Get(self)->GetLineNumber();

  // Return type: simple
  return _retval;
}

int CEF_CALLBACK v8stack_frame_get_column(struct _cef_v8stack_frame_t* self) {
  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING

  DCHECK(self);
  if (!self)
    return 0;

  // Execute
  int _retval = CefV8StackFrameCppToC::Get(self)->GetColumn();

  // Return type: simple
  return _retval;
}

int CEF_CALLBACK v8stack_frame_is_eval(struct _cef_v8stack_frame_t* self) {
  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING

  DCHECK(self);
  if (!self)
    return 0;

  // Execute
  bool _retval = CefV8StackFrameCppToC::Get(self)->IsEval();

  // Return type: bool
  return _retval;
}

int CEF_CALLBACK
v8stack_frame_is_constructor(struct _cef_v8stack_frame_t* self) {
  // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING

  DCHECK(self);
  if (!self)
    return 0;

  // Execute
  bool _retval = CefV8StackFrameCppToC::Get(self)->IsConstructor();

  // Return type: bool
  return _retval;
}

}  // namespace

// CONSTRUCTOR - Do not edit by hand.

CefV8StackFrameCppToC::CefV8StackFrameCppToC() {
  GetStruct()->is_valid = v8stack_frame_is_valid;
  GetStruct()->get_script_name = v8stack_frame_get_script_name;
  GetStruct()->get_script_name_or_source_url =
      v8stack_frame_get_script_name_or_source_url;
  GetStruct()->get_function_name = v8stack_frame_get_function_name;
  GetStruct()->get_line_number = v8stack_frame_get_line_number;
  GetStruct()->get_column = v8stack_frame_get_column;
  GetStruct()->is_eval = v8stack_frame_is_eval;
  GetStruct()->is_constructor = v8stack_frame_is_constructor;
}

// DESTRUCTOR - Do not edit by hand.

CefV8StackFrameCppToC::~CefV8StackFrameCppToC() {}

template <>
CefRefPtr<CefV8StackFrame> CefCppToCRefCounted<
    CefV8StackFrameCppToC,
    CefV8StackFrame,
    cef_v8stack_frame_t>::UnwrapDerived(CefWrapperType type,
                                        cef_v8stack_frame_t* s) {
  NOTREACHED() << "Unexpected class type: " << type;
  return nullptr;
}

template <>
CefWrapperType CefCppToCRefCounted<CefV8StackFrameCppToC,
                                   CefV8StackFrame,
                                   cef_v8stack_frame_t>::kWrapperType =
    WT_V8STACK_FRAME;
