aboutsummaryrefslogtreecommitdiff
path: root/src/util/serialize.cpp
Commit message (Collapse)AuthorAge
* Move files to subdirectories (#6599)Vitaliy2017-11-08
| | | | * Move files around
* serialize: use a temporary for SerializeExceptionLoïc Blot2017-08-21
| | | | Exception must always use temporary instead of global copied exception instances, it's not recommended and should have undefined issues
* Code modernization: subfolders (#6283)Loïc Blot2017-08-19
| | | | | | | | | | | | | * Code modernization: subfolders Modernize various code on subfolders client, network, script, threading, unittests, util * empty function * default constructor/destructor * for range-based loops * use emplace_back instead of push_back * C++ STL header style * Make connection.cpp readable in a pointed place + typo
* C++11 cleanup on constructors (#6000)Vincent Glize2017-06-19
| | | | * C++11 cleanup on constructors dir script
* Add ItemStack key-value meta storagerubenwardy2017-02-04
|
* Fix misc. MinGW and Valgrind warningskwolekr2015-11-08
|
* Add BufReader and vector-based serialization methodskwolekr2015-10-15
|
* Clean up util/serialization.{cpp,h} and add unit testskwolekr2015-08-01
|
* Increase limit of serialized long stringskwolekr2015-07-14
|
* Add more robust error checking to deSerialize*String routineskwolekr2015-07-13
| | | | | Add serializeHexString() Clean up util/serialize.cpp
* For usages of assert() that are meant to persist in Release builds (when ↵Craig Robbins2015-03-07
| | | | NDEBUG is defined), replace those usages with persistent alternatives
* serialize.h: use machine native byte swapping if available, fall-back to ↵Rafael Reilova2014-11-21
| | | | | | | | | | | | | | | | | | | | | previous generic method if not (supported for GCC using endian.h, detection done in cmake) write/readARGB8() - just write 32-bit color in one op, instead of 4 1-byte ops cleanup: removed unneeded buffer init for some serialize-out functions use a #define for the fixed point factor in read/writeF1000() nodemetadata.cpp, nodetimer.cpp optimzation: simpler deserialize node position method staticobject.cpp: cleanup: use util/serialize.h inlines instead of its own de/serialization serialize.cpp: minor optimization/cleanup: avoid generation of unneeded string temporary CMakeLists.txt, cmake_config.h.in: detection of endian.h config.h: added HAVE_ENDIAN_H Commits due to feedback squashed Signed-off-by: Craig Robbins <kde.psych@gmail.com>
* Fix serializing of signed numbers in serializeStructToStringShadowNinja2014-03-21
|
* Make serializeStructToString use an ostringstreamShadowNinja2014-03-15
|
* Revert "Use fixed-width format specifiers in serializeStructToString"ShadowNinja2014-03-14
| | | | | This reverts commit 875f1327a47f78d783c3abc7f7acc3977dc286ec. Fixed width format specifiers are only officially availale in C99 and C++11.
* Use fixed-width format specifiers in serializeStructToStringShadowNinja2014-03-13
|
* Replace usage of long long with u64/s64ShadowNinja2014-03-12
|
* Add minetest.set_noiseparam_defaults() Lua APIkwolekr2014-02-15
|
* Omnicleanup: header cleanup, add ModApiUtil shared between game and mainmenuKahrl2013-08-14
|
* Update Copyright YearsSfan52013-02-24
|
* Change Minetest-c55 to MinetestPilzAdam2013-02-24
|
* Initially split utility.h to multiple files in util/Perttu Ahola2012-06-17
a id='n395' href='#n395'>395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456
package net.minetest.minetest;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.Vector;
import java.util.Iterator;
import java.lang.Object;

import android.app.Activity;
import android.content.res.AssetFileDescriptor;

import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Display;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.graphics.Rect;
import android.graphics.Paint;
import android.text.TextPaint;

public class MinetestAssetCopy extends Activity
{
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		
		setContentView(R.layout.assetcopy);
		
		m_ProgressBar = (ProgressBar) findViewById(R.id.progressBar1);
		m_Filename = (TextView) findViewById(R.id.textView1);
		
		Display display = getWindowManager().getDefaultDisplay();
		m_ProgressBar.getLayoutParams().width = (int) (display.getWidth() * 0.8);
		m_ProgressBar.invalidate();
		
		/* check if there's already a copy in progress and reuse in case it is*/
		MinetestAssetCopy prevActivity = 
				(MinetestAssetCopy) getLastNonConfigurationInstance();
		if(prevActivity!= null) {
			m_AssetCopy = prevActivity.m_AssetCopy;
		}
		else {
			m_AssetCopy = new copyAssetTask();
			m_AssetCopy.execute();
		}
	}
	
	/* preserve asset copy background task to prevent restart of copying */
	/* this way of doing it is not recommended for latest android version */
	/* but the recommended way isn't available on android 2.x */
	public Object onRetainNonConfigurationInstance()
	{
		return this;
	}
	
	ProgressBar m_ProgressBar;
	TextView m_Filename;
	
	copyAssetTask m_AssetCopy;
	
	private class copyAssetTask extends AsyncTask<String, Integer, String>
	{
		private long getFullSize(String filename)
		{
			long size = 0;
			try {
				InputStream src = getAssets().open(filename);
				byte[] buf = new byte[4096];
				
				int len = 0;
				while ((len = src.read(buf)) > 0)
				{
					size += len;
				}
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
			return size;
		}

		@Override
		protected String doInBackground(String... files)
		{
			m_foldernames  = new Vector<String>();
			m_filenames    = new Vector<String>();
			m_tocopy       = new Vector<String>();
			m_asset_size_unknown = new Vector<String>();
			String baseDir = 
					Environment.getExternalStorageDirectory().getAbsolutePath()
					+ "/";
			
			
			// prepare temp folder
			File TempFolder = new File(baseDir + "Minetest/tmp/");
			
			if (!TempFolder.exists())
			{
				TempFolder.mkdir();
			}
			else {
				File[] todel = TempFolder.listFiles();
				
				for(int i=0; i < todel.length; i++)
				{
					Log.v("MinetestAssetCopy","deleting: " + todel[i].getAbsolutePath());
					todel[i].delete();
				}
			}
			
			// add a .nomedia file
			try {
				OutputStream dst = new FileOutputStream(baseDir + "Minetest/.nomedia");
				dst.close();
			} catch (IOException e) {
				Log.e("MinetestAssetCopy","Failed to create .nomedia file");
				e.printStackTrace();
			}
			
			
			// build lists from prepared data
			BuildFolderList();
			BuildFileList();
			
			// scan filelist
			ProcessFileList();
			
			// doing work
			m_copy_started = true;
			m_ProgressBar.setMax(m_tocopy.size());
			
			for (int i = 0; i < m_tocopy.size(); i++)
			{
				try
				{
					String filename = m_tocopy.get(i);
					publishProgress(i);
					
					boolean asset_size_unknown = false;
					long filesize = -1;
					
					if (m_asset_size_unknown.contains(filename))
					{
						File testme = new File(baseDir + "/" + filename);
						
						if(testme.exists())
						{
							filesize = testme.length();
						}
						asset_size_unknown = true;
					}
					
					InputStream src;
					try
					{
						src = getAssets().open(filename);
					} catch (IOException e) {
						Log.e("MinetestAssetCopy","Copying file: " + filename + " FAILED (not in assets)");
						e.printStackTrace();
						continue;
					}
					
					// Transfer bytes from in to out
					byte[] buf = new byte[1*1024];
					int len = src.read(buf, 0, 1024);
					
					/* following handling is crazy but we need to deal with    */
					/* compressed assets.Flash chips limited livetime due to   */
					/* write operations, we can't allow large files to destroy */
					/* users flash.                                            */
					if (asset_size_unknown)
					{
						if ( (len > 0) && (len < buf.length) && (len == filesize))
						{
							src.close();
							continue;
						}
						
						if (len == buf.length)
						{
							src.close();
							long size = getFullSize(filename);
							if ( size == filesize)
							{
								continue;
							}
							src = getAssets().open(filename);
							len = src.read(buf, 0, 1024);
						}
					}
					if (len > 0)
					{
						int total_filesize = 0;
						OutputStream dst;
						try
						{
							dst = new FileOutputStream(baseDir + "/" + filename);
						} catch (IOException e) {
							Log.e("MinetestAssetCopy","Copying file: " + baseDir +
							"/" + filename + " FAILED (couldn't open output file)");
							e.printStackTrace();
							src.close();
							continue;
						}
						dst.write(buf, 0, len);
						total_filesize += len;
						
						while ((len = src.read(buf)) > 0)
						{
							dst.write(buf, 0, len);
							total_filesize += len;
						}
						
						dst.close();
						Log.v("MinetestAssetCopy","Copied file: " +
									m_tocopy.get(i) + " (" + total_filesize +
									" bytes)");
					}
					else if (len < 0)
					{
						Log.e("MinetestAssetCopy","Copying file: " +
								m_tocopy.get(i) + " failed, size < 0");
					}
					src.close();
				} 
				catch (IOException e)
				{
					Log.e("MinetestAssetCopy","Copying file: " +
							m_tocopy.get(i) + " failed");
					e.printStackTrace();
				}
			}
			return "";
		}
		
		
		/**
		 * update progress bar
		 */
		protected void onProgressUpdate(Integer... progress)
		{
			
			if (m_copy_started)
			{
				boolean shortened = false;
				String todisplay = m_tocopy.get(progress[0]);
				m_ProgressBar.setProgress(progress[0]);
				
				// make sure our text doesn't exceed our layout width
				Rect bounds = new Rect();
				Paint textPaint = m_Filename.getPaint();
				textPaint.getTextBounds(todisplay, 0, todisplay.length(), bounds);
				
				while (bounds.width() > getResources().getDisplayMetrics().widthPixels * 0.7) {
					if (todisplay.length() < 2) {
						break;
					}
					todisplay = todisplay.substring(1);
					textPaint.getTextBounds(todisplay, 0, todisplay.length(), bounds);
					shortened = true;
				}
				
				if (! shortened) {
					m_Filename.setText(todisplay);
				}
				else {
					m_Filename.setText(".." + todisplay);
				}
			}
			else
			{
				boolean shortened = false;
				String todisplay = m_Foldername;
				String full_text = "scanning " + todisplay + " ...";
				// make sure our text doesn't exceed our layout width
				Rect bounds = new Rect();
				Paint textPaint = m_Filename.getPaint();
				textPaint.getTextBounds(full_text, 0, full_text.length(), bounds);
				
				while (bounds.width() > getResources().getDisplayMetrics().widthPixels * 0.7) {
					if (todisplay.length() < 2) {
						break;
					}
					todisplay = todisplay.substring(1);
					full_text = "scanning " + todisplay + " ...";
					textPaint.getTextBounds(full_text, 0, full_text.length(), bounds);
					shortened = true;
				}
				
				if (! shortened) {
					m_Filename.setText(full_text);
				}
				else {
					m_Filename.setText("scanning .." + todisplay + " ...");
				}
			}
		}
		
		/**
		 * check al files and folders in filelist
		 */
		protected void ProcessFileList()
		{
			String FlashBaseDir = 
					Environment.getExternalStorageDirectory().getAbsolutePath();
			
			Iterator itr = m_filenames.iterator();
			
			while (itr.hasNext())
			{
				String current_path = (String) itr.next();
				String FlashPath = FlashBaseDir + "/" + current_path;
				
				if (isAssetFolder(current_path))
				{
					/* store information and update gui */
					m_Foldername = current_path;
					publishProgress(0);
					
					/* open file in order to check if it's a folder */
					File current_folder = new File(FlashPath);
					if (!current_folder.exists())
					 {
						if (!current_folder.mkdirs())
						{
							Log.e("MinetestAssetCopy","\t failed create folder: " +
									FlashPath);
						}
						else
						{
							Log.v("MinetestAssetCopy","\t created folder: " +
									FlashPath);
						}
					}
					
					continue;
				}
				
				/* if it's not a folder it's most likely a file */
				boolean refresh = true;
				
				File testme = new File(FlashPath);
				
				long asset_filesize = -1;
				long stored_filesize = -1;
				
				if (testme.exists())
				{
					try
					{
						AssetFileDescriptor fd = getAssets().openFd(current_path);
						asset_filesize         = fd.getLength();
						fd.close();
					} 
					catch (IOException e)
					{
						refresh = true;
						m_asset_size_unknown.add(current_path);
						Log.e("MinetestAssetCopy","Failed to open asset file \"" +
								FlashPath + "\" for size check");
					}
					
					stored_filesize = testme.length();
					
					if (asset_filesize == stored_filesize)
					{
						refresh = false;
					}
					
				}
				
				if (refresh)
				{
					m_tocopy.add(current_path);
				}
			}
		}
		
		/**
		 * read list of folders prepared on package build
		 */
		protected void BuildFolderList()
		{
			try
			{
				InputStream is = getAssets().open("index.txt");
				BufferedReader reader = new BufferedReader(new InputStreamReader(is));
		
				String line = reader.readLine();
				while (line != null)
				{
					m_foldernames.add(line);
					line = reader.readLine();
				}
				is.close();
			} catch (IOException e1)
			{
				Log.e("MinetestAssetCopy","Error on processing index.txt");
				e1.printStackTrace();
			}
		}
		
		/**
		 * read list of asset files prepared on package build
		 */
		protected void BuildFileList()
		{
			long entrycount = 0;
			try
			{
				InputStream is = getAssets().open("filelist.txt");
				BufferedReader reader = new BufferedReader(new InputStreamReader(is));
		
				String line = reader.readLine();
				while (line != null)
				{
					m_filenames.add(line);
					line = reader.readLine();
					entrycount ++;
				}
				is.close();
			}
			catch (IOException e1)
			{
				Log.e("MinetestAssetCopy","Error on processing filelist.txt");
				e1.printStackTrace();
			}
		}
		
		protected void onPostExecute (String result)
		{
			finish();
		}
		
		protected boolean isAssetFolder(String path)
		{
			return m_foldernames.contains(path);
		}
		
		boolean m_copy_started = false;
		String m_Foldername = "media";
		Vector<String> m_foldernames;
		Vector<String> m_filenames;
		Vector<String> m_tocopy;
		Vector<String> m_asset_size_unknown;
	}
}