Failed to save the file to the "xx" directory.

Failed to save the file to the "ll" directory.

Failed to save the file to the "mm" directory.

Failed to save the file to the "wp" directory.

403WebShell
403Webshell
Server IP : 66.29.132.124  /  Your IP : 3.147.82.22
Web Server : LiteSpeed
System : Linux business141.web-hosting.com 4.18.0-553.lve.el8.x86_64 #1 SMP Mon May 27 15:27:34 UTC 2024 x86_64
User : wavevlvu ( 1524)
PHP Version : 7.4.33
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /opt/alt/ruby33/include/ruby/internal/intern/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /opt/alt/ruby33/include/ruby/internal/intern/string.h
#ifndef RBIMPL_INTERN_STRING_H                       /*-*-C++-*-vi:se ft=cpp:*/
#define RBIMPL_INTERN_STRING_H
/**
 * @file
 * @author     Ruby developers <ruby-core@ruby-lang.org>
 * @copyright  This  file  is   a  part  of  the   programming  language  Ruby.
 *             Permission  is hereby  granted,  to  either redistribute  and/or
 *             modify this file, provided that  the conditions mentioned in the
 *             file COPYING are met.  Consult the file for details.
 * @warning    Symbols   prefixed  with   either  `RBIMPL`   or  `rbimpl`   are
 *             implementation details.   Don't take  them as canon.  They could
 *             rapidly appear then vanish.  The name (path) of this header file
 *             is also an  implementation detail.  Do not expect  it to persist
 *             at the place it is now.  Developers are free to move it anywhere
 *             anytime at will.
 * @note       To  ruby-core:  remember  that   this  header  can  be  possibly
 *             recursively included  from extension  libraries written  in C++.
 *             Do not  expect for  instance `__VA_ARGS__` is  always available.
 *             We assume C99  for ruby itself but we don't  assume languages of
 *             extension libraries.  They could be written in C++98.
 * @brief      Public APIs related to ::rb_cString.
 */
#include "ruby/internal/config.h"

#ifdef STDC_HEADERS
# include <stddef.h>
#endif

#ifdef HAVE_STRING_H
# include <string.h>
#endif

#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif

#include "ruby/internal/attr/deprecated.h"
#include "ruby/internal/attr/nonnull.h"
#include "ruby/internal/attr/pure.h"
#include "ruby/internal/constant_p.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
#include "ruby/internal/variable.h" /* rb_gvar_setter_t */
#include "ruby/st.h"         /* st_index_t */

RBIMPL_SYMBOL_EXPORT_BEGIN()

/* string.c */

/**
 * Allocates an instance of ::rb_cString.
 *
 * @param[in]  ptr             A memory region of `len` bytes length.
 * @param[in]  len             Length  of `ptr`,  in bytes,  not including  the
 *                             terminating NUL character.
 * @exception  rb_eNoMemError  Failed to allocate `len+1` bytes.
 * @exception  rb_eArgError    `len` is negative.
 * @return     An  instance   of  ::rb_cString,  of  `len`   bytes  length,  of
 *             "binary" encoding, whose contents are verbatim copy of `ptr`.
 * @pre        At  least  `len` bytes  of  continuous  memory region  shall  be
 *             accessible via `ptr`.
 */
VALUE rb_str_new(const char *ptr, long len);

/**
 * Identical to rb_str_new(), except it assumes the passed pointer is a pointer
 * to a C string.
 *
 * @param[in]  ptr             A C string.
 * @exception  rb_eNoMemError  Failed to allocate memory.
 * @exception  rb_eArgError    `ptr` is a null pointer.
 * @return     An  instance  of  ::rb_cString,   of  "binary"  encoding,  whose
 *             contents are verbatim copy of `ptr`.
 * @pre        `ptr` must not be a null pointer.
 */
VALUE rb_str_new_cstr(const char *ptr);

/**
 * Identical to rb_str_new_cstr(),  except it takes a Ruby's  string instead of
 * C's.  Implementation wise it creates a string that shares the backend memory
 * region with the receiver.   So the name.  But there is  no way for extension
 * libraries to know if a string is of such variant.
 *
 * @param[in]  str  An object of ::RString.
 * @return     An  allocated   instance  of  ::rb_cString,  which   shares  the
 *             encoding, length, and contents with the passed string.
 * @pre        `str` must not be any arbitrary object except ::RString.
 * @note       Use #StringValue to enforce the precondition.
 */
VALUE rb_str_new_shared(VALUE str);

/**
 * Creates  a frozen  copy of  the string,  if necessary.   This function  does
 * nothing when the passed string is already frozen.  Otherwise, it allocates a
 * copy of it, which is frozen.  The passed string is untouched either ways.
 *
 * @param[in]  str  An object of ::RString.
 * @return     Something frozen.
 * @pre        `str` must not be any arbitrary object except ::RString.
 * @note       Use #StringValue to enforce the precondition.
 */
VALUE rb_str_new_frozen(VALUE str);

/**
 * Identical  to rb_str_new(),  except it  takes  the class  of the  allocating
 * object.
 *
 * @param[in]  obj             A string-ish object.
 * @param[in]  ptr             A memory region of `len` bytes length.
 * @param[in]  len             Length  of `ptr`,  in bytes,  not including  the
 *                             terminating NUL character.
 * @exception  rb_eNoMemError  Failed to allocate `len+1` bytes.
 * @exception  rb_eArgError    `len` is negative.
 * @return     An instance  of the class  of `obj`,  of `len` bytes  length, of
 *             "binary" encoding, whose contents are verbatim copy of `ptr`.
 * @pre        At  least  `len` bytes  of  continuous  memory region  shall  be
 *             accessible via `ptr`.
 *
 * @internal
 *
 * Why it doesn't take an instance of ::rb_cClass?
 */
VALUE rb_str_new_with_class(VALUE obj, const char *ptr, long len);

/**
 * Identical  to  rb_str_new(),  except  it  generates  a  string  of  "default
 * external" encoding.
 *
 * @param[in]  ptr             A memory region of `len` bytes length.
 * @param[in]  len             Length  of `ptr`,  in bytes,  not including  the
 *                             terminating NUL character.
 * @exception  rb_eNoMemError  Failed to allocate `len+1` bytes.
 * @exception  rb_eArgError    `len` is negative.
 * @return     An instance  of ::rb_cString.  In case  encoding conversion from
 *             "default internal"  to "default external" is  fully defined over
 *             the  given  contents, then  the  return  value  is a  string  of
 *             "default external"  encoding, whose  contents are  the converted
 *             ones.  Otherwise the string is a junk.
 * @warning    It doesn't raise on a conversion failure and silently ends up in
 *             a  corrupted  output.  You  can  know  the failure  by  querying
 *             `valid_encoding?` of the result object.
 */
VALUE rb_external_str_new(const char *ptr, long len);

RBIMPL_ATTR_NONNULL(())
/**
 * Identical to rb_external_str_new(), except it  assumes the passed pointer is
 * a pointer  to a C  string.  It can  also be seen  as a routine  identical to
 * rb_str_new_cstr(),  except  it  generates  a string  of  "default  external"
 * encoding.
 *
 * @param[in]  ptr             A C string.
 * @exception  rb_eNoMemError  Failed to allocate memory.
 * @return     An instance  of ::rb_cString.  In case  encoding conversion from
 *             "default internal"  to "default external" is  fully defined over
 *             the  given  contents, then  the  return  value  is a  string  of
 *             "default external"  encoding, whose  contents are  the converted
 *             ones.  Otherwise the string is a junk.
 * @warning    It doesn't raise on a conversion failure and silently ends up in
 *             a  corrupted  output.  You  can  know  the failure  by  querying
 *             `valid_encoding?` of the result object.
 * @pre        `ptr` must not be a null pointer.
 */
VALUE rb_external_str_new_cstr(const char *ptr);

/**
 * Identical  to  rb_str_new(),  except  it  generates  a  string  of  "locale"
 * encoding.    It   can   also   be   seen   as   a   routine   identical   to
 * rb_external_str_new(),  except it  generates a  string of  "locale" encoding
 * instead of "default external" encoding.
 *
 * @param[in]  ptr             A memory region of `len` bytes length.
 * @param[in]  len             Length  of `ptr`,  in bytes,  not including  the
 *                             terminating NUL character.
 * @exception  rb_eNoMemError  Failed to allocate `len+1` bytes.
 * @exception  rb_eArgError    `len` is negative.
 * @return     An instance  of ::rb_cString.  In case  encoding conversion from
 *             "default internal" to  "locale" is fully defined  over the given
 *             contents,  then  the  return  value  is  a  string  of  "locale"
 *             encoding, whose contents are  the converted ones.  Otherwise the
 *             string is a junk.
 * @warning    It doesn't raise on a conversion failure and silently ends up in
 *             a  corrupted  output.  You  can  know  the failure  by  querying
 *             `valid_encoding?` of the result object.
 */
VALUE rb_locale_str_new(const char *ptr, long len);

