Library globals

Source std . string.nas

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
# ------------------------------------------------------------------------------
# A C++ like string class (http://en.cppreference.com/w/cpp/string/basic_string)
# ------------------------------------------------------------------------------
# SPDX-License-Identifier: GPL-2.0-or-later
#
# NOTE! This copyright does *not* cover user models that use these Nasal
# services by normal function calls - this is merely considered normal use
# of the code, and does *not* fall under the heading of "derived work."
#
# Copyright (C) 2012-2013 by Thomas Geymayer

#load only once (via /Nasal/std.nas) not via C++ module loader
if (ishash(globals["std"]) and ishash(std["String"]))
    return;

var String = {
# public:
  new: func(str)
  {
    return { parents: [String], _str: str };
  },
  # compare(s)
  # compare(pos, n, s)
  #
  # @param s    String to compare to
  # @param pos  Position of first character used to compare
  # @param n    Number of characters to compare
  compare: func
  {
    var s = "";
    var pos = 0;
    var n = -1;

    var num = size(arg);
    if( num == 1 )
      s = arg[0];
    else if( num == 3 )
    {
      pos = arg[0];
      n = arg[1];
      s = arg[2];
    }
    else
      die("std::string::compare: Invalid args");

    if( n < 0 )
      n = me.size();
    else if( n > me.size() )
      return 0;

    if( n != size(s) )
      return 0;

    for(var i = pos; i < n; i += 1)
      if( me._str[i] != s[i] )
        return 0;
    return 1;
  },
  
  # returns index (zero based) of first occurrence of s
  # searching from pos
  find_first_of: func(s, pos = 0)
  {
    return me._find(pos, size(me._str), s, 1);
  },
  find: func(s, pos = 0)
  {
    return me.find_first_of(s, pos);
  },
  find_first_not_of: func(s, pos = 0)
  {
    return me._find(pos, size(me._str), s, 0);
  },
  substr: func(pos, len = nil)
  {
    return substr(me._str, pos, len);
  },
  starts_with: func(s)
  {
    return me.compare(0, size(s), s);
  },
  size: func()
  {
    return size(me._str);
  },
# private:
  _eq: func(pos, s)
  {
    for(var i = 0; i < size(s); i += 1)
      if( me._str[pos] == s[i] )
        return 1;
    return 0;
  },
  _find: func(first, last, s, eq)
  {
    if( first < 0 or last < 0 )
      return -1;

    var sign = first <= last ? 1 : -1;
    for(var i = first; sign * i < last; i += sign)
      if( me._eq(i, s) == eq )
        return i;
    return -1;
  }
};

# for backward compatibility
var string = {parents: [String]};
string.new = func {
    logprint(LOG_ALERT, "Deprecated use of std.string, please use std.String instead.");
    return String.new(arg[0]);
}

# converts a string to an unsigned integer
var stoul = func(str, base = 10)
{
  var val = 0;
  for(var pos = 0; pos < size(str); pos += 1)
  {
    var c = str[pos];

    if( globals.string.isdigit(c) )
      var digval = c - `0`;
    else if( globals.string.isalpha(c) )
      var digval = globals.string.toupper(c) - `A` + 10;
    else
      break;

    if( digval >= base )
      break;

    val = val * base + digval;
  }

  return val;
};