root/NEWT0/trunk/src/newt_core/NewtStr.c

Revision 113, 12.5 kB (checked in by gnue, 17 months ago)

'#pragma mark' is invalidated by '#if 0'

Line 
1/**
2 * @file    NewtStr.c
3 * @brief   文字列処理
4 *
5 * @author  M.Nukui
6 * @date    2004-01-25
7 *
8 * Copyright (C) 2003-2004 M.Nukui All rights reserved.
9 */
10
11
12/* ヘッダファイル */
13#include <string.h>
14
15#include "config.h"
16
17#include "NewtCore.h"
18#include "NewtStr.h"
19
20
21/* 関数プロトタイプ */
22static newtRef  NewtParamStr(char * baseStr, size_t baseStrLen, newtRefArg paramStrArray, bool ifthen);
23static bool     NewtBeginsWith(const char * str, const char * sub);
24static bool     NewtEndsWith(const char * str, const char * sub);
25
26
27#if 0
28#pragma mark -
29#endif
30/*------------------------------------------------------------------------*/
31/** ベース文字列のパラメータを置き換えて新しい文字列を作成する
32 *
33 * @param baseStr       [in] ベース文字列(C文字列)
34 * @param baseStrLen    [in] ベース文字列の長さ
35 * @param paramStrArray [in] パラメータ配列
36 * @param ifthen        [in] 条件処理
37 *
38 * @return 文字列オブジェクト
39 */
40
41newtRef NewtParamStr(char * baseStr, size_t baseStrLen, newtRefArg paramStrArray, bool ifthen)
42{
43    newtRefVar  dstStr;
44    newtRefVar  r;
45    size_t  fpos = 0;
46    size_t  fst = 0;
47    size_t  len;
48    size_t  n;
49    size_t  truePos;
50    size_t  trueLen;
51    size_t  falsePos;
52    size_t  falseLen;
53    char *  found;
54    char    c;
55
56    dstStr = NewtMakeString("", false);
57
58    do
59    {
60        found = memchr(&baseStr[fst], '^', baseStrLen - fst);
61
62        if (found == NULL)
63            break;
64
65        c = found[1];
66
67        len = found - (baseStr + fpos);
68        NewtStrCat2(dstStr, &baseStr[fpos], len);
69        fpos += len;
70        fst = fpos + 1;
71
72        if ('0' <= c && c <= '9')
73        {
74            fpos += 2;
75            fst = fpos;
76
77            r = NewtGetArraySlot(paramStrArray, c - '0');
78
79            if (NewtRefIsNotNIL(r))
80            {
81                NcStrCat(dstStr, r);
82            }
83        }
84        else if (ifthen && c == '?')
85        {
86            c = found[2];
87
88            if ('0' <= c && c <= '9')
89            {
90                n = c - '0';
91
92                truePos = fpos + 3;
93                found = memchr(&baseStr[truePos], '|', baseStrLen - truePos);
94
95                if (found != NULL)
96                {
97                    falsePos = found + 1 - baseStr;
98                    trueLen = falsePos - truePos - 1;
99
100                    found = memchr(&baseStr[falsePos], '|', baseStrLen - falsePos);
101
102                    if (found != NULL)
103                    {
104                        fpos = found + 1 - baseStr;
105                    }
106                    else
107                    {
108                        fpos = baseStrLen;
109                    }
110
111                    falseLen = fpos - falsePos - 1;
112                }
113                else
114                {
115                    trueLen = baseStrLen - truePos;
116
117                    falsePos = baseStrLen;
118                    falseLen = 0;
119
120                    fpos = baseStrLen;
121                }
122
123                fst = fpos;
124
125                r = NewtGetArraySlot(paramStrArray, n);
126
127                if (NewtRefIsNotNIL(r))
128                {
129                    r = NewtParamStr(&baseStr[truePos], trueLen, paramStrArray, false);
130                    NcStrCat(dstStr, r);
131                }
132                else
133                {
134                    if (falsePos == baseStrLen)
135                        break;
136
137                    r = NewtParamStr(&baseStr[falsePos], falseLen, paramStrArray, false);
138                    NcStrCat(dstStr, r);
139                }
140            }
141        }
142    } while(true);
143
144    len = baseStrLen - fpos;
145
146    if (0 < len)
147    {
148        NewtStrCat2(dstStr, &baseStr[fpos], len);
149    }
150
151    return dstStr;
152}
153
154
155/*------------------------------------------------------------------------*/
156/** 文字列の前半部が部分文字列と一致するかチェックする
157 *
158 * @param str       [in] 文字列
159 * @param sub       [in] 部分文字列
160 *
161 * @retval          true    前半部が部分文字列と一致する
162 * @retval          false   前半部が部分文字列と一致しない
163 */
164
165bool NewtBeginsWith(const char * str, const char * sub)
166{
167    int32_t len;
168    int32_t sublen;
169
170    len = strlen(str);
171    sublen = strlen(sub);
172
173    if (len < sublen)
174        return false;
175    else
176        return (strncasecmp(str, sub, sublen) == 0);
177}
178
179
180/*------------------------------------------------------------------------*/
181/** 文字列の最後尾が部分文字列と一致するかチェックする
182 *
183 * @param str       [in] 文字列
184 * @param sub       [in] 部分文字列
185 *
186 * @retval          true    最後尾が部分文字列と一致する
187 * @retval          false   最後尾が部分文字列と一致しない
188 */
189
190bool NewtEndsWith(const char * str, const char * sub)
191{
192    int32_t st;
193
194    st = strlen(str) - strlen(sub);
195
196    if (st < 0)
197        return false;
198    else
199        return (strcasecmp(str + st, sub) == 0);
200}
201
202
203#if 0
204#pragma mark -
205#endif
206/*------------------------------------------------------------------------*/
207/** 整数を文字に変換する
208 *
209 * @param rcvr      [in] レシーバ
210 * @param r         [in] 整数
211 *
212 * @return          文字
213 *
214 * @note            グローバル関数用
215 */
216
217newtRef NsChr(newtRefArg rcvr, newtRefArg r)
218{
219    if (! NewtRefIsInteger(r))
220        return NewtThrow(kNErrNotAnInteger, r);
221
222    return NewtMakeCharacter(NewtRefToInteger(r));
223}
224
225
226/*------------------------------------------------------------------------*/
227/** 文字を整数に変換する
228 *
229 * @param rcvr      [in] レシーバ
230 * @param r         [in] 文字
231 *
232 * @return          整数
233 *
234 * @note            グローバル関数用
235 */
236
237newtRef NsOrd(newtRefArg rcvr, newtRefArg r)
238{
239    if (! NewtRefIsCharacter(r))
240        return NewtThrow(kNErrNotAnInteger, r);
241
242    return NewtMakeInteger(NewtRefToCharacter(r));
243}
244
245
246#if 0
247#pragma mark -
248#endif
249/*------------------------------------------------------------------------*/
250/** 文字列の長さを取得
251 *
252 * @param rcvr      [in] レシーバ
253 * @param r         [in] 文字列オブジェクト
254 *
255 * @return          文字列の長さ
256 *
257 * @note            グローバル関数用
258 */
259
260newtRef NsStrLen(newtRefArg rcvr, newtRefArg r)
261{
262    if (! NewtRefIsString(r))
263        return NewtThrow(kNErrNotAString, r);
264
265    return NewtMakeInteger(NewtStringLength(r));
266}
267
268
269/*------------------------------------------------------------------------*/
270/** オブジェクトを表示可能な文字列に変換する
271 *
272 * @param rcvr      [in] レシーバ
273 * @param r         [in] オブジェクト
274 *
275 * @return          文字列オブジェクト
276 *
277 * @note            グローバル関数用
278 */
279
280newtRef NsSPrintObject(newtRefArg rcvr, newtRefArg r)
281{
282    newtRefVar  str;
283
284    str = NSSTR("");
285
286    NcStrCat(str, r);
287
288    return str;
289}
290
291
292/*------------------------------------------------------------------------*/
293/** 文字列を指定の区切り文字で分解する
294 *
295 * @param rcvr      [in] レシーバ
296 * @param r         [in] 文字列オブジェクト
297 * @param sep       [in] 区切り文字
298 *
299 * @return          配列オブジェクト
300 *
301 * @note            グローバル関数用
302 */
303
304newtRef NsSplit(newtRefArg rcvr, newtRefArg r, newtRefArg sep)
305{
306    newtRefVar  result;
307
308    if (! NewtRefIsString(r))
309        return NewtThrow(kNErrNotAString, r);
310
311    switch (NewtGetRefType(sep, true))
312    {
313        case kNewtCharacter:
314            {
315                newtRefVar  v;
316                char *      next;
317                char *      s;
318                int         c;
319
320                s = NewtRefToString(r);
321                c = NewtRefToCharacter(sep);
322
323                result = NewtMakeArray(kNewtRefUnbind, 0);
324
325                while (*s)
326                {
327                    next = strchr(s, c);
328                    if (next == NULL) break;
329
330                    v = NewtMakeString2(s, next - s, false);
331                    NcAddArraySlot(result, v);
332                    s = next + 1;
333                }
334
335                if (s == NewtRefToString(r))
336                    v = r;
337                else
338                    v = NSSTR(s);
339
340                NcAddArraySlot(result, v);
341            }
342            break;
343
344        default:
345            {
346                newtRefVar  initObj[] = {r};
347
348                result = NewtMakeArray2(kNewtRefNIL, sizeof(initObj) / sizeof(newtRefVar), initObj);
349            }
350            break;
351    }
352
353    return result;
354}
355
356
357/*------------------------------------------------------------------------*/
358/** ベース文字列のパラメータを置き換えて新しい文字列を作成する
359 *
360 * @param rcvr          [in] レシーバ
361 * @param baseString    [in] ベース文字列
362 * @param paramStrArray [in] パラメータ配列
363 *
364 * @return          文字列オブジェクト
365 *
366 * @note            グローバル関数用
367 */
368
369newtRef NsParamStr(newtRefArg rcvr, newtRefArg baseString, newtRefArg paramStrArray)
370{
371    if (! NewtRefIsString(baseString))
372        return NewtThrow(kNErrNotAString, baseString);
373
374    if (! NewtRefIsArray(paramStrArray))
375        return NewtThrow(kNErrNotAnArray, paramStrArray);
376
377    return NewtParamStr(NewtRefToString(baseString), NewtStringLength(baseString), paramStrArray, true);
378}
379
380/*------------------------------------------------------------------------*/
381/**
382 * Extract the substring of a string.
383 *
384 * @param rcvr  self (ignored).
385 * @param r     the string to create a substring of.
386 * @param start the offset of the first character of the substring.
387 * @param count the number of characters to extract or NIL to go til the end.
388 * @return a new string
389 *
390 * @note highly unefficient.
391 */
392
393newtRef NsSubStr(newtRefArg rcvr, newtRefArg r, newtRefArg start, newtRefArg count)
394{
395    char* theString;
396    char* theBuffer;
397    int theStart, theEnd;
398    size_t theLen;
399    newtRefVar theResult;
400   
401    (void) rcvr;
402   
403    /* check parameters */
404    if (! NewtRefIsString(r))
405        return NewtThrow(kNErrNotAString, r);
406    if (! NewtRefIsInteger(start))
407        return NewtThrow(kNErrNotAnInteger, start);
408   
409    theString = NewtRefToString(r);
410    theLen = strlen(theString);
411   
412    theStart = NewtRefToInteger(start);
413
414    if (!NewtRefIsNIL(count))
415    {
416        if (!NewtRefIsInteger(count))
417        {
418            return NewtThrow(kNErrNotAnInteger, count);
419        }
420        theEnd = theStart + NewtRefToInteger(count);
421        if (theEnd > theLen)
422        {
423            return NewtThrow(kNErrOutOfRange, count);
424        }
425    } else {
426        theEnd = theLen;
427    }
428
429    /* new length */
430    theLen = theEnd - theStart;
431   
432    /* create a buffer to copy the characters to */
433    theBuffer = (char*) malloc(theLen + 1);
434    (void) memcpy(theBuffer, (const char*) &theString[theStart], theLen);
435    theBuffer[theLen] = 0;
436    theResult = NewtMakeString(theBuffer, false);
437    free(theBuffer);
438   
439    return theResult;
440}
441
442/*------------------------------------------------------------------------*/
443/**
444 * Determine if two strings are equal, ignoring case.
445 *
446 * @param rcvr  self (ignored).
447 * @param a     the first string to consider.
448 * @param b     the second string to consider.
449 * @return true if the two strings are equal, nil otherwise.
450 */
451
452newtRef NsStrEqual(newtRefArg rcvr, newtRefArg a, newtRefArg b)
453{
454    char* aString;
455    char* bString;
456    newtRefVar theResult = kNewtRefNIL;
457   
458    (void) rcvr;
459
460    /* check parameters */
461    if (! NewtRefIsString(a))
462    {
463        theResult = NewtThrow(kNErrNotAString, a);
464    } else if (! NewtRefIsString(b)) {
465        theResult = NewtThrow(kNErrNotAString, b);
466    } else if (a == b) {
467        theResult = kNewtRefTRUE;
468    } else {   
469        aString = NewtRefToString(a);
470        bString = NewtRefToString(b);
471   
472        if (strcasecmp(aString, bString) == 0)
473        {
474            theResult = kNewtRefTRUE;
475        }
476    }
477   
478    return theResult;
479}
480
481/*------------------------------------------------------------------------*/
482/**
483 * Compare two strings, returning an integer representing the result of the
484 * comparison. The comparison is case sensitive.
485 *
486 * @param rcvr  self (ignored).
487 * @param a     the first string to consider.
488 * @param b     the second string to consider.
489 * @return an integer representing the result of the comparison (a < b -> < 0,
490 *         a = b -> 0, a > b -> > 0)
491 */
492
493newtRef NsStrExactCompare(newtRefArg rcvr, newtRefArg a, newtRefArg b)
494{
495    char* aString;
496    char* bString;
497    newtRefVar theResult;
498   
499    (void) rcvr;
500
501    /* check parameters */
502    if (! NewtRefIsString(a))
503    {
504        theResult = NewtThrow(kNErrNotAString, a);
505    } else if (! NewtRefIsString(b)) {
506        theResult = NewtThrow(kNErrNotAString, b);
507    } else if (a == b) {
508        theResult = NewtMakeInteger(0);
509    } else {   
510        aString = NewtRefToString(a);
511        bString = NewtRefToString(b);
512   
513        theResult = NewtMakeInteger(strcmp(aString, bString));
514    }
515   
516    return theResult;
517}
518
519
520/*------------------------------------------------------------------------*/
521/** 文字列の前半部が部分文字列と一致するかチェックする
522 *
523 * @param rcvr      [in] レシーバ
524 * @param str       [in] 文字列
525 * @param sub       [in] 部分文字列
526 *
527 * @retval          TRUE    前半部が部分文字列と一致する
528 * @retval          NIL     前半部が部分文字列と一致しない
529 */
530
531newtRef NsBeginsWith(newtRefArg rcvr, newtRefArg str, newtRefArg sub)
532{
533    bool    result;
534
535    if (! NewtRefIsString(str))
536        return NewtThrow(kNErrNotAString, str);
537
538    if (! NewtRefIsString(sub))
539        return NewtThrow(kNErrNotAString, sub);
540
541    result = NewtBeginsWith(NewtRefToString(str), NewtRefToString(sub));
542
543    return NewtMakeBoolean(result);
544}
545
546
547/*------------------------------------------------------------------------*/
548/** 文字列の最後尾が部分文字列と一致するかチェックする
549 *
550 * @param rcvr      [in] レシーバ
551 * @param str       [in] 文字列
552 * @param sub       [in] 部分文字列
553 *
554 * @retval          TRUE    最後尾が部分文字列と一致する
555 * @retval          NIL     最後尾が部分文字列と一致しない
556 */
557
558newtRef NsEndsWith(newtRefArg rcvr, newtRefArg str, newtRefArg sub)
559{
560    bool    result;
561
562    if (! NewtRefIsString(str))
563        return NewtThrow(kNErrNotAString, str);
564
565    if (! NewtRefIsString(sub))
566        return NewtThrow(kNErrNotAString, sub);
567
568    result = NewtEndsWith(NewtRefToString(str), NewtRefToString(sub));
569
570    return NewtMakeBoolean(result);
571}
Note: See TracBrowser for help on using the browser.