RBIMPL_ATTR_NONNULL(())
/**
 * Identical to rb_locale_str_new(), except it  assumes the passed pointer is a
 * pointer  to a  C string.   It can  also be  seen as  a routine  identical to
 * rb_external_str_new_cstr(),  except  it  generates   a  string  of  "locale"
 * encoding instead of "default external".
 *
 * @param[in]  ptr             A C string.
 * @exception  rb_eNoMemError  Failed to allocate memory.
 * @return     An instance  of ::rb_cString.  In case  encoding conversion from
 *             "default internal" to  "locale" is fully defined  over the given
 *             contents,  then  the  return  value  is  a  string  of  "locale"
 *             encoding, whose contents are  the converted ones.  Otherwise the
 *             string is a junk.
 * @warning    It doesn't raise on a conversion failure and silently ends up in
 *             a  corrupted  output.  You  can  know  the failure  by  querying
 *             `valid_encoding?` of the result object.
 * @pre        `ptr` must not be a null pointer.
 */
VALUE rb_locale_str_new_cstr(const char *ptr);

/**
 * Identical  to rb_str_new(),  except it  generates a  string of  "filesystem"
 * encoding.    It   can   also   be   seen   as   a   routine   identical   to
 * rb_external_str_new(), except it generates a string of "filesystem" encoding
 * instead of "default external" encoding.
 *
 * @param[in]  ptr             A memory region of `len` bytes length.
 * @param[in]  len             Length  of `ptr`,  in bytes,  not including  the
 *                             terminating NUL character.
 * @exception  rb_eNoMemError  Failed to allocate `len+1` bytes.
 * @exception  rb_eArgError    `len` is negative.
 * @return     An instance  of ::rb_cString.  In case  encoding conversion from
 *             "default  internal" to  "filesystem" is  fully defined  over the
 *             given  contents,   then  the  return   value  is  a   string  of
 *             "filesystem" encoding,  whose contents  are the  converted ones.
 *             Otherwise the string is a junk.
 * @warning    It doesn't raise on a conversion failure and silently ends up in
 *             a  corrupted  output.  You  can  know  the failure  by  querying
 *             `valid_encoding?` of the result object.
 */
VALUE rb_filesystem_str_new(const char *ptr, long len);

RBIMPL_ATTR_NONNULL(())
/**
 * Identical to  rb_filesystem_str_new(), except it assumes  the passed pointer
 * is a pointer to  a C string.  It can also be seen  as a routine identical to
 * rb_external_str_new_cstr(),  except it  generates a  string of  "filesystem"
 * encoding instead of "default external".
 *
 * @param[in]  ptr             A C string.
 * @exception  rb_eNoMemError  Failed to allocate memory.
 * @return     An instance  of ::rb_cString.  In case  encoding conversion from
 *             "default  internal" to  "filesystem" is  fully defined  over the
 *             given  contents,   then  the  return   value  is  a   string  of
 *             "filesystem" encoding,  whose contents  are the  converted ones.
 *             Otherwise the string is a junk.
 * @warning    It doesn't raise on a conversion failure and silently ends up in
 *             a  corrupted  output.  You  can  know  the failure  by  querying
 *             `valid_encoding?` of the result object.
 * @pre        `ptr` must not be a null pointer.
 */
VALUE rb_filesystem_str_new_cstr(const char *ptr);

/**
 * Allocates  a "string  buffer".   A  string buffer  here  is  an instance  of
 * ::rb_cString, whose  capacity is bigger than  the length of it.   If you can
 * say  that a  string grows  to  a specific  amount  of bytes,  this could  be
 * effective than resizing a string over and over again and again.
 *
 * @param[in]  capa  Designed capacity of the generating string.
 * @return     An empty string, of "binary" encoding, whose capacity is `capa`.
 */
VALUE rb_str_buf_new(long capa);

RBIMPL_ATTR_NONNULL(())
/**
 * This is a rb_str_buf_new() + rb_str_buf_cat() combo.
 *
 * @param[in]  ptr             A C string.
 * @exception  rb_eNoMemError  Failed to allocate memory.
 * @return     An  instance  of  ::rb_cString,   of  "binary"  encoding,  whose
 *             contents are verbatim copy of `ptr`.
 * @pre        `ptr` must not be a null pointer.
 *
 * @internal
 *
 * This must be identical to rb_str_new_cstr(), except done in inefficient way?
 * @shyouhei doesn't understand why this is not a simple alias.
 */
VALUE rb_str_buf_new_cstr(const char *ptr);

/**
 * Allocates a  "temporary" string.  This is  a hidden empty string.   Handy on
 * occasions.
 *
 * @param[in]  len  Designed length of the string.
 * @return     A hidden, empty string.
 * @see        rb_obj_hide()
 */
VALUE rb_str_tmp_new(long len);

/**
 * Identical  to rb_str_new(),  except  it  generates a  string  of "US  ASCII"
 * encoding.  This  is different from  rb_external_str_new(), not only  for the
 * output encoding, but also it doesn't convert the contents.
 *
 * @param[in]  ptr             A memory region of `len` bytes length.
 * @param[in]  len             Length  of `ptr`,  in bytes,  not including  the
 *                             terminating NUL character.
 * @exception  rb_eNoMemError  Failed to allocate `len+1` bytes.
 * @exception  rb_eArgError    `len` is negative.
 * @return     An  instance   of  ::rb_cString,  of  `len`   bytes  length,  of
 *             "US ASCII" encoding, whose contents are verbatim copy of `ptr`.
 */
VALUE rb_usascii_str_new(const char *ptr, long len);

/**
 * Identical to rb_str_new_cstr(),  except it generates a string  of "US ASCII"
 * encoding.   It   can   also   be    seen   as   a   routine   Identical   to
 * rb_usascii_str_new(), except it assumes the passed pointer is a pointer to a
 * C string.
 *
 * @param[in]  ptr             A C string.
 * @exception  rb_eNoMemError  Failed to allocate memory.
 * @exception  rb_eArgError    `ptr` is a null pointer.
 * @return     An  instance  of ::rb_cString,  of  "US  ASCII" encoding,  whose
 *             contents are verbatim copy of `ptr`.
 * @pre        `ptr` must not be a null pointer.
 */
VALUE rb_usascii_str_new_cstr(const char *ptr);

/**
 * Identical to rb_str_new(), except it generates a string of "UTF-8" encoding.
 *
 * @param[in]  ptr             A memory region of `len` bytes length.
 * @param[in]  len             Length  of `ptr`,  in bytes,  not including  the
 *                             terminating NUL character.
 * @exception  rb_eNoMemError  Failed to allocate `len+1` bytes.
 * @exception  rb_eArgError    `len` is negative.
 * @return     An  instance   of  ::rb_cString,  of  `len`   bytes  length,  of
 *             "UTF-8" encoding, whose contents are verbatim copy of `ptr`.
 */
VALUE rb_utf8_str_new(const char *ptr, long len);

/**
 * Identical  to rb_str_new_cstr(),  except it  generates a  string of  "UTF-8"
 * encoding.    It   can   also   be   seen   as   a   routine   Identical   to
 * rb_usascii_str_new(), except it assumes the passed pointer is a pointer to a
 * C string.
 *
 * @param[in]  ptr             A C string.
 * @exception  rb_eNoMemError  Failed to allocate memory.
 * @exception  rb_eArgError    `ptr` is a null pointer.
 * @return     An instance of ::rb_cString, of "UTF-8" encoding, whose contents
 *             are verbatim copy of `ptr`.
 * @pre        `ptr` must not be a null pointer.
 */
VALUE rb_utf8_str_new_cstr(const char *ptr);

/**
 * @name Special strings that are backended by C string literals.
 *
 *  *_str_new_static functions are intended for C string literals.
 *  They require memory in the range [ptr, ptr+len] to always be readable.
 *  Note that this range covers a total of len + 1 bytes.
 *
 * @{
 */

/**
 * Identical to rb_str_new(), except it takes a C string literal.
 *
 * @param[in]  ptr           A C string literal.
 * @param[in]  len           `strlen(ptr)`.
 * @exception  rb_eArgError  `len` out of range of `size_t`.
 * @pre        `ptr` must be a C string constant.
 * @return     An instance of ::rb_cString, of "binary" encoding, whose backend
 *             storage is the passed C string literal.
 * @warning    It is  a very  bad idea to  write to a  C string  literal (often
 *             immediate  SEGV shall  occur).  Consider  return values  of this
 *             function be read-only.
 *
 * @internal
 *
 * Surprisingly it can take NULL, and generates an empty string.
 */
VALUE rb_str_new_static(const char *ptr, long len);

/**
 * Identical to rb_str_new_static(), except it generates a string of "US ASCII"
 * encoding instead of "binary".  It can also be seen as a routine identical to
 * rb_usascii_str_new(), except it takes a C string literal.
 *
 * @param[in]  ptr           A C string literal.
 * @param[in]  len           `strlen(ptr)`.
 * @exception  rb_eArgError  `len` out of range of `size_t`.
 * @pre        `ptr` must be a C string constant.
 * @return     An  instance  of ::rb_cString,  of  "US  ASCII" encoding,  whose
 *             backend storage is the passed C string literal.
 * @warning    It is  a very  bad idea to  write to a  C string  literal (often
 *             immediate  SEGV shall  occur).  Consider  return values  of this
 *             function be read-only.
 */
