// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#ifndef RUNTIME_BIN_UTILS_H_
#define RUNTIME_BIN_UTILS_H_

#include <stdlib.h>
#include <string.h>

#include "include/dart_api.h"
#include "platform/globals.h"
#include "platform/utils.h"

namespace dart {
namespace bin {

class OSError {
 public:
  enum SubSystem { kSystem, kGetAddressInfo, kBoringSSL, kUnknown = -1 };

  OSError();
  OSError(int code, const char* message, SubSystem sub_system) {
    sub_system_ = sub_system;
    code_ = code;
    message_ = NULL;  // SetMessage will free existing message.
    SetMessage(message);
  }
  virtual ~OSError() { free(message_); }

  // Reload this OSError with the current OS error, discarding the previous.
  void Reload();

  SubSystem sub_system() { return sub_system_; }
  int code() { return code_; }
  char* message() { return message_; }
  void SetCodeAndMessage(SubSystem sub_system, int code);

 private:
  void set_sub_system(SubSystem sub_system) { sub_system_ = sub_system; }
  void set_code(int code) { code_ = code; }
  void SetMessage(const char* message) {
    free(message_);
    if (message == NULL) {
      message_ = NULL;
    } else {
      message_ = Utils::StrDup(message);
    }
  }

  SubSystem sub_system_;
  int code_;
  char* message_;

  DISALLOW_COPY_AND_ASSIGN(OSError);
};

class StringUtils {
 public:
  // The following methods convert the argument if needed.  The
  // conversions are only needed on Windows. If the methods returns a
  // pointer that is different from the input pointer, the returned
  // pointer is allocated with malloc and should be freed using free.
  //
  // If the len argument is passed then that number of characters are
  // converted. If len is -1, conversion will stop at the first NUL
  // character. If result_len is not NUL, it is used to set the number
  // of characters in the result.
  //
  // A return value of `nullptr` indicates that the conversion is not supported,
  // which is true on all platforms other than Windows.
  static const char* ConsoleStringToUtf8(const char* str,
                                         intptr_t len = -1,
                                         intptr_t* result_len = NULL);
  static char* ConsoleStringToUtf8(char* str,
                                   intptr_t len = -1,
                                   intptr_t* result_len = NULL);
  static const char* Utf8ToConsoleString(const char* utf8,
                                         intptr_t len = -1,
                                         intptr_t* result_len = NULL);
  static char* Utf8ToConsoleString(char* utf8,
                                   intptr_t len = -1,
                                   intptr_t* result_len = NULL);

 private:
  DISALLOW_ALLOCATION();
  DISALLOW_IMPLICIT_CONSTRUCTORS(StringUtils);
};

class ShellUtils {
 public:
  // Convert all the arguments to UTF8. On Windows, the arguments are
  // encoded in the current code page and not UTF8.
  //
  // Returns true if the arguments are converted. In that case
  // each of the arguments need to be deallocated using free.
  static bool GetUtf8Argv(int argc, char** argv);

 private:
  DISALLOW_ALLOCATION();
  DISALLOW_IMPLICIT_CONSTRUCTORS(ShellUtils);
};

class TimerUtils {
 public:
  static void InitOnce();
  static int64_t GetCurrentMonotonicMicros();
  static int64_t GetCurrentMonotonicMillis();
  static void Sleep(int64_t millis);

 private:
  DISALLOW_ALLOCATION();
  DISALLOW_IMPLICIT_CONSTRUCTORS(TimerUtils);
};

}  // namespace bin
}  // namespace dart

#endif  // RUNTIME_BIN_UTILS_H_
