Ejemplo n.º 1
0
void CLockBox9::on_add_node_child(StateDataNode* parent, StateDataNode* child) {
    if(child->get_id().name == NAME_LOCKBOX) {
        /** @todo Perhaps it's necessary to copy volume DATA to lock DATA, depending on the flags.
            Without this, if application only modifies a region of lock DATA
            the contents of the surface DATA corresponding to a non modified regions
            of lock DATA are overwritten with zeroes.
        */

        // Calculate size of DATA node and resize it
        D3DFORMAT format;
        child->get_parent()->get_child(StateId(NAME_FORMAT))->read_data(&format);
        UINT left, right, top, bottom, front, back;
        child->get_child(StateId(NAME_LEFT))->read_data(&left);
        child->get_child(StateId(NAME_RIGHT))->read_data(&right);
        child->get_child(StateId(NAME_TOP))->read_data(&top);
        child->get_child(StateId(NAME_BOTTOM))->read_data(&bottom);
        child->get_child(StateId(NAME_TOP))->read_data(&front);
        child->get_child(StateId(NAME_BOTTOM))->read_data(&back);
        UINT width = right - left;
        UINT height = bottom - top;
        UINT depth = back - front;
        // Change units for compressed formats
        /// @note Depth is not affected
        if(is_compressed(format)) {
            width = width / 4 + (((width % 4) == 0) ? 0 : 1);
            height = height / 4 + (((height % 4) == 0) ? 0 : 1);
        }
        UINT size = depth * width * height * texel_size(format);
        child->get_child(StateId(NAME_DATA))->set_data_size(size);
        D3D_DEBUG( cout << "CLOCKBOX9: Resizing SLOCKBOX DATA to " << (int)size << endl; )
Ejemplo n.º 2
0
int grpc_byte_buffer_reader_init(grpc_byte_buffer_reader *reader,
                                 grpc_byte_buffer *buffer) {
  grpc_slice_buffer decompressed_slices_buffer;
  reader->buffer_in = buffer;
  switch (reader->buffer_in->type) {
    case GRPC_BB_RAW:
      grpc_slice_buffer_init(&decompressed_slices_buffer);
      if (is_compressed(reader->buffer_in)) {
        if (grpc_msg_decompress(reader->buffer_in->data.raw.compression,
                                &reader->buffer_in->data.raw.slice_buffer,
                                &decompressed_slices_buffer) == 0) {
          gpr_log(GPR_ERROR,
                  "Unexpected error decompressing data for algorithm with enum "
                  "value '%d'.",
                  reader->buffer_in->data.raw.compression);
          memset(reader, 0, sizeof(*reader));
          return 0;
        } else { /* all fine */
          reader->buffer_out =
              grpc_raw_byte_buffer_create(decompressed_slices_buffer.slices,
                                          decompressed_slices_buffer.count);
        }
        grpc_slice_buffer_destroy(&decompressed_slices_buffer);
      } else { /* not compressed, use the input buffer as output */
        reader->buffer_out = reader->buffer_in;
      }
      reader->current.index = 0;
      break;
  }
  return 1;
}
Ejemplo n.º 3
0
char *file_uncompress(char *filename)
{
    static char newfile[MAXFNAMELEN];
    char command[BUFSIZ], *ptr, *suffix = NULL;

    /* Filename to be returned */
    strcpy(newfile, filename);

    /* Uncompress depending on compression method */
    if(is_gzipped(filename)) {
        if(!env_inpath("gunzip"))
            return(NULL);
        sprintf(command, "gunzip -f %s", filename);
        if(!system(command))
            return(NULL);
        suffix = ".gz";
    }
    else if(is_compressed(filename)) {
        if(!env_inpath("uncompress"))
            return(NULL);
        sprintf(command, "uncompress -f %s", filename);
        if(!system(command))
            return(NULL);
        suffix = ".Z";
    }

    /* Strip of suffix if it was there */
    if(suffix != NULL) {
        if((ptr = strstr(newfile, suffix)) != NULL)
            *ptr = 0;
    }

    /* Return uncomprssed filename */
    return(newfile);
}
Ejemplo n.º 4
0
void grpc_byte_buffer_reader_destroy(grpc_byte_buffer_reader *reader) {
  switch (reader->buffer_in->type) {
    case GRPC_BB_RAW:
      /* keeping the same if-else structure as in the init function */
      if (is_compressed(reader->buffer_in)) {
        grpc_byte_buffer_destroy(reader->buffer_out);
      }
      break;
  }
}
Ejemplo n.º 5
0
void grpc_byte_buffer_reader_init(grpc_byte_buffer_reader *reader,
                                  grpc_byte_buffer *buffer) {
  gpr_slice_buffer decompressed_slices_buffer;
  reader->buffer_in = buffer;
  switch (reader->buffer_in->type) {
    case GRPC_BB_RAW:
      gpr_slice_buffer_init(&decompressed_slices_buffer);
      if (is_compressed(reader->buffer_in)) {
        grpc_msg_decompress(reader->buffer_in->data.raw.compression,
                            &reader->buffer_in->data.raw.slice_buffer,
                            &decompressed_slices_buffer);
        reader->buffer_out =
            grpc_raw_byte_buffer_create(decompressed_slices_buffer.slices,
                                        decompressed_slices_buffer.count);
        gpr_slice_buffer_destroy(&decompressed_slices_buffer);
      } else { /* not compressed, use the input buffer as output */
        reader->buffer_out = reader->buffer_in;
      }
      reader->current.index = 0;
      break;
  }
}
Ejemplo n.º 6
0
/**
 * @internal
 */
static void update_progress_counters(winx_file_info *f,udefrag_job_parameters *jp)
{
    ULONGLONG filesize;

    jp->pi.files ++;
    if(is_directory(f)) jp->pi.directories ++;
    if(is_compressed(f)) jp->pi.compressed ++;
    jp->pi.processed_clusters += f->disp.clusters;

    filesize = f->disp.clusters * jp->v_info.bytes_per_cluster;
    if(filesize >= GIANT_FILE_SIZE)
        jp->f_counters.giant_files ++;
    else if(filesize >= HUGE_FILE_SIZE)
        jp->f_counters.huge_files ++;
    else if(filesize >= BIG_FILE_SIZE)
        jp->f_counters.big_files ++;
    else if(filesize >= AVERAGE_FILE_SIZE)
        jp->f_counters.average_files ++;
    else if(filesize >= SMALL_FILE_SIZE)
        jp->f_counters.small_files ++;
    else
        jp->f_counters.tiny_files ++;
}
Ejemplo n.º 7
0
int main(int argc, char **argv)
{
	header_keys keys;
	u8 rawkheaderBk[0x90];

	if(argc < 2)
	{
		printf("USAGE: PrxEncrypter [prx]\n");
		return 0;
	}

	memset(in_buffer, 0, sizeof(in_buffer));
	memset(out_buffer, 0, sizeof(out_buffer));
	memset(kirk_raw, 0, sizeof(kirk_raw));
	memset(kirk_enc, 0, sizeof(kirk_enc));
	memset(elf, 0, sizeof(elf));

	kirk_init();

	int elfSize = load_elf(argv[1]);

	if(elfSize < 0) {
		printf("Cannot open %s\n", argv[1]);

		return 0;
	}

	Header_List *target_header = get_header_list( elfSize );

	if( target_header == NULL ) {
		printf("PRX SIGNER: Elf is to big\n");

		return 0;
	}

	u8 *kirkHeader	= target_header->kirkHeader;
	u8 *pspHeader	= target_header->pspHeader;
	int krawSize = get_kirk_size(kirkHeader);

	if (is_compressed(pspHeader)) {
		elfSize = get_elf_size(pspHeader);
		gzip_compress(elf, elf, elfSize);
	}

	memcpy(kirk_raw, kirkHeader, 0x110);
	memcpy(rawkheaderBk, kirk_raw, sizeof(rawkheaderBk));

	kirk_decrypt_keys((u8*)&keys, kirk_raw);
	memcpy(kirk_raw, &keys, sizeof(header_keys));
	memcpy(kirk_raw+0x110, elf, elfSize);

	if(kirk_CMD0(kirk_enc, kirk_raw, sizeof(kirk_enc), 0) != 0)
	{
		printf("PRX SIGNER: Could not encrypt elf\n");
		return 0;
	}

	memcpy(kirk_enc, rawkheaderBk, sizeof(rawkheaderBk));

	if(kirk_forge(kirk_enc, sizeof(kirk_enc)) != 0)
	{
		printf("PRX SIGNER: Could not forge cmac block\n");

		return 0;
	}

	memcpy(out_buffer, pspHeader, 0x150);
	memcpy(out_buffer+0x150, kirk_enc+0x110, krawSize-0x110);

	return dumpFile("./data.psp", out_buffer, (krawSize-0x110)+0x150);
}
Ejemplo n.º 8
0
bool mvt_tile::decode(std::string &message) {
	layers.clear();
	std::string src;

	if (is_compressed(message)) {
		std::string uncompressed;
		decompress(message, uncompressed);
		src = uncompressed;
	} else {
		src = message;
	}

	protozero::pbf_reader reader(src);

	while (reader.next()) {
		switch (reader.tag()) {
		case 3: /* layer */
		{
			protozero::pbf_reader layer_reader(reader.get_message());
			mvt_layer layer;

			while (layer_reader.next()) {
				switch (layer_reader.tag()) {
				case 1: /* name */
					layer.name = layer_reader.get_string();
					break;

				case 3: /* key */
					layer.keys.push_back(layer_reader.get_string());
					break;

				case 4: /* value */
				{
					protozero::pbf_reader value_reader(layer_reader.get_message());
					mvt_value value;

					while (value_reader.next()) {
						switch (value_reader.tag()) {
						case 1: /* string */
							value.type = mvt_string;
							value.string_value = value_reader.get_string();
							break;

						case 2: /* float */
							value.type = mvt_float;
							value.numeric_value.float_value = value_reader.get_float();
							break;

						case 3: /* double */
							value.type = mvt_double;
							value.numeric_value.double_value = value_reader.get_double();
							break;

						case 4: /* int */
							value.type = mvt_int;
							value.numeric_value.int_value = value_reader.get_int64();
							break;

						case 5: /* uint */
							value.type = mvt_uint;
							value.numeric_value.uint_value = value_reader.get_uint64();
							break;

						case 6: /* sint */
							value.type = mvt_sint;
							value.numeric_value.sint_value = value_reader.get_sint64();
							break;

						case 7: /* bool */
							value.type = mvt_bool;
							value.numeric_value.bool_value = value_reader.get_bool();
							break;

						default:
							value_reader.skip();
							break;
						}
					}

					layer.values.push_back(value);
					break;
				}

				case 5: /* extent */
					layer.extent = layer_reader.get_uint32();
					break;

				case 2: /* feature */
				{
					protozero::pbf_reader feature_reader(layer_reader.get_message());
					mvt_feature feature;
					std::vector<uint32_t> geoms;

					while (feature_reader.next()) {
						switch (feature_reader.tag()) {
						case 2: /* tag */
						{
							auto pi = feature_reader.get_packed_uint32();
							for (auto it = pi.first; it != pi.second; ++it) {
								feature.tags.push_back(*it);
							}
							break;
						}

						case 3: /* feature type */
							feature.type = feature_reader.get_enum();
							break;

						case 4: /* geometry */
						{
							auto pi = feature_reader.get_packed_uint32();
							for (auto it = pi.first; it != pi.second; ++it) {
								geoms.push_back(*it);
							}
							break;
						}

						default:
							feature_reader.skip();
							break;
						}
					}

					long long px = 0, py = 0;
					for (size_t g = 0; g < geoms.size(); g++) {
						uint32_t geom = geoms[g];
						uint32_t op = geom & 7;
						uint32_t count = geom >> 3;

						if (op == mvt_moveto || op == mvt_lineto) {
							for (size_t k = 0; k < count && g + 2 < geoms.size(); k++) {
								px += protozero::decode_zigzag32(geoms[g + 1]);
								py += protozero::decode_zigzag32(geoms[g + 2]);
								g += 2;

								feature.geometry.push_back(mvt_geometry(op, px, py));
							}
						} else {
							feature.geometry.push_back(mvt_geometry(op, 0, 0));
						}
					}

					layer.features.push_back(feature);
					break;
				}

				default:
					layer_reader.skip();
					break;
				}
			}

			for (size_t i = 0; i < layer.keys.size(); i++) {
				layer.key_map.insert(std::pair<std::string, size_t>(layer.keys[i], i));
			}
			for (size_t i = 0; i < layer.values.size(); i++) {
				layer.value_map.insert(std::pair<mvt_value, size_t>(layer.values[i], i));
			}

			layers.push_back(layer);
			break;
		}

		default:
			reader.skip();
			break;
		}
	}

	return true;
}
Ejemplo n.º 9
0
    bool ktx_texture::operator==(const ktx_texture &rhs) const
    {
        if (this == &rhs)
            return true;

// This is not super deep because I want to avoid poking around into internal state (such as the header)

#define CMP(x)      \
    if (x != rhs.x) \
        return false;
        CMP(get_ogl_internal_fmt());
        CMP(get_width());
        CMP(get_height());
        CMP(get_depth());
        CMP(get_num_mips());
        CMP(get_array_size());
        CMP(get_num_faces());
        CMP(is_compressed());
        CMP(get_block_dim());

        // The image fmt/type shouldn't matter with compressed textures.
        if (!is_compressed())
        {
            CMP(get_ogl_fmt());
            CMP(get_ogl_type());
        }

        CMP(get_total_images());

        CMP(get_opposite_endianness());

        // Do an order insensitive key/value comparison.
        dynamic_string_array lhs_keys;
        get_keys(lhs_keys);

        dynamic_string_array rhs_keys;
        rhs.get_keys(rhs_keys);

        if (lhs_keys.size() != rhs_keys.size())
            return false;

        lhs_keys.sort(dynamic_string_less_than_case_sensitive());
        rhs_keys.sort(dynamic_string_less_than_case_sensitive());

        for (uint32_t i = 0; i < lhs_keys.size(); i++)
            if (lhs_keys[i].compare(rhs_keys[i], true) != 0)
                return false;

        for (uint32_t i = 0; i < lhs_keys.size(); i++)
        {
            uint8_vec lhs_data, rhs_data;
            if (!get_key_value_data(lhs_keys[i].get_ptr(), lhs_data))
                return false;
            if (!get_key_value_data(lhs_keys[i].get_ptr(), rhs_data))
                return false;
            if (lhs_data != rhs_data)
                return false;
        }

        // Compare images.
        for (uint32_t l = 0; l < get_num_mips(); l++)
        {
            for (uint32_t a = 0; a < get_array_size(); a++)
            {
                for (uint32_t f = 0; f < get_num_faces(); f++)
                {
                    for (uint32_t z = 0; z < get_depth(); z++)
                    {
                        const uint8_vec &lhs_img = get_image_data(l, a, f, z);
                        const uint8_vec &rhs_img = rhs.get_image_data(l, a, f, z);

                        if (lhs_img != rhs_img)
                            return false;
                    }
                }
            }
        }
#undef CMP
        return true;
    }
Ejemplo n.º 10
0
int transform(const char *fpath, const struct stat *sb, int typeflag, struct FTW* ftwbuf)
{
	int compress_type;
	int fd_s, fd_t;
	struct stat stbuf_s;
	struct utimbuf utime_s;
	char *tmpname;
	off_t size;
	compressor_t *decomp;

	if (typeflag != FTW_F || !S_ISREG(sb->st_mode))
		return 0;

	/* internal file (attribute file, dedup DB) */
	if (strncmp(&fpath[ftwbuf->base], FUSECOMPRESS_PREFIX, sizeof(FUSECOMPRESS_PREFIX) - 1) == 0)
		return 0;

	if (verbose)
		fprintf(stderr, "%s: ", fpath);

	if (comp && !is_compressible(&fpath[ftwbuf->base])) {
		if (verbose)
			fprintf(stderr, "incompressible\n");
		return 0;
	}

	compress_type = is_compressed(fpath);
	if (compress_type < -1)
	{
		fprintf(stderr, "failed to check %s for compression status\n", fpath);
		errors++;
		return 0;
	}

	/* if this is the type we are supposed to recompress, decompress
	   it first */
	if (comp && recomp && compress_type == recomp->type) {
		compressor_t *temp_c = comp;
		int temp_v = verbose;
		comp = NULL;
		if (verbose)
			fprintf(stderr, "recompress ");
		verbose = 0;
		transform(fpath, sb, typeflag, ftwbuf);
		verbose = temp_v;
		comp = temp_c;
		compress_type = -1;
	}

	if (comp && compress_type >= 0)
	{
		if (verbose)
			fprintf(stderr, "compressed already\n");
		return 0;
	}
	if (!comp && compress_type < 0)
	{
		if (verbose)
			fprintf(stderr, "uncompressed already\n");
		return 0;
	}

	fd_s = file_open(fpath, O_RDONLY);
	if (fstat(fd_s, &stbuf_s) < 0)
	{
		perror("unable to fstat");
		return -1;
	}
	tmpname = file_create_temp(&fd_t);
	current_tmp_file = tmpname;

	if (!tmpname)
	{
		fprintf(stderr, "unable to create temporary file for compression\n");
		return -1;
	}

	if (comp)
	{
		if (lseek(fd_t, sizeof(header_t), SEEK_SET) < 0)
		{
			perror("failed to seek beyond header");
			goto out;
		}
		size = comp->compress(NULL, fd_s, fd_t);
		if (lseek(fd_t, 0, SEEK_SET) < 0)
		{
			perror("failed to seek to beginning");
			goto out;
		}
		if (file_write_header(fd_t, comp, stbuf_s.st_size) < 0)
		{
			perror("failed to write header");
			goto out;
		}
	}
	else
	{
		if (file_read_header_fd(fd_s, &decomp, &size) < 0)
		{
			perror("unable to read header");
			goto out;
		}
		size = decomp->decompress(fd_s, fd_t);
	}

	if (size == (off_t) - 1)
	{
		fprintf(stderr, "compression failed\n");
		goto out;
	}
	close(fd_s);
	close(fd_t);
	if (rename(tmpname, fpath) < 0)
	{
		perror("failed to rename tempfile");
		goto out;
	}

	current_tmp_file = NULL;

	if (lchown(fpath, stbuf_s.st_uid, stbuf_s.st_gid) < 0)
	{
		perror("unable to set owner/group");
		/* do not abort; the filesystem may not support this */
	}
	if (chmod(fpath, stbuf_s.st_mode) < 0)
	{
		perror("unable to set permissions");
		/* do not abort; the filesystem may not support this */
	}
	utime_s.actime = stbuf_s.st_atime;
	utime_s.modtime = stbuf_s.st_mtime;
	if (utime(fpath, &utime_s) < 0)
	{
		perror("failed to set timestamps");
		goto out;
	}

	if (verbose)
		fprintf(stderr, "ok\n");

	return 0;

out:
	close(fd_s);
	close(fd_t);
	unlink(tmpname);
	return -1;
}
Ejemplo n.º 11
0
 jushort start_pc(int index) {
   GUARANTEE(((index * 3) + 1) < length(),
             "local var table: start_pc index out of range");
   return is_compressed() ? ubyte_at((index * 3) + 1) :
                  ushort_at((index * 3) + 1);
 }
Ejemplo n.º 12
0
 jushort line_number(int index) {
   GUARANTEE(((index * 2) + 1) < length(),
             "line number table line_num index out of bounds");
   return is_compressed() ? ubyte_at((index * 2) + 1) :
                 short_at((index * 2) + 1);
 }
Ejemplo n.º 13
0
 jushort pc(int index) {
   GUARANTEE((index * 2) < length(),
             "line number table pc index out of bounds");
   return is_compressed() ? ubyte_at(index * 2) :
                  ushort_at(index * 2);
 }
Ejemplo n.º 14
0
 jushort slot(int index) {
   GUARANTEE((index * 3) < length(),
             "local var table: slot index out of range");
   return is_compressed() ? ubyte_at(index * 3) :
                  ushort_at(index * 3);
 }
Ejemplo n.º 15
0
//проверка является ли формат несжатым
bool is_uncompressed (PixelFormat format)
{
  return !is_compressed (format);
}
Ejemplo n.º 16
0
static int save_lua_report(udefrag_job_parameters *jp)
{
    wchar_t *path = NULL;
    WINX_FILE *f;
    wchar_t *cn;
    wchar_t compname[MAX_COMPUTERNAME_LENGTH + 1];
    char utf8_compname[(MAX_COMPUTERNAME_LENGTH + 1) * 4];
    char buffer[512];
    struct prb_traverser t;
    winx_file_info *file;
    char *comment;
    char *status;
    int length;
    winx_time tm;
    
    /* should be enough for any path in UTF-8 encoding */
    #define MAX_UTF8_PATH_LENGTH (256 * 1024)
    char *utf8_path;
    
    utf8_path = winx_tmalloc(MAX_UTF8_PATH_LENGTH);
    if(utf8_path == NULL){
        mtrace();
        return (-1);
    }
    
    path = get_report_path(jp);
    if(path == NULL)
        return UDEFRAG_NO_MEM;
    
    f = winx_fbopen(path,"w",RSB_SIZE);
    if(f == NULL){
        f = winx_fopen(path,"w");
        if(f == NULL){
            winx_free(path);
            winx_free(utf8_path);
            return (-1);
        }
    }

    /* print header */
    cn = winx_getenv(L"COMPUTERNAME");
    if(cn){
        wcsncpy(compname,cn,MAX_COMPUTERNAME_LENGTH + 1);
        compname[MAX_COMPUTERNAME_LENGTH] = 0;
        winx_free(cn);
    } else {
        wcscpy(compname,L"nil");
    }
    winx_to_utf8(utf8_compname,sizeof(utf8_compname),compname);
    memset(&tm,0,sizeof(winx_time));
    (void)winx_get_local_time(&tm);
    (void)_snprintf(buffer,sizeof(buffer),
        "-- UltraDefrag report for disk %c:\r\n\r\n"
        "format_version = 7\r\n\r\n"
        "volume_letter = \"%c\"\r\n"
        "computer_name = \"%hs\"\r\n\r\n"
        "current_time = {\r\n"
        "\tyear = %04i,\r\n"
        "\tmonth = %02i,\r\n"
        "\tday = %02i,\r\n"
        "\thour = %02i,\r\n"
        "\tmin = %02i,\r\n"
        "\tsec = %02i,\r\n"
        "\tisdst = false\r\n"
        "}\r\n\r\n"
        "files = {\r\n",
        jp->volume_letter, jp->volume_letter,utf8_compname,
        (int)tm.year,(int)tm.month,(int)tm.day,
        (int)tm.hour,(int)tm.minute,(int)tm.second
        );
    buffer[sizeof(buffer) - 1] = 0;
    (void)winx_fwrite(buffer,1,strlen(buffer),f);
    
    /* print body */
    prb_t_init(&t,jp->fragmented_files);
    file = prb_t_first(&t,jp->fragmented_files);
    while(file){
        if(is_directory(file))
            comment = "[DIR]";
        else if(is_compressed(file))
            comment = "[CMP]";
        else
            comment = " - ";
        
        /*
        * On change of status strings don't forget
        * also to adjust write_file_status routine
        * in udreportcnv.lua file.
        */
        if(is_locked(file))
            status = "locked";
        else if(is_moving_failed(file))
            status = "move failed";
        else if(is_in_improper_state(file))
            status = "invalid";
        else
            status = " - ";
        
        (void)_snprintf(buffer, sizeof(buffer),
            "\t{fragments = %u,"
            "size = %I64u,"
            "comment = \"%s\","
            "status = \"%s\","
            "path = \"",
            (UINT)file->disp.fragments,
            file->disp.clusters * jp->v_info.bytes_per_cluster,
            comment,
            status
            );
        buffer[sizeof(buffer) - 1] = 0;
        (void)winx_fwrite(buffer,1,strlen(buffer),f);

        if(file->path != NULL){
            /* skip \??\ sequence in the beginning of the path */
            length = (int)wcslen(file->path);
            if(length > 4){
                convert_to_utf8_path(utf8_path,MAX_UTF8_PATH_LENGTH,file->path + 4);
            } else {
                convert_to_utf8_path(utf8_path,MAX_UTF8_PATH_LENGTH,file->path);
            }
            (void)winx_fwrite(utf8_path,1,strlen(utf8_path),f);
        }

        (void)strcpy(buffer,"\"},\r\n");
        (void)winx_fwrite(buffer,1,strlen(buffer),f);

        file = prb_t_next(&t);
    }
    
    /* print footer */
    (void)strcpy(buffer,"}\r\n");
    (void)winx_fwrite(buffer,1,strlen(buffer),f);

    itrace("report saved to %ws",path);
    winx_fclose(f);
    winx_free(path);
    winx_free(utf8_path);
    return 0;
}
Ejemplo n.º 17
0
 jushort code_length(int index) {
   GUARANTEE(((index * 3) + 2) < length(),
             "local var table: code_length index out of range");
   return is_compressed() ? ubyte_at((index * 3) + 2) :
                  ushort_at((index * 3) + 2);
 }