VALUE rb_usascii_str_new_static(const char *ptr, long len);

/**
 * Identical to  rb_str_new_static(), except it  generates a string  of "UTF-8"
 * encoding instead of "binary".  It can also be seen as a routine identical to
 * rb_utf8_str_new(), except it takes a C string literal.
 *
 * @param[in]  ptr           A C string literal.
 * @param[in]  len           `strlen(ptr)`.
 * @exception  rb_eArgError  `len` out of range of `size_t`.
 * @pre        `ptr` must be a C string constant.
 * @return     An instance of ::rb_cString,  of "UTF-8" encoding, whose backend
 *             storage is the passed C string literal.
 * @warning    It is  a very  bad idea to  write to a  C string  literal (often
 *             immediate  SEGV shall  occur).  Consider  return values  of this
 *             function be read-only.
 */
VALUE rb_utf8_str_new_static(const char *ptr, long len);

/** @} */

/**
 * Identical to rb_interned_str(),  except it takes a Ruby's  string instead of
 * C's.  It can also be seen  as a routine identical to to rb_str_new_shared(),
 * except it returns an infamous "f"string.
 *
 * @param[in]  str  An object of ::RString.
 * @return     An instance  of ::rb_cString, either cached  or allocated, which
 *             has the identical encoding, length, and contents with the passed
 *             string.
 * @pre        `str` must not be any arbitrary object except ::RString.
 * @note       Use #StringValue to enforce the precondition.
 *
 * @internal
 *
 * It  actually  finds  or  creates  a fstring  of  the  needed  property,  and
 * destructively modifies  the receiver behind-the-scene  so that it  becomes a
 * shared string whose parent is the returning fstring.
 */
VALUE rb_str_to_interned_str(VALUE str);

/**
 * Identical to rb_str_new(), except it returns an infamous "f"string.  What is
 * a  fstring?  Well  it is  a special  subkind of  strings that  is immutable,
 * deduped globally, and managed by our GC.   It is much like a Symbol (in fact
 * Symbols  are dynamic  these days  and are  backended using  fstrings).  This
 * concept has been  silently introduced at some point in  2.x era.  Since then
 * it  gained  wider acceptance  in  the  core.   Starting from  3.x  extension
 * libraries can also generate ones.
 *
 * @param[in]  ptr           A memory region of `len` bytes length.
 * @param[in]  len           Length  of  `ptr`,  in bytes,  not  including  the
 *                           terminating NUL character.
 * @exception  rb_eArgError  `len` is negative.
 * @return     A  found or  created instance  of ::rb_cString,  of `len`  bytes
 *             length, of  "binary" encoding,  whose contents are  identical to
 *             that of `ptr`.
 * @pre        At  least  `len` bytes  of  continuous  memory region  shall  be
 *             accessible via `ptr`.
 */
VALUE rb_interned_str(const char *ptr, long len);

RBIMPL_ATTR_NONNULL(())
/**
 * Identical to  rb_interned_str(), except it  assumes the passed pointer  is a
 * pointer to a C's  string.  It can also be seen as a  routine identical to to
 * rb_str_to_interned_str(), except  it takes a  C's string instead  of Ruby's.
 * Or it can  also be seen as a routine  identical to rb_str_new_cstr(), except
 * it returns an infamous "f"string.
 *
 * @param[in]  ptr             A C string.
 * @exception  rb_eNoMemError  Failed to allocate memory.
 * @return     An  instance  of  ::rb_cString,   of  "binary"  encoding,  whose
 *             contents are verbatim copy of `ptr`.
 * @pre        `ptr` must not be a null pointer.
 */
VALUE rb_interned_str_cstr(const char *ptr);

/**
 * Destroys the given string for no reason.
 *
 * @warning  DO NOT USE IT.
 * @warning  Leave this task to our GC.
 * @warning  It was a bad idea at the first place to let you know about it.
 *
 * @param[out]  str  The string to be executed.
 * @post        The given string no longer exists.
 * @note        Maybe `String#clear` could be what you want.
 *
 * @internal
 *
 * Should have moved this to `internal/string.h`.
 */
void rb_str_free(VALUE str);

/**
 * Replaces the contents of the former with the latter.
 *
 * @param[out]  dst  Destination object.
 * @param[in]   src  Source object.
 * @pre         Both  objects   must  not  be  any   arbitrary  objects  except
 *              ::RString.
 * @post        `dst`'s  former  components  are  abandoned.  It  now  has  the
 *              identical encoding, length, and contents to `src`.
 * @see         rb_str_replace()
 *
 * @internal
 *
 * @shyouhei  doesn't understand  why this  is useful  to extension  libraries.
 * Just use rb_str_replace().  What's wrong with that?
 */
void rb_str_shared_replace(VALUE dst, VALUE src);

/**
 * Identical to  rb_str_cat_cstr(), except  it takes  Ruby's string  instead of
 * C's.  It can also be seen as a routine identical to rb_str_shared_replace(),
 * except it appends instead of replaces.
 *
 * @param[out]  dst                 Destination object.
 * @param[in]   src                 Source object.
 * @exception   rb_eEncCompatError  Can't mix the encodings.
 * @exception   rb_eArgError        Result string too big.
 * @return      The passed `dst`.
 * @pre         Both  objects   must  not  be  any   arbitrary  objects  except
 *              ::RString.
 * @post        `dst`  has  the  contents  of  `src`  appended,  with  encoding
 *              converted into `dst`'s one, into the end of `dst`.
 */
VALUE rb_str_buf_append(VALUE dst, VALUE src);

/** @alias{rb_str_cat} */
VALUE rb_str_buf_cat(VALUE, const char*, long);

/** @alias{rb_str_cat_cstr} */
VALUE rb_str_buf_cat2(VALUE, const char*);

RBIMPL_ATTR_NONNULL(())
/**
 * Identical to  rb_str_cat_cstr(), except  it additionally assumes  the source
 * string be a NUL terminated ASCII string.
 *
 * @param[out]  dst           Destination object.
 * @param[in]   src           Source string.
 * @exception   rb_eArgError  Result string too big.
 * @return      The passed `dst`.
 * @pre         `dst` must not be any arbitrary object except ::RString.
 * @pre         `src` must be a NUL terminated ASCII string.
 * @post        `dst`  has  the  contents  of  `src`  appended,  with  encoding
 *              converted into `dst`'s one, into the end of `dst`.
 */
VALUE rb_str_buf_cat_ascii(VALUE dst, const char *src);

/**
 * Try converting an  object to its stringised representation  using its `to_s`
 * method, if  any.  If  there is  no such thing,  it resorts  to rb_any_to_s()
 * output.
 *
 * @param[in]  obj  Arbitrary ruby object to stringise.
 * @return     An instance of ::rb_cString.
 */
VALUE rb_obj_as_string(VALUE obj);

/**
 * Try converting an object to its stringised representation using its `to_str`
 * method, if any.  If there is no such thing, returns ::RUBY_Qnil.
 *
 * @param[in]  obj            Arbitrary ruby object to stringise.
 * @exception  rb_eTypeError  `obj.to_str` returned something non-String.
 * @retval     RUBY_Qnil      No conversion from obj to String defined.
 * @return     otherwise      Stringised representation of `obj`.
 * @see        rb_io_check_io
 * @see        rb_check_array_type
 * @see        rb_check_hash_type
 */
VALUE rb_check_string_type(VALUE obj);

/**
 * Asserts that  the given  string's encoding is  (Ruby's definition  of) ASCII
 * compatible.
 *
 * @param[in]  obj                 An instance of ::rb_cString.
 * @exception  rb_eEncCompatError  `obj` is ASCII incompatible.
 *
 * @internal
 *
 * @shyouhei doesn't know if this is an  Easter egg or an official feature, but
 * this function  can in fact take  non-strings such as Symbols,  Regexps, IOs,
 * etc.  However if something unsupported is  passed, it causes SEGV.  It seems
 * the feature is kind of untested.
 */
void rb_must_asciicompat(VALUE obj);

/**
 * Duplicates a string.
 *
 * @param[in]  str  String in question to duplicate.
 * @return     A duplicated new instance.
 * @pre        `str` must be of ::RString.
 */
VALUE rb_str_dup(VALUE str);

/**
 * I guess there  is no use case  of this function in  extension libraries, but
 * this is  a routine identical  to rb_str_dup(),  except it always  creates an
 * instance of ::rb_cString regardless of the given object's class.  This makes
 * the most sense when the passed string is formerly hidden by rb_obj_hide().
 *
 * @param[in]  str  A string, possibly hidden.
 * @return     A duplicated new instance of ::rb_cString.
 */
