www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - A new class -->String

reply "jinheking" <caoqi bgi.net.cn> writes:
I want to make a Class like java's String Class.
module jdk2d.lang;

import std.stdio;
/*
* The <code>String</code> class represents character strings. All
* string literals in D programs, such as <code>"abc"</code>, are
* implemented as instances of this class.
*  author  Caoqi
*  version 0.001, 07/03/30
*  since   JDK2D 0.02
*  url     http://jinheking.javaeye.com/admin
* <p>
*/

public class  String{
  private final wchar[] value;

  /** The offset is the first index of the storage that is used. */
  private final int offset;

  /** The count is the number of characters in the String. */
  private final int count;

  /*
   * Initializes a newly created { code String} object so that it represents
   * an empty character sequence.  Note that use of this constructor is
   * unnecessary since Strings are immutable.
   */
  this(){
   this.offset = 0;
   this.count = 0;
   this.value = new wchar[0];
  }

  String opAssign(wchar[] value) {
   int size = value.length;
   offset = 0;
   count = size;
   value = value;
   return this;
    }

  /*
     * Allocates a new { code String} so that it represents the sequence of
     * characters currently contained in the character array argument. The
     * contents of the character array are copied; subsequent modification 
of
     * the character array does not affect the newly created string.
     *
     *  param  value
     *         The initial value of the string
     */
    public this(wchar[] value) {
   int size = value.length;
   this.offset = 0;
   this.count = size;
   this.value = value;
    }

  /**
     * Returns the length of this string.
     * The length is equal to the number of <a 
href="Character.html#unicode">Unicode
     * code units</a> in the string.
     *
     *  return  the length of the sequence of characters represented by this
     *          object.
     */
    public int length() {
        return count;
    }

    /**
     * Returns <tt>true</tt> if, and only if, { link #length()} is 
<tt>0</tt>.
     *
     *  return <tt>true</tt> if { link #length()} is <tt>0</tt>, otherwise
     * <tt>false</tt>
     *
     *  since JDK2D 0.01
     */
    public bool isEmpty() {
    return count == 0;
    }
  /**
     * Returns the index within this string of the first occurrence of the
     * specified substring. The integer returned is the smallest value
     * <i>k</i> such that:
     * <blockquote><pre>
     * this.startsWith(str, <i>k</i>)
     * </pre></blockquote>
     * is <code>true</code>.
     *
     *  param   str   any string.
     *  return  if the string argument occurs as a substring within this
     *          object, then the index of the first character of the first
     *          such substring is returned; if it does not occur as a
     *          substring, <code>-1</code> is returned.
     */

    public int indexOf(String str) {
   return indexOf(str, 0);
    }

    public int indexOf(wchar[] str) {
   return indexOf(str, 0);
    }

    /**
     * Returns the index within this string of the first occurrence of the
     * specified substring, starting at the specified index.  The integer
     * returned is the smallest value <tt>k</tt> for which:
     * <blockquote><pre>
     *     k &gt;= Math.min(fromIndex, this.length()) && 
this.startsWith(str, k)
     * </pre></blockquote>
     * If no such value of <i>k</i> exists, then -1 is returned.
     *
     *  param   str         the substring for which to search.
     *  param   fromIndex   the index from which to start the search.
     *  return  the index within this string of the first occurrence of the
     *          specified substring, starting at the specified index.
     */
    public int indexOf(String str, int fromIndex) {
        return indexOf(value, offset, count,
                       str.value, str.offset, str.count, fromIndex);
    }

    public int indexOf(wchar[] wstr, int fromIndex) {
       String str=new String(wstr);
        return indexOf(value, offset, count,
                       str.value, str.offset, str.count, fromIndex);
    }

    /**
     * Code shared by String and StringBuffer to do searches. The
     * source is the character array being searched, and the target
     * is the string being searched for.
     *
     *  param   source       the characters being searched.
     *  param   sourceOffset offset of the source string.
     *  param   sourceCount  count of the source string.
     *  param   target       the characters being searched for.
     *  param   targetOffset offset of the target string.
     *  param   targetCount  count of the target string.
     *  param   fromIndex    the index to begin searching from.
     */
    static int indexOf(wchar[] source, int sourceOffset, int sourceCount,
                       wchar[] target, int targetOffset, int targetCount,
                       int fromIndex) {
   if (fromIndex >= sourceCount) {
              return (targetCount == 0 ? sourceCount : -1);
   }
       if (fromIndex < 0) {
           fromIndex = 0;
       }
   if (targetCount == 0) {
       return fromIndex;
   }

          wchar first  = target[targetOffset];
          int max = sourceOffset + (sourceCount - targetCount);

          for (int i = sourceOffset + fromIndex; i <= max; i++) {
              /* Look for first character. */
              if (source[i] != first) {
                i++;
                  while (i <= max && source[i] != first){
                   i++;
                  }
              }

              /* Found first character, now look at the rest of v2 */
              if (i <= max) {
                  int j = i + 1;
                  int end = j + targetCount - 1;
                  for (int k = targetOffset + 1; j < end && (source[j] == 
target[k]);j++){
                    k++;
                  }

                  if (j == end) {
                      /* Found whole string. */
                      return i - sourceOffset;
                  }
              }
          }
          return -1;
      }

 char[] toString(){
  return cast(char[])std.utf.toUTF8(this.value);
 }
}

