genericopenlibs/cstdlib/USTLIB/GETENV.CPP
changeset 0 e4d67989cc36
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/genericopenlibs/cstdlib/USTLIB/GETENV.CPP	Tue Feb 02 02:01:42 2010 +0200
@@ -0,0 +1,251 @@
+// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Abstraction for "an environment" holding pairs of C strings (name, value)
+// 
+//
+
+#include "ENVIRON.H"
+#include "LPOSIX.H"
+#include <string.h>
+
+TPtrC16 TEnvVar::ValuePtr(const wchar_t* aValue)
+//
+// Turn a zero-terminated string into a descriptor which contains the terminator
+//
+	{
+	TText16* value = (TText16*)aValue;
+	return TPtrC16(value, User::StringLength(value)+1);
+	}
+
+void TEnvVar::ConstructL(const TDesC16& aName, const wchar_t* aValue)
+	{
+	TPtrC16 valueZ = ValuePtr(aValue);
+	HBufC16* valueCopy = valueZ.AllocLC();
+	iName = aName.AllocL();
+	iValue = valueCopy;
+	CleanupStack::Pop();
+	}
+
+void TEnvVar::Release()
+	{
+	delete iName;
+	iName=0;
+	delete iValue;
+	iValue=0;
+	}
+
+TInt TEnvVar::SetValue(const wchar_t* aValue)
+//
+// Change the value - if this returns an error then the original value is still intact
+//
+	{
+	TPtrC16 valueZ = ValuePtr(aValue);
+	HBufC16* valueCopy=valueZ.Alloc();
+	if (valueCopy==0)
+		return KErrNoMemory;
+	delete iValue;
+	iValue = valueCopy;
+	return KErrNone;
+	}
+
+
+HBufC16* TEnvVar::Match(const TDesC16& aName)
+//
+// return value if the name matches
+//
+	{
+	if (iName!=0 && iName->Compare(aName)==0)
+		return iValue;
+	return 0;
+	}
+
+TUint TEnvVar::Length() const
+//
+// How much space do we need to externalize this pair?
+// The format is name followed by '\0' followed by value followed by '\0'
+//
+	{
+	if (iName==0) 
+		return 0;
+	return iName->Length()+iValue->Length()+2;
+	}
+
+TInt TEnvVar::Externalize(const wchar_t* aPair, TDes16& aBuffer)
+//
+// static function to externalize a "name=value" definition
+//
+	{
+	const wchar_t* cp=aPair;
+	for (cp=aPair; *cp; ++cp)
+		{
+		if (*cp==L'=')
+			break;
+		}
+	if (*cp!=L'=')
+		return 0;	// malformed
+
+	TPtrC16 name((TText16*)aPair,cp-aPair);
+	TPtrC16 value((TText16*)(cp+1));
+	aBuffer.Append(name);
+	aBuffer.Append(TChar(0));
+	aBuffer.Append(value);
+	aBuffer.Append(TChar(0));
+	return 1;
+	}
+
+TInt TEnvVar::Externalize(TDes16& aBuffer)
+	{
+	if (iName==0) 
+		return 0;
+	aBuffer.Append(*iName);
+	aBuffer.Append(TChar(0));
+	aBuffer.Append(*iValue);
+	aBuffer.Append(TChar(0));
+	return 1;
+	}
+
+void TEnvVar::ConstructL(const TText16*& aPtr)
+	{
+	TPtrC16 name(aPtr);
+	aPtr+=name.Length()+1;
+	ConstructL(name,(const wchar_t*)aPtr);
+	aPtr+=iValue->Length()+1;
+	}
+
+CEnvironment::~CEnvironment()
+	{
+	while (iCount>0)
+		{
+		--iCount;
+		iVars[iCount].Release();
+		}
+	User::Free(iVars);
+	}
+
+
+void CEnvironment::ConstructL(TUint aCount, TDes16& aBuffer)
+//
+// Set up the environment from a descriptor. If this leaves then
+// the CEnvironment destructor will be able to clean up properly.
+//
+	{
+	// always allocate at least one slot - makes life easier elsewhere
+	TInt bytes = (aCount+1)*sizeof(TEnvVar);
+	iVars=(TEnvVar*) User::AllocL(bytes);
+	Mem::FillZ(iVars,bytes);
+	iCount=aCount+1;
+
+	const TText16* data=aBuffer.Ptr();
+	for (TUint i=0; i<aCount; ++i)
+		iVars[i].ConstructL(data);
+	}
+
+HBufC16* CEnvironment::ExternalizeLC(TUint& aCount, wchar_t** envp)
+	{
+	if (envp==0)
+		return ExternalizeLC(aCount);	// get current environment
+	// Externalize supplied environment
+	TInt length=0;
+	wchar_t** ep=envp;
+	for (ep=envp; *ep; ++ep)
+		length+=wcslen(*ep)+1;
+	HBufC16* retBuf = HBufC16::NewLC(length);
+	TInt nvars=0;
+	TPtr16 hbuf16=retBuf->Des();
+	for (ep=envp; *ep; ++ep)
+		nvars+=TEnvVar::Externalize(*ep, hbuf16);
+	aCount=nvars;
+	return retBuf;
+	}
+
+HBufC16* CEnvironment::ExternalizeLC(TUint& aCount)
+	{
+	TInt length=0;
+	TUint i=0;
+	for (i=0; i<iCount; ++i)
+		length+=iVars[i].Length();
+	HBufC16* retBuf = HBufC16::NewLC(length);
+	TInt nvars=0;
+	TPtr16 hbuf16=retBuf->Des();
+	for (i=0; i<iCount; i++)
+		nvars+=iVars[i].Externalize(hbuf16);
+	aCount=nvars;
+	return retBuf;
+	}
+
+// The interface used to support the STDLIB routines
+
+wchar_t * CEnvironment::getenv(const wchar_t* aName) const
+	{
+	TPtrC16 name((TText16*)aName);
+	for (TUint i=0; i<iCount; ++i)
+		{
+		HBufC16* value=iVars[i].Match(name);
+		if (value)
+			{
+			const wchar_t* vptr = (const wchar_t*)(value->Ptr());
+			return CONST_CAST(wchar_t*,vptr);	// I hope nobody modifies this data...
+			}
+		}
+	return 0;
+	}
+
+int CEnvironment::setenv(const wchar_t* aName, const wchar_t* aValue, int aReplace, int& anErrno)
+	{
+	TPtrC16 name((TText16*)aName);
+	TUint freeSlot=iCount;
+	TEnvVar* ep=iVars;
+	for (TUint i=0; i<iCount; ++i,++ep)
+		{
+		if (ep->NotEmpty())
+			{
+			const TDesC16* existing=ep->Match(name);
+			if (existing)
+				{
+				TInt err=KErrNone;
+				if (aReplace)
+					ep->SetValue(aValue);
+				return MapError(err,anErrno);
+				}
+			}
+		else
+			freeSlot=i;
+		}
+	if (freeSlot==iCount)	
+		{
+		// no free slots, time to grow the array
+		ep=(TEnvVar*)User::ReAlloc(iVars,(iCount+1)*sizeof(TEnvVar));
+		if (ep==0)
+			return KErrNoMemory;
+		iVars=ep;
+		++iCount;
+		}
+	TRAPD(ret,iVars[freeSlot].ConstructL(name,aValue));
+	return MapError(ret,anErrno);
+	}
+
+void CEnvironment::unsetenv(const wchar_t* aName)
+	{
+	TPtrC16 name((TText16*)aName);
+	for (TUint i=0; i<iCount; ++i)
+		{
+		const TDesC16* value=iVars[i].Match(name);
+		if (value)
+			{
+			iVars[i].Release();
+			return;
+			}
+		}
+	}
+