VALUE rb_str_resurrect(VALUE str);

/**
 * Obtains a "temporary  lock" of the string.  This  advisory locking mechanism
 * prevents other  cooperating threads from  tampering the receiver.   The same
 * thing could be done via freeze mechanism,  but this one can also be unlocked
 * using rb_str_unlocktmp().
 *
 * @param[out]  str               String to lock.
 * @exception   rb_eRuntimeError  `str` already locked.
 * @return      The given string.
 * @post        The string is locked.
 */
VALUE rb_str_locktmp(VALUE str);

/**
 * Releases a lock formerly obtained by rb_str_locktmp().
 *
 * @param[out]  str               String to unlock.
 * @exception   rb_eRuntimeError  `str` already unlocked.
 * @return      The given string.
 * @post        The string is locked.
 */
VALUE rb_str_unlocktmp(VALUE str);

/** @alias{rb_str_new_frozen} */
VALUE rb_str_dup_frozen(VALUE);

/** @alias{rb_str_new_frozen} */
#define rb_str_dup_frozen rb_str_new_frozen

/**
 * Generates a new string, concatenating the former to the latter.  It can also
 * be seen as a routine identical  to rb_str_append(), except it doesn't tamper
 * the passed strings to create a new one instead.
 *
 * @param[in]  lhs                 Source string #1.
 * @param[in]  rhs                 Source string #2.
 * @exception  rb_eEncCompatError  Can't mix the encodings.
 * @exception  rb_eArgError        Result string too big.
 * @return     A new string containing `rhs` concatenated to `lhs`.
 * @pre        Both objects must not be any arbitrary objects except ::RString.
 * @note       This  operation  doesn't commute.   Don't  get  confused by  the
 *             "plus"  terminology.   For  historical reasons  there  are  some
 *             noncommutative `+`s in Ruby.  This is one of such things.  There
 *             has been a long discussion around `+`s in programming languages.
 */
VALUE rb_str_plus(VALUE lhs, VALUE rhs);

/**
 * Repetition of a string.
 *
 * @param[in]  str           String to repeat.
 * @param[in]  num           Count, something numeric.
 * @exception  rb_eArgError  `num` is negative.
 * @return     A new string repeating `num` times of `str`.
 */
VALUE rb_str_times(VALUE str, VALUE num);

/**
 * Byte  offset to  character offset  conversion.   This makes  sense when  the
 * receiver is in  a multibyte encoding.  The string's i-th  character does not
 * always sit at its  i-th byte.  This function scans the  contents to find the
 * character index that matches the byte  index.  Generally speaking this is an
 * `O(n)` operation.  Could be slow.
 *
 * @param[in]  str  The string to scan.
 * @param[in]  pos  Offset, in bytes.
 * @return     Offset, in characters.
 */
long rb_str_sublen(VALUE str, long pos);

/**
 * This is the implementation of two-argumented `String#slice`.
 *
 * - Returns the substring of the given `len` found in `str` at offset `beg`:
 *
 *   ```ruby
 *   'foo'[0, 2] # => "fo"
 *   'foo'[0, 0] # => ""
 *   ```
 *
 * - Counts backward from the end of `str` if `beg` is negative:
 *
 *   ```ruby
 *   'foo'[-2, 2] # => "oo"
 *   ```
 *
 * - Special case: returns a  new empty string if `beg` is  equal to the length
 *   of `str`:
 *
 *   ```ruby
 *   'foo'[3, 2] # => ""
 *   ```
 *
 * - Returns a null pointer if `beg` is out of range:
 *
 *   ```ruby
 *   'foo'[4, 2] # => nil
 *   'foo'[-4, 2] # => nil
 *   ```
 *
 * - Returns the trailing substring of `str` if `len` is large:
 *
 *   ```ruby
 *   'foo'[1, 50] # => "oo"
 *   ```
 *
 * - Returns a null pointer if `len` is negative:
 *
 *   ```ruby
 *   'foo'[0, -1] # => nil
 *   ```
 *
 * @param[in]  str        The string to slice.
 * @param[in]  beg        Requested offset of the substring.
 * @param[in]  len        Requested length of the substring.
 * @retval     RUBY_Qnil  Parameters out of range.
 * @retval     otherwise  A  new   string  whose  contents  is   the  specified
 *                        substring of `str`.
 * @pre        `str` must not be any arbitrary objects except ::RString.
 */
VALUE rb_str_substr(VALUE str, long beg, long len);

/**
 * Identical to  rb_str_substr(), except  the numbers  are interpreted  as byte
 * offsets instead of character offsets.
 *
 * @param[in]  str  The string to slice.
 * @param[in]  beg  Requested offset of the substring.
 * @param[in]  len  Requested length of the substring.
 * @return     A new string whose contents is the specified substring of `str`.
 * @pre        `str` must not be any arbitrary objects except ::RString.
 * @pre        `beg` and `len` must not point to OOB contents.
 */
VALUE rb_str_subseq(VALUE str, long beg, long len);

/**
 * Identical  to rb_str_substr(),  except it  returns a  C's string  instead of
 * Ruby's.
 *
 * @param[in]      str        The string to slice.
 * @param[in]      beg        Requested offset of the substring.
 * @param[in,out]  len        Requested length of the substring.
 * @retval         NULL       Parameters out of range.
 * @retval         otherwise  A pointer inside of `str`'s backend storage where
 *                            the specified substring exist.
 * @pre            `str` must not be any arbitrary objects except ::RString.
 * @post           `len` is updated to have the length of the return value.
 */
char *rb_str_subpos(VALUE str, long beg, long *len);

/**
 * Declares that the string is about to be modified.  This for instance let the
 * string have a dedicated backend storage.
 *
 * @param[out]  str               String about to be modified.
 * @exception   rb_eRuntimeError  `str` is `locktmp`-ed.
 * @exception   rb_eFrozenError   `str` is frozen.
 * @pre         `str` must not be any arbitrary objects except ::RString.
 * @post        Upon  successful return  the passed  string is  eligible to  be
 *              modified.
 */
void rb_str_modify(VALUE str);

/**
 * Identical to rb_str_modify(), except it additionally expands the capacity of
 * the receiver.
 *
 * @param[out]  str               Target string to modify.
 * @param[in]   capa              Additional capacity to add.
 * @exception   rb_eArgError      `capa` is negative.
 * @exception   rb_eRuntimeError  `str` is `locktmp`-ed.
 * @exception   rb_eFrozenError   `str` is frozen.
 * @pre         `str` must not be any arbitrary objects except ::RString.
 * @post        Upon successful  return the passed  string is modified  so that
 *              its capacity is increased for `capa` bytes.
 */
void rb_str_modify_expand(VALUE str, long capa);

/**
 * This is the implementation of `String#freeze`.
 *
 * @param[out]  str  Target string to freeze.
 * @return      The passed string.
 * @post        Upon successful return the passed string is frozen.
 */
VALUE rb_str_freeze(VALUE str);

/**
 * Overwrites the  length of the  string.  Typically this  is used to  shrink a
 * string that was formerly expanded.
 *
 * ```CXX
 * extern int fd;
 * auto str = rb_eval_string("'...'");
 * rb_str_modify_expand(str, BUFSIZ);
 * if (auto len = recv(fd, RSTRING_PTR(str), BUFSIZ, 0); len >= 0) {
 *     rb_str_set_len(str, len);
 * }
 * else {
 *     rb_sys_fail("recv(2)");
 * }
 * ```
 *
 * @param[out]  str               String to shrink.
 * @param[in]   len               New length of the string.
 * @exception   rb_eRuntimeError  `str` is `locktmp`-ed.
 * @exception   rb_eFrozenError   `str` is frozen.
 * @pre         `str` must not be any arbitrary objects except ::RString.
 * @post        Upon successful return `str`'s length is set to `len`.
 */
void rb_str_set_len(VALUE str, long len);

/**
 * Overwrites the length of the  string.  In contrast to rb_str_set_len(), this
 * function can also expand a string.
 *
 * @param[out]  str               String to shrink.
 * @param[in]   len               New length of the string.
 * @exception   rb_eArgError      `len` is negative.
 * @exception   rb_eRuntimeError  `str` is `locktmp`-ed.
 * @exception   rb_eFrozenError   `str` is frozen.
 * @return      The passed `str`.
 * @pre         `str` must not be any arbitrary objects except ::RString.
 * @post        Upon successful return `str` is  either expanded or shrunken to
 *              have its length be `len`.
 */
VALUE rb_str_resize(VALUE str, long len);

/**
 * Destructively appends the passed contents to the string.
 *
 * @param[out]  dst           Destination object.
 * @param[in]   src           Contents to append.
 * @param[in]   srclen        Length of `src`.
 * @exception   rb_eArgError  `srclen` is negative.
 * @return      The passed `dst`.
 * @pre         `dst` must not be any arbitrary objects except ::RString.
 * @post        `dst` has the contents of `ptr` appended.
 */
VALUE rb_str_cat(VALUE dst, const char *src, long srclen);