public static void  main() {
   String str = new String("The quick brown fox jumped over the lazy dog.");
   String s1 = new String("abc");
   s1="abc";
   writefln(s1);
   printf("%d\n",str.indexOf("z"));
   printf("%d\n",str.isEmpty());
} 
Apr 03 2007
next sibling parent reply Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
jinheking wrote:
 I want to make a Class like java's String Class.
 module jdk2d.lang;
 
 import std.stdio;
 /*
 * The <code>String</code> class represents character strings. All
 * string literals in D programs, such as <code>"abc"</code>, are
 * implemented as instances of this class.
I don't think last bit is going to happen.
 *  author  Caoqi
 *  version 0.001, 07/03/30
 *  since   JDK2D 0.02
 *  url     http://jinheking.javaeye.com/admin
 * <p>
 */
 
 public class  String{
   private final wchar[] value;
 
   /** The offset is the first index of the storage that is used. */
   private final int offset;
 
   /** The count is the number of characters in the String. */
   private final int count;
Those last two are unnecessary. wchar[] + slicing takes care of everything. So all you need is private final wchar[] value; (and when the new constness proposal comes through, add const (or better yet, invariant) to that)
   /*
    * Initializes a newly created { code String} object so that it represents
    * an empty character sequence.  Note that use of this constructor is
    * unnecessary since Strings are immutable.
    */
   this(){
    this.offset = 0;
    this.count = 0;
    this.value = new wchar[0];
just this.value = null; will do just fine.
   }
 
   String opAssign(wchar[] value) {
    int size = value.length;
    offset = 0;
    count = size;
    value = value;
    return this;
(You forgot a 'this' in front of the left-hand 'value' in that assignment) this.value = value.dup; To be sure the code outside can't modify the contents. Once constness comes through, add an overload that takes an invariant wchar[] and doesn't dup.
     }
 
   /*
      * Allocates a new { code String} so that it represents the sequence of
      * characters currently contained in the character array argument. The
      * contents of the character array are copied; subsequent modification 
 of
      * the character array does not affect the newly created string.
      *
      *  param  value
      *         The initial value of the string
      */
     public this(wchar[] value) {
    int size = value.length;
    this.offset = 0;
    this.count = size;
    this.value = value;
Same as above: this.value = value.dup;
     }
 
   /**
      * Returns the length of this string.
      * The length is equal to the number of <a 
 href="Character.html#unicode">Unicode
      * code units</a> in the string.
      *
      *  return  the length of the sequence of characters represented by this
      *          object.
      */
     public int length() {
         return count;
return value.length;
     }
 
     /**
      * Returns <tt>true</tt> if, and only if, { link #length()} is 
 <tt>0</tt>.
      *
      *  return <tt>true</tt> if { link #length()} is <tt>0</tt>, otherwise
      * <tt>false</tt>
      *
      *  since JDK2D 0.01
      */
     public bool isEmpty() {
     return count == 0;
return value.length == 0;
     }
   /**
      * Returns the index within this string of the first occurrence of the
      * specified substring. The integer returned is the smallest value
      * <i>k</i> such that:
      * <blockquote><pre>
      * this.startsWith(str, <i>k</i>)
      * </pre></blockquote>
      * is <code>true</code>.
      *
      *  param   str   any string.
      *  return  if the string argument occurs as a substring within this
      *          object, then the index of the first character of the first
      *          such substring is returned; if it does not occur as a
      *          substring, <code>-1</code> is returned.
      */
 
     public int indexOf(String str) {
    return indexOf(str, 0);
     }
 
     public int indexOf(wchar[] str) {
    return indexOf(str, 0);
     }
 
     /**
      * Returns the index within this string of the first occurrence of the
      * specified substring, starting at the specified index.  The integer
      * returned is the smallest value <tt>k</tt> for which:
      * <blockquote><pre>
      *     k &gt;= Math.min(fromIndex, this.length()) && 
 this.startsWith(str, k)
      * </pre></blockquote>
      * If no such value of <i>k</i> exists, then -1 is returned.
      *
      *  param   str         the substring for which to search.
      *  param   fromIndex   the index from which to start the search.
      *  return  the index within this string of the first occurrence of the
      *          specified substring, starting at the specified index.
      */
     public int indexOf(String str, int fromIndex) {
         return indexOf(value, offset, count,
                        str.value, str.offset, str.count, fromIndex);
     }
 
     public int indexOf(wchar[] wstr, int fromIndex) {
        String str=new String(wstr);
         return indexOf(value, offset, count,
                        str.value, str.offset, str.count, fromIndex);
     }
 
     /**
      * Code shared by String and StringBuffer to do searches. The
      * source is the character array being searched, and the target
      * is the string being searched for.
      *
      *  param   source       the characters being searched.
      *  param   sourceOffset offset of the source string.
      *  param   sourceCount  count of the source string.
      *  param   target       the characters being searched for.
      *  param   targetOffset offset of the target string.
      *  param   targetCount  count of the target string.
      *  param   fromIndex    the index to begin searching from.
      */
     static int indexOf(wchar[] source, int sourceOffset, int sourceCount,
                        wchar[] target, int targetOffset, int targetCount,
                        int fromIndex) {
    if (fromIndex >= sourceCount) {
               return (targetCount == 0 ? sourceCount : -1);
    }
        if (fromIndex < 0) {
            fromIndex = 0;
        }
    if (targetCount == 0) {
        return fromIndex;
    }
 
           wchar first  = target[targetOffset];
           int max = sourceOffset + (sourceCount - targetCount);
 
           for (int i = sourceOffset + fromIndex; i <= max; i++) {
               /* Look for first character. */
               if (source[i] != first) {
                 i++;
                   while (i <= max && source[i] != first){
                    i++;
                   }
               }
 
               /* Found first character, now look at the rest of v2 */
               if (i <= max) {
                   int j = i + 1;
                   int end = j + targetCount - 1;
                   for (int k = targetOffset + 1; j < end && (source[j] == 
 target[k]);j++){
                     k++;
                   }
 
                   if (j == end) {
                       /* Found whole string. */
                       return i - sourceOffset;
                   }
               }
           }
           return -1;
       }
Using slicing so offset and counts don't need to be passed will allow you to implement these more cleanly, I think.
 
  char[] toString(){
   return cast(char[])std.utf.toUTF8(this.value);
This is broken for your implementation but just fine for mine. (It doesn't work for substrings in yours, it'll convert the entire string instead of just the part this String object represents)
  }
 }
 
 public static void  main() {
    String str = new String("The quick brown fox jumped over the lazy dog.");
    String s1 = new String("abc");
    s1="abc";
    writefln(s1);
    printf("%d\n",str.indexOf("z"));
    printf("%d\n",str.isEmpty());
 }
