001/*
002 * This file is part of OCaml-Java runtime.
003 * Copyright (C) 2007-2013 Xavier Clerc.
004 *
005 * OCaml-Java runtime is free software; you can redistribute it and/or modify
006 * it under the terms of the GNU Lesser General Public License as published by
007 * the Free Software Foundation; either version 3 of the License, or
008 * (at your option) any later version.
009 *
010 * OCaml-Java runtime is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013 * GNU Lesser General Public License for more details.
014 *
015 * You should have received a copy of the GNU Lesser General Public License
016 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
017 */
018
019package org.ocamljava.runtime.wrappers;
020
021import org.ocamljava.runtime.values.Value;
022
023/**
024 * The {@code OCamlString} class is the wrapper class for OCaml values of
025 * type {@code string}.
026 *
027 * @author <a href="mailto:xclerc@ocamljava.org">Xavier Clerc</a>
028 * @version 2.0
029 * @since 2.0
030 */
031public final class OCamlString extends OCamlValue implements CharSequence {
032
033    /** Wrapper for {@code OCamlString} values. */
034    public static final Wrapper<OCamlString> WRAPPER = new SimpleWrapper<OCamlString>() {
035
036        /**
037         * {@inheritDoc}
038         */
039        @Override
040        public OCamlString wrap(final Value v) {
041            return new OCamlString(v);
042        } // end method 'wrap(Value)'
043
044    }; // end anonymous inner-class
045
046    /**
047     * Constructs a new instance wrapping the passed value.
048     * @param v value to wrap - should not be {@code null}
049     */
050    private OCamlString(final Value v) {
051        super(v);
052    } // end constructor(Value)
053
054    /**
055     * {@inheritDoc}
056     */
057    @Override
058    public Wrapper<? extends OCamlString> getWrapper() {
059        return OCamlString.WRAPPER;
060    } // end method 'getWrapper()'
061
062    /**
063     * {@inheritDoc}
064     */
065    @Override
066    public Wrapper<? extends OCamlValue> getWrapper(final int idx) {
067        return OCamlUnit.WRAPPER;
068    } // end method 'getWrapper(int)'
069
070    /**
071     * Returns the wrapped value as a {@code String}.
072     * @return the wrapped value, converted to a {@code String}
073     */
074    public String stringValue() {
075        return this.value.asString();
076    } // end method 'stringValue()'
077
078    /**
079     * Returns the {@code byte} value at the specified index.
080     * @param idx index of {@code byte} value
081     * @return the {@code byte} value at the specified index
082     */
083    public byte byteAt(final int idx) {
084        return this.value.getByte(idx);
085    } // end method 'byteAt(int)'
086
087    /**
088     * {@inheritDoc}
089     */
090    @Override
091    public char charAt(final int idx) {
092        return (char) this.value.getUnsignedByte(idx);
093    } // end method 'charAt(int)'
094
095    /**
096     * Changes the {@code byte} value at the specified index.
097     * @param idx index of {@code byte} value to modify
098     * @param b new value
099     */
100    public void setByteAt(final int idx, final byte b) {
101        this.value.setByte(idx, b);
102    } // end method 'setByteAt(int, byte)'
103
104    /**
105     * Changes the {@code char} value at the specified index.
106     * @param idx index of {@code char} value to modify
107     * @param c new value
108     */
109    public void setCharAt(final int idx, final char c) {
110        this.value.setUnsignedByte(idx, c);
111    } // end method 'setCharAt(int)'
112
113    /**
114     * {@inheritDoc}
115     */
116    @Override
117    public int length() {
118        return (int) this.value.sizeBytes();
119    } // end method 'length()'
120
121    /**
122     * {@inheritDoc}
123     */
124    @Override
125    public CharSequence subSequence(final int start, final int end) {
126        return this.value.asString().subSequence(start, end);
127    } // end method 'subSequence(int, int)'
128
129    /**
130     * {@inheritDoc}
131     */
132    @Override
133    public int hashCode() {
134        return this.value.asString().hashCode(); // XXX Value.hashBytes() ?
135    } // end method 'hashCode()'
136
137    /**
138     * {@inheritDoc}
139     */
140    @Override
141    public boolean equals(final Object obj) {
142        if (obj instanceof OCamlString) {
143            final OCamlString that = (OCamlString) obj;
144            return this.value.asString().equals(that.value.asString()); // XXX Value.equalStrings(-) ?
145        } else {
146            return false;
147        } // end if/else
148    } // end method 'equals(Object)'
149
150    /**
151     * {@inheritDoc}
152     */
153    @Override
154    public String toString() {
155        final StringBuilder sb = new StringBuilder();
156        sb.append("OCamlString(");
157        sb.append(this.value.asString());
158        sb.append(")");
159        return sb.toString();
160    } // end method 'toString()'
161
162    /**
163     * Constructs a new {@code string} value, and wraps it.
164     * @param v value to wrap
165     * @return a new {@code OCamlString} instance wrapping the passed value
166     */
167    public static OCamlString create(final String v) {
168        return new OCamlString(Value.createString(v));
169    } // end method 'create(String)'
170
171    /**
172     * Wraps the passed value.
173     * @param v value to wrap - should not be {@code null}
174     * @return a new {@code OCamlString} instance wrapping the passed value
175     */
176    public static OCamlString wrap(final Value v) {
177        assert v != null : "null v";
178        return new OCamlString(v);
179    } // end method 'wrap(Value)'
180
181    /**
182     * Returns a wrapper for {@code OCamlString} values.
183     * @return a wrapper for {@code OCamlString} values
184     */
185    public static Wrapper<? extends OCamlString> wrapper() {
186        return OCamlString.WRAPPER;
187    } // end method 'wrapper()'
188
189} // end class 'OCamlString'