/**
 * Identical to rb_str_cat(), except it assumes the passed pointer is a pointer
 * to a C string.
 *
 * @param[out]  dst           Destination object.
 * @param[in]   src           Contents to append.
 * @exception   rb_eArgError  Result string too big.
 * @exception   rb_eArgError  `src` is a null pointer.
 * @return      The passed `dst`.
 * @pre         `dst` must not be any arbitrary objects except ::RString.
 * @pre         `src` must not be a null pointer.
 * @post        `dst` has the contents of `src` appended.
 */
VALUE rb_str_cat_cstr(VALUE dst, const char *src);

/** @alias{rb_str_cat_cstr} */
VALUE rb_str_cat2(VALUE, const char*);

/**
 * Identical to  rb_str_buf_append(), except  it converts  the right  hand side
 * before concatenating.
 *
 * @param[out]  dst                 Destination object.
 * @param[in]   src                 Source object.
 * @exception   rb_eEncCompatError  Can't mix the encodings.
 * @exception   rb_eArgError        Result string too big.
 * @return      The passed `dst`.
 * @pre         `dst` must not be any arbitrary objects except ::RString.
 * @post        `dst`  has  the  contents  of  `src`  appended,  with  encoding
 *              converted into `dst`'s one, into the end of `dst`.
 */
VALUE rb_str_append(VALUE dst, VALUE src);

/**
 * Identical  to  rb_str_append(), except  it  also  accepts  an integer  as  a
 * codepoint.  This resembles `String#<<`.
 *
 * @param[out]  dst                 Destination object.
 * @param[in]   src                 Source object, String or Numeric.
 * @exception   rb_eRangeError      Source numeric is out of range.
 * @exception   rb_eEncCompatError  Source string too long.
 * @exception   rb_eArgError        Result string too big.
 * @return      The passed `dst`.
 * @pre         `dst` must not be any arbitrary objects except ::RString.
 * @post        `dst`  has  the  contents  of  `src`  appended,  with  encoding
 *              converted into `dst`'s one, into the end of `dst`.
 */
VALUE rb_str_concat(VALUE dst, VALUE src);

/* random.c */

/**
 * This is a universal hash function.
 *
 * @warning    This function changes its value per process.
 * @param[in]  ptr  Target message.
 * @param[in]  len  Length of `ptr` in bytes.
 * @return     A pseudorandom number suitable for Hash's hash value.
 * @see        Aumasson,  JP., Bernstein,  D.J., "SipHash:  A Fast  Short-Input
 *             PRF",  In  proceedings  of   13th  International  Conference  on
 *             Cryptology in  India (INDOCRYPT 2012), LNCS  7668, pp.  489-508,
 *             2012.  http://doi.org/10.1007/978-3-642-34931-7_28
*/
st_index_t rb_memhash(const void *ptr, long len);

/**
 * Starts a series of hashing.  Suppose you have a struct:
 *
 * ```CXX
 * struct foo_tag {
 *     unsigned char bar;
 *     uint32_t baz;
 * };
 * ```
 *
 * It is not a  wise idea to call rb_memhash() over it,  because there could be
 * padding bits.  Instead you should explicitly iterate over each fields:
 *
 * ```CXX
 * foo_tag foo = { 0, 0, };
 * st_index_t hash = 0;
 *
 * hash = rb_hash_start(0);
 * hash = rb_hash_uint(hash, foo.bar);
 * hash = rb_hash_uint32(hash, foo.baz);
 * hash = rb_hash_end(hash);
 * ```
 *
 * @param[in]  i  Initial value.
 * @return     A hash value.
 */
st_index_t rb_hash_start(st_index_t i);

/** @alias{st_hash_uint32} */
#define rb_hash_uint32(h, i) st_hash_uint32((h), (i))

/** @alias{st_hash_uint} */
#define rb_hash_uint(h, i) st_hash_uint((h), (i))

/** @alias{st_hash_end} */
#define rb_hash_end(h) st_hash_end(h)

/* string.c */

/**
 * Calculates a hash value of a string.   This is one of the two functions that
 * constructs struct ::st_hash_type.
 *
 * @param[in]  str  An object of ::RString.
 * @return     A hash value.
 * @pre        `str` must not be any arbitrary object except ::RString.
 *
 * @internal
 *
 * Although safe to call, there must be no particular use case of this function
 * for extension libraries.  Only ruby internals must know about it.
 *
 * This is not a simple alias  of rb_memhash(), because it considers the passed
 * string's encoding as well as its contents.
 */
st_index_t rb_str_hash(VALUE str);

/**
 * Compares two  strings.  This  is one  of the  two functions  that constructs
 * struct ::st_hash_type.
 *
 * @param[in]  str1  A string.
 * @param[in]  str2  Another string.
 * @retval     1     They have identical contents, length, and encodings.
 * @retval     0     Otherwise.
 * @pre        Both   objects   must  not  be  any   arbitrary  objects  except
 *             ::RString.
 *
 * @internal
 *
 * In contrast to  rb_str_hash(), this could be handy for  comparison that only
 * concerns equality.  rb_str_cmp() returns 1, 0, -1.
 */
int rb_str_hash_cmp(VALUE str1, VALUE str2);

/**
 * Checks  if  two   strings  are  comparable  each  other   or  not.   Because
 * rb_str_cmp()  must  return  "lesser  than" or  "greater  than"  information,
 * comparing two strings needs a stricter restriction.  Both sides must be in a
 * same set of strings which have total order.  This is to check that property.
 * Intuitive it  sounds?  But they  can have different encodings.   A character
 * and another might or might not appear in the same order in their codepoints.
 * It is complicated than you think.
 *
 * @param[in]  str1  A string.
 * @param[in]  str2  Another string.
 * @retval     1     They agree on a total order.
 * @retval     0     Otherwise.
 * @pre        Both   objects   must  not  be  any   arbitrary  objects  except
 *             ::RString.
 */
int rb_str_comparable(VALUE str1, VALUE str2);

/**
 * Compares two strings, as in `strcmp(3)`.  This does not consider the current
 * locale, but considers the encodings of both sides instead.
 *
 * @param[in]  lhs  A string.
 * @param[in]  rhs  Another string.
 * @retval     -1   `lhs` is "bigger than" `rhs`.
 * @retval      1   `rhs` is "bigger than" `lhs`.
 * @retval      0    Otherwise, e.g. not comparable.
 * @pre        Both   objects   must  not  be  any   arbitrary  objects  except
 *             ::RString.
 */
int rb_str_cmp(VALUE lhs, VALUE rhs);

/**
 * Equality of two strings.
 *
 * If `str2` is not a String, it  resorts to `str2 == str1`.  Otherwise if they
 * are not comparable, returns ::RUBY_Qfalse.   Otherwise if they have the same
 * contents  and   the  length,   returns  ::RUBY_Qtrue.    Otherwise,  returns
 * ::RUBY_Qfalse.
 *
 * @param[in]  str1         A string.
 * @param[in]  str2         Another string.
 * @retval     RUBY_Qtrue   They are equal.
 * @retval     RUBY_Qfalse  They are either different, or not comparable.
 */
VALUE rb_str_equal(VALUE str1, VALUE str2);

/**
 * Shrinks the given string for the given number of bytes.
 *
 * @param[out]  str               String to squash.
 * @param[in]   len               Number of bytes to reduce.
 * @exception   rb_eRuntimeError  `str` is `locktmp`-ed.
 * @exception   rb_eFrozenError   `str` is frozen.
 * @return      The passed `str`.
 * @pre         `str` must not be any arbitrary objects except ::RString.
 * @post        `str` is shrunken.
 * @warning     Can break a multibyte character in middle.
 *
 * @internal
 *
 * What if `len` is negative?
 */
VALUE rb_str_drop_bytes(VALUE str, long len);

/**
 * Replaces some  (or all) of  the contents of the  given string.  This  is the
 * implementation of three-argumented `String#[]=`.
 *
 * @param[out]  dst               Target string to update.
 * @param[in]   beg               Offset of the affected portion.
 * @param[in]   len               Length of the affected portion.
 * @param[in]   src               Object to be assigned.
 * @exception   rb_eTypeError     `src` has no implicit conversion to String.
 * @exception   rb_eIndexError    `len` is negative, or `beg` is OOB.
 * @exception   rb_eRuntimeError  `dst` is `locktmp`-ed.
 * @exception   rb_eFrozenError   `dst` is frozen.
 * @note        Unlike rb_str_substr(), this function raises.
 * @post        A  portion of  `dst`  from  `beg` to  `len`  is the  stringised
 *              representation of `src`.  If that replacement string is not the
 *              same  length as  the portion  it  is replacing,  `dst` will  be
 *              resized accordingly.
 */
void rb_str_update(VALUE dst, long beg, long len, VALUE src);

