FileDocCategorySizeDatePackage
SmsSplitter.javaAPI DocAndroid 1.5 API3781Wed May 06 22:42:46 BST 2009com.android.im.imps

SmsSplitter.java

/*
 * Copyright (C) 2008 Esmertec AG.
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.im.imps;

import java.nio.ByteBuffer;

/**
 * A helper class to split the payload into several segments to meet the size
 * constraint of the sms.
 *
 */
public class SmsSplitter {
    private static final int MAX_SEGMENT_COUNT = 26;

    private ByteBuffer mOutBuffer;
    private int mMaxSegmentLen;

    private byte[] mData;
    private int mPreambleEnd;

    private int mCurrentSegment;
    private int mSegmentCount;

    public SmsSplitter(int maxLen) {
        mMaxSegmentLen = maxLen;
        mOutBuffer = ByteBuffer.allocate(maxLen);
    }

    /**
     * Split the data into several segments to meet the size constraint.
     *
     * @param data
     *            The data to split. MUST be a valid PTS primitive.
     * @return The count of segments of the result or -1 if the data is too long.
     */
    public int split(byte[] data) {
        mData = data;
        mCurrentSegment = 0;
        calculateSegments();
        if (mSegmentCount > MAX_SEGMENT_COUNT) {
            mSegmentCount = -1;
        }
        return mSegmentCount;
    }

    public boolean hasNext() {
        return mCurrentSegment < mSegmentCount;
    }

    /**
     * Gets the next segment.
     *
     * @return The next segment.
     * @throws IndexOutOfBoundsException
     */
    public byte[] getNext() {
        if (mCurrentSegment >= mSegmentCount) {
            throw new IndexOutOfBoundsException();
        }
        byte[] segment;
        if (mSegmentCount == 1) {
            segment = mData;
        } else {
            mOutBuffer.clear();
            // The original preamble
            mOutBuffer.put(mData, 0, mPreambleEnd);
            // Two character of DD
            mOutBuffer.put((byte) ('a' + mCurrentSegment));
            mOutBuffer.put((byte) ('a' + mSegmentCount - 1));
            // The space after preamble
            mOutBuffer.put((byte) ' ');

            // The payload
            int segmentPayload = mMaxSegmentLen - mPreambleEnd - 3;
            int offset = mPreambleEnd + 1 + segmentPayload * mCurrentSegment;
            int len = (offset + segmentPayload > mData.length) ?
                    mData.length - offset : segmentPayload;
            mOutBuffer.put(mData, offset, len);

            mOutBuffer.flip();
            segment = new byte[mOutBuffer.limit()];
            mOutBuffer.get(segment);
        }
        mCurrentSegment++;
        return segment;
    }

    private void calculateSegments() {
        int totalLen = mData.length;
        if (totalLen < mMaxSegmentLen) {
            mSegmentCount = 1;
        } else {
            searchPreambleEnd();
            int newPreambleLen = mPreambleEnd + 2;
            int segmentPayload = mMaxSegmentLen - newPreambleLen - 1;
            int totalPayload = totalLen - mPreambleEnd - 1;
            mSegmentCount = (totalPayload + segmentPayload -1) / segmentPayload;
        }
    }

    private void searchPreambleEnd() {
        byte[] data = mData;
        int index = 0;
        while(index < data.length && data[index] != ' ') {
            index++;
        }
        mPreambleEnd = index;
    }
}