home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1994 June / NEBULA_SE.ISO / SourceCode / MiscKit / Source / MiscStringInsertion.m < prev    next >
Encoding:
Text File  |  1994-03-04  |  7.0 KB  |  270 lines

  1. //
  2. //    MiscStringInsertion.m
  3. //        Written by Don Yacktman (c) 1993 by Don Yacktman.
  4. //                Version 1.7  All rights reserved.
  5. //        This notice may not be removed from this source code.
  6. //
  7. //    This object is included in the MiscKit by permission from the author
  8. //    and its use is governed by the MiscKit license, found in the file
  9. //    "LICENSE.rtf" in the MiscKit distribution.  Please refer to that file
  10. //    for a list of all applicable permissions and restrictions.
  11. //    
  12.  
  13. #import <misckit/MiscString.h>
  14.  
  15. @implementation MiscString(Insertion)
  16.  
  17. // This category is composed of methods which insert characters or
  18. // strings into a MiscString.
  19.  
  20. - cat:(const char *)aString
  21. {
  22.     if (!aString) return nil; // so strlen() stays sane.  Thanks Steve Hayman!
  23.     return [self cat:aString n:strlen(aString) fromZone:[self zone]];
  24. }
  25.  
  26. - cat:(const char *)aString n:(int)n
  27. {
  28.     return [self cat:aString n:n fromZone:[self zone]];
  29. }
  30.  
  31. - cat:(const char *)aString fromZone:(NXZone *)zone
  32. {
  33.     if (!aString) return nil; // so strlen() stays sane.  Thanks Steve Hayman!
  34.     return [self cat:aString n:strlen(aString) fromZone:zone];
  35. }
  36.  
  37. - cat:(const char *)aString n:(int)n fromZone:(NXZone *)zone
  38. {
  39.     char *newBuffer; int newSize;
  40.     if (!(aString || buffer)) return nil;
  41.     if (!buffer) return [self setStringValue:aString fromZone:zone];
  42.     if (!aString) return self;
  43.     if (n > strlen(aString)) n = strlen(aString);
  44.     newSize = length + n + 1;
  45.     if (newSize > _length) {
  46.         newBuffer = (char *)NXZoneMalloc(zone, newSize);
  47.         _length = newSize;
  48.         newBuffer[0] = '\0';
  49.         strcat(newBuffer, buffer);
  50.         strncat(newBuffer, aString, n);
  51.         free(buffer);
  52.         buffer = newBuffer;
  53.     } else  strncat(buffer, aString, n);
  54.     length = strlen(buffer);
  55.     return self;
  56. }
  57.  
  58. - concatenate:sender
  59. { // note return self here; assume that there's nothing to add...
  60.     if (![sender respondsTo:@selector(stringValue)]) return self;
  61.     return [self cat:[sender stringValue]
  62.                  n:strlen([sender stringValue])
  63.                  fromZone:[self zone]];
  64. }
  65.  
  66. - concatenate:sender n:(int)n
  67. {
  68.     if (![sender respondsTo:@selector(stringValue)]) return self;
  69.     return [self cat:[sender stringValue] n:n fromZone:[self zone]];
  70. }
  71.  
  72. - concatenate:sender fromZone:(NXZone *)zone
  73. {
  74.     if (![sender respondsTo:@selector(stringValue)]) return self;
  75.     return [self cat:[sender stringValue]
  76.             n:strlen([sender stringValue]) fromZone:zone];
  77. }
  78.  
  79. - concatenate:sender n:(int)n fromZone:(NXZone *)zone
  80. {
  81.     if (![sender respondsTo:@selector(stringValue)]) return self;
  82.     return [self cat:[sender stringValue] n:n fromZone:zone];
  83. }
  84.  
  85. - insert:(const char *)aString at:(int)index
  86. // inserts given string into buffer starting at index.
  87. // (the first character is position #0)
  88. {
  89.     id temp1;
  90.     id temp2;
  91.  
  92.     if ((aString == NULL) || (strlen(aString)<=0)) return self;
  93.     if (index < 0) index = 0;         
  94.     if (index >= length) return [self cat:aString];
  95.  
  96.     temp1 = [self left:index];
  97.     if (!temp1) temp1 = [[[self class] alloc] init];
  98.     temp2 = [self right:length-index];  
  99.     [[temp1 cat:aString] concatenate:temp2];
  100.     [self setStringValue:[temp1 stringValue]];
  101.  
  102.     [temp1 free];
  103.     [temp2 free];
  104.     return self;
  105. }
  106.  
  107. - insertString:(id)sender at:(int)index
  108. // cover for insert:at: for a String object
  109. {
  110.     if (![sender respondsTo:@selector(stringValue)]) return self;
  111.     return [self insert:[sender stringValue] at:index];
  112. }
  113.  
  114. - insertChar:(char)aChar at:(int)index
  115. {
  116.     id tempStr;
  117.     id retval;
  118.  
  119.     if (aChar == 0) return self;    // or should this return nil? DAY: leave it
  120.  
  121.     tempStr = [[[[[self class] alloc] init] allocateBuffer:2] addChar:aChar];
  122.     retval = [self insert:[tempStr stringValue] at:index];
  123.     [tempStr free];
  124.     return retval;
  125. }
  126.  
  127. - insertChar:(char)aChar    // does an insert at the front (for chars)
  128. { // added for convenience; as you see it is redundant.
  129.     return [self insertChar:aChar at:0];
  130. }
  131.  
  132. // catStrings:    - a convenience function to append a list of strings
  133. //                to a string object.
  134. //    use like this:
  135. //        [aString addStrings:string0, string1, string2, string3, string4, NULL];
  136. //    make sure to have the ending NULL!
  137. //
  138. // Note from Don:  I've decided to use a version sent in by David Moffett
  139. //        since it is a bit more concise.
  140.  
  141. - catStrings:  ( const char *) strings,  ...;
  142. {
  143.     const char *aString;
  144.     va_list ptr;
  145.   
  146.     va_start( ptr, strings );
  147.     aString = strings;
  148.     while (aString) {
  149.         [self cat:aString n:strlen(aString) fromZone:[self zone]];
  150.         aString = va_arg(ptr, char *);
  151.     }
  152.     va_end( ptr );       
  153.     return self;
  154. }
  155.  
  156. // and here's one modified to handle MiscStrings -- don
  157. - concatenateStrings:(id)strings,  ...
  158. {
  159.     id aString;
  160.     va_list ptr;
  161.   
  162.     va_start(ptr, strings);
  163.     aString = strings;
  164.     while (aString) {
  165.         if ([aString respondsTo:@selector(stringValue)]) {
  166.             const char *sptr = [aString stringValue];
  167.             [self cat:sptr
  168.                     n:([aString respondsTo:@selector(length)] ?
  169.                             [aString length] : strlen(sptr))
  170.                     fromZone:[self zone]];
  171.         }
  172.         aString = va_arg(ptr, id);
  173.     }
  174.     va_end( ptr );       
  175.     return self;
  176. }
  177.  
  178. - insert:(const char *)aString    // does an insert at the front (for char *'s)
  179. { // added for convenience; as you see it is redundant.
  180.     return [self insert:aString at:0];
  181. }
  182.  
  183. - insertString:aString    // does an insert at the front (for objects)
  184. { // added for convenience; as you see it is redundant.
  185.     return [self insertString:aString at:0];
  186. }
  187.  
  188. - addChar:(char)aChar
  189. {
  190.   if (aChar) [self cat:&aChar n:1];
  191.   return self;
  192. }
  193.  
  194.  
  195. // The following methods are from the MOString by Mike Ferris:
  196.  
  197. - insertFromFormat:(const char *)format, ...
  198. // Prepends the given format string after formatting before the contents
  199. // of the receiver.
  200. {
  201.     va_list param_list;
  202.     
  203.     va_start(param_list, format);
  204.     [self insertAt:0 fromFormat:format, param_list];
  205.     va_end(param_list);
  206.     return self;
  207. }
  208.  
  209. - insertAt:(int)index fromFormat:(const char *)format, ...
  210. {
  211.     char *buf;
  212.     va_list param_list;
  213.     
  214.     va_start(param_list, format);
  215.     buf = MiscBuildStringFromFormatV(format, param_list);
  216.     [self insert:buf at:index];
  217.     NX_FREE(buf);
  218.     va_end(param_list);
  219.     return self;
  220. }
  221.  
  222. - catFromFormat:(const char *)format, ...
  223. // Appends to the string from the printf style format string and arguments.
  224. {
  225.     char *buf;
  226.     va_list param_list;
  227.  
  228.     va_start(param_list, format);
  229.     buf = MiscBuildStringFromFormatV(format, param_list);
  230.     [self cat:buf];
  231.     NX_FREE(buf);
  232.     va_end(param_list);
  233.     return self;
  234. }
  235.  
  236. // Here's an alternative way to catFromFormat, courtesy of Steve Hayman.
  237. // For now, we're keeping everything in the MiscBuildStringFromFormatV
  238. // function for simplicity.
  239. /* This method is currently commented out and not compiled.
  240. - printf:(const char *)fmt, ...
  241. {
  242.     NXStream *mem;
  243.     char *streambuf;
  244.     int len, maxlen;
  245.     va_list  ap;
  246.  
  247.     va_start(ap, fmt);
  248.     
  249.     // open a memory stream ...
  250.     mem = NXOpenMemory( NULL, 0, NX_WRITEONLY );
  251.     
  252.     // printf everything to the memory stream ...
  253.     NXVPrintf( mem, fmt, ap );
  254.     // and make sure it's null terminated
  255.     NXPutc( mem, '\0' );
  256.     // and get pointers to the buffer where the stream is ...
  257.     NXGetMemoryBuffer( mem, &streambuf, &len, &maxlen );
  258.     
  259.     // and append the text to ourself
  260.     [self cat:streambuf];
  261.     
  262.     // and free the memory stream.
  263.     NXCloseMemory(mem, NX_FREEBUFFER);
  264.     va_end(ap);
  265.  
  266.     return self;
  267. }
  268. */
  269. @end
  270.