/**
 * Replaces the contents  of the former object with the  stringised contents of
 * the latter.
 *
 * @param[out]  dst               Destination object.
 * @param[in]   src               Source object.
 * @exception   rb_eTypeError     `src` has no implicit conversion to String.
 * @exception   rb_eRuntimeError  `dst` is `locktmp`-ed.
 * @exception   rb_eFrozenError   `dst` is frozen.
 * @return      The passed `dst`.
 * @pre        `dst` must not be any arbitrary object except ::RString.
 * @post        `dst`'s  former  components  are  abandoned.  It  now  has  the
 *              identical encoding, length, and contents to `src`.
 */
VALUE rb_str_replace(VALUE dst, VALUE src);

/**
 * Generates a "readable" version of the receiver.
 *
 * @warning    The output is _insecure_.  Never feed one to `eval`.
 * @warning    The output is not always in the same encoding as the given one.
 * @warning    A  character might  or might  not be  escaped, depending  on the
 *             result encoding.
 * @param[in]  str  String to inspect.
 * @return     Its inspection, either  in default internal encoding  if any, or
 *             in default external encoding otherwise.
 * @see        rb_str_dump()
 *
 * @internal
 *
 * This is a  (silent) fix of an actual vulnerability  feeding `inspect` output
 * strings to `eval`:
 * https://github.com/hiki/hiki/commit/8771a6e25198e264a2bf9dc1c102fea2cc8ff975
 *
 * ... and its advisory:
 * http://hikiwiki.org/en/advisory20040712.html
 */
VALUE rb_str_inspect(VALUE str);

/**
 * "Inverse" of rb_eval_string().  Returns a quoted version of the string.  All
 * non-printing characters are replaced by  `\uNNNN` or `\xHH` notation and all
 * special characters are escaped.  The result string is guaranteed to render a
 * string of the same contents when passed to `eval` and friends.
 *
 * @param[in]  str               String to dump.
 * @exception  rb_eRuntimeError  Too  many  escape   sequences  causes  integer
 *                               overflow on the length of the string.
 * @return     An  US-ASCII string  that  includes all  the  necessary info  to
 *             reconstruct the original string.
 */
VALUE rb_str_dump(VALUE str);

/**
 * Divides  the  given string  based  on  the  given  delimiter.  This  is  the
 * 1-argument 0-block version of `String#split`.
 *
 * @param[in]  str            Object in question to split.
 * @param[in]  delim          Delimiter, in C string.
 * @exception  rb_eTypeError  `str` has no implicit conversion to String.
 * @exception  rb_eArgError   `delim` is a null pointer.
 * @return     An array of  strings, which are substrings of  the passed `str`.
 *             If `delim` is an empty C string (i.e. `""`), `str` is split into
 *             each characters.  If `delim` is a C string whose sole content is
 *             a whitespace (i.e.  `" "`), `str` is split  on whitespaces, with
 *             leading  and   trailing  whitespace   and  runs   of  contiguous
 *             whitespace  characters  ignored.    Otherwise,  `str`  is  split
 *             according to `delim`.
 */
VALUE rb_str_split(VALUE str, const char *delim);

/**
 * This is a ::rb_gvar_setter_t that refutes non-string assignments.
 *
 * @exception  rb_eTypeError  Passed something non-string.
 */
rb_gvar_setter_t rb_str_setter;

/* symbol.c */

/**
 * Identical  to  rb_to_symbol(),  except  it assumes  the  receiver  being  an
 * instance of ::RString.
 *
 * @param[in]  str               The name of the id.
 * @exception  rb_eRuntimeError  Too many symbols.
 * @return     A (possibly new) id whose value is the given `str`.
 * @pre        `str` must not be any arbitrary object except ::RString.
 * @note       These   days  Ruby   internally   has  two   kinds  of   symbols
 *             (static/dynamic).   Symbols created  using  this function  would
 *             become dynamic ones; i.e. would  be garbage collected.  It could
 *             be safer for you to use it than alternatives, when applicable.
 */
VALUE rb_str_intern(VALUE str);

/* string.c */

/**
 * This is an rb_sym2str() + rb_str_dup() combo.
 *
 * @param[in]  sym  A symbol to query.
 * @return     A string duplicating the symbol's backend storage.
 *
 * @internal
 *
 * This function  causes SEGV  when the  passed value is  a static  symbol that
 * doesn't exist.
 */
VALUE rb_sym_to_s(VALUE sym);

/**
 * Counts the  number of characters (not  bytes) that are stored  inside of the
 * given string.  This  of course depends on its encoding.   Also this function
 * generally runs  in O(n), because  for instance you  have to scan  the entire
 * string to know how many characters are there in a UTF-8 string.
 *
 * @param[in]  str  Target string to query.
 * @return     Its number of characters.
 */
long rb_str_strlen(VALUE str);

/**
 * Identical to rb_str_strlen(), except it returns the value in ::rb_cInteger.
 *
 * @param[in]  str  Target string to query.
 * @return     Its number of characters.
 */
VALUE rb_str_length(VALUE);

/**
 * "Inverse" of rb_str_sublen().  This function  scans the contents to find the
 * byte index that matches the character  index.  Generally speaking this is an
 * `O(n)` operation.  Could be slow.
 *
 * @param[in]  str  The string to scan.
 * @param[in]  pos  Offset, in characters.
 * @return     Offset, in bytes.
 */
long rb_str_offset(VALUE str, long pos);

RBIMPL_ATTR_PURE()
/**
 * Queries the capacity of the given string.
 *
 * @see        ::RString::capa
 * @param[in]  str  String in question.
 * @return     Its capacity.
 */
size_t rb_str_capacity(VALUE str);

/**
 * Shortens `str` and adds three dots, an  ellipsis, if it is longer than `len`
 * characters.  The length of the returned string in characters is less than or
 * equal to `len`.  If the length of `str` is less than or equal `len`, returns
 * `str` itself.   The encoding of returned  string is equal to  that of passed
 * one.  The class of returned string is equal to that of passed one.
 *
 * @param[in]  str             The string to shorten.
 * @param[in]  len             The maximum string length.
 * @exception  rb_eIndexError  `len` is negative.
 * @retval     str             No need to add ellipsis.
 * @retval     otherwise       A new, shortened string.
 * @note       The length is counted in characters.
 */
VALUE rb_str_ellipsize(VALUE str, long len);

/**
 * "Cleanses" the string.   A string has its encoding and  its contents.  They,
 * in practice,  do not  always fit.  There  are strings in  the wild  that are
 * "broken"; include bit  patterns that are not allowed by  its encoding.  That
 * can  happen  when  a  user  copy&pasted something  bad,  network  input  got
 * clobbered by a middleman, cosmic rays hit the physical memory, and many more
 * occasions.  This function takes such strings, and fills the "broken" portion
 * with the passed replacement bit pattern.
 *
 * This function also takes a ruby block.  That is a neat way to do things, but
 * can be  annoying when the  caller function want to  use a block  for another
 * purpose.
 *
 * @param[in]  str                 Target string to scrub.
 * @param[in]  repl                Replacement  string.  When  it is  a string,
 *                                 this function  takes that as  a replacement.
 *                                 When it is  ::RUBY_Qnil, this function tries
 *                                 to  yield a  block  (if any)  and takes  its
 *                                 evaluated value  as a replacement.   In case
 *                                 of   ::RUBY_Qnil  without   a  block,   this
 *                                 function takes  an encoding-specific default
 *                                 character (`U+FFFD`, for instance) as a last
 *                                 resort.
 * @exception  rb_eTypeError       `repl` is neither string nor nil.
 * @exception  rb_eArgError        `repl` itself is broken.
 * @exception  rb_eEncCompatError  `repl` and `str` are incompatible.
 * @retval     RUBY_Qnil           `str` is already clean.
 * @retval     otherwise           A new, clean string.
 */
VALUE rb_str_scrub(VALUE str, VALUE repl);

/**
 * Searches for  the "successor"  of a string.   This function  is complicated!
 * This is  the only function in  the entire ruby  API (either C or  Ruby) that
 * generates a string out of thin air.  First, the successor to an empty string
 * is a new empty string:
 *
 * ```ruby
 * ''.succ # => ""
 * ```
 *
 * Otherwise  the successor  is  calculated by  "incrementing" characters.  The
 * first character to  be incremented is the rightmost alphanumeric:  or, if no
 * alphanumerics, the rightmost character:
 *
 * ```ruby
 * 'THX1138'.succ # => "THX1139"
 * '<<koala>>'.succ # => "<<koalb>>"
 * '***'.succ # => '**+'
 * ```
 *
 * The  successor to  a digit  is another  digit, "carrying"  to the  next-left
 * character for  a "rollover"  from 9  to 0, and  prepending another  digit if
 * necessary:
 *
 * ```ruby
 * '00'.succ # => "01"
 * '09'.succ # => "10"
 * '99'.succ # => "100"
 * '-9'.succ # => "-10"
 * ```
 *
 * The successor to  a letter is another  letter of the same  case, carrying to
 * the next-left  character for  a rollover,  and prepending  another same-case
 * letter if necessary:
 *
 * ```ruby
 * 'aa'.succ # => "ab"
 * 'az'.succ # => "ba"
 * 'zz'.succ # => "aaa"
 * 'AA'.succ # => "AB"
 * 'AZ'.succ # => "BA"
 * 'ZZ'.succ # => "AAA"
 * ```
 *
 * The successor to  a non-alphanumeric character is the next  character in the
 * underlying  character set's  collating sequence,  carrying to  the next-left
 * character for a rollover, and prepending another character if necessary:
 *
 * ```ruby
 * s = "\u03A1"
 * s.succ # => "\u03A3"  # There is no such thing like \u03A2.
 * s = 255.chr * 3
 * s # => "\xFF\xFF\xFF"
 * s.succ # => "\x01\x00\x00\x00"
 * ```
 *
 * Carrying can occur between and among mixtures of alphanumeric characters:
 *
 * ```ruby
 * s = 'zz99zz99'
 * s.succ # => "aaa00aa00"
 * s = '99zz99zz'
 * s.succ # => "100aa00aa"
 * s = '1.9.9'
 * s.succ # => "2.0.0"
 * ```
 *
 * @param[in]  orig  Predecessor string.
 * @return     Successor string.
 */