As a final note, there's a (less Java-like) string class implementation at http://www.dprogramming.com/dstring.php. It stores its data as char[], wchar[] or dchar[] and tries to use whichever is the most space-efficient yet can still store all elements in a single array element. The last bit allows it to implement "intuitive" slicing, never slicing in the middle of a group of UTF-8 or UTF-16 code units that form a single character point (if I got the terminology right).
Apr 04 2007
next sibling parent reply "jinheking" <caoqi bgi.net.cn> writes:
String opAssign(wchar[] value) {
   int size = value.length;
   offset = 0;
   count = size;
   value = value;
   return this;
    }

That is this funcation!

"Frits van Bommel" <fvbommel REMwOVExCAPSs.nl>
дÈëÏûÏ¢ÐÂÎÅ:euvo53$3rg$1 digitalmars.com...
 jinheking wrote:
 I want to make a Class like java's String Class.
 module jdk2d.lang;

 import std.stdio;
 /*
 * The <code>String</code> class represents character strings. All
 * string literals in D programs, such as <code>"abc"</code>, are
 * implemented as instances of this class.
I don't think last bit is going to happen.
 *  author  Caoqi
 *  version 0.001, 07/03/30
 *  since   JDK2D 0.02
 *  url     http://jinheking.javaeye.com/admin
 * <p>
 */

 public class  String{
   private final wchar[] value;

   /** The offset is the first index of the storage that is used. */
   private final int offset;

   /** The count is the number of characters in the String. */
   private final int count;
Those last two are unnecessary. wchar[] + slicing takes care of everything. So all you need is private final wchar[] value; (and when the new constness proposal comes through, add const (or better yet, invariant) to that)
   /*
    * Initializes a newly created { code String} object so that it 
 represents
    * an empty character sequence.  Note that use of this constructor is
    * unnecessary since Strings are immutable.
    */
   this(){
    this.offset = 0;
    this.count = 0;
    this.value = new wchar[0];
just this.value = null; will do just fine.
   }

   String opAssign(wchar[] value) {
    int size = value.length;
    offset = 0;
    count = size;
    value = value;
    return this;
(You forgot a 'this' in front of the left-hand 'value' in that assignment) this.value = value.dup; To be sure the code outside can't modify the contents. Once constness comes through, add an overload that takes an invariant wchar[] and doesn't dup.
     }

   /*
      * Allocates a new { code String} so that it represents the sequence 
 of
      * characters currently contained in the character array argument. 
 The
      * contents of the character array are copied; subsequent 
 modification of
      * the character array does not affect the newly created string.
      *
      *  param  value
      *         The initial value of the string
      */
     public this(wchar[] value) {
    int size = value.length;
    this.offset = 0;
    this.count = size;
    this.value = value;
Same as above: this.value = value.dup;
     }

   /**
      * Returns the length of this string.
      * The length is equal to the number of <a 
 href="Character.html#unicode">Unicode
      * code units</a> in the string.
      *
      *  return  the length of the sequence of characters represented by 
 this
      *          object.
      */
     public int length() {
         return count;
return value.length;
     }

     /**
      * Returns <tt>true</tt> if, and only if, { link #length()} is 
 <tt>0</tt>.
      *
      *  return <tt>true</tt> if { link #length()} is <tt>0</tt>, 
 otherwise
      * <tt>false</tt>
      *
      *  since JDK2D 0.01
      */
     public bool isEmpty() {
     return count == 0;
return value.length == 0;
     }
   /**
      * Returns the index within this string of the first occurrence of 
 the
      * specified substring. The integer returned is the smallest value
      * <i>k</i> such that:
      * <blockquote><pre>
      * this.startsWith(str, <i>k</i>)
      * </pre></blockquote>
      * is <code>true</code>.
      *
      *  param   str   any string.
      *  return  if the string argument occurs as a substring within this
      *          object, then the index of the first character of the 
 first
      *          such substring is returned; if it does not occur as a
      *          substring, <code>-1</code> is returned.
      */

     public int indexOf(String str) {
    return indexOf(str, 0);
     }

     public int indexOf(wchar[] str) {
    return indexOf(str, 0);
     }

     /**
      * Returns the index within this string of the first occurrence of 
 the
      * specified substring, starting at the specified index.  The integer
      * returned is the smallest value <tt>k</tt> for which:
      * <blockquote><pre>
      *     k &gt;= Math.min(fromIndex, this.length()) && 
 this.startsWith(str, k)
      * </pre></blockquote>
      * If no such value of <i>k</i> exists, then -1 is returned.
      *
      *  param   str         the substring for which to search.
      *  param   fromIndex   the index from which to start the search.
      *  return  the index within this string of the first occurrence of 
 the
      *          specified substring, starting at the specified index.
      */
     public int indexOf(String str, int fromIndex) {
         return indexOf(value, offset, count,
                        str.value, str.offset, str.count, fromIndex);
     }

     public int indexOf(wchar[] wstr, int fromIndex) {
        String str=new String(wstr);
         return indexOf(value, offset, count,
                        str.value, str.offset, str.count, fromIndex);
     }

     /**
      * Code shared by String and StringBuffer to do searches. The
      * source is the character array being searched, and the target
      * is the string being searched for.
      *
      *  param   source       the characters being searched.
      *  param   sourceOffset offset of the source string.
      *  param   sourceCount  count of the source string.
      *  param   target       the characters being searched for.
      *  param   targetOffset offset of the target string.
      *  param   targetCount  count of the target string.
      *  param   fromIndex    the index to begin searching from.
      */
     static int indexOf(wchar[] source, int sourceOffset, int sourceCount,
                        wchar[] target, int targetOffset, int targetCount,
                        int fromIndex) {
    if (fromIndex >= sourceCount) {
               return (targetCount == 0 ? sourceCount : -1);
    }
        if (fromIndex < 0) {
            fromIndex = 0;
        }
    if (targetCount == 0) {
        return fromIndex;
    }

           wchar first  = target[targetOffset];
           int max = sourceOffset + (sourceCount - targetCount);

           for (int i = sourceOffset + fromIndex; i <= max; i++) {
               /* Look for first character. */
               if (source[i] != first) {
                 i++;
                   while (i <= max && source[i] != first){
                    i++;
                   }
               }

               /* Found first character, now look at the rest of v2 */
               if (i <= max) {
                   int j = i + 1;
                   int end = j + targetCount - 1;
                   for (int k = targetOffset + 1; j < end && (source[j] == 
 target[k]);j++){
                     k++;
                   }

                   if (j == end) {
                       /* Found whole string. */
                       return i - sourceOffset;
                   }
               }
           }
           return -1;
       }
Using slicing so offset and counts don't need to be passed will allow you to implement these more cleanly, I think.
  char[] toString(){
   return cast(char[])std.utf.toUTF8(this.value);
This is broken for your implementation but just fine for mine. (It doesn't work for substrings in yours, it'll convert the entire string instead of just the part this String object represents)
  }
 }

 public static void  main() {
    String str = new String("The quick brown fox jumped over the lazy 
 dog.");
    String s1 = new String("abc");
    s1="abc";
    writefln(s1);
    printf("%d\n",str.indexOf("z"));
    printf("%d\n",str.isEmpty());
 }
As a final note, there's a (less Java-like) string class implementation at http://www.dprogramming.com/dstring.php. It stores its data as char[], wchar[] or dchar[] and tries to use whichever is the most space-efficient yet can still store all elements in a single array element. The last bit allows it to implement "intuitive" slicing, never slicing in the middle of a group of UTF-8 or UTF-16 code units that form a single character point (if I got the terminology right).
Apr 04 2007
parent reply Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
jinheking wrote:
 String opAssign(wchar[] value) {
    int size = value.length;
    offset = 0;
    count = size;
    value = value;
    return this;
     }
 
 That is this funcation!
I'm sorry, I don't understand what you're trying to say. If you were confused about my comment on that function in particular, let me try to reword it: The way I would code that function (assuming the class fields stay the same) would be like so: --- String opAssign(wchar[] value) { offset = 0; count = value.length; this.value = value.dup; return this; } --- The 'this.' makes sure it assigns to the 'value' defined at the top of the class, not the one parameter. The '.dup' makes a copy of the string passed in to make sure nobody else can change the value of the String object, since you want it to be immutable.
Apr 04 2007
parent "jinheking" <caoqi bgi.net.cn> writes:
Your advice is right
I changed my fun below:
/**
  *
  * <code>String str=new String("abc");</code>
  * <code>str="abcd";</code>
  *  param  wc
    *         The initial value of the string
  */
  String opAssign(wchar[] wc) {
   this.offset = 0;
   this.count = wc.length;
   this.value = wc.dup;
   return this;
    }

void test(){
    String str=new String("abc"); //True
    str="abcd"; //True
    String s2="aa";//false  //which reason
}

How do do it?



"Frits van Bommel" <fvbommel REMwOVExCAPSs.nl>
дÈëÏûÏ¢ÐÂÎÅ:euvsh7$ekg$1 digitalmars.com...
 jinheking wrote:
 String opAssign(wchar[] value) {
    int size = value.length;
    offset = 0;
    count = size;
    value = value;
    return this;
     }

 That is this funcation!
I'm sorry, I don't understand what you're trying to say. If you were confused about my comment on that function in particular, let me try to reword it: The way I would code that function (assuming the class fields stay the same) would be like so: --- String opAssign(wchar[] value) { offset = 0; count = value.length; this.value = value.dup; return this; } --- The 'this.' makes sure it assigns to the 'value' defined at the top of the class, not the one parameter. The '.dup' makes a copy of the string passed in to make sure nobody else can change the value of the String object, since you want it to be immutable.
Apr 04 2007
prev sibling parent "jinheking" <caoqi bgi.net.cn> writes:
As a final note, there's a (less Java-like) string class implementation at 
http://www.dprogramming.com/dstring.php. It stores its data as char[], 
wchar[] or dchar[] and tries to use whichever is the most space-efficient 
yet can still store all elements in a single array element. The last bit 
allows it to implement "intuitive" slicing, never slicing in the middle of 
a group of UTF-8 or UTF-16 code units that form a single character point 
(if I got the terminology right).
Next time,I will do it.If I have this power. I hope you help me.ok?
Apr 04 2007
prev sibling next sibling parent reply "David B. Held" <dheld codelogicconsulting.com> writes:
jinheking wrote:
 I want to make a Class like java's String Class.
 [...]
Well, I believe the intention is that when 'invariant' gets added to the language, we will get string thusly: alias invariant char[] string; Note that this leaves out all of the member functions that one expects from String. However, with immutable strings, it is perfectly safe (and, perhaps, preferable) to implement all that functionality as free functions. If there were a way to switch between method call and free function syntax, then this distinction would become moot (and maybe we will get that as well...). Dave
Apr 04 2007
parent reply =?ISO-8859-1?Q?Jari-Matti_M=E4kel=E4?= <jmjmak utu.fi.invalid> writes:
David B. Held wrote:
 jinheking wrote:
 I want to make a Class like java's String Class.
 [...]
Well, I believe the intention is that when 'invariant' gets added to the language, we will get string thusly: alias invariant char[] string; Note that this leaves out all of the member functions that one expects from String. However, with immutable strings, it is perfectly safe (and, perhaps, preferable) to implement all that functionality as free functions. If there were a way to switch between method call and free function syntax, then this distinction would become moot (and maybe we will get that as well...).
D has that already :) char[] moo; void doSomething(char[] baa) { ... } void main() { moo.doSomething(); }
Apr 04 2007
parent reply "David B. Held" <dheld codelogicconsulting.com> writes:
Jari-Matti Mäkelä wrote:
 David B. Held wrote:
 jinheking wrote:
 I want to make a Class like java's String Class.
 [...]
