home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1995 August / NEBULA.mdf / SourceCode / Classes / RCString / RCStringInsert.m < prev    next >
Encoding:
Text File  |  1993-01-19  |  4.6 KB  |  191 lines

  1. #import <RCString.h>
  2. /*
  3.     Copyright (C) 1992. Bruce Ediger.
  4.  
  5.       This program is free software; you can redistribute it and/or modify
  6.     it under the terms of the GNU Library General Public License.
  7. */
  8.  
  9. //
  10. // implementation of "insertion" methods
  11. //
  12.  
  13. @implementation RCString (Insertion)
  14.  
  15. // all of the other Insertion category methods are
  16. // wrappers around this one.  No doubt it would be
  17. // very wise if this method did not modify anAsciiString.
  18. - insertString:  (char *)anAsciiString at:(int)index
  19. {
  20.     int iLength, iSumTotal;
  21.     char *bpTmp;
  22.  
  23.     // Simple checks before expending further effort.
  24.     if (anAsciiString == p->s)
  25.         return self;  // try to avoid some weird recursion
  26.     else if (anAsciiString == NULL)
  27.         return self;
  28.     else if ((iLength = strlen(anAsciiString)) <= 0)
  29.         return self;
  30.     else if (index < 0)
  31.         return self;
  32.  
  33.     if (index > p->l - 1)
  34.         index = p->l - 1;  // silently trim insertion point to fit
  35.  
  36.     // Something's going to happen for sure.  Copy the reference.
  37.     if (p->n > 1)
  38.         [self copyReference];
  39.  
  40.     iSumTotal = p->l + iLength;  // p->l includes 1 for trailing null
  41.     bpTmp = malloc(iSumTotal);
  42.     if (bpTmp) {
  43.         if (index == 0) {
  44.             // insert at beginning of internal string
  45.             bcopy(anAsciiString, bpTmp, iLength);
  46.             if (p->s && p->l > 1)
  47.                 bcopy(p->s, &bpTmp[iLength], p->l);
  48.         } else if (index == p->l - 1) {
  49.             // insert at end of internal string
  50.             if (p->s && p->l > 1)
  51.                 bcopy(p->s, bpTmp, p->l - 1);
  52.             bcopy(anAsciiString, &bpTmp[p->l - 1], iLength);
  53.         } else {
  54.             // insert at arbitrary location
  55.             if (p->s && p->l > 1) {
  56.                 bcopy(p->s, bpTmp, index);
  57.                 bcopy(&p->s[index], &bpTmp[index + iLength], p->l - index);
  58.             }
  59.             bcopy(anAsciiString, &bpTmp[index], iLength);
  60.         }
  61.         bpTmp[iSumTotal - 1] = '\0';
  62.         if (p->s)
  63.             free(p->s);
  64.         p->s = bpTmp;
  65.         p->l = iSumTotal;
  66.     }
  67.  
  68.     return self;
  69. }
  70.  
  71. // -appendString: and -prependString: can be special
  72. // cases of -insertString:at:.  But they don't have to
  73. // be.  They may be faster as special case implementations.
  74.  
  75. - appendString:(char *)anAsciiString
  76. {
  77.     return [self insertString:anAsciiString at:p->l - 1];
  78. }
  79.  
  80. - prependString:(char *)anAsciiString
  81. {
  82.     return [self insertString:anAsciiString at:0];
  83. }
  84.  
  85. // *Object methods are just wrappers around the insertString:at:
  86. // method.  There may be a better way.
  87.  
  88. - appendObject:  (RCString *)anotherObject
  89. {
  90.     if (anotherObject) {
  91.         return [self insertString:[anotherObject data] at:0];
  92.     }
  93.     return self;
  94. }
  95.  
  96. - prependObject: (RCString *)anotherObject
  97. {
  98.     if (anotherObject) {
  99.         return [self insertString:[anotherObject data] at:p->l - 1];
  100.     }
  101.     return self;
  102. }
  103.  
  104. - insertObject:  (RCString *)anotherObject at:(int)index
  105. {
  106.     if (anotherObject && index >= 0) {
  107.         return [self insertString:[anotherObject data] at:index];
  108.     }
  109.     return self;
  110. }
  111.  
  112. // These final two are not wrappers around -insertString:at:
  113. // I just can't think of a better category to put it in.
  114.  
  115. // There's some internal dependencies: this method is used by the
  116. // regular expression stuff in another category.
  117. - replaceStringAt:(int)index extent:(int)length with:(char *)aString
  118. {
  119.     int iLength;
  120.  
  121.     if (length >= 0 && aString != NULL && (iLength = strlen(aString)) > 0
  122.         && index >=0 && index <= p->l)
  123.     {
  124.         char *bpTmp;
  125.  
  126.         if((bpTmp = malloc(p->l + iLength)) != NULL)
  127.         {
  128.             bcopy(p->s, bpTmp, index);
  129.             bcopy(aString, &(bpTmp[index]), iLength);
  130.             bcopy(&(p->s[index + length]), &(bpTmp[index + iLength]),
  131.                 p->l - index - length);
  132.  
  133.             if (p->n == 1)
  134.             {
  135.                 if (p->s) free(p->s); // this is the only reference
  136.                 p->s = bpTmp;
  137.                 p->l = p->l + iLength;
  138.             } else {
  139.                 struct srep *spOld = p;
  140.  
  141.                 // Decrement ref count on old internal rep, 
  142.                 // conjure up new internal ref.
  143.                 --p->n;
  144.                 p = (struct srep *)malloc(sizeof(struct srep));
  145.                 p->s = bpTmp;
  146.                 p->l = spOld->l + iLength;
  147.                 p->n = 1;
  148.             }
  149.         }
  150.     }
  151.     return self;
  152. }
  153.  
  154. - replaceStringAt:(int)index extent:(int)replength with:(char *)aString extent:(int)strlength
  155. {
  156.     if (replength >= 0 && aString != NULL && strlength > 0
  157.         && index >=0 && index <= p->l)
  158.     {
  159.         char *bpTmp;
  160.  
  161.         // allocate memory for a new asciiz string
  162.         if((bpTmp = malloc(p->l + strlength)) != NULL)
  163.         {
  164.             bcopy(p->s, bpTmp, index);
  165.             bcopy(aString, &(bpTmp[index]), strlength);
  166.             bcopy(&(p->s[index + replength]), &(bpTmp[index + strlength]),
  167.                 p->l - index - replength);
  168.  
  169.             if (p->n == 1)
  170.             {
  171.                 if (p->s) free(p->s); // this is the only reference
  172.                 p->s = bpTmp;
  173.                 p->l = p->l + strlength;
  174.             } else {
  175.                 struct srep *spOld = p;
  176.  
  177.                 // Decrement ref count on old internal rep, 
  178.                 // conjure up new internal ref.
  179.                 --p->n;
  180.                 p = (struct srep *)malloc(sizeof(struct srep));
  181.                 p->s = bpTmp;
  182.                 p->l = spOld->l + strlength;
  183.                 p->n = 1;
  184.             }
  185.         }
  186.     }
  187.     return self;
  188. }
  189.  
  190. @end
  191.