VALUE rb_str_succ(VALUE orig);

RBIMPL_ATTR_NONNULL(())
/**
 * @private
 *
 * This is an implementation detail.  Don't bother.
 *
 * @param[in]  str  A C string.
 * @return     `strlen`, casted to `long`.
 */
static inline long
rbimpl_strlen(const char *str)
{
    return RBIMPL_CAST((long)strlen(str));
}

RBIMPL_ATTR_NONNULL(())
/**
 * @private
 *
 * This is an implementation detail.  Don't bother.
 *
 * @param[in]  str  A C string literal.
 * @return     Corresponding Ruby string.
 */
static inline VALUE
rbimpl_str_new_cstr(const char *str)
{
    long len = rbimpl_strlen(str);
    return rb_str_new_static(str, len);
}

RBIMPL_ATTR_NONNULL(())
/**
 * @private
 *
 * This is an implementation detail.  Don't bother.
 *
 * @param[in]  str  A C string literal.
 * @return     Corresponding Ruby string.
 */
static inline VALUE
rbimpl_usascii_str_new_cstr(const char *str)
{
    long len = rbimpl_strlen(str);
    return rb_usascii_str_new_static(str, len);
}

RBIMPL_ATTR_NONNULL(())
/**
 * @private
 *
 * This is an implementation detail.  Don't bother.
 *
 * @param[in]  str  A C string literal.
 * @return     Corresponding Ruby string.
 */
static inline VALUE
rbimpl_utf8_str_new_cstr(const char *str)
{
    long len = rbimpl_strlen(str);
    return rb_utf8_str_new_static(str, len);
}

RBIMPL_ATTR_NONNULL(())
/**
 * @private
 *
 * This is an implementation detail.  Don't bother.
 *
 * @param[in]  str  A C string literal.
 * @return     Corresponding Ruby string.
 */
static inline VALUE
rbimpl_external_str_new_cstr(const char *str)
{
    long len = rbimpl_strlen(str);
    return rb_external_str_new(str, len);
}

RBIMPL_ATTR_NONNULL(())
/**
 * @private
 *
 * This is an implementation detail.  Don't bother.
 *
 * @param[in]  str  A C string literal.
 * @return     Corresponding Ruby string.
 */
static inline VALUE
rbimpl_locale_str_new_cstr(const char *str)
{
    long len = rbimpl_strlen(str);
    return rb_locale_str_new(str, len);
}

RBIMPL_ATTR_NONNULL(())
/**
 * @private
 *
 * This is an implementation detail.  Don't bother.
 *
 * @param[in]  str  A C string literal.
 * @return     Corresponding Ruby string.
 */
static inline VALUE
rbimpl_str_buf_new_cstr(const char *str)
{
    long len = rbimpl_strlen(str);
    VALUE buf = rb_str_buf_new(len);
    return rb_str_buf_cat(buf, str, len);
}

RBIMPL_ATTR_NONNULL(())
/**
 * @private
 *
 * This is an implementation detail.  Don't bother.
 *
 * @param[out]  buf  A string buffer.
 * @param[in]   str  A C string literal.
 * @return      `buf` itself.
 */
static inline VALUE
rbimpl_str_cat_cstr(VALUE buf, const char *str)
{
    long len = rbimpl_strlen(str);
    return rb_str_cat(buf, str, len);
}

RBIMPL_ATTR_NONNULL(())
/**
 * @private
 *
 * This is an implementation detail.  Don't bother.
 *
 * @param[in]  exc  An exception class.
 * @param[in]  str  A C string literal.
 * @return     An instance of `exc`.
 */
static inline VALUE
rbimpl_exc_new_cstr(VALUE exc, const char *str)
{
    long len = rbimpl_strlen(str);
    return rb_exc_new(exc, str, len);
}

/**
 * Allocates an instance of ::rb_cString.
 *
 * @param[in]  str             A memory region of `len` bytes length.
 * @param[in]  len             Length  of `ptr`,  in bytes,  not including  the
 *                             terminating NUL character.
 * @exception  rb_eNoMemError  Failed to allocate `len+1` bytes.
 * @exception  rb_eArgError    `len` is negative.
 * @return     An  instance   of  ::rb_cString,  of  `len`   bytes  length,  of
 *             "binary" encoding, whose contents are verbatim copy of `str`.
 * @pre        At  least  `len` bytes  of  continuous  memory region  shall  be
 *             accessible via `str`.
 */
#define rb_str_new(str, len)                    \
    ((RBIMPL_CONSTANT_P(str) &&                 \
      RBIMPL_CONSTANT_P(len) ?                  \
      rb_str_new_static      :                  \
      rb_str_new) ((str), (len)))

/**
 * Identical to #rb_str_new, except it assumes  the passed pointer is a pointer
 * to a C string.
 *
 * @param[in]  str             A C string.
 * @exception  rb_eNoMemError  Failed to allocate memory.
 * @return     An  instance  of  ::rb_cString,   of  "binary"  encoding,  whose
 *             contents are verbatim copy of `str`.
 * @pre        `str` must not be a null pointer.
 */
#define rb_str_new_cstr(str)                    \
    ((RBIMPL_CONSTANT_P(str) ?                  \
      rbimpl_str_new_cstr    :                  \
      rb_str_new_cstr) (str))

/**
 * Identical  to  #rb_str_new, except  it  generates  a  string of  "US  ASCII"
 * encoding.  This  is different from  rb_external_str_new(), not only  for the
 * output encoding, but also it doesn't convert the contents.
 *
 * @param[in]  str             A memory region of `len` bytes length.
 * @param[in]  len             Length  of `str`,  in bytes,  not including  the
 *                             terminating NUL character.
 * @exception  rb_eNoMemError  Failed to allocate `len+1` bytes.
 * @exception  rb_eArgError    `len` is negative.
 * @return     An  instance   of  ::rb_cString,  of  `len`   bytes  length,  of
 *             "US ASCII" encoding, whose contents are verbatim copy of `str`.
 */
#define rb_usascii_str_new(str, len)            \
    ((RBIMPL_CONSTANT_P(str)    &&              \
      RBIMPL_CONSTANT_P(len)    ?               \
      rb_usascii_str_new_static :               \
      rb_usascii_str_new) ((str), (len)))

/**
 * Identical to #rb_str_new, except it generates a string of "UTF-8" encoding.
 *
 * @param[in]  str             A memory region of `len` bytes length.
 * @param[in]  len             Length  of `str`,  in bytes,  not including  the
 *                             terminating NUL character.
 * @exception  rb_eNoMemError  Failed to allocate `len+1` bytes.
 * @exception  rb_eArgError    `len` is negative.
 * @return     An  instance   of  ::rb_cString,  of  `len`   bytes  length,  of
 *             "UTF-8" encoding, whose contents are verbatim copy of `str`.
 */
#define rb_utf8_str_new(str, len)               \
    ((RBIMPL_CONSTANT_P(str) &&                 \
      RBIMPL_CONSTANT_P(len) ?                  \
      rb_utf8_str_new_static :                  \
      rb_utf8_str_new) ((str), (len)))

/**
 * Identical to  #rb_str_new_cstr, except it  generates a string of  "US ASCII"
 * encoding.    It   can   also   be   seen   as   a   routine   Identical   to
 * #rb_usascii_str_new, except it assumes the passed  pointer is a pointer to a
 * C string.
 *
 * @param[in]  str             A C string.
 * @exception  rb_eNoMemError  Failed to allocate memory.
 * @return     An  instance  of ::rb_cString,  of  "US  ASCII" encoding,  whose
 *             contents are verbatim copy of `str`.
 * @pre        `str` must not be a null pointer.
 */
#define rb_usascii_str_new_cstr(str)            \
    ((RBIMPL_CONSTANT_P(str)      ?             \
      rbimpl_usascii_str_new_cstr :             \
      rb_usascii_str_new_cstr) (str))