Well, I believe the intention is that when 'invariant' gets added to the language, we will get string thusly: alias invariant char[] string; Note that this leaves out all of the member functions that one expects from String. However, with immutable strings, it is perfectly safe (and, perhaps, preferable) to implement all that functionality as free functions. If there were a way to switch between method call and free function syntax, then this distinction would become moot (and maybe we will get that as well...).
D has that already :) char[] moo; void doSomething(char[] baa) { ... } void main() { moo.doSomething(); }
Well, it isn't general: void foo(int x) { int y = x; } unittest { int z = 5; z.foo(); } test.d(43): Error: no property 'foo' for type 'int' test.d(43): Error: function expected before (), not 1 of type int Dave
Apr 05 2007
parent reply =?ISO-8859-1?Q?Jari-Matti_M=E4kel=E4?= <jmjmak utu.fi.invalid> writes:
David B. Held wrote:
 Jari-Matti Mäkelä wrote:
 David B. Held wrote:
 If there were a way to switch between method call and free
 function syntax, then this distinction would become moot (and maybe we
 will get that as well...).
 D has that already :)
 Well, it isn't general:
 
 void foo(int x) { int y = x; }
 
 unittest
 {
     int z = 5;
     z.foo();
 }
 
 test.d(43): Error: no property 'foo' for type 'int'
 test.d(43): Error: function expected before (), not 1 of type int
