/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef INCLUDE_PERFETTO_EXT_BASE_STRING_SPLITTER_H_
#define INCLUDE_PERFETTO_EXT_BASE_STRING_SPLITTER_H_

#include <string>

namespace perfetto {
namespace base {

// C++ version of strtok(). Splits a string without making copies or any heap
// allocations. Destructs the original string passed in input.
// Supports the special case of using \0 as a delimiter.
// The token returned in output are valid as long as the input string is valid.
class StringSplitter {
 public:
  // Whether an empty string (two delimiters side-to-side) is a valid token.
  enum class EmptyTokenMode {
    DISALLOW_EMPTY_TOKENS,
    ALLOW_EMPTY_TOKENS,

    DEFAULT = DISALLOW_EMPTY_TOKENS,
  };

  // Can take ownership of the string if passed via std::move(), e.g.:
  // StringSplitter(std::move(str), '\n');
  StringSplitter(std::string,
                 char delimiter,
                 EmptyTokenMode empty_token_mode = EmptyTokenMode::DEFAULT);

  // Splits a C-string. The input string will be forcefully null-terminated (so
  // str[size - 1] should be == '\0' or the last char will be truncated).
  StringSplitter(char* str,
                 size_t size,
                 char delimiter,
                 EmptyTokenMode empty_token_mode = EmptyTokenMode::DEFAULT);

  // Splits the current token from an outer StringSplitter instance. This is to
  // chain splitters as follows:
  // for (base::StringSplitter lines(x, '\n'); ss.Next();)
  //   for (base::StringSplitter words(&lines, ' '); words.Next();)
  StringSplitter(StringSplitter*,
                 char delimiter,
                 EmptyTokenMode empty_token_mode = EmptyTokenMode::DEFAULT);

  // Returns true if a token is found (in which case it will be stored in
  // cur_token()), false if no more tokens are found.
  bool Next();

  // Returns the current token iff last call to Next() returned true. In this
  // case it guarantees that the returned string is always null terminated.
  // In all other cases (before the 1st call to Next() and after Next() returns
  // false) returns nullptr.
  char* cur_token() { return cur_; }

  // Returns the length of the current token (excluding the null terminator).
  size_t cur_token_size() const { return cur_size_; }

 private:
  StringSplitter(const StringSplitter&) = delete;
  StringSplitter& operator=(const StringSplitter&) = delete;
  void Initialize(char* str, size_t size);

  std::string str_;
  char* cur_;
  size_t cur_size_;
  char* next_;
  char* end_;  // STL-style, points one past the last char.
  const char delimiter_;
  const EmptyTokenMode empty_token_mode_;
};

}  // namespace base
}  // namespace perfetto

#endif  // INCLUDE_PERFETTO_EXT_BASE_STRING_SPLITTER_H_
