001    /*
002     * This file is part of muCommander, http://www.mucommander.com
003     * Copyright (C) 2002-2008 Maxence Bernard
004     *
005     * muCommander is free software; you can redistribute it and/or modify
006     * it under the terms of the GNU 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     * muCommander 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 General Public License for more details.
014     *
015     * You should have received a copy of the GNU General Public License
016     * along with this program.  If not, see <http://www.gnu.org/licenses/>.
017     */
018    
019    
020    package com.mucommander.io;
021    
022    
023    /**
024     * Contains a number of bytes which have been read/written from/to a {@link CounterInputStream}/{@link CounterOutputStream}.
025     *
026     * <p>Provided methods allow to read the the byte count, add a number bytes to it or reset it (make it zero).
027     *
028     * <p>This class is thread safe, ensuring that the counter is always in a consistent state.</p>
029     *
030     * @see com.mucommander.io.CounterInputStream
031     * @see com.mucommander.io.CounterOutputStream
032     * @author Maxence Bernard
033     */
034    public class ByteCounter {
035    
036        /** Byte count */
037        private long count;
038    
039        /** Byte counter to add to the value returned by {@link #getByteCount()} */
040        private ByteCounter addedCounter;
041    
042        
043        /**
044         * Creates a new ByteCounter with an initial byte count equal to zero.
045         */
046        public ByteCounter() {
047        }
048    
049        /**
050         * Creates a new ByteCounter with an initial byte count equal to zero and using the given ByteCounter.
051         *
052         * <p>The value returned by {@link #getByteCount()} will be the sum of the internal byte count and the one from
053         * the specified ByteCounter, as returned by its {@link #getByteCount()} method. Resetting this ByteCounter's value
054         * will only affect the internal byte count and not the one from the specified ByteCounter.
055         */
056        public ByteCounter(ByteCounter counter) {
057            this.addedCounter = counter;
058        }
059    
060    
061        /**
062         * Return the number of bytes which have been accounted for.
063         */
064        public synchronized long getByteCount() {
065            if(addedCounter!=null)
066                return count + addedCounter.getByteCount();
067    
068            return this.count;
069        }
070    
071    
072        /**
073         * Increases the byte counter by the provided number of bytes. If the specified number is negative,
074         * the byte counter will be left unchanged (won't be decreased).
075         *
076         * @param nbBytes number of bytes to add to the byte counter, will be ignored if negative
077         */
078        public synchronized void add(long nbBytes) {
079            if(nbBytes>0)
080                this.count += nbBytes;
081        }
082    
083    
084        /**
085         * Increases the byte counter by the number of bytes contained in the specified counter (as returned by its
086         * {@link #getByteCount()} method) and resets its byte counter after (if specified).
087         *
088         * @param counter the Bytecounter to add to this one, and reset after (if specified).
089         * @param resetAfter if true, the specified counter will be reset after its byte count has been added to this ByteCounter
090         */
091        public synchronized void add(ByteCounter counter, boolean resetAfter) {
092            // Hold a lock on the provided counter to make sure that it is not modified or accessed
093            // while this operation is carried out
094            synchronized(counter) {
095                add(counter.getByteCount());
096                if(resetAfter)
097                    counter.reset();
098            }
099        }
100    
101    
102        /**
103         * Resets the byte counter (make it zero).
104         */
105        public synchronized void reset() {
106            this.count = 0;
107        }
108    }