Hm, I wonder if that's a compiler bug. I have not used this feature recently, but I recall it used to work. I even have bindings where this feature is used to provide an alternative syntax for a wrapper class. Now that I tested it, it only seems to work with arrays and AAs anymore. But it's still enough to implement those string functions though.
Apr 05 2007
parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
Jari-Matti Mäkelä wrote:
 David B. Held wrote:
 Jari-Matti Mäkelä wrote:
 David B. Held wrote:
 If there were a way to switch between method call and free
 function syntax, then this distinction would become moot (and maybe we
 will get that as well...).
 D has that already :)
 Well, it isn't general:

 void foo(int x) { int y = x; }

 unittest
 {
     int z = 5;
     z.foo();
 }

 test.d(43): Error: no property 'foo' for type 'int'
 test.d(43): Error: function expected before (), not 1 of type int
Hm, I wonder if that's a compiler bug. I have not used this feature recently, but I recall it used to work. I even have bindings where this feature is used to provide an alternative syntax for a wrapper class. Now that I tested it, it only seems to work with arrays and AAs anymore. But it's still enough to implement those string functions though.
From what I understand, it's not a feature, it's a bug. No, I'm serious: this happens because of a bug in DMD. The only reason it's never been fixed is because people actually really, really like that it works :) The whole "switch function to member of first arg" thing is only usable, as you said, on arrays and AAs. Having it usable in general would be wicked-nifty-awesome-keen, to mix my colloquialisms. :) -- Daniel -- int getRandomNumber() { return 4; // chosen by fair dice roll. // guaranteed to be random. } http://xkcd.com/ v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
Apr 05 2007
parent reply Jari-Matti =?UTF-8?B?TcOka2Vsw6Q=?= <jmjmak utu.fi.invalid> writes:
Daniel Keep wrote:

 
 
 Jari-Matti Mäkelä wrote:
 David B. Held wrote:
 Jari-Matti Mäkelä wrote:
 David B. Held wrote:
 If there were a way to switch between method call and free
 function syntax, then this distinction would become moot (and maybe we
 will get that as well...).
 D has that already :)
 Well, it isn't general:

 void foo(int x) { int y = x; }

 unittest
 {
     int z = 5;
     z.foo();
 }

 test.d(43): Error: no property 'foo' for type 'int'
 test.d(43): Error: function expected before (), not 1 of type int
Hm, I wonder if that's a compiler bug. I have not used this feature recently, but I recall it used to work. I even have bindings where this feature is used to provide an alternative syntax for a wrapper class. Now that I tested it, it only seems to work with arrays and AAs anymore. But it's still enough to implement those string functions though.
From what I understand, it's not a feature, it's a bug. No, I'm serious: this happens because of a bug in DMD. The only reason it's never been fixed is because people actually really, really like that it works :)
Ah, you're right. I didn't find it in the language docs either.
 The whole "switch function to member of first arg" thing is only usable,
 as you said, on arrays and AAs.  Having it usable in general would be
 wicked-nifty-awesome-keen, to mix my colloquialisms. :)
In Scala language this can be "safely" done with views and implicit type conversions. If this "poor man's version" isn't a good solution in the long run, at least there is another way to do this that has strong academic backing behind it. That alternative is also much more flexible.
Apr 05 2007
parent reply Dan <murpsoft hotmail.com> writes:
I totally disagree with Class'ing a simple data type just to introduce
functions to handle it.

Especially since you can use that pretty OO notation on arrays simply by having
the functions accept the array as the first argument.  This works:

void slice(inout char[] s, size_t start, size_t finish){
...
}

char[] myS = "Hello!  How are you?";

myS.slice(2,6);
Apr 05 2007
parent reply Jari-Matti =?UTF-8?B?TcOka2Vsw6Q=?= <jmjmak utu.fi.invalid> writes:
Dan wrote:

 
 I totally disagree with Class'ing a simple data type just to introduce
 functions to handle it.
