jswrap_string.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /*
  2. * This file is part of Espruino, a JavaScript interpreter for Microcontrollers
  3. *
  4. * Copyright (C) 2013 Gordon Williams <gw@pur3.co.uk>
  5. *
  6. * This Source Code Form is subject to the terms of the Mozilla Public
  7. * License, v. 2.0. If a copy of the MPL was not distributed with this
  8. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  9. *
  10. * ----------------------------------------------------------------------------
  11. * This file is designed to be parsed during the build process
  12. *
  13. * JavaScript String Functions
  14. * ----------------------------------------------------------------------------
  15. */
  16. #include "jswrap_string.h"
  17. /*JSON{ "type":"class",
  18. "class" : "String",
  19. "check" : "jsvIsString(var)",
  20. "description" : ["This is the built-in class for Text Strings.",
  21. "Text Strings in Espruino are not zero-terminated, so you can store zeros in them." ]
  22. }*/
  23. /*JSON{ "type":"constructor", "class": "String", "name": "String",
  24. "description" : "Create a new String",
  25. "generate" : "jswrap_string_constructor",
  26. "params" : [ [ "str", "JsVar", "A value to turn into a string. If undefined or not supplied, an empty String is created." ] ],
  27. "return" : [ "JsVar", "A String" ]
  28. }*/
  29. JsVar *jswrap_string_constructor(JsVar *a) {
  30. if (!a) return jsvNewFromEmptyString(); // no argument - return an empty string
  31. return jsvAsString(a, false);
  32. }
  33. /*JSON{ "type":"staticmethod", "class": "String", "name" : "fromCharCode",
  34. "description" : "Return the character represented by the given character code.",
  35. "generate" : "jswrap_string_fromCharCode",
  36. "params" : [ [ "code", "int", "The character code to create a character from (range 0-255)"] ],
  37. "return" : ["JsVar", "The character"]
  38. }*/
  39. JsVar *jswrap_string_fromCharCode(JsVarInt code) {
  40. // We do this so we can handle '/0' in a string
  41. JsVar *r = jsvNewFromEmptyString();
  42. if (r) { // out of mem?
  43. char ch = (char)code;
  44. jsvAppendStringBuf(r, &ch, 1);
  45. }
  46. return r;
  47. }
  48. /*JSON{ "type":"method", "class": "String", "name" : "charAt",
  49. "description" : "Return a single character at the given position in the String.",
  50. "generate" : "jswrap_string_charAt",
  51. "params" : [ [ "pos", "int", "The character number in the string. Negative values return characters from end of string (-1 = last char)"] ],
  52. "return" : ["JsVar", "The character in the string"]
  53. }*/
  54. JsVar *jswrap_string_charAt(JsVar *parent, JsVarInt idx) {
  55. // We do this so we can handle '/0' in a string
  56. JsVar *r = jsvNewFromEmptyString();
  57. if (r) { // out of mem?
  58. char ch = jsvGetCharInString(parent, (int)idx);
  59. jsvAppendStringBuf(r, &ch, 1);
  60. }
  61. return r;
  62. }
  63. /*JSON{ "type":"method", "class": "String", "name" : "charCodeAt",
  64. "description" : ["Return the integer value of a single character at the given position in the String.",
  65. "Note that this returns 0 not 'NaN' for out of bounds characters"],
  66. "generate" : "jswrap_string_charCodeAt",
  67. "params" : [ [ "pos", "int", "The character number in the string. Negative values return characters from end of string (-1 = last char)"] ],
  68. "return" : ["int", "The integer value of a character in the string"]
  69. }*/
  70. JsVarInt jswrap_string_charCodeAt(JsVar *parent, JsVarInt idx) {
  71. return jsvGetCharInString(parent, (int)idx);
  72. }
  73. /*JSON{ "type":"method", "class": "String", "name" : "indexOf",
  74. "description" : "Return the index of substring in this string, or -1 if not found",
  75. "generate" : "jswrap_string_indexOf",
  76. "params" : [ [ "substring", "JsVar", "The string to search for"] ],
  77. "return" : ["int", "The index of the string, or -1 if not found"]
  78. }*/
  79. JsVarInt jswrap_string_indexOf(JsVar *parent, JsVar *v) {
  80. // slow, but simple!
  81. v = jsvAsString(v, false);
  82. if (!v) return 0; // out of memory
  83. int idx = -1;
  84. int l = (int)jsvGetStringLength(parent) - (int)jsvGetStringLength(v);
  85. for (idx=0;idx<=l;idx++) {
  86. if (jsvCompareString(parent, v, idx, 0, true)==0) {
  87. jsvUnLock(v);
  88. return idx;
  89. }
  90. }
  91. jsvUnLock(v);
  92. return -1;
  93. }
  94. /*JSON{ "type":"method", "class": "String", "name" : "substring",
  95. "generate" : "jswrap_string_substring",
  96. "params" : [ [ "start", "int", "The start character index"],
  97. [ "end", "JsVar", "The end character index"] ],
  98. "return" : ["JsVar", "The part of this string between start and end"]
  99. }*/
  100. JsVar *jswrap_string_substring(JsVar *parent, JsVarInt pStart, JsVar *vEnd) {
  101. JsVar *res;
  102. JsVarInt pEnd = jsvIsUndefined(vEnd) ? JSVAPPENDSTRINGVAR_MAXLENGTH : (int)jsvGetInteger(vEnd);
  103. if (pStart<0) pStart=0;
  104. if (pEnd<0) pEnd=0;
  105. if (pEnd<pStart) {
  106. JsVarInt l = pStart;
  107. pStart = pEnd;
  108. pEnd = l;
  109. }
  110. res = jsvNewWithFlags(JSV_STRING);
  111. if (!res) return 0; // out of memory
  112. jsvAppendStringVar(res, parent, (int)pStart, (int)(pEnd-pStart));
  113. return res;
  114. }
  115. /*JSON{ "type":"method", "class": "String", "name" : "substr",
  116. "generate" : "jswrap_string_substr",
  117. "params" : [ [ "start", "int", "The start character index"],
  118. [ "len", "JsVar", "The number of characters"] ],
  119. "return" : ["JsVar", "Part of this string from start for len characters"]
  120. }*/
  121. JsVar *jswrap_string_substr(JsVar *parent, JsVarInt pStart, JsVar *vLen) {
  122. JsVar *res;
  123. JsVarInt pLen = jsvIsUndefined(vLen) ? JSVAPPENDSTRINGVAR_MAXLENGTH : (int)jsvGetInteger(vLen);
  124. if (pLen<0) pLen=0;
  125. res = jsvNewWithFlags(JSV_STRING);
  126. if (!res) return 0; // out of memory
  127. jsvAppendStringVar(res, parent, (int)pStart, (int)pLen);
  128. return res;
  129. }
  130. /*JSON{ "type":"method", "class": "String", "name" : "split",
  131. "description" : "Return an array made by splitting this string up by the separator. eg. ```'1,2,3'.split(',')==[1,2,3]```",
  132. "generate" : "jswrap_string_split",
  133. "params" : [ [ "separator", "JsVar", "The start character index"] ],
  134. "return" : ["JsVar", "Part of this string from start for len characters"]
  135. }*/
  136. JsVar *jswrap_string_split(JsVar *parent, JsVar *split) {
  137. JsVar *array;
  138. int last, idx, arraylen=0;
  139. int splitlen = (int)jsvGetStringLength(split);
  140. int l = (int)jsvGetStringLength(parent) - splitlen;
  141. last = 0;
  142. array = jsvNewWithFlags(JSV_ARRAY);
  143. if (!array) return 0; // out of memory
  144. for (idx=0;idx<=l;idx++) {
  145. if (idx==l || jsvCompareString(parent, split, idx, 0, true)==0) {
  146. JsVar *part = jsvNewFromEmptyString();
  147. if (!part) break; // out of memory
  148. JsVar *idxvar = jsvMakeIntoVariableName(jsvNewFromInteger(arraylen++), part);
  149. if (idxvar) { // could be out of memory
  150. if (idx==l) idx=l+splitlen; // if the last element, do to the end of the string
  151. jsvAppendStringVar(part, parent, last, idx-last);
  152. jsvAddName(array, idxvar);
  153. last = idx+splitlen;
  154. jsvUnLock(idxvar);
  155. }
  156. jsvUnLock(part);
  157. }
  158. }
  159. return array;
  160. }