LCOV - code coverage report
Current view: directory - js/src/vm - Xdr.h (source / functions) Found Hit Coverage
Test: app.info Lines: 125 86 68.8 %
Date: 2012-04-07 Functions: 40 30 75.0 %

       1                 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2                 :  * vim: set ts=8 sw=4 et tw=78:
       3                 :  *
       4                 :  * ***** BEGIN LICENSE BLOCK *****
       5                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       6                 :  *
       7                 :  * The contents of this file are subject to the Mozilla Public License Version
       8                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       9                 :  * the License. You may obtain a copy of the License at
      10                 :  * http://www.mozilla.org/MPL/
      11                 :  *
      12                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      13                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      14                 :  * for the specific language governing rights and limitations under the
      15                 :  * License.
      16                 :  *
      17                 :  * The Original Code is SpiderMonkey string object code.
      18                 :  *
      19                 :  * The Initial Developer of the Original Code is
      20                 :  * the Mozilla Foundation.
      21                 :  * Portions created by the Initial Developer are Copyright (C) 2011
      22                 :  * the Initial Developer. All Rights Reserved.
      23                 :  *
      24                 :  * Contributor(s):
      25                 :  *
      26                 :  * Alternatively, the contents of this file may be used under the terms of
      27                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      28                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      30                 :  * of those above. If you wish to allow use of your version of this file only
      31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      32                 :  * use your version of this file under the terms of the MPL, indicate your
      33                 :  * decision by deleting the provisions above and replace them with the notice
      34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      35                 :  * the provisions above, a recipient may use your version of this file under
      36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      37                 :  *
      38                 :  * ***** END LICENSE BLOCK ***** */
      39                 : 
      40                 : #ifndef Xdr_h___
      41                 : #define Xdr_h___
      42                 : 
      43                 : #include "jsapi.h"
      44                 : #include "jsprvtd.h"
      45                 : #include "jsnum.h"
      46                 : 
      47                 : namespace js {
      48                 : 
      49                 : /*
      50                 :  * Bytecode version number. Increment the subtrahend whenever JS bytecode
      51                 :  * changes incompatibly.
      52                 :  *
      53                 :  * This version number is XDR'd near the front of xdr bytecode and
      54                 :  * aborts deserialization if there is a mismatch between the current
      55                 :  * and saved versions. If deserialization fails, the data should be
      56                 :  * invalidated if possible.
      57                 :  */
      58                 : static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 113);
      59                 : 
      60                 : class XDRBuffer {
      61                 :   public:
      62            4780 :     XDRBuffer(JSContext *cx)
      63            4780 :       : context(cx), base(NULL), cursor(NULL), limit(NULL) { }
      64                 : 
      65           25523 :     JSContext *cx() const {
      66           25523 :         return context;
      67                 :     }
      68                 : 
      69            2390 :     void *getData(uint32_t *lengthp) const {
      70                 :         JS_ASSERT(size_t(cursor - base) <= size_t(UINT32_MAX));
      71            2390 :         *lengthp = uint32_t(cursor - base);
      72            2390 :         return base;
      73                 :     }
      74                 : 
      75            2411 :     void setData(const void *data, uint32_t length) {
      76            2411 :         base = static_cast<uint8_t *>(const_cast<void *>(data));
      77            2411 :         cursor = base;
      78            2411 :         limit = base + length;
      79            2411 :     }
      80                 : 
      81           71531 :     const uint8_t *read(size_t n) {
      82           71531 :         JS_ASSERT(n <= size_t(limit - cursor));
      83           71531 :         uint8_t *ptr = cursor;
      84           71531 :         cursor += n;
      85           71531 :         return ptr;
      86                 :     }
      87                 : 
      88            2496 :     const char *readCString() {
      89            2496 :         char *ptr = reinterpret_cast<char *>(cursor);
      90            2496 :         cursor = reinterpret_cast<uint8_t *>(strchr(ptr, '\0')) + 1;
      91            2496 :         JS_ASSERT(base < cursor);
      92            2496 :         JS_ASSERT(cursor <= limit);
      93            2496 :         return ptr;
      94                 :     }
      95                 : 
      96           74027 :     uint8_t *write(size_t n) {
      97           74027 :         if (n > size_t(limit - cursor)) {
      98            2390 :             if (!grow(n))
      99               0 :                 return NULL;
     100                 :         }
     101           74027 :         uint8_t *ptr = cursor;
     102           74027 :         cursor += n;
     103           74027 :         return ptr;
     104                 :     }
     105                 : 
     106            2390 :     static bool isUint32Overflow(size_t n) {
     107            2390 :         return size_t(-1) > size_t(UINT32_MAX) && n > size_t(UINT32_MAX);
     108                 :     }
     109                 : 
     110                 :     void freeBuffer();
     111                 : 
     112                 :   private:
     113                 :     bool grow(size_t n);
     114                 : 
     115                 :     JSContext   *const context;
     116                 :     uint8_t     *base;
     117                 :     uint8_t     *cursor;
     118                 :     uint8_t     *limit;
     119                 : };
     120                 : 
     121                 : /* We use little-endian byteorder for all encoded data */
     122                 : 
     123                 : #if defined IS_LITTLE_ENDIAN
     124                 : 
     125                 : inline uint32_t
     126          117336 : NormalizeByteOrder32(uint32_t x)
     127                 : {
     128          117336 :     return x;
     129                 : }
     130                 : 
     131                 : inline uint16_t
     132               0 : NormalizeByteOrder16(uint16_t x)
     133                 : {
     134               0 :     return x;
     135                 : }
     136                 : 
     137                 : #elif defined IS_BIG_ENDIAN
     138                 : 
     139                 : inline uint32_t
     140                 : NormalizeByteOrder32(uint32_t x)
     141                 : {
     142                 :     return (x >> 24) | ((x >> 8) & 0xff00) | ((x << 8) & 0xff0000) | (x << 24);
     143                 : }
     144                 : 
     145                 : inline uint16_t
     146                 : NormalizeByteOrder16(uint16_t x)
     147                 : {
     148                 :     return (x >> 8) | (x << 8);
     149                 : }
     150                 : 
     151                 : #else
     152                 : #error "unknown byte order"
     153                 : #endif
     154                 : 
     155                 : template <XDRMode mode>
     156                 : class XDRState {
     157                 :   public:
     158                 :     XDRBuffer buf;
     159                 : 
     160                 :   protected:
     161                 :     JSPrincipals *principals;
     162                 :     JSPrincipals *originPrincipals;
     163                 : 
     164            4780 :     XDRState(JSContext *cx)
     165            4780 :       : buf(cx), principals(NULL), originPrincipals(NULL) {
     166            4780 :     }
     167                 : 
     168                 :   public:
     169           25523 :     JSContext *cx() const {
     170           25523 :         return buf.cx();
     171                 :     }
     172                 : 
     173               0 :     bool codeUint8(uint8_t *n) {
     174                 :         if (mode == XDR_ENCODE) {
     175               0 :             uint8_t *ptr = buf.write(sizeof *n);
     176               0 :             if (!ptr)
     177               0 :                 return false;
     178               0 :             *ptr = *n;
     179                 :         } else {
     180               0 :             *n = *buf.read(sizeof *n);
     181                 :         }
     182               0 :         return true;
     183                 :     }
     184                 : 
     185               0 :     bool codeUint16(uint16_t *n) {
     186                 :         uint16_t tmp;
     187                 :         if (mode == XDR_ENCODE) {
     188               0 :             uint8_t *ptr = buf.write(sizeof tmp);
     189               0 :             if (!ptr)
     190               0 :                 return false;
     191               0 :             tmp = NormalizeByteOrder16(*n);
     192               0 :             memcpy(ptr, &tmp, sizeof tmp);
     193                 :         } else {
     194               0 :             memcpy(&tmp, buf.read(sizeof tmp), sizeof tmp);
     195               0 :             *n = NormalizeByteOrder16(tmp);
     196                 :         }
     197               0 :         return true;
     198                 :     }
     199                 : 
     200          117336 :     bool codeUint32(uint32_t *n) {
     201                 :         uint32_t tmp;
     202                 :         if (mode == XDR_ENCODE) {
     203           58668 :             uint8_t *ptr = buf.write(sizeof tmp);
     204           58668 :             if (!ptr)
     205               0 :                 return false;
     206           58668 :             tmp = NormalizeByteOrder32(*n);
     207           58668 :             memcpy(ptr, &tmp, sizeof tmp);
     208                 :         } else {
     209           58668 :             memcpy(&tmp, buf.read(sizeof tmp), sizeof tmp);
     210           58668 :             *n = NormalizeByteOrder32(tmp);
     211                 :         }
     212          117336 :         return true;
     213                 :     }
     214                 : 
     215               0 :     bool codeDouble(double *dp) {
     216                 :         jsdpun tmp;
     217                 :         if (mode == XDR_ENCODE) {
     218               0 :             uint8_t *ptr = buf.write(sizeof tmp);
     219               0 :             if (!ptr)
     220               0 :                 return false;
     221               0 :             tmp.d = *dp;
     222               0 :             tmp.s.lo = NormalizeByteOrder32(tmp.s.lo);
     223               0 :             tmp.s.hi = NormalizeByteOrder32(tmp.s.hi);
     224               0 :             memcpy(ptr, &tmp.s.lo, sizeof tmp.s.lo);
     225               0 :             memcpy(ptr + sizeof tmp.s.lo, &tmp.s.hi, sizeof tmp.s.hi);
     226                 :         } else {
     227               0 :             const uint8_t *ptr = buf.read(sizeof tmp);
     228               0 :             memcpy(&tmp.s.lo, ptr, sizeof tmp.s.lo);
     229               0 :             memcpy(&tmp.s.hi, ptr + sizeof tmp.s.lo, sizeof tmp.s.hi);
     230               0 :             tmp.s.lo = NormalizeByteOrder32(tmp.s.lo);
     231               0 :             tmp.s.hi = NormalizeByteOrder32(tmp.s.hi);
     232               0 :             *dp = tmp.d;
     233                 :         }
     234               0 :         return true;
     235                 :     }
     236                 : 
     237            9984 :     bool codeBytes(void *bytes, size_t len) {
     238                 :         if (mode == XDR_ENCODE) {
     239            4992 :             uint8_t *ptr = buf.write(len);
     240            4992 :             if (!ptr)
     241               0 :                 return false;
     242            4992 :             memcpy(ptr, bytes, len);
     243                 :         } else {
     244            4992 :             memcpy(bytes, buf.read(len), len);
     245                 :         }
     246            9984 :         return true;
     247                 :     }
     248                 : 
     249                 :     /*
     250                 :      * During encoding the string is written into the buffer together with its
     251                 :      * terminating '\0'. During decoding the method returns a pointer into the
     252                 :      * decoding buffer and the caller must copy the string if it will outlive
     253                 :      * the decoding buffer.
     254                 :      */
     255            4992 :     bool codeCString(const char **sp) {
     256                 :         if (mode == XDR_ENCODE) {
     257            2496 :             size_t n = strlen(*sp) + 1;
     258            2496 :             uint8_t *ptr = buf.write(n);
     259            2496 :             if (!ptr)
     260               0 :                 return false;
     261            2496 :             memcpy(ptr, *sp, n);
     262                 :         } else {
     263            2496 :             *sp = buf.readCString();
     264                 :         }
     265            4992 :         return true;
     266                 :     }
     267                 : 
     268            7871 :     bool codeChars(jschar *chars, size_t nchars);
     269            7871 :     bool codeString(JSString **strp);
     270                 : 
     271              12 :     bool codeFunction(JSObject **objp);
     272              30 :     bool codeScript(JSScript **scriptp);
     273                 : 
     274            2496 :     void initScriptPrincipals(JSScript *script) {
     275               0 :         JS_ASSERT(mode == XDR_DECODE);
     276                 :         
     277                 :         /* The origin principals must be normalized at this point. */
     278            2496 :         JS_ASSERT_IF(principals, originPrincipals);
     279            2496 :         JS_ASSERT(!script->principals);
     280            2496 :         JS_ASSERT(!script->originPrincipals);
     281            2496 :         if (principals) {
     282              17 :             script->principals = principals;
     283              17 :             JS_HoldPrincipals(principals);
     284                 :         }
     285            2496 :         if (originPrincipals) {
     286              22 :             script->originPrincipals = originPrincipals;
     287              22 :             JS_HoldPrincipals(originPrincipals);
     288                 :         }
     289            2496 :     }
     290                 : };
     291                 : 
     292                 : class XDREncoder : public XDRState<XDR_ENCODE> {
     293                 :   public:
     294            2390 :     XDREncoder(JSContext *cx)
     295            2390 :       : XDRState<XDR_ENCODE>(cx) {
     296            2390 :     }
     297                 : 
     298            2390 :     ~XDREncoder() {
     299            2390 :         buf.freeBuffer();
     300            2390 :     }
     301                 : 
     302            2369 :     const void *getData(uint32_t *lengthp) const {
     303            2369 :         return buf.getData(lengthp);
     304                 :     }
     305                 : 
     306              21 :     void *forgetData(uint32_t *lengthp) {
     307              21 :         void *data = buf.getData(lengthp);
     308              21 :         buf.setData(NULL, 0);
     309              21 :         return data;
     310                 :     }
     311                 : };
     312                 : 
     313                 : class XDRDecoder : public XDRState<XDR_DECODE> {
     314                 :   public:
     315                 :     XDRDecoder(JSContext *cx, const void *data, uint32_t length,
     316                 :                JSPrincipals *principals, JSPrincipals *originPrincipals);
     317                 : 
     318                 : };
     319                 : 
     320                 : } /* namespace js */
     321                 : 
     322                 : #endif /* Xdr_h___ */

Generated by: LCOV version 1.7