I'm sure we all agree on that. Extending previously closed classes is a valuable feature in modern object oriented programming.
 
 Especially since you can use that pretty OO notation on arrays simply by
 having the functions accept the array as the first argument.  This works:
 
 void slice(inout char[] s, size_t start, size_t finish){
 ...
 }
 
 char[] myS = "Hello!  How are you?";
 
 myS.slice(2,6);
That is what I pointed out previously. But the current syntax is limited to a few special cases. You cannot do something like auto myS = "moo"; char[] opMul(char[] str, int count) { char[] tmp; for(int i=0; i<count; i++) tmp ~= str; return tmp; } auto s2 = myS * 3; // = "moomoomoo" Also you cannot specify constraints on the use of these implicit conversions. I have not enough expertise on this, but it is good to know that some other languages have found working solutions.
Apr 05 2007
next sibling parent Dan <murpsoft hotmail.com> writes:
Jari-Matti Mäkelä Wrote:

 Dan wrote:
 I totally disagree with Class'ing a simple data type just to introduce
 functions to handle it.
I'm sure we all agree on that. Extending previously closed classes is a valuable feature in modern object oriented programming.
...
 a few special cases. You cannot do something like
 
 auto myS = "moo";
 
 char[] opMul(char[] str, int count) {
         char[] tmp;
         for(int i=0; i<count; i++) tmp ~= str;
         return tmp;
 }
 
 auto s2 = myS * 3;  // = "moomoomoo"
If what you want is operator overrides, I'd recommend a struct. Semantically, it's equivalent to using the simple data type, while allowing you to sugar coat it in the same way as a class.
Apr 05 2007
prev sibling parent reply "David B. Held" <dheld codelogicconsulting.com> writes:
Jari-Matti Mäkelä wrote:
 [...]
 I'm sure we all agree on that. Extending previously closed classes is a
 valuable feature in modern object oriented programming.
 [...]
The free vs. method syntax proposal I mentioned earlier is not equivalent to extending closed classes. The latter would imply the ability to add virtual functions and method overloads outside the definition of the class, or accessing private members, which are not possible under this proposal. Dave
Apr 05 2007
parent Jari-Matti =?UTF-8?B?TcOka2Vsw6Q=?= <jmjmak utu.fi.invalid> writes:
David B. Held wrote:

 Jari-Matti Mäkelä wrote:
 [...]
 I'm sure we all agree on that. Extending previously closed classes is a
 valuable feature in modern object oriented programming.
 [...]
The free vs. method syntax proposal I mentioned earlier is not equivalent to extending closed classes.
You're right and I wasn't referring to that anymore ;)
 The latter would imply the 
 ability to add virtual functions and method overloads outside the
 definition of the class, or accessing private members, which are not
 possible under this proposal.
What I had in mind was that view + impl. conversion approach. In D it might be possible to do that all statically. Adding new members and overloading old would be possible, but I'm not sure if accessing private or even protected members through this mechanism is the right choice.
 
 Dave
Apr 06 2007
prev sibling next sibling parent "Frank Benoit (keinfarbton)" <benoit tionex.removethispart.de> writes:
I wonder if you are currently starting to port java code to D.
If so, I want to introduce you to this project:
http://www.dsource.org/projects/tioport
Apr 04 2007
prev sibling next sibling parent BLS <nanali wanadoo.fr> writes:
Hi ,
Pretty sure that you ll like this stuff .

http://www.mbutscher.de/antlrd/

Quote from ANTLR-D
<
Because of the different string concepts of D and Java, the string handling is
rather inconvenient. The runtime sources use a class WString which is similar
to Java's String class. WString is based on 16 bit wchar characters.

beside it would  be nice if you are willing to share your Tool chain with us. I
am f.i. interested in building a GUI-Frontend, based on NetBeans for TIOPORT
....
Bjoern 


Frank Benoit (keinfarbton) Wrote:

 I wonder if you are currently starting to port java code to D.
 If so, I want to introduce you to this project:
 http://www.dsource.org/projects/tioport
 
Apr 04 2007
prev sibling parent reply "jinheking" <caoqi bgi.net.cn> writes:
//module jdk2d.lang;

import std.stdio;
import std.string;

/**
* The <code>String</code> class represents character strings. All
* string literals in D programs, such as <code>String str=new 
String("abc");</code>,
* <br /><code>str="Hello world";</code>
* are implemented as instances of this class.<br />
* final wchar[] value; The value is the String's value.<br />
* final int offset;    The offset is the first index of the storage that is 
used.<br />
* final int count;     The count is the number of characters in the String. 
<br />
* Authors:  Caoqi
* version: 0.021
* Date: April 5, 2007
* History: March 30,2007 V0.01
* License: BSD
* See_Also:
       My blog, <a href=" http://jinheking.javaeye.com/"> 
http://jinheking.javaeye.com/</a>

* <p>
*/




/// Documentation for String
public class  String{
 private:
  final wchar[] value; ///The value is the String's value.
  final int offset;    ///The offset is the first index of the storage that 
is used.
  final int count;     ///The count is the number of characters in the 
String.

 public:
  /**
   * Initializes a newly created { code String} object so that it represents
   * an empty character sequence.  Note that use of this constructor is
   * unnecessary since Strings are immutable.
   */
  this(){
   this.offset = 0;
   this.count = 0;
   this.value = null;
  }
  /**
  * Params:wc = The initial value of the string
    * Return:
    *        String
    * <code>String str=new String("abc");</code><br />
  * <code>str="abcd";</code>
  */
  String opAssign(wchar[] wc) {
   this.offset = 0;
   this.count = wc.length;
   this.value = wc.dup;
   return this;
    }

