root/core/PrintWriter.cpp

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. write
  2. writeHexNibble
  3. writeHexByte
  4. writeHexWord
  5. writeHexAddr
  6. formatTypeName
  7. formatP
  8. format
  9. formatV

/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (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.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is [Open Source Virtual Machine.].
 *
 * The Initial Developer of the Original Code is
 * Adobe System Incorporated.
 * Portions created by the Initial Developer are Copyright (C) 2004-2006
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *   Adobe AS3 Team
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */


#include "avmplus.h"
#if defined FEATURE_NANOJIT
#include "CodegenLIR.h"
#endif 

namespace avmplus
{
        int PrintWriter::write(const void *buffer, int count)
        {
                if (m_stream) {
                        int result = m_stream->write(buffer, count);

                        const char *ptr = (const char *) buffer;
                        while (--count >= 0) {
                                switch (*ptr) {
                                case '\n':
                                        col = 0;
                                        break;
                                case '\t':
                                        col = ((col>>3)+1)<<3;
                                        break;
                                default:
                                        col++;
                                        break;
                                }
                                ptr++;
                        }

                        return result;
                } else {
                        return 0;
                }                       
        }
        
        PrintWriter& PrintWriter::operator<< (tabstop tabs)
        {
                while (col <= tabs.getSpaces()) {
                        *this << ' ';
                }
                return *this;
        }

        PrintWriter& PrintWriter::operator<< (hexAddr value)
        {
                writeHexAddr(value.getValue());
                return *this;
        }
        
        PrintWriter& PrintWriter::operator<< (percent value)
        {
                if (value.getPercent() < 10) {
                        *this << ' ';
                }
                Stringp s = MathUtils::convertDoubleToString(m_core, value.getPercent());
                StringIndexer str(s);
                for (int32_t i = 0; i < s->length(); i++)
                {
                        wchar ch = str[i];
                        *this << ch;
                        if (ch == '.' && i < s->length() - 1) {
                                *this << str[++i];
                                break;
                        }
                }
                return *this;
        }
        
        PrintWriter& PrintWriter::operator<< (const char *str)
        {
                write(str, String::Length(str));
                return *this;
        }

        PrintWriter& PrintWriter::operator<< (bool b)
        {
                *this << (b ? "true" : "false");
                return *this;
        }

        PrintWriter& PrintWriter::operator<< (const wchar *str)
        {
                while (*str) {
                        *this << *str++;
                }
                return *this;
        }

        PrintWriter& PrintWriter::operator<< (char value)
        {
                write(&value, 1);
                return *this;
        }

        PrintWriter& PrintWriter::operator<< (wchar value)
        {
                // Encode the character as UTF-8
                if (value < 0x80) {
                        *this << (char)value;
                } else {
                        uint8 Octets[6];
                        int OctetsLen = UnicodeUtils::Ucs4ToUtf8((uint32)value, Octets);
                        write(Octets, OctetsLen);
                }
                return *this;
        }
        
        PrintWriter& PrintWriter::operator<< (int32_t value)
        {
                Stringp s = MathUtils::convertIntegerToStringBase10(m_core, value, MathUtils::kTreatAsSigned);
                return *this << s;
        }

        PrintWriter& PrintWriter::operator<< (uint64_t value)
        {
                // use the intptr_t version - it is 64, not 32 bits
                Stringp s = MathUtils::convertIntegerToStringRadix(m_core, (intptr_t) value, 10, MathUtils::kTreatAsUnsigned);
                return *this << s;
        }

        PrintWriter& PrintWriter::operator<< (int64_t value)
        {
                // use the intptr_t version - it is 64, not 32 bits
                Stringp s = MathUtils::convertIntegerToStringRadix(m_core, (intptr_t) value, 10, MathUtils::kTreatAsSigned);
                return *this << s;
        }

#if defined AVMPLUS_MAC && defined AVMPLUS_64BIT
        PrintWriter& PrintWriter::operator<< (ptrdiff_t value)
        {
                // use the sintptr version - it is 64, not 32 bits
                Stringp s = MathUtils::convertIntegerToStringRadix(m_core, (intptr_t) value, 10, MathUtils::kTreatAsSigned);
                return *this << s;
        }
#endif

        PrintWriter& PrintWriter::operator<< (uint32_t value)
        {
                Stringp s = MathUtils::convertIntegerToStringBase10(m_core, value, MathUtils::kTreatAsUnsigned);
                return *this << s;
        }

        PrintWriter& PrintWriter::operator<< (double value)
        {
                return *this << MathUtils::convertDoubleToString(m_core, value);
        }

        PrintWriter& PrintWriter::operator<< (Stringp str)
        {
                if (!str)
                        return *this << "(null)";
                
                StringIndexer str_idx(str);
                for (int i=0, n=str_idx->length(); i<n; i++) 
                {
                        *this << (wchar)str_idx[i];
                }
                return *this;
        }

        PrintWriter& PrintWriter::operator<< (ScriptObject *obj)
        {
#ifdef AVMPLUS_VERBOSE
                if (obj) {
                        return *this << obj->format(m_core);
                } else {
                        return *this << "null";
                }
#else
                (void)obj;
                AvmAssert(0); // this is only supported in AVMPLUS_VERBOSE builds
                return *this;
#endif
        }
        PrintWriter& PrintWriter::operator<< (const Traits *obj)
        {
#ifdef AVMPLUS_VERBOSE
                if (obj) {
                        return *this << obj->format(m_core);
                } else {
                        return *this << "*";
                }
#else
                (void)obj;
                AvmAssert(0); // this is only supported in AVMPLUS_VERBOSE builds
                return *this;
#endif
        }
        PrintWriter& PrintWriter::operator<< (const MethodInfo *obj)
        {
#ifdef AVMPLUS_VERBOSE
                if (obj) {
                        return *this << obj->format(m_core);
                } else {
                        return *this << "null";
                }
#else
                (void)obj;
                AvmAssert(0); // this is only supported in AVMPLUS_VERBOSE builds
                return *this;
#endif
        }

        PrintWriter& PrintWriter::operator<< (const Multiname& obj)
        {
                // Made available in non-AVMPLUS_VERBOSE builds for describeType
//#ifdef AVMPLUS_VERBOSE
#if 1
                return *this << obj.format(m_core);
#else
                AvmAssert(0); // this is only supported in AVMPLUS_VERBOSE builds
                return *this;
#endif
        }

        PrintWriter& PrintWriter::operator<< (Namespacep ns)
        {
                // Made available in non-AVMPLUS_VERBOSE builds for describeType
//#ifdef AVMPLUS_VERBOSE
#if 1
                if (ns)
                        return *this << ns->format(m_core);
                else
                        return *this << "null";
#else
                AvmAssert(0); // this is only supported in AVMPLUS_VERBOSE builds
                return *this;
#endif
        }       

#if VMCFG_METHOD_NAMES
        PrintWriter& PrintWriter::operator<< (const ScopeTypeChain* s)
        {
                if (s)
                        return *this << s->format(m_core);
                else
                        return *this << "null";
        }       

        PrintWriter& PrintWriter::operator<< (const ScopeChain* s)
        {
                if (s)
                        return *this << s->format(m_core);
                else
                        return *this << "null";
        }       
#endif

        void PrintWriter::writeHexNibble(uint8 value)
        {
                if (value < 10) {
                        *this << (char)(value+'0');
                } else {
                        *this << (char)(value+'A'-10);
                }
        }
        
        void PrintWriter::writeHexByte(uint8 value)
        {
                writeHexNibble(value>>4);
                writeHexNibble(value&0x0f);
        }

        void PrintWriter::writeHexWord(uint16 value)
        {
                writeHexByte((uint8)(value>>8));
                writeHexByte((uint8)(value&0xff));
        }

        void PrintWriter::writeHexAddr(uintptr value)
        {
#ifdef AVMPLUS_64BIT
                writeHexByte(uint8((value>>56) & 0xff));
                writeHexByte(uint8((value>>48) & 0xff));
                writeHexByte(uint8((value>>40) & 0xff));
                writeHexByte(uint8((value>>32) & 0xff));
#endif
                writeHexByte(uint8((value>>24) & 0xff));
                writeHexByte(uint8((value>>16) & 0xff));
                writeHexByte(uint8(value>>8));
                writeHexByte(uint8(value&0xff));
        }
        
        void PrintWriter::formatTypeName(Traits* t)
        {
                if (!t)
                {
                        *this << "*";
                        return;
                }

                if (t->base == m_core->traits.class_itraits)
                {
                        t = t->itraits;
                        *this << "class ";
                }
                
                Namespacep ns = t->ns();
                if (ns != NULL && !ns->isPublic())
                        *this << ns << ".";
                
                Stringp n = t->name();
                if (n)
                        *this << n;
                else
                        *this << "(null)";
        }

#ifdef AVMPLUS_VERBOSE
        void PrintWriter::formatP(const char* format, Stringp arg1, Stringp arg2, Stringp arg3)
        {
                while (*format) 
                {
                        if (*format == '%') 
                        {
                                switch (*++format) 
                                {
                                        case '1':
                                                AvmAssertMsg(arg1!=0, "Expected argument got null");
                                                if (arg1) *this << arg1;
                                                break;

                                        case '2':
                                                AvmAssertMsg(arg2!=0, "Expected argument got null");
                                                if (arg2) *this << arg2;
                                                break;

                                        case '3':
                                                AvmAssertMsg(arg3!=0, "Expected argument got null");
                                                if (arg3) *this << arg3;
                                                break;

                                        default:
                                                AvmAssertMsg(0, "Invalid specifier; should be between '1' and '3'");
                                                break;
                                }
                        }
                        else
                        {
                                *this << *format;
                        }
                        format++;
                }
        }

        void PrintWriter::format(const char *format, ...)
        {
                va_list ap;
                va_start(ap, format);
                formatV(format, ap);
                va_end(ap);
        }

        void PrintWriter::formatV(const char *format, va_list ap)
        {
                while (*format) {
                        if (*format == '%') {
                                switch (*++format) {
                                case 's':
                                        *this << va_arg(ap, char*);
                                        break;
                                case 'w':
                                        *this << va_arg(ap, wchar*);
                                        break;
                                case 'a':
                                        *this << m_core->format(va_arg(ap, Atom));
                                        break;
                                case 'o':
                                        *this << va_arg(ap, ScriptObject*);
                                        break;
                                case 't': 
                                        formatTypeName(va_arg(ap, Traits*));
                                        break;
                                case 'm':
                                        *this << va_arg(ap, MethodInfo*);
                                        break;
                                case 'n':
                                        *this << va_arg(ap, Multiname*)->format(m_core, Multiname::MULTI_FORMAT_NAME_ONLY);
                                        break;
                                case 'N':
                                        *this << va_arg(ap, Multiname*)->format(m_core, Multiname::MULTI_FORMAT_NS_ONLY);
                                        break;
                                case 'S':
                                        *this << va_arg(ap, Stringp);
                                        break;
                                case '2':
                                        {
                                                // A 2-digit integer.
                                                int value = va_arg(ap, int);
                                                *this << (char) ((value/10) + '0');
                                                *this << (char) ((value%10) + '0');
                                        }
                                        break;
                                case '3':
                                        {
                                                // A 3-char month, used by Date.
                                                char *str = va_arg(ap, char *);
                                                *this << str[0] << str[1] << str[2];
                                        }
                                        break;
                                case 'c':
                                        {
                                                // gcc complains if you put va_arg(ap, char)
                                                char value = (char)(va_arg(ap, int));
                                                *this << value;
                                        }
                                        break;
                                case 'f':
                                        *this << va_arg(ap, double);
                                        break;
                                case 'd':
                                        *this << va_arg(ap, int);
                                        break;
                                case 'D':
                                        *this << va_arg(ap, int64);
                                        break;
                                }
                        } else {
                                *this << *format;
                        }
                        format++;
                }
                va_end(ap);
        }
#endif /* VERBOSE */
}       

/* [<][>][^][v][top][bottom][index][help] */