StringClassWord.cpp
Go to the documentation of this file.
1 /*----------------------------------------------------------------------------*/
2 /* */
3 /* Copyright (c) 1995, 2004 IBM Corporation. All rights reserved. */
4 /* Copyright (c) 2005-2009 Rexx Language Association. All rights reserved. */
5 /* */
6 /* This program and the accompanying materials are made available under */
7 /* the terms of the Common Public License v1.0 which accompanies this */
8 /* distribution. A copy is also available at the following address: */
9 /* http://www.oorexx.org/license.html */
10 /* */
11 /* Redistribution and use in source and binary forms, with or */
12 /* without modification, are permitted provided that the following */
13 /* conditions are met: */
14 /* */
15 /* Redistributions of source code must retain the above copyright */
16 /* notice, this list of conditions and the following disclaimer. */
17 /* Redistributions in binary form must reproduce the above copyright */
18 /* notice, this list of conditions and the following disclaimer in */
19 /* the documentation and/or other materials provided with the distribution. */
20 /* */
21 /* Neither the name of Rexx Language Association nor the names */
22 /* of its contributors may be used to endorse or promote products */
23 /* derived from this software without specific prior written permission. */
24 /* */
25 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
26 /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
27 /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */
28 /* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
29 /* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
30 /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */
31 /* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */
32 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY */
33 /* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */
34 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
35 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
36 /* */
37 /*----------------------------------------------------------------------------*/
38 /******************************************************************************/
39 /* REXX Kernel */
40 /* */
41 /* Word-related REXX string methods */
42 /* */
43 /******************************************************************************/
44 
45 #include <ctype.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <math.h>
49 #include "RexxCore.h"
50 #include "StringClass.hpp"
51 #include "StringUtil.hpp"
52 
53 
54 /* the DELWORD function */
55 /******************************************************************************/
56 /* Arguments: nth word to start deleting */
57 /* number of words to delete */
58 /* */
59 /* Returned: string, with length words deleted */
60 /******************************************************************************/
61 // in behaviour
63  RexxInteger *plength)
64 {
65  char *Current; /* current pointer position */
66  const char *Word; /* current word pointer */
67  const char *NextSite; /* next word */
68  sizeB_t WordPos; /* needed word position */
69  size_t Count; /* count of words */
70  sizeB_t Length; /* remaining length */
71  sizeB_t WordLength; /* word size */
72  sizeB_t FrontLength; /* front substring */
73  RexxString *Retval; /* return value */
74 
75  /* convert position to binary */
76  WordPos = positionArgument(position, ARG_ONE);
77  /* get num of words to delete, the */
78  /* default is "a very large number" */
80 
81  Length = this->getBLength(); /* get string length */
82  if (Length == 0) /* null string? */
83  {
84  Retval = OREF_NULLSTRING; /* result is null also */
85  }
86  else if (Count == 0) /* deleting zero words? */
87  {
88  Retval = this; /* just use this string */
89  }
90  else
91  {
92  Word = this->getStringData(); /* point to the string */
93  /* get the first word */
94  WordLength = StringUtil::nextWord(&Word, &Length, &NextSite);
95  while (--WordPos != 0 && WordLength != 0)
96  { /* loop until we reach tArget */
97  Word = NextSite; /* copy the start pointer */
98  /* get the next word */
99  WordLength = StringUtil::nextWord(&Word, &Length, &NextSite);
100  }
101  if (WordPos != 0) /* run out of words first */
102  {
103  Retval = this; /* return entire string */
104  }
105  else
106  { /* count off number of words */
107  /* calculate front length */
108  FrontLength = (size_t)(Word - this->getStringData());
109  while (--Count != 0 && WordLength != 0)
110  { /* loop until we reach tArget */
111  Word = NextSite; /* copy the start pointer */
112  /* get the next word */
113  WordLength = StringUtil::nextWord(&Word, &Length, &NextSite);
114  }
115  if (Length != 0) /* didn't use up the string */
116  {
117  StringUtil::skipBlanks(&NextSite, &Length);/* skip over trailing blanks */
118  }
119  /* allocate return string */
120  Retval = raw_string(FrontLength + Length);
121  /* point to data portion */
122  Current = Retval->getWritableData();
123  if (FrontLength != 0)
124  { /* have a leading portion? */
125  /* copy into the result */
126  memcpy(Current, this->getStringData(), FrontLength);
127  Current += FrontLength; /* step output position */
128  }
129  if (Length != 0) /* any string left? */
130  {
131  /* copy what's left */
132  memcpy(Current, NextSite, Length);
133  }
134  }
135  }
136  return Retval; /* return deleted string */
137 }
138 
139 /* the SPACE function */
140 /******************************************************************************/
141 /* Arguments: number of pad characters between each word */
142 /* pad character */
143 /* */
144 /* Returned: string */
145 /******************************************************************************/
146 // in behaviour
148  RexxString *pad)
149 {
150  sizeC_t Spaces; /* requested spacing */
151  codepoint_t PadChar; /* pad character */
152  char *Current; /* current pointer position */
153  const char *Word; /* current word pointer */
154  const char *NextSite; /* next word */
155  sizeB_t Count; /* count of words */
156  sizeB_t WordSize; /* size of words */
157  sizeB_t Length; /* remaining length */
158  sizeB_t WordLength; /* word size */
159  RexxString *Retval; /* return value */
160 
161  /* get the spacing count */
162  Spaces = optionalLengthArgument(space_count, 1, ARG_ONE);
163 
164  /* get the pad character */
165  PadChar = optionalPadArgument(pad, ' ', ARG_TWO);
166 
167  Length = this->getBLength(); /* get the string length */
168  Count = 0; /* no words yet */
169  WordSize = 0; /* no characters either */
170  Word = this->getStringData(); /* point to the string */
171  /* get the first word */
172  WordLength = StringUtil::nextWord(&Word, &Length, &NextSite);
173 
174  while (WordLength != 0)
175  { /* loop until we reach tArget */
176  Count++; /* count the word */
177  WordSize += WordLength; /* add in the word length */
178  Word = NextSite; /* copy the start pointer */
179  /* get the next word */
180  WordLength = StringUtil::nextWord(&Word, &Length, &NextSite);
181  }
182  if (Count == 0) /* no words? */
183  {
184  Retval = OREF_NULLSTRING; /* this is a null string */
185  }
186  else
187  { /* real words */
188  Count--; /* step back one */
189  /* get space for output */
190  Retval = raw_string(WordSize + Count * size_v(Spaces)); // todo m17n : Spaces is a char count
191  /* point to output area */
192  Current = Retval->getWritableData();
193 
194  Length = this->getBLength(); /* recover the length */
195  Word = this->getStringData(); /* point to the string */
196  /* get the first word */
197  WordLength = StringUtil::nextWord(&Word, &Length, &NextSite);
198 
199  while (Count-- != 0)
200  { /* loop for each word */
201  /* copy the word over */
202  memcpy(Current, Word, WordLength);
203  Current += WordLength; /* step over the word */
204  if (Spaces != 0)
205  { /* if have gaps... */
206  /* fill in the pad chars */
207  memset(Current, PadChar, size_v(Spaces)); // todo m17n
208  Current += size_v(Spaces); /* step over the pad chars */ // todo m17n
209  }
210  Word = NextSite; /* copy the start pointer */
211  /* get the next word */
212  WordLength = StringUtil::nextWord(&Word, &Length, &NextSite);
213  }
214  /* copy the word over */
215  memcpy(Current, Word, WordLength);
216  }
217  return Retval; /* return spaced string */
218 }
219 
220 
221 /* the SUBWORD function */
222 /******************************************************************************/
223 /* Arguments: Starting word postion */
224 /* number of words */
225 /* */
226 /* Returned: string, contains the requested number of words from source */
227 /******************************************************************************/
228 // in behaviour
230 {
231  return StringUtil::subWord(getStringData(), getBLength(), position, plength);
232 }
233 
234 
235 /**
236  * Returns an array of all words contained in the given range
237  * of the string, using the same extraction rules used
238  * for subWord() and word().
239  *
240  * @param position The optional starting position. If not provided, extraction
241  * starts with the first word.
242  * @param plength The number of words to extract. If omitted, will extract
243  * from the starting postion to the end of the string.
244  *
245  * @return An array containing the extracted words. If no words are
246  * available within the given range, this returns an empty
247  * array.
248  */
250 {
251  return StringUtil::subWords(getStringData(), getBLength(), position, plength);
252 }
253 
254 
255 /* the WORD function */
256 /******************************************************************************/
257 /* Arguments: which word we want. */
258 /* */
259 /* Returned: string, containing nth word. */
260 /******************************************************************************/
261 // in behaviour
263 {
264  return StringUtil::word(getStringData(), getBLength(), position);
265 }
266 
267 /* the WORDINDEX function */
268 /******************************************************************************/
269 /* Arguments: word we want position of. */
270 /* */
271 /* Returned: integer, actual char position of nth word */
272 /******************************************************************************/
273 // in behaviour
275 {
276  return StringUtil::wordIndex(getStringData(), getBLength(), position);
277 }
278 
279 /* the WORDLENGTH function */
280 /******************************************************************************/
281 /* Arguments: nth word we want length of */
282 /* */
283 /* Returned: integer, length of nth word */
284 /******************************************************************************/
285 // in behaviour
287 {
288  return StringUtil::wordLength(getStringData(), getBLength(), position);
289 }
290 
291 
292 /**
293  * Perform a wordpos search on a string object.
294  *
295  * @param phrase The search phrase
296  * @param pstart The starting search position.
297  *
298  * @return The index of the match location.
299  */
300 // in behaviour
302 {
303  return StringUtil::wordPos(getStringData(), getBLength(), phrase, pstart);
304 }
305 
306 
307 /**
308  * Perform a caseless wordpos search on a string object.
309  *
310  * @param phrase The search phrase
311  * @param pstart The starting search position.
312  *
313  * @return The index of the match location.
314  */
315 // in behaviour
317 {
318  return StringUtil::caselessWordPos(getStringData(), getBLength(), phrase, pstart);
319 }
320 
321 /* the WORDS function */
322 /******************************************************************************/
323 /* Arguments: none */
324 /* */
325 /* Returned: integer, number os words in source */
326 /******************************************************************************/
327 // in behaviour
329 {
330  size_t tempCount = StringUtil::wordCount(this->getStringData(), this->getBLength());
331  return new_integer(tempCount);
332 }
333 
334 
RexxInteger * new_integer(wholenumber_t v)
codepoint_t optionalPadArgument(RexxObject *o, codepoint_t d, size_t p)
Definition: RexxCore.h:382
const int ARG_TWO
Definition: RexxCore.h:81
size_t optionalLengthArgument(RexxObject *o, size_t d, size_t p)
Definition: RexxCore.h:343
const int ARG_ONE
Definition: RexxCore.h:80
RexxString * raw_string(stringsizeB_t bl, stringsizeC_t cl=-1)
stringsize_t positionArgument(RexxObject *argument, size_t position)
static const wholenumber_t MAX_WHOLENUMBER
Definition: Numerics.hpp:62
RexxArray * subWords(RexxInteger *, RexxInteger *)
RexxInteger * wordIndex(RexxInteger *)
RexxString * subWord(RexxInteger *, RexxInteger *)
const char * getStringData()
RexxString * space(RexxInteger *, RexxString *)
char * getWritableData()
RexxString * word(RexxInteger *)
RexxInteger * words()
RexxInteger * caselessWordPos(RexxString *, RexxInteger *)
RexxInteger * wordLength(RexxInteger *)
RexxInteger * wordPos(RexxString *, RexxInteger *)
RexxString * delWord(RexxInteger *, RexxInteger *)
sizeB_t getBLength()
static RexxInteger * wordIndex(const char *data, sizeB_t length, RexxInteger *position)
static RexxString * word(const char *data, sizeB_t length, RexxInteger *position)
static void skipBlanks(const char **String, sizeB_t *StringLength)
static RexxInteger * wordPos(const char *data, sizeB_t length, RexxString *phrase, RexxInteger *pstart)
static RexxInteger * wordLength(const char *data, sizeB_t length, RexxInteger *position)
static RexxInteger * caselessWordPos(const char *data, sizeB_t length, RexxString *phrase, RexxInteger *pstart)
static RexxArray * subWords(const char *data, sizeB_t length, RexxInteger *position, RexxInteger *plength)
static RexxString * subWord(const char *data, sizeB_t length, RexxInteger *position, RexxInteger *plength)
static size_t wordCount(const char *String, sizeB_t StringLength)
static sizeB_t nextWord(const char **String, sizeB_t *StringLength, const char **NextString)
stringsizeC_t sizeC_t
Definition: rexx.h:242
ssize_t codepoint_t
Definition: rexx.h:232
#define size_v(X)
Definition: rexx.h:237
stringsizeB_t sizeB_t
Definition: rexx.h:248