  /**
  * <code>s1>s2</code>
  * Params: s = The initial value of the string
    * Return: bool
  */
  int opCmp(String s){
   return std.string.cmp(cast(char[])this.value, cast(char[])s.value);
  }
  /*
     * Allocates a new { code String} so that it represents the sequence of
     * characters currently contained in the character array argument. The
     * contents of the character array are copied; subsequent modification 
of
     * the character array does not affect the newly created string.
     *
     * Param:  value =  The initial value of the string
     */
    public this(wchar[] value) {
   int size = value.length;
   this.offset = 0;
   this.count = size;
   this.value = value;
    }

  /**
     * Returns the length of this string.
     * The length is equal to the number of <a 
href="Character.html#unicode">Unicode
     * code units</a> in the string.
     *
     * Return:  The length of the sequence of characters represented by this
     *          object.
     */
    public int length() {
        return this.value.length;
    }

    /**
     * Returns <tt>true</tt> if, and only if, { link #length()} is 
<tt>0</tt>.
     *
     * Return <tt>true</tt> if { link #length()} is <tt>0</tt>, otherwise
     * <tt>false</tt>
     */
    public bool isEmpty() {
    return count == 0;
    }
  /**
     * Returns the index within this string of the first occurrence of the
     * specified substring. The integer returned is the smallest value
     * <i>k</i> such that:
     * <blockquote><pre>
     * this.startsWith(str, <i>k</i>)
     * </pre></blockquote>
     * is <code>true</code>.
     *
     * Params:   str =  any String.
     * Return:  if the string argument occurs as a substring within this
     *          object, then the index of the first character of the first
     *          such substring is returned; if it does not occur as a
     *          substring, <code>-1</code> is returned.
     */

    public int indexOf(String str) {
   return indexOf(str, 0);
    }
    /**
     * Returns the index within this string of the first occurrence of the
     * specified substring. The integer returned is the smallest value
     * <i>k</i> such that:
     * <blockquote><pre>
     * this.startsWith(str, <i>k</i>)
     * </pre></blockquote>
     * is <code>true</code>.
     *
     * Params:   str =  any String.
     * Return:  if the string argument occurs as a substring within this
     *          object, then the index of the first character of the first
     *          such substring is returned; if it does not occur as a
     *          substring, <code>-1</code> is returned.
     */
    public int indexOf(wchar[] str) {
   return indexOf(str, 0);
    }

    /**
     * Returns the index within this string of the first occurrence of the
     * specified substring, starting at the specified index.  The integer
     * returned is the smallest value <tt>k</tt> for which:
     * <blockquote><pre>
     *     k &gt;= Math.min(fromIndex, this.length()) && 
this.startsWith(str, k)
     * </pre></blockquote>
     * If no such value of <i>k</i> exists, then -1 is returned.
     *
     * Param:   str    =     the substring for which to search.
     * Param:   fromIndex  = the index from which to start the search.
     * Return:  the index within this string of the first occurrence of the
     *          specified substring, starting at the specified index.
     */
    public int indexOf(String str, int fromIndex) {
        return indexOf(value, offset, count,
                       str.value, str.offset, str.count, fromIndex);
    }
     /**
     * Returns the index within this string of the first occurrence of the
     * specified substring, starting at the specified index.  The integer
     * returned is the smallest value <tt>k</tt> for which:
     * <blockquote><pre>
     *     k &gt;= Math.min(fromIndex, this.length()) && 
this.startsWith(str, k)
     * </pre></blockquote>
     * If no such value of <i>k</i> exists, then -1 is returned.
     *
     * Param:   str    =     the substring for which to search.
     * Param:   fromIndex  = the index from which to start the search.
     * Return:  the index within this string of the first occurrence of the
     *          specified substring, starting at the specified index.
     */
    public int indexOf(wchar[] wstr, int fromIndex) {
       String str=new String(wstr);
        return indexOf(value, offset, count,
                       str.value, str.offset, str.count, fromIndex);
    }

    /**
     * Code shared by String and StringBuffer to do searches. The
     * source is the character array being searched, and the target
     * is the string being searched for.
     *
     * Params:   source =      the characters being searched.
     * Params:   sourceOffset= offset of the source string.
     * Params:   sourceCount=  count of the source string.
     * Params:   target   =    the characters being searched for.
     * Params:   targetOffset =offset of the target string.
     * Params:   targetCount = count of the target string.
     * Params:   fromIndex  =  the index to begin searching from.
     * Return:  the index within this string of the first occurrence of the
     *          specified substring, starting at the specified index.
     */
    static int indexOf(wchar[] source, int sourceOffset, int sourceCount,
                       wchar[] target, int targetOffset, int targetCount,
                       int fromIndex) {
   if (fromIndex >= sourceCount) {
              return (targetCount == 0 ? sourceCount : -1);
   }
       if (fromIndex < 0) {
           fromIndex = 0;
       }
   if (targetCount == 0) {
       return fromIndex;
   }

          wchar first  = target[targetOffset];
          int max = sourceOffset + (sourceCount - targetCount);

          for (int i = sourceOffset + fromIndex; i <= max; i++) {
              /* Look for first character. */
              if (source[i] != first) {
                i++;
                  while (i <= max && source[i] != first){
                   i++;
                  }
              }

              /* Found first character, now look at the rest of v2 */
              if (i <= max) {
                  int j = i + 1;
                  int end = j + targetCount - 1;
                  for (int k = targetOffset + 1; j < end && (source[j] == 
target[k]);j++){
                    k++;
                  }

                  if (j == end) {
                      /* Found whole string. */
                      return i - sourceOffset;
                  }
              }
          }
          return -1;
      }
 /**
 * Return:The String's value
 */
 char[] toString(){
  return cast(char[])std.utf.toUTF8(this.value);
 }
}
/++++++++++++++++++++++++
  + Our function.
  + Example:
  + --------------------------
  +  import std.stdio;
  +
  +  void foo()
  +  {
  +      String str=new String("Hi,jdk2d String,I need you!") ;
  +      writefln(str);  /* print the string */
  +      str="Next,I calculate the str's length"
  +      writefln(str);  /* print the string */
  +      printf("%d\n",str.length());
  +  }
  + --------------------------
  +/