/**
 * Identical  to #rb_str_new_cstr,  except  it generates  a  string of  "UTF-8"
 * encoding.  It can  also be seen as a routine  Identical to #rb_utf8_str_new,
 * except it assumes the passed pointer is a pointer to a C string.
 *
 * @param[in]  str             A C string.
 * @exception  rb_eNoMemError  Failed to allocate memory.
 * @return     An instance of ::rb_cString, of "UTF-8" encoding, whose contents
 *             are verbatim copy of `str`.
 * @pre        `str` must not be a null pointer.
 */
#define rb_utf8_str_new_cstr(str)               \
    ((RBIMPL_CONSTANT_P(str)   ?                \
      rbimpl_utf8_str_new_cstr :                \
      rb_utf8_str_new_cstr) (str))

/**
 * Identical  to #rb_str_new_cstr,  except it  generates a  string of  "default
 * external" encoding.
 *
 * @param[in]  str             A C string.
 * @exception  rb_eNoMemError  Failed to allocate memory.
 * @return     An instance  of ::rb_cString.  In case  encoding conversion from
 *             "default internal"  to "default external" is  fully defined over
 *             the  given  contents, then  the  return  value  is a  string  of
 *             "default external"  encoding, whose  contents are  the converted
 *             ones.  Otherwise the string is a junk.
 * @warning    It doesn't raise on a conversion failure and silently ends up in
 *             a  corrupted  output.  You  can  know  the failure  by  querying
 *             `valid_encoding?` of the result object.
 * @pre        `str` must not be a null pointer.
 */
#define rb_external_str_new_cstr(str)           \
    ((RBIMPL_CONSTANT_P(str)       ?            \
      rbimpl_external_str_new_cstr :            \
      rb_external_str_new_cstr) (str))

/**
 * Identical  to #rb_external_str_new_cstr,  except  it generates  a string  of
 * "locale" encoding instead of "default external".
 *
 * @param[in]  str             A C string.
 * @exception  rb_eNoMemError  Failed to allocate memory.
 * @return     An instance  of ::rb_cString.  In case  encoding conversion from
 *             "default internal" to  "locale" is fully defined  over the given
 *             contents,  then  the  return  value  is  a  string  of  "locale"
 *             encoding, whose contents are  the converted ones.  Otherwise the
 *             string is a junk.
 * @warning    It doesn't raise on a conversion failure and silently ends up in
 *             a  corrupted  output.  You  can  know  the failure  by  querying
 *             `valid_encoding?` of the result object.
 * @pre        `str` must not be a null pointer.
 */
#define rb_locale_str_new_cstr(str)             \
    ((RBIMPL_CONSTANT_P(str)     ?              \
      rbimpl_locale_str_new_cstr :              \
      rb_locale_str_new_cstr) (str))

/**
 * Identical to #rb_str_new_cstr, except done differently.
 *
 * @param[in]  str             A C string.
 * @exception  rb_eNoMemError  Failed to allocate memory.
 * @return     An  instance  of  ::rb_cString,   of  "binary"  encoding,  whose
 *             contents are verbatim copy of `str`.
 * @pre        `str` must not be a null pointer.
 */
#define rb_str_buf_new_cstr(str)                \
    ((RBIMPL_CONSTANT_P(str)  ?                 \
      rbimpl_str_buf_new_cstr :                 \
      rb_str_buf_new_cstr) (str))

/**
 * Identical to rb_str_cat(), except it assumes the passed pointer is a pointer
 * to a C string.
 *
 * @param[out]  buf                 Destination object.
 * @param[in]   str                 Contents to append.
 * @exception   rb_eArgError        Result string too big.
 * @return      The passed `buf`.
 * @pre         `buf` must not be any arbitrary objects except ::RString.
 * @pre         `str` must not be a null pointer.
 * @post        `buf` has the contents of `str` appended.
 */
#define rb_str_cat_cstr(buf, str)               \
    ((RBIMPL_CONSTANT_P(str) ?                  \
      rbimpl_str_cat_cstr    :                  \
      rb_str_cat_cstr) ((buf), (str)))

/**
 * Identical to rb_exc_new(), except it assumes the passed pointer is a pointer
 * to a C string.
 *
 * @param[out]  exc  A subclass of ::rb_eException.
 * @param[in]   str  Message to raise.
 * @return      An instance of `exc` whose message is `str`.
 * @pre         `str` must not be a null pointer.
 */
#define rb_exc_new_cstr(exc, str)               \
    ((RBIMPL_CONSTANT_P(str) ?                  \
      rbimpl_exc_new_cstr    :                  \
      rb_exc_new_cstr) ((exc), (str)))

#define rb_str_new2 rb_str_new_cstr                  /**< @old{rb_str_new_cstr} */
#define rb_str_new3 rb_str_new_shared                /**< @old{rb_str_new_shared} */
#define rb_str_new4 rb_str_new_frozen                /**< @old{rb_str_new_frozen} */
#define rb_str_new5 rb_str_new_with_class            /**< @old{rb_str_new_with_class} */
#define rb_str_buf_new2 rb_str_buf_new_cstr          /**< @old{rb_str_buf_new_cstr} */
#define rb_usascii_str_new2 rb_usascii_str_new_cstr  /**< @old{rb_usascii_str_new_cstr} */
#define rb_str_buf_cat rb_str_cat                    /**< @alias{rb_str_cat} */
#define rb_str_buf_cat2 rb_str_cat_cstr              /**< @old{rb_usascii_str_new_cstr} */
#define rb_str_cat2 rb_str_cat_cstr                  /**< @old{rb_str_cat_cstr} */

/**
 * Length of a string literal.
 *
 * @param[in]  str  A C String literal.
 * @return     An integer  constant expression that represents  `str`'s length,
 *             in bytes, not including the terminating NUL character.
 */
#define rb_strlen_lit(str) (sizeof(str "") - 1)

/**
 * Identical to rb_str_new_static(), except it cannot take string variables.
 *
 * @param[in]  str  A C string literal.
 * @pre        `str` must not be a variable.
 * @return     An instance of ::rb_cString, of "binary" encoding, whose backend
 *             storage is the passed C string literal.
 * @warning    It is  a very  bad idea to  write to a  C string  literal (often
 *             immediate  SEGV shall  occur).  Consider  return values  of this
 *             function be read-only.
 */
#define rb_str_new_lit(str) rb_str_new_static((str), rb_strlen_lit(str))

/**
 * Identical  to  rb_usascii_str_new_static(),  except it  cannot  take  string
 * variables.
 *
 * @param[in]  str           A C string literal.
 * @pre        `str` must not be a variable.
 * @return     An  instance  of ::rb_cString,  of  "US  ASCII" encoding,  whose
 *             backend storage is the passed C string literal.
 * @warning    It is  a very  bad idea to  write to a  C string  literal (often
 *             immediate  SEGV shall  occur).  Consider  return values  of this
 *             function be read-only.
 */
#define rb_usascii_str_new_lit(str) rb_usascii_str_new_static((str), rb_strlen_lit(str))

/**
 * Identical  to   rb_utf8_str_new_static(),  except  it  cannot   take  string
 * variables.
 *
 * @param[in]  str           A C string literal.
 * @pre        `str` must not be a variable.
 * @return     An instance of ::rb_cString,  of "UTF-8" encoding, whose backend
 *             storage is the passed C string literal.
 * @warning    It is  a very  bad idea to  write to a  C string  literal (often
 *             immediate  SEGV shall  occur).  Consider  return values  of this
 *             function be read-only.
 */
#define rb_utf8_str_new_lit(str) rb_utf8_str_new_static((str), rb_strlen_lit(str))

/**
 * Identical  to   rb_enc_str_new_static(),  except   it  cannot   take  string
 * variables.
 *
 * @param[in]  str           A C string literal.
 * @param[in]  enc           A pointer to an encoding.
 * @pre        `str` must not be a variable.
 * @return     An  instance  of ::rb_cString,  of  the  passed encoding,  whose
 *             backend storage is the passed C string literal.
 * @warning    It is  a very  bad idea to  write to a  C string  literal (often
 *             immediate  SEGV shall  occur).  Consider  return values  of this
 *             function be read-only.
 */
#define rb_enc_str_new_lit(str, enc) rb_enc_str_new_static((str), rb_strlen_lit(str), (enc))

#define rb_str_new_literal(str) rb_str_new_lit(str)                    /**< @alias{rb_str_new_lit} */
#define rb_usascii_str_new_literal(str) rb_usascii_str_new_lit(str)    /**< @alias{rb_usascii_str_new_lit} */
#define rb_utf8_str_new_literal(str) rb_utf8_str_new_lit(str)          /**< @alias{rb_utf8_str_new_lit} */
#define rb_enc_str_new_literal(str, enc) rb_enc_str_new_lit(str, enc)  /**< @alias{rb_enc_str_new_lit} */

RBIMPL_SYMBOL_EXPORT_END()

#endif /* RBIMPL_INTERN_STRING_H */

Youez - 2016 - github.com/yon3zu
LinuXploit