public static void  main() {
   String str = new String("The quick brown fox jumped over the lazy dog.");
   String s1 = new String("abc");
   s1="abc";
   String s2=new String("ab");

   writef("s1=");
   writefln(s1);
   writef("s2=");
   writefln(s2);

   if(s1>s2)
    printf("s1>s2=%.*s\n","true");
   else
    printf("s1>s2=%.*s\n","false");
   String s3=new String("ab");
   String s4=new String("abc");

   writef("s3=");
   writefln(s3);
   writef("s4=");
   writefln(s4);
   if(s3>s4)
    printf("s3>s4=%.*s\n","true");
   else
    printf("s3>s4=%.*s\n","false");

   printf("%d\n",str.indexOf("z"));
   printf("%d\n",str.isEmpty());

 }
-----------------------------------------------------------------------------------
String.ddoc
B = <b>$0</b>
I = <i>$0</i>
U = <u>$0</u>
P = <p>$0</p>
DL = <dl>$0</dl>
DT = <dt>$0</dt>
DD = <dd>$0</dd>
TABLE = <table>$0</table>
TR = <tr>$0</tr>
TH = <th>$0</th>
TD = <td>$0</td>
OL = <ol>$0</ol>
UL = <ul>$0</ul>
LI = <li>$0</li>
BIG = <big>$0</big>
SMALL = <small>$0</small>
BR = <br>
LINK = <a href="$0">$0</a>
LINK2 = <a href="$1">$+</a>

RED = <font color=red>$0</font>
BLUE = <font color=blue>$0</font>
GREEN = <font color=green>$0</font>
YELLOW =<font color=yellow>$0</font>
BLACK = <font color=black>$0</font>
WHITE = <font color=white>$0</font>

D_CODE = <pre class="d_code">$0</pre>
D_COMMENT = $(GREEN $0)
D_STRING  = $(RED $0)
D_KEYWORD = $(BLUE $0)
D_PSYMBOL = $(U $0)
D_PARAM   = $(I $0)

DDOC = <html><head>
 <META http-equiv="content-type" content="text/html; charset=utf-8">
 <title>$(TITLE)</title>
 </head><body>
 <h1>$(TITLE)</h1>
 $(BODY)
 </body></html>

DDOC_COMMENT   = <!-- $0 -->
DDOC_DECL      = $(DT $(BIG $0))
DDOC_DECL_DD   = $(DD $0)
DDOC_DITTO     = $(BR)$0
DDOC_SECTIONS  = $0
DDOC_SUMMARY   = $0$(BR)$(BR)
DDOC_DESCRIPTION = $0$(BR)$(BR)
DDOC_AUTHORS   = $(B Authors:)$(BR)
  $0$(BR)$(BR)
DDOC_BUGS      = $(RED BUGS:)$(BR)
  $0$(BR)$(BR)
DDOC_COPYRIGHT = $(B Copyright:)$(BR)
  $0$(BR)$(BR)
DDOC_DATE      = $(B Date:)$(BR)
  $0$(BR)$(BR)
DDOC_DEPRECATED = $(RED Deprecated:)$(BR)
  $0$(BR)$(BR)
DDOC_EXAMPLES  = $(B Examples:)$(BR)
  $0$(BR)$(BR)
DDOC_HISTORY   = $(B History:)$(BR)
  $0$(BR)$(BR)
DDOC_LICENSE   = $(B License:)$(BR)
  $0$(BR)$(BR)
DDOC_RETURNS   = $(B Returns:)$(BR)
  $0$(BR)$(BR)
DDOC_SEE_ALSO  = $(B See Also:)$(BR)
  $0$(BR)$(BR)
DDOC_STANDARDS = $(B Standards:)$(BR)
  $0$(BR)$(BR)
DDOC_THROWS    = $(B Throws:)$(BR)
  $0$(BR)$(BR)
DDOC_VERSION   = $(B Version:)$(BR)
  $0$(BR)$(BR)
DDOC_SECTION_H = $(B $0)$(BR)$(BR)
DDOC_SECTION   = $0$(BR)$(BR)
DDOC_MEMBERS   = $(DL $0)
DDOC_MODULE_MEMBERS   = $(DDOC_MEMBERS $0)
DDOC_CLASS_MEMBERS    = $(DDOC_MEMBERS $0)
DDOC_STRUCT_MEMBERS   = $(DDOC_MEMBERS $0)
DDOC_ENUM_MEMBERS     = $(DDOC_MEMBERS $0)
DDOC_TEMPLATE_MEMBERS = $(DDOC_MEMBERS $0)
DDOC_PARAMS    = $(B Params:)$(BR)\n$(TABLE $0)$(BR)
DDOC_PARAM_ROW = $(TR $0)
DDOC_PARAM_ID  = $(TD $0)
DDOC_PARAM_DESC  = $(TD $0)
DDOC_BLANKLINE = $(BR)$(BR)

DDOC_PSYMBOL = $(U $0)
DDOC_KEYWORD = $(B $0)
DDOC_PARAM = $(I $0)
------------------------------------------------------------------------------------

dmd  -D String.d String.ddoc 
Apr 05 2007
parent "jinheking" <caoqi bgi.net.cn> writes:
Document HTML
http://www.caoqi.com/d
DÓïÑÔÊÇÓÉDigital Mars¹«Ë¾¿ª·¢µÄ±à³ÌÓïÑÔ£¬ÆðÒòÊÇΪÁ˸ĽøC£«£«¡£ËüÓëC¶þ½øÖƼæÈÝ£¨²»ÍêÈ«£©£¬¿É±à
Apr 05 2007