Public Methods Reference
ClientApi methods
ClientApi::DefineClient( const char *, Error * )
Sets P4CLIENT
in the Windows registry and applies
the setting immediately.
Virtual? |
No |
|
Class |
||
Arguments |
|
the new |
|
an |
|
Returns |
|
Notes
To make the new P4CLIENT
setting apply to the
next command executed with
Run()
,
DefineClient()
sets the value in the registry and then calls
SetClient()
.
Example
The following code illustrates how this method might be used to
make a Windows client application start up with a default
P4CLIENT
setting.
client.Init( &e ); client.DefineClient( "default_workspace", &e );
ClientApi::DefineHost( const char *, Error * )
Sets P4HOST
in the Windows registry and applies the
setting immediately.
Virtual? |
No |
|
Class |
||
Arguments |
|
the new |
|
an |
|
Returns |
|
Notes
To make the new P4HOST
setting apply to the next
command executed with
Run()
,
DefineHost()
sets the value in the registry and then calls
SetHost()
.
Example
The following code illustrates how this method might be used to
make a Windows client application start up with a default
P4HOST
setting.
client.Init( &e ); client.DefineHost( "default_host", &e );
ClientApi::DefineIgnoreFile( const char *, Error * )
Sets P4IGNORE
in the Windows registry and applies
the setting immediately.
Virtual? |
No |
|
Class |
||
Arguments |
|
the new |
|
an |
|
Returns |
|
Notes
To make the new P4IGNORE
setting apply to the
next command executed with
Run()
,
DefineIgnoreFile()
sets the value in the registry and then calls
SetIgnoreFile()
.
Example
The following code illustrates how this method might be used to
make a Windows client application start up with a default
P4IGNORE
setting.
# include "clientapi.h" int main() { ClientApi client; Error e; client.Init( &e ); client.DefineIgnoreFile( ".p4ignore", &e ); }
ClientApi::DefinePassword( const char *, Error * )
Sets P4PASSWD
in the Windows registry and applies
the setting immediately.
Virtual? |
No |
|
Class |
||
Arguments |
|
the new |
|
an |
|
Returns |
|
Notes
To make the new P4PASSWD
setting apply to the
next command executed with
Run()
,
DefinePassword()
sets the value in the registry and then calls
SetPassword()
.
DefinePassword()
does not define a new server-side password
for the user.
Call
DefinePassword()
with either the plaintext password, or its MD5 hash
Example
The following code illustrates how this method might be used to
make a Windows client application start up with a default
P4PASSWD
setting.
client.Init( &e ); client.DefinePassword( "default_pass", &e );
ClientApi::DefinePort( const char *, Error * )
Sets P4PORT
in the Windows registry and applies the
setting immediately.
Virtual? |
No |
|
Class |
||
Arguments |
|
the new |
|
an |
|
Returns |
|
Notes
In order to make the new P4PORT
setting apply to
the next client connection opened with
Init()
,
DefinePort()
sets the value in the registry and then calls
SetPort()
.
Example
The following code illustrates how this method might be used to make a Windows client application automatically set itself to access a backup server if the primary server fails to respond. (This example assumes the existence of a backup server that perfectly mirrors the primary server.)
client.Init( &e ); if ( e.IsFatal() ) { e.Clear(); ui.OutputError( "No response from server - switching to backup!\n" ); client.DefinePort( "backup:1666", &e ); client.Init( &e ); }
The first command to which the primary server fails to respond
results in the error message and the program reinitializing the
client to point to the server at backup:1666
.
Subsequent commands do not display the warning because the new
P4PORT
value has been set in the registry.
ClientApi::DefineUser( const char *, Error * )
Sets P4USER
in the Windows registry and applies the
setting immediately.
Virtual? |
No |
|
Class |
||
Arguments |
|
the new |
|
an |
|
Returns |
|
Notes
To make the new P4USER
setting apply to the next
command executed with
Run()
,
DefineUser()
sets the value in the registry and then calls
SetUser()
.
Example
The following code illustrates how this method might be used to
make a Windows client application start up with a default
P4USER
setting.
client.Init( &e ); client.DefineUser( "default_user", &e );
ClientApi::Dropped()
Check if connection is no longer usable.
Virtual? |
No |
|
Class |
||
Arguments |
None |
|
Returns |
|
nonzero if the connection has dropped |
Notes
Dropped()
is usually called after
Run()
;
it then checks whether the command completed successfully. If the
Init()
is only followed by one
Run()
,
as in p4api.cc
, calling
Final()
and then checking the Error
is sufficient to see
whether the connection was dropped. However, if you plan to make many
calls to
Run()
after one call to
Init()
,
Dropped()
provides a way to check that the commands are completing without
actually cleaning up the connection with
Final()
.
Example
The
Dropped()
method is useful if you want to reuse a client connection multiple
times, and need to make sure that the connection is still alive.
For example, an application for stress-testing a Perforce server might run "p4 have" 10,000 times or until the connection dies:
ClientApi client; MyClientUser ui; //this ClientUser subclass doesn't output anything. Error e; client.Init( &e ); int count = 0; while ( !( client.Dropped() ) && count < 10000 ) { count++; client.Run( "have", &ui ); } printf( "Checked have list %d times.\n", count ); client.Final( &e ); // Clean up connection.
If the
Dropped()
result is true, the while
loop ends. The actual
error message remains inaccessible until after the call to
client.Final()
to close the connection and store the error.
ClientApi::Final( Error * )
Close connection and return error count.
Virtual? |
No |
|
Class |
||
Arguments |
|
an |
Returns |
|
final number of errors |
Notes
Call this method after you are finished using the
ClientApi
object in order to clean up the
connection. Every call to
Init()
must eventually be followed by exactly one call to
Final()
.
Example
The following example is a slight modification of
p4api.cc
, and reports the number of errors
before the program exits:
client.Init( &e ); client.SetArgv( argc - 2, argv + 2 ); client.Run( argv[1], &ui ); printf( "There were %d errors.\n", client.Final( &e ) );
ClientApi::GetClient()
Get current client setting.
Virtual? |
No |
|
Class |
||
Arguments |
None |
|
Returns |
|
a reference to the client setting |
Notes
The return value of
GetClient()
is a fixed reference to this ClientApi
object's
setting.
Assigning the return value to a StrPtr
results in
a StrPtr
containing a Text()
value that changes if the ClientApi
object's
client setting changes.
Assigning the return value to a StrBuf
copies the
text in its entirety for future access, rather than simply storing a
reference to data that might change later.
Under some circumstances,
GetClient()
calls
GetHost()
and returns that value - specifically, if no suitable
P4CLIENT
value is available in the environment, or
previously set with
SetClient()
.
(This is why, under the Perforce client, client name defaults to the
host name if not explicitly set.)
In some instances,
GetHost()
does not return valid results until after a call to
Init()
- see the
GetHost()
documentation for details.
Example
This example demonstrates the use of
GetClient()
and the difference between StrPtr
s and
StrBuf
s.
ClientApi client; StrPtr p; StrBuf b; client.Init(); client.SetClient( "one" ); p = client.GetClient(); b = client.GetClient(); client.SetClient( "two" ); printf( "Current client %s = %s\n", client.GetClient().Text(), p.Text() ); printf( "Previous client setting was %s\n", b.Text() );
Executing the preceding code produces the following output:
Current client two = two Previous client setting was one
ClientApi::GetConfig()
Get current configuration file.
Virtual? |
No |
|
Class |
||
Arguments |
None |
|
Returns |
|
a reference to the config file setting |
Notes
See
GetClient()
for more about the StrPtr
return value.
If the P4CONFIG
has not been set,
GetConfig()
returns "noconfig
".
Example
The following example demonstrates the usage of
GetConfig()
.
ClientApi client; printf( "Current P4CONFIG is %s\n", client.GetConfig().Text() );
Executing the preceding code without having specified a configuration file produces the following output:
C:\perforce> a.out Current P4CONFIG is noconfig
ClientApi::GetCwd()
Get current working directory.
Virtual? |
No |
|
Class |
||
Arguments |
None |
|
Returns |
|
a reference to the name of the current directory |
Notes
See
GetClient()
for more about the StrPtr
return value.
If the working directory has been set by a call to
SetCwd()
or
SetCwdNoReload()
,
subsequent calls to
GetCwd()
return that setting regardless of the actual working directory.
Example
The following example demonstrates the usage of
GetCwd()
.
ClientApi client; printf( "Current directory is %s\n", client.GetCwd().Text() );
Executing the preceding code produces the following output:
C:\perforce> a.out Current directory is c:\perforce
ClientApi::GetHost()
Get client hostname.
Virtual? |
No |
|
Class |
||
Arguments |
None |
|
Returns |
|
a reference to the hostname |
Notes
See
GetClient()
for more about the StrPtr
return value.
In some instances,
GetHost()
is not valid until after the network connection has been
established with
Init()
.
GetHost()
attempts to pull its value from earlier
SetHost()
calls, then from P4HOST
in the environment, and
then from the value of "hostname" returned by the client OS. If
none of these is applicable, a reverse DNS lookup is performed,
but the lookup will not work unless the connection has been
established with
Init()
.
To guarantee valid results, call
GetHost()
only after
Init()
or
SetHost()
.
As
GetHost()
may sometimes be called during the execution of
GetClient()
,
this warning applies to both methods.
As noted above,
GetHost()
does not necessarily return the actual hostname of the machine
if it has been overridden by P4HOST
or an earlier
call to
SetHost()
.
Example
The following example demonstrates the usage of
GetHost()
.
ClientApi client; client.Init(); printf( "Client hostname is %s\n", client.GetHost().Text() );
Executing the preceding code produces the following output:
shire% a.out Client hostname is shire
ClientApi::GetIgnore()
Virtual? |
No |
|
Class |
||
Arguments |
None |
|
Returns |
|
an |
Notes
If P4IGNORE
is not set, no paths are ignored.
Example
This example demonstrates the use of
GetIgnore()
.
if ( client->GetIgnore()->Reject( *clientPath, client->GetIgnoreFile() ) ) { /* handling for ignored file */ } }
ClientApi::GetIgnoreFile()
Get the full path name of the ignore file used for the current connection.
Virtual? |
No |
|
Class |
||
Arguments |
None |
|
Returns |
|
a reference to the path of the ignore file. |
Notes
See
GetClient()
for more about the StrPtr
return value.
If the P4IGNORE
is unset,
GetIgnoreFile()
returns an uninitialized StrPtr
.
Example
This example demonstrates the use of
GetIgnoreFile()
.
# include "clientapi.h" int main() { ClientApi client; printf( "The current ignore file is '%s'\n", client.GetIgnoreFile().Text() ); }
Executing the preceding code produces output similar to the following:
The current ignore file is .p4ignore
ClientApi::GetOs()
Get name of client operating system.
Virtual? |
No |
|
Class |
||
Arguments |
None |
|
Returns |
|
a reference to the OS string |
Notes
See
GetClient()
for more about the StrPtr
return value.
GetOs()
returns one of "UNIX
",
"vms
", "NT
",
"Mac
", or null.
Example
The following example demonstrates the usage of
GetOs()
.
ClientApi client; printf( "Client OS is %s\n", client.GetOs().Text() );
Executing the preceding code under Windows produces the following output:
C:\perforce> a.out Client OS is NT
Executing the preceding code on a UNIX machine produces the following output:
shire$ a.out Client OS is UNIX
ClientApi::GetPassword()
Get password setting.
Virtual? |
No |
|
Class |
||
Arguments |
None |
|
Returns |
|
a reference to the password |
Notes
See
GetClient()
for more about the StrPtr
return value.
This method returns the password currently set on the client,
which may or may not be the one set on the server for this user.
The command "p4 passwd" sets
P4PASSWD
on the client machine to an MD5 hash of
the actual password, in which case
GetPassword()
returns this MD5 hash rather than the plaintext version.
However, if the user sets P4PASSWD
directly with
the plaintext version,
GetPassword()
returns that plaintext version. In both instances, the result is
the same as that displayed by "p4 set" or an
equivalent command that displays the value of the
P4PASSWD
environment variable.
SetPassword()
overrides the P4PASSWD
value, and subsequent
GetPassword()
calls return the new value set by
SetPassword()
rather than the one in the environment.
Example
The following example demonstrates the usage of
GetPassword()
.
ClientApi client; printf( "Your password is %s\n", client.GetPassword().Text() );
The following session illustrates the effect of password settings on
GetPassword()
:
> p4 set P4PASSWD=p455w04d > a.out Your password is p455w04d > p4 passwd Enter new password: Re-enter new password: Password updated. > a.out Your password is 6F577E10961C8F7B519501097131787C
ClientApi::GetPort()
Get current port setting.
Virtual? |
No |
|
Class |
||
Arguments |
None |
|
Returns |
|
a reference to the port setting |
Notes
See
GetClient()
for more about the StrPtr
return value.
If the environment variable P4PORT
is unset,
GetPort()
sets the port to the default value of
perforce:1666
.
Example
The following example demonstrates the usage of
GetPort()
.
ClientApi client; printf( "You're looking for a server at %s\n", \ client.GetPort().Text() );
Executing the preceding code produces the following output:
You're looking for a server at perforce:1666
ClientApi::GetProtocol( const char * )
Get protocol information for this connection.
Virtual? |
No |
|
Class |
||
Arguments |
|
the name of the protocol variable being checked |
Returns |
|
a pointer to the variable's value |
Notes
If the variable is unset, the return value is null. If there is
a value, it will be a number in most cases, but in the form of a
StrPtr
rather than an int
.
Call
GetProtocol()
only after a call to
Run()
,
because protocol information is not available until after a call
to
Run()
.
Calling
GetProtocol()
before
Run()
results in a return value of null
, which
looks misleadingly like an indication that the variable is
unset.
GetProtocol()
reports only on variables set by the server, not variables set
by the client with calls to
SetProtocol()
.
Example
The following example code checks whether the server is case-sensitive.
... client.Init( &e ); ... client.Run(); if ( client.Dropped() ) { client.Final( &e ); } if ( client.GetProtocol( "nocase" ) ) printf( "Server case-insensitive.\n" ); else printf( "Server is case-sensitive.\n" );
ClientApi::GetUser()
Get current user setting.
Virtual? |
No |
|
Class |
||
Arguments |
None |
|
Returns |
|
a reference to the user setting |
Notes
See
GetClient()
for more about the StrPtr
return value.
Example
The following example demonstrates the usage of
GetUser()
.
ClientApi client; printf( "Your username is %s\n", client.GetUser().Text() );
Executing the preceding code as testuser
produces the following output:
Your username is testuser
ClientApi::Init( Error * )
Establish a connection and prepare to run commands.
Virtual? |
No |
|
Class |
||
Arguments |
|
an |
Returns |
|
Notes
Init()
must be called to establish a connection before any commands can
be sent to the server. Each call to
Init()
must be followed by exactly one call to
Final()
.
If an error occurs during Init()
,
it is most likely a connection error, with a severity of E_FATAL
.
Example
The following code from p4api.cc
opens a
connection with
Init()
,
sets arguments, runs a command, and closes the connection with
Final()
.
ClientUser ui; ClientApi client; Error e; client.Init( &e ); client.SetArgv( argc - 2, argv + 2 ); client.Run( argv[1], &ui ); client.Final( &e ); return 0;
ClientApi::Run( const char *, ClientUser * )
Run a Perforce command and return when it completes.
Virtual? |
No |
|
Class |
||
Arguments |
|
the name of the command to run |
|
a pointer to a |
|
Returns |
|
Notes
The func
argument to
Run()
is the Perforce command to run, (for instance,
info
or files
). Command
arguments are not included and must be set separately with
StrDict::SetArgv()
.
Initialize the connection with
Init()
before calling
Run()
,
because without a connection, no commands can be sent to the
server. Attempting to call
Run()
before
Init()
will probably result in a fatal runtime error.
Run()
returns only after the command completes. Note that all
necessary calls to ClientUser
methods are
made during the execution of
Run()
,
as dictated by the server.
Example
The code below runs p4 info, using
ClientUser::OutputInfo()
to display the results to the user. If a subclass of
ClientUser
is used here as the
ui
argument, that subclass's implementation
of
OutputInfo()
is used to display the results of the command.
ClientApi client; ClientUser ui; Error e; client.Init( &e ); client.Run( "info", &ui ); client.Final( &e );
ClientApi::SetBreak( KeepAlive *breakCallback )
Establish a callback that is called every 0.5 seconds during command execution.
Virtual? |
No |
|
Class |
||
Arguments |
|
keepalive callback for user interrupt |
Returns |
void
|
Notes
To establish the callback routine, you must call
SetBreak()
after
ClientApi::Init()
.
See also
Example
The following example implements a custom
IsAlive()
that can be called three times before returning 0 and terminating the
connection. If the call to run the changes
command
takes less than 1.5 seconds to complete on the server side, the
program outputs the list of changes. If the call to run the
changes
command takes more than 1.5 seconds, the
connection is interrupted.
#include <clientapi.h> // subclass KeepAlive to implement a customized IsAlive function. class MyKeepAlive : public KeepAlive { public: int IsAlive(); }; // Set up the interrupt callback. After being called 3 times, // interrupt 3 times, interrupt the current server operation. int MyKeepAlive::IsAlive() { static int counter = 0; if ( ++counter > 3 ) { counter = 0; return( 0 ); } return( 1 ); } // Now test the callback ClientUser ui; ClientApi client; MyKeepAlive cb; Error e; client.Init( &e ); client.SetBreak( &cb ); // SetBreak must happen after the Init client.Run( "changes", &ui ); client.Final( &e );
ClientApi::SetClient( const StrPtr * )
Sets the client setting to be used for this connection.
Virtual? |
No |
|
Class |
||
Arguments |
|
the new client setting |
Returns |
void
|
Notes
SetClient()
does not permanently set the P4CLIENT
value in
the environment or registry. The new setting applies only to
commands executed by calling this ClientApi
object's
Run()
method.
Example
The following example displays two client specifications by calling
SetClient()
between
Run()
commands.
ClientApi client; ClientUser ui; StrBuf sb1; StrBuf sb2; sb1 = "client_one"; sb2 = "client_two"; args[0] = "-o"; client.SetClient( &sb1 ); client.SetArgv( 1, args ); client.Run( "client", &ui ); client.SetClient( &sb2 ); client.SetArgv( 1, args ); client.Run( "client", &ui );
ClientApi::SetClient( const char * )
Sets the client setting to be used for this connection.
Virtual? |
No |
|
Class |
||
Arguments |
|
the new client setting |
Returns |
void
|
Notes
SetClient()
does not permanently set the P4CLIENT
value in
the environment or registry. The new setting applies only to
commands executed by calling this ClientApi
object's
Run()
method.
Example
The following example displays two client specifications by calling
SetClient()
between
Run()
commands.
ClientApi client; ClientUser ui; char *args[1]; args[0] = "-o"; client.SetClient( "client_one" ); client.SetArgv( 1, args ); client.Run( "client", &ui ); client.SetClient( "client_two" ); client.SetArgv( 1, args ); client.Run( "client", &ui );
ClientApi::SetCwd( const StrPtr * )
Sets the working directory to be used for this connection.
Virtual? |
No |
|
Class |
||
Arguments |
|
the new directory path |
Returns |
void
|
Notes
SetCwd()
does not permanently set a new working directory in the client
environment. The new setting applies only to commands executed
by calling this ClientApi
object's
Run()
method.
Example
The following code sets different working directories and displays them with p4 info.
ClientApi client; ClientUser ui; StrBuf sb1; StrBuf sb2; sb1 = "C:\one"; sb2 = "C:\two"; client.SetCwd( &sb1 ); client.Run( "info", &ui ); client.SetCwd( &sb2 ); client.Run( "info", &ui );
ClientApi::SetCwd( const char * )
Sets the working directory to be used for this connection.
Virtual? |
No |
|
Class |
||
Arguments |
|
the new directory path |
Returns |
void
|
Notes
SetCwd()
does not permanently set a new working directory in the client
environment. The new setting applies only to commands executed
by calling this ClientApi
object's
Run()
method.
Example
The following code sets different working directories and displays them with p4 info.
ClientApi client; ClientUser ui; client.SetCwd( "C:\one" ); client.Run( "info", &ui ); client.SetCwd( "C:\two" ); client.Run( "info", &ui );
ClientApi::SetCwdNoReload( const StrPtr * )
Sets the working directory to be used for this connection without
checking P4CONFIG
.
Virtual? |
No |
|
Class |
||
Arguments |
|
the new directory path |
Returns |
void
|
Notes
SetCwdNoReload()
does not permanently set a new working directory in the client
environment. The new setting applies only to commands executed
by calling this ClientApi
object's
Run()
method.
Unlike
SetCwd()
,
SetCwdNoReload()
ignores any P4CONFIG
files found in the new
directory hierarchy.
Example
The following code sets different working directories and displays them with p4 info.
ClientApi client; ClientUser ui; StrBuf sb1; StrBuf sb2; sb1 = "C:\one"; sb2 = "C:\two"; client.SetCwdNoReload( &sb1 ); client.Run( "info", &ui ); client.SetCwdNoReload( &sb2 ); client.Run( "info", &ui );
ClientApi::SetCwdNoReload( const char * )
Sets the working directory to be used for this connection without
checking P4CONFIG
.
Virtual? |
No |
|
Class |
||
Arguments |
|
the new directory path |
Returns |
void
|
Notes
SetCwdNoReload()
does not permanently set a new working directory in the client
environment. The new setting applies only to commands executed
by calling this ClientApi
object's
Run()
method.
Unlike
SetCwd()
,
SetCwdNoReload()
ignores any P4CONFIG
files found in the new
directory hierarchy.
Example
The following code sets different working directories and displays them with p4 info.
ClientApi client; ClientUser ui; client.SetCwdNoReload( "C:\one" ); client.Run( "info", &ui ); client.SetCwdNoReload( "C:\two" ); client.Run( "info", &ui );
ClientApi::SetHost( const StrPtr * )
Sets the hostname to be used for this connection.
Virtual? |
No |
|
Class |
||
Arguments |
|
the new hostname value |
Returns |
void
|
Notes
SetHost()
does not permanently change the host name of the client or set
P4HOST
in the environment. The new setting
applies only to commands executed by calling this
ClientApi
object's
Run()
method.
Example
The following example sets different hostnames and displays them with p4 info.
ClientApi client; ClientUser ui; StrBuf sb1; StrBuf sb2; sb1 = "magic"; sb2 = "shire"; client.SetHost( &sb1 ); client.Run( "info", &ui ); client.SetHost( &sb2 ); client.Run( "info", &ui );
ClientApi::SetHost( const char * )
Sets the hostname to be used for this connection.
Virtual? |
No |
|
Class |
||
Arguments |
|
the new hostname value |
Returns |
void
|
Notes
SetHost()
does not permanently change the host name of the client or set
P4HOST
in the environment. The new setting
applies only to commands executed by calling this
ClientApi
object's
Run()
method.
Example
The following example sets different hostnames and displays them with p4 info.
ClientApi client; ClientUser ui; client.SetHost( "magic" ); client.Run( "info", &ui ); client.SetHost( "shire" ); client.Run( "info", &ui );
ClientApi::SetIgnoreFile( const StrPtr * )
Sets the full path name of the ignore file to be used for this connection.
Virtual? |
No |
|
Class |
||
Arguments |
|
the full path name of the new ignore file |
Returns |
void
|
Notes
SetIgnoreFile()
does not permanently set the P4IGNORE
value in
the environment or registry. The new setting applies only to
commands executed by calling this ClientApi
object's
Run()
method.
Example
The following example sets an ignore file location by calling
SetIgnoreFile()
.
# include "clientapi.h" int main() { ClientApi client; StrBuf sb; sb = ".p4ignore"; client.SetIgnoreFile( &sb; ); }
ClientApi::SetIgnoreFile( const char * )
Sets the full path name of the ignore file to be used for this connection.
Virtual? |
No |
|
Class |
||
Arguments |
|
the full path name of the new ignore file |
Returns |
void
|
Notes
SetIgnoreFile()
does not permanently set the P4IGNORE
value in
the environment or registry. The new setting applies only to
commands executed by calling this ClientApi
object's
Run()
method.
Example
The following example sets a ticket file location by calling
SetIgnoreFile()
.
# include "clientapi.h" int main() { ClientApi client; client.SetIgnoreFile( ".p4ignore" ); }
ClientApi::SetPassword( const StrPtr * )
Sets the password to be used for this connection.
Virtual? |
No |
|
Class |
||
Arguments |
|
the new password value |
Returns |
void
|
Notes
SetPassword()
does not permanently change the P4PASSWD
value in
the environment, nor does it in any way change the password that
has been set on the server. The new setting applies only to
authentication attempts for commands executed by calling this
ClientApi
object's
Run()
method.
Example
The following trivial example demonstrates how to hard-code a password into an application without making it (immediately) user-visible.
ClientApi client; ClientUser ui; StrBuf sb; sb = "p455w04d"; client.SetPassword( &sb ); client.SetArgv( argc - 2, argv + 2 ); client.Run( argv[1], &ui );
ClientApi::SetPassword( const char * )
Sets the password to be used for this connection.
Virtual? |
No |
|
Class |
||
Arguments |
|
the new password value |
Returns |
void
|
Notes
SetPassword()
does not permanently change the P4PASSWD
value in
the environment, nor does it in any way change the password that
has been set on the server. The new setting applies only to
authentication attempts for commands executed by calling this
ClientApi
object's
Run()
method.
Example
The following trivial example demonstrates how to hard-code a password into an application without making it (immediately) user-visible.
ClientApi client; ClientUser ui; client.SetPassword( "p455w04d" ); client.SetArgv( argc - 2, argv + 2 ); client.Run( argv[1], &ui );
ClientApi::SetPort( const StrPtr * )
Sets the port to be used to open this connection.
Virtual? |
No |
|
Class |
||
Arguments |
|
the new port value |
Returns |
void
|
Notes
SetPort()
does not permanently change the P4PORT
value in
the environment. The new setting applies only to new connections
established by calling this ClientApi
object's
Init()
method.
Example
The following example demonstrates setting a new port value before initializing the connection.
ClientApi client; Error e; StrBuf sb; sb = "ssl:magic:1666"; client.SetPort( &sb ); client.Init( &e );
ClientApi::SetPort( const char * )
Sets the port to be used to open this connection.
Virtual? |
No |
|
Class |
||
Arguments |
|
the new port value |
Returns |
void
|
Notes
SetPort()
does not permanently change the P4PORT
value in
the environment. The new setting applies only to new connections
established by calling this ClientApi
object's
Init()
method.
Example
The following example demonstrates setting a new port value before initializing the connection.
ClientApi client; Error e; client.SetPort( "magic:1666" ); client.Init( &e );
ClientApi::SetProg( const StrPtr * )
Sets the application or script name for this connection.
Virtual? |
No |
|
Class |
||
Arguments |
|
the new program name |
Returns |
void
|
Notes
SetProg()
sets the identity of a client application as reported by the
p4 monitor command, or as recorded by server
logging.
See also
Example
The following example appears as MyApp
in the
output of p4 monitor show.
ClientApi client; ClientUser ui; StrBuf sb; Error e; sb.Set( "MyApp" ); client.Init( &e ); client.SetProg( &sb ); client.Run( "info", &ui );
ClientApi::SetProg( const char * )
Sets the application or script name for this connection.
Virtual? |
No |
|
Class |
||
Arguments |
|
the new program name |
Returns |
void
|
Notes
SetProg()
sets the identity of a client application as reported by the
p4 monitor command, or as recorded by server
logging.
See also
Example
The following example appears as MyApp
in the
output of p4 monitor show.
ClientApi client; ClientUser ui; Error e; client.Init( &e ); client.SetProg( "MyApp" ); client.Run( "info", &ui );
ClientApi::SetProtocol( char *, char * )
Sets special protocols for the server to use.
Virtual? |
No |
|
Class |
||
Arguments |
|
the name of the variable to set |
|
the new value for that variable |
|
Returns |
|
Notes
SetProtocol()
must be called before the connection is established with
Init()
.
The following variables are supported by
SetProtocol()
:
Variable |
Meaning |
---|---|
|
To enable tagged output (if tagged output for the
command is supported by the server), set the
|
|
To enable specially formatted application forms, set
the |
|
Set the |
By default, the value of the api
protocol
variable matches the version of the API with which you built
your application; under most circumstances, you do not need to
set the protocol version from within your application. If you
are concerned about changes in server behavior, you can manually
set the api
variable in order to protect your
code against such changes.
For instance, the "p4 info" command supports
tagged output as of server release 2003.2, and changes to this
format were made in 2004.2. Code requesting tagged output from
"p4 info" that was compiled against the
2003.1 API library may break (that is, start producing tagged
output) when running against a 2003.2 or newer server. To
prevent this from happening, set api
to the
value corresponding to the desired server release.
Command |
Set api to |
Tagged output supported? |
---|---|---|
|
unset |
Only if both server and API are at 2004.2 or greater |
<=55 |
Output is not tagged; behaves like 2003.1 or earlier, even if server supports tagged output. |
|
=56 |
Output is tagged; behaves like 2003.2. |
|
=57 |
Output is tagged; behaves like 2004.1, 2004.2, or 2005.1. |
|
=58 |
Output is tagged; behaves like 2005.2 or greater |
Example
The following example demonstrates the use of
SetProtocol()
to enable tagged output. The result of this call is that the
ClientUser
object uses
OutputStat()
to handle the output, rather than
OutputInfo()
.
ClientApi client; Error e; client.SetProtocol( "tag", "" ); client.Init( &e ); client.Run( "branches", &ui ); client.Final( &e );
The following code illustrates how to ensure forward compatibility when compiling against newer versions of the Perforce API or connecting to newer Perforce servers.
ClientApi client; Error e; printf( "Output is tagged depending on API or server level.\n" ); client.SetProtocol( "tag", "" ); // request tagged output client.Init( &e ); client.Run( "info", &ui ); client.Final( &e ); printf( "Force 2003.1 behavior regardless of API or server level.\n" ); client.SetProtocol( "tag", "" ); //request tagged output client.SetProtocol( "api", "55" ); // but force 2003.1 mode (untagged) client.Init( &e ); client.Run( "info", &ui ); client.Final( &e ); printf( "Request 2003.2 output if API and server support it.\n" ); client.SetProtocol( "tag", ""); // request tagged output client.SetProtocol( "api", "56"); // force 2003.2 mode (tagged) client.Init( &e ); client.Run( "info", &ui ); client.Final( &e );
The "p4 info" command supports tagged output
only as of server release 2003.2. In the example, the first
Run()
leaves api
unset; if both the client API and
Perforce server support tagged output for p4
info (that is, if you link this code with the 2003.2
or later API and run it against a 2003.2 or
later server), the output is tagged. If you link the same code
with the libraries from the 2003.1 release of the API, however,
the first
Run()
returns untagged output even if connected to a 2003.2
server. By setting api
to
55
, the second
Run()
ensures 2003.1 behavior regardless of API or server level. The
third call to
Run()
supports 2003.2 behavior against a 2003.2 server and protects
against future changes.
ClientApi::SetProtocolV( char * )
Sets special protocols for the server to use.
Virtual? |
No |
|
Class |
||
Arguments |
|
the name and value of the variable to set in
|
Returns |
|
Notes
SetProtocolV()
functions identically to
SetProtocol()
,
except that its argument is a single string of the format
.
variable
=value
Example
The following example demonstrates the use of
SetProtocolV()
to enable tagged output. The result is that the
ClientUser
object uses
OutputStat()
to handle the output, rather than
OutputInfo()
.
ClientApi client; Error e; client.SetProtocolV( "tag=" ); client.Init( &e ); client.Run( "branches", &ui ); client.Final( &e );
ClientApi::SetTicketFile( const StrPtr * )
Sets the full path name of the ticket file to be used for this connection.
Virtual? |
No |
|
Class |
||
Arguments |
|
the full path name of the new ticket file |
Returns |
void
|
Notes
SetTicketFile()
does not permanently set the P4TICKETS
value in
the environment or registry. The new setting applies only to
commands executed by calling this ClientApi
object's
Run()
method.
Example
The following example sets a ticket file location by calling
SetTicketFile()
.
ClientApi client; StrBuf sb; sb = "/tmp/ticketfile.txt"; client.SetTicketFile( &sb );
ClientApi::SetTicketFile( const char * )
Sets the full path name of the ticket file to be used for this connection.
Virtual? |
No |
|
Class |
||
Arguments |
|
the full path name of the new ticket file |
Returns |
void
|
Notes
SetTicketFile()
does not permanently set the P4TICKETS
value in
the environment or registry. The new setting applies only to
commands executed by calling this ClientApi
object's
Run()
method.
Example
The following example sets a ticket file location by calling
SetTicketFile()
.
ClientApi client; client.SetTicketFile( "/tmp/ticketfile.txt" );
ClientApi::SetUi( ClientUser * )
Reset the ClientUser
object used for this
connection.
Virtual? |
No |
|
Class |
||
Arguments |
|
a pointer to a |
Returns |
void
|
Notes
Unless you pass the ClientUser
object to the
Run()
method, you must first call
SetUi()
.
The new setting applies to commands executed by calling this
ClientApi
object's
Run()
method.
Example
The following example illustrates two ways to run p4 info:
ClientApi client; ClientUser ui; client.Run( "info", &ui ); client.SetUi( &ui ); client.Run( "info" );
ClientApi::SetUser( const StrPtr * )
Sets the user for this connection.
Virtual? |
No |
|
Class |
||
Arguments |
|
the new user name setting |
Returns |
void
|
Notes
SetUser()
does not permanently set the P4USER
value in the
environment or registry. Calling this method is equivalent to using
the "-u
" global option from the command line
to set the user value for a single command, with the exception that a
single ClientApi
object can be used to invoke
multiple commands in a row.
If the user setting is to be in effect for the command when it is
executed, you must call
SetUser()
before calling
Run()
.
Example
The following example displays two user specifications by calling
SetUser()
between
Run()
commands.
ClientApi client; Error e; StrBuf sb1; StrBuf sb2; sb1 = "user1"; sb2 = "user2"; char *args[1]; args[0] = "-o"; client.SetUser( &sb1 ); client.SetArgv( 1, args ); client.Run( "user", &ui ); client.SetUser( &sb2 ); client.SetArgv( 1, args ); client.Run( "user", &ui );
ClientApi::SetUser( const char * )
Sets the user for this connection.
Virtual? |
No |
|
Class |
||
Arguments |
|
the new user name setting |
Returns |
void
|
Notes
SetUser()
does not permanently set the P4USER
value in the
environment or registry. Calling this method is equivalent to
using the "-u
" global option from the
command line to set the user value for a single command, with
the exception that a single ClientApi
object
can be used to invoke multiple commands in a row.
If the user setting is to be in effect for the command when it
is executed, you must call
SetUser()
before calling
Run()
.
Example
The following example displays two user specifications by
calling
SetUser()
between
Run()
commands.
ClientApi client; Error e; char *args[1]; args[0] = "-o"; client.SetUser( "user1" ); client.SetArgv( 1, args ); client.Run( "user", &ui ); client.SetUser( "user2" ); client.SetArgv( 1, args ); client.Run( "user", &ui );
ClientApi::SetVersion( const StrPtr * )
Sets the application or script version for this connection.
Virtual? |
No |
|
Class |
||
Arguments |
|
the new version number |
Returns |
void
|
Notes
SetVersion()
sets the version number of a client application as reported by
the p4 monitor -e command, or as recorded by
server logging.
If a client application compiled with version 2005.2 or later of
the API does not call
SetVersion
()
,
then the version string reported by p4 monitor
-e (and recorded in the server log) defaults to the
api
value appropriate for the server level as
per
SetProtocol()
.
Call
SetVersion()
after calling
Init()
and before each call to
Run()
.
Example
The following example appears as 2005.2
in
the output of p4 monitor show -e.
ClientApi client; ClientUser ui; StrBuf sb; Error e; sb.Set( "2005.2" ); client.Init( &e ); client.SetVersion( &sb ); client.Run( "info", &ui );
ClientApi::SetVersion( const char * )
Sets the application or script version for this connection.
Virtual? |
No |
|
Class |
||
Arguments |
|
the new version number |
Returns |
void
|
Notes
SetVersion()
sets the version number of a client application as reported by
the p4 monitor -e command, or as recorded by
server logging.
If a client application compiled with version 2005.2 or later of
the API does not call
SetVersion
()
,
then the version string reported by p4 monitor
-e (and recorded in the server log) defaults to the
api
value appropriate for the server level as
per
SetProtocol()
.
Call
SetVersion()
after calling
Init()
and before each call to
Run()
.
Example
The following example appears as 2005.2
in
the output of p4 monitor show -e.
ClientApi client; ClientUser ui; Error e; client.Init( &e ); client.SetVersion( "2005.2" ); client.Run( "info", &ui );
ClientProgress methods
ClientProgress::Description( const StrPtr *, int )
Sets up a description and defines the units by which command progress is measured.
Virtual? |
Yes |
|
Class |
||
Arguments |
|
description from the server |
|
the units in which progress is to be measured |
|
Returns |
|
 |
Notes
The API calls this method on command startup, supplying your
implementation with a description and a client progress unit type.
The units
in which client progress is measured are
defined in clientprog.h
as follows:
Client Progress Unit |
Value |
Meaning |
---|---|---|
CPU_UNSPECIFIED
|
0
|
No units specified |
CPU_PERCENT
|
1
|
Value is a percentage |
CPU_FILES
|
2
|
Value is a count of files |
CPU_KBYTES
|
3
|
Value is in kilobytes |
CPU_MBYTES
|
4
|
Value is in megabytes |
See also
Example
Create a subclass of ClientProgress
and define an
implementation of
Description()
,
even if it is a trivial implementation:
void MyProgress::Description( const StrPtr *desc, int units ) { printf( "Starting command:\n" ); }
ClientProgress::Done( int )
Called when an operation completes.
Virtual? |
Yes |
|
Class |
||
Arguments |
|
operation status: 1 if failed, 0 if successful |
Returns |
|
Notes
The API calls Done()
on command completion with 0
for success, or 1 for failure.
See also
Example
To change the way completed actions are reported, create a subclass
of ClientProgress
and define an alternate
implementation of
Done()
.
For example, to output "Command failed" or "Command completed" upon
success or failure, implement
Done()
as follows:
void MyProgress::Done( int fail ) { printf( fail ? "Command failed\n" : "Command completed\n"); }
ClientProgress::Total( long )
Defines the number of units requested during the operation, if known.
Virtual? |
Yes |
|
Class |
||
Arguments |
|
Total number of client progress units expected, if known |
Returns |
|
Notes
The API calls this method if and when it has determined the number of
client progress units, as defined by
Description()
,
are to be processed during the command.
If the total number of expected units changes during the lifetime of a command, the API may call this method more than once. (The total number of expected units is not the same as the number of remaining units; certain commands may result in multiple calls to this method as the server determines more about the amount of data to be retrieved.)
See also
Example
To report how many progress units are expected, create a subclass of
ClientProgress
and define an alternate
implementation of
Total()
.
For example, the following method outputs the number of units expected and is called when, if, and as the total number of expected units changes over the lifetime of the command:
void MyProgress::Total( long units ) { printf( "Now expecting %l units\n" ); }
ClientProgress::Update( long )
Reports on command progress and user cancellation requests.
Virtual? |
Yes |
|
Class |
||
Arguments |
|
Total number of progress units processed, if known |
Returns |
|
Notes
The API calls the
Update()
method periodically during the life of a command and reports on the
number of client progress units processed. (Because a million calls
for an update of one million 1024-byte files would be prohibitive,
not every unit of progress is reported.) Instead, the API calls this
method periodically depending on a combination of elapsed time and
number of client progress units processed.
In addition to reporting progress in terms of the units defined by
Description()
,
if
Update()
returns non-zero, the API interprets it as a user request to cancel
the operation.
See also
Example
To report on units processed, create a subclass of
ClientProgress
and define an alternate
implementation of
Update()
.
A trivial implementation ignores cancel requests by always returning
0; a more useful implementation might resemble the following:
void MyProgress::Update( long units ) { if ( cancelclicked() ) // has anyone clicked the Cancel button? { return 1; // yes, user wishes to cancel } else { displayGUI( units ); // show how many units have been processed return 0; // user has not requested cancel, continue processing } }
ClientUser methods
ClientUser::CreateProgress( int )
Create a
ClientProgress
object by subclassing, or null if no progress indicator is desired.
Virtual? |
Yes |
|
Class |
||
Arguments |
|
the type of progress to be reported |
Returns |
a pointer to the new |
Notes
To enable progress reporting for a command, create a
ClientProgress
object and then implement
ProgressIndicator()
to return 0 or 1 depending on whether or not you want to enable the
progress indicator. (You typically implement
ProgressIndicator()
to return 1, and call it only when a progress indicator is desired.)
The API calls this method with the appropriate
ProgressType
as defined in
clientprog.h
. The following
ProgressTypes
can be reported:
Client Progress Type |
Value |
Meaning |
---|---|---|
|
|
Files sent to server |
|
|
Files received from server |
|
|
Files transmitted |
|
|
Computation performed server-side |
ClientUser::Diff( FileSys *, FileSys *, int, char *, Error * )
Diff two files, and display the results.
Virtual? |
Yes |
|
Class |
||
Arguments |
|
the first file to be diffed |
|
the second file to be diffed |
|
|
should output be paged? |
|
|
flags to diff routine |
|
|
an |
|
Returns |
|
Notes
This method is used by p4 diff and to display
diffs from an interactive p4 resolve. If no
external diff program is specified, the diff is carried out with a
Diff
object (part of the Perforce C/C++ API);
otherwise,
Diff()
simply calls the specified external program.
As with
Merge()
,
the external program is invoked with
ClientUser::RunCmd()
.
If doPage
is nonzero and the
P4PAGER
environment variable is set, the output is
piped through the executable specified by P4PAGER
.
See also
Example
In its default implementation, this method is called by an application when p4 diff is run. For example:
p4 diff -dc file.c
results in a call to
Diff()
with the arguments:
Argument |
Value |
---|---|
|
a temp file containing the head revision of depot file
|
|
the local workspace version of file
|
|
|
|
|
|
a normal |
The diff is performed by creating a Diff
object,
giving it f1
and f2
as its
inputs, and -c
as its flag. The end result is
sent to stdout
. If either of the files is binary,
the message "files differ
" is printed instead.
Selecting the "d
" option during an interactive
p4 resolve also calls the
Diff()
method, with the doPage
argument set to 1.
If the environment variable P4PAGER
or
PAGER
is set, then setting doPage
to 1 causes the diff output to be fed through the specified pager. If
P4PAGER
and PAGER
are unset,
dopage
has no effect and the resolve routine
displays the diff output normally.
To enable an application to override the default diff routine, create
a subclass of ClientUser
that overrides the
Diff()
method, and use this subclass in place of ClientUser
.
As an example, suppose that you have a special diff program designed
for handling binary files, and you want p4 diff to
use it whenever asked to diff binary files (rather than display the
default "files differ...
").
Furthermore, you want to keep your current P4DIFF
setting for the purpose of diffing text files, so you decide to use a
new environment variable called P4DIFFBIN
to reference
the binary diff program. If P4DIFFBIN
is set and one
of the files is non-text, the P4DIFFBIN
program is
invoked as P4DIFF
is in the default implementation.
Otherwise, the default implementation is called.
Most of the following code is copied and pasted from the default implementation.
MyClientUser::Diff( FileSys *f1, FileSys *f2, int doPage, char *df, Error *e ) { const char *diff = enviro->Get( "P4DIFFBIN" ); if ( diff && ( !f1->IsTextual() || !f2->IsTextual() ) ) // binary diff { if ( !df || !*df ) { RunCmd( diff, 0, f1->Name(), f2->Name(), 0, pager, e ); } else { StrBuf flags; flags.Set( "-", 1 ); flags << df; RunCmd( diff, flags. Text(), f1->Name(), f2->Name(), 0, pager, e ); } } else ClientUser::Diff( f1, f2, doPage, df, e ); }
ClientUser::Diff( FileSys *, FileSys *, FileSys *, int, char *, Error * )
Diff two files, and output the results to a third file.
Virtual? |
Yes |
|
Class |
||
Arguments |
|
the first file to be diffed |
|
the second file to be diffed |
|
|
the target file for diff output |
|
|
should output be paged? |
|
|
flags to diff routine |
|
|
an |
|
Returns |
|
 |
Notes
This method works like
Diff()
,
but instead of sending data to the standard output, writes the data
to the specified output file.
ClientUser::Edit( FileSys *, Error * )
Bring up the given file in a text editor. Called by all p4 commands that edit specifications.
Virtual? |
Yes |
|
Class |
||
Arguments |
|
the file to be edited |
|
an |
|
Returns |
|
Notes
The FileSys *
argument to
Edit()
refers to a client temp file that contains the specification that is
to be given to the server.
Edit()
does not send the file to the server; its only job is to modify the
file. In the default implementation,
Edit()
does not return until the editor has returned.
There is also a three-argument version of
Edit()
,
for which the default two-argument version is simply a wrapper. The
three-argument version takes an Enviro
object as
an additional argument, and the two-argument version simply passes
the member variable enviro
as this argument. Only
the two-argument version is virtual.
Example
The p4 client command is one of several Perforce
commands that use
ClientUser::Edit()
to allow the user to modify a specification. When the command is
executed, the server sends the client specification to the client
machine, where it is held in a temp file.
Edit()
is then called with that file as an argument, and an editor is
spawned. When the editor closes,
Edit()
returns, and the temp file is sent to the server.
To allow modification of a specification by other means, such as a
customized dialog or an automated process, create a subclass of
ClientUser
that overrides the
Edit()
method and use this subclass in place of
ClientUser
.
Suppose that you have already written a function that takes a
FileSys
as input, opens a custom dialog, and
returns when the file has been modified. Replace the body of
Edit()
in your subclass with a call to your function, as follows:
void MyClientUser::Edit( FileSys *f1, Error *e ) { MyDialog( f1 ); }
ClientUser::ErrorPause( char *, Error * )
Outputs an error and prompts for a keystroke to continue.
Virtual? |
Yes |
|
Class |
||
Arguments |
|
the error message to be printed |
|
an |
|
Returns |
|
Notes
The default implementation of
ErrorPause()
consists solely of calls to
OutputError()
and
Prompt()
.
Example
One situation that results in a call to
ErrorPause()
is an incorrectly edited specification; for example:
> p4 client ... Error in client specification. Error detected at line 31. Wrong number of words for field 'Root'. Hit return to continue...
In this instance, the first three lines of output were the
errBuf
argument to
ErrorPause()
;
they were displayed using
OutputError()
.
To display an error and prompt for confirmation within a GUI
application, create a subclass of ClientUser
that
overrides
ErrorPause()
and use this subclass in place of ClientUser
.
Suppose that you have a function MyWarning()
that
takes a char *
as an argument, and displays the
argument text in an appropriate popup dialog that has to be clicked
to be dismissed. You can implement
ErrorPause()
as a call to this function, as follows:
void MyClientUser::ErrorPause( char *errBuf, Error *e ) { MyWarning( errBuf ); }
Within a GUI, the warning text and "OK" button are probably
bundled into a single dialog, so overriding
ErrorPause()
is a better approach than overriding
OutputError()
and
Prompt()
separately.
ClientUser::File( FileSysType )
Create a FileSys
object for reading and writing
files in the client workspace.
Virtual? |
Yes |
|
Class |
||
Arguments |
|
the file type of the file to be created |
Returns |
|
a pointer to the new |
Notes
This method is a wrapper for
FileSys::Create()
.
Example
ClientUser::File()
is generally called whenever it's necessary to manipulate files in
the client workspace. For example, a p4 sync,
p4 edit, or p4 revert makes one
call to
File()
for each workspace file with which the command interacts.
An alternate implementation might return a subclass of
FileSys
. For example, if you have defined a class
MyFileSys
and want your
MyClientUser
class to use members of this class
rather than the base FileSys
, reimplement
File()
to return a MyFileSys
instead:
FileSys * MyClientUser::File( FileSysType type ) { return MyFileSys::Create( type ); }
ClientUser::Finished()
Called after client commands finish.
Virtual? |
Yes |
|
Class |
||
Arguments |
None |
|
Returns |
|
Notes
This function is called by the server at the end of every Perforce command, but in its default implementation, it has no effect. The default implementation of this function is empty - it takes nothing, does nothing, and returns nothing.
Example
To trigger an event after the completion of a command, create a
subclass of ClientUser
and provide a new
implementation of
Finished()
that calls that event.
For example, if you want your application to beep after each command,
put the command into
Finished()
,
as follows.
void MyClientUser::Finished() { printf( "Finished!\n%c", 7 ); }
ClientUser::HandleError( Error * )
Process error data after a failed command.
Virtual? |
Yes |
|
Class |
||
Arguments |
|
an |
Returns |
|
Notes
The default implementation formats the error with
Error::Fmt()
and outputs the result with
OutputError()
.
2002.1 and newer servers do not call
HandleError()
to display errors. Instead, they call
Message()
.
The default implementation of
Message()
calls
HandleError()
if its argument is a genuine error; as a result, older code that uses
HandleError()
can be used with the newer API and newer servers so long as the
default implementation of
Message()
is retained.
Example
HandleError()
is called whenever a command encounters an error. For example:
> p4 files nonexistent nonexistent - no such file(s).
In this case, the Error
object given to
HandleError()
contains the text
"nonexistent - no such file(s).
"
and has a severity of 2 (E_WARN
).
To handle errors in a different way, create a subclass of
ClientUser
with an alternate implementation of
HandleError()
.
For example, if you want an audible warning on a fatal error, implement
HandleError()
as follows:
void MyClientUser::HandleError( Error *err ) { if ( err->IsFatal() ) printf ( "Fatal error!\n%c", 7 ); }
ClientUser::Help( const char *const * )
Displays a block of help text to the user. Used by p4 resolve but not p4 help.
Virtual? |
Yes |
|
Class |
||
Arguments |
|
an array of arrays containing the help text. |
Returns |
|
Notes
This function is called by p4 resolve when the
"?
" option is selected during an interactive
resolve. The default implementation displays the help text given to
it, one line at a time.
Example
The default implementation is called in order to display the "merge
options" block of help text during a resolve by dumping the text to
stdout
.
To display the resolve help text in another manner, create a subclass
of ClientUser
with an alternate implementation of
Help()
.
For example, suppose you'd like a helpful message about the meaning of "yours" and "theirs" to be attached to the help message. Define the method as follows:
void MyClientUser::Help( const char *const *help ) { for ( ; *help; help++ ) printf( "%s\n", *help ); printf( "Note: In integrations, yours is the target file, \ theirs is the source file.\n" ); }
ClientUser::InputData( StrBuf *, Error * )
Provide data from stdin
to p4 <
command
> -i.
Virtual? |
Yes |
|
Class |
||
Arguments |
|
the |
|
an |
|
Returns |
|
Notes
Any command that edits a specification can take the
-i
option; this method supplies the data for
the specification. In the default implementation, the data comes from
stdin
, but an alternate implementation can accept
the data from any source. This method is the only way to send a
specification to the server without first putting it into a local
file.
Example
The default implementation is called during a normal invocation of p4 client -i.
p4 client -i < clispec.txt
In this example, clispec.txt
is fed to the command
as stdin
. Its contents are appended to the
StrBuf
that is given as an argument to
InputData()
,
and this StrBuf
is given to the server after
InputData()
returns.
To read the data from a different source, create a subclass of
ClientUser
with an alternate implementation of
InputData()
.
For example, suppose that you want to be able to edit a client
specification without creating a local temp file. You've already
written a function which generates the new client specification and
stores it as a StrBuf
variable in your
ClientUser
subclass. To send your modified client
specification to the server when running p4 client
-i with your modified ClientUser
,
implement
InputData()
to read data from that StrBuf
.
The example below assumes that the subclass
MyClientUser
has a variable called
mySpec
that already contains the valid client
specification before running p4 client -i.
void MyClientUser::InputData( StrBuf *buf, Error *e ) { buf->Set( mySpec ); }
ClientUser::Merge( FileSys *, FileSys *, FileSys *, FileSys *, Error * )
Call an external merge program to merge three files during resolve.
Virtual? |
Yes |
|
Class |
||
Arguments |
|
the "base" file |
|
the "theirs" file |
|
|
the "yours" file |
|
|
the final output file |
|
|
an |
|
Returns |
|
Notes
Merge()
is called if the "m
" option is selected during an
interactive resolve.
Merge()
does not call the Perforce merge program; it merely invokes external
merge programs (including P4Merge as well as third-party tools).
External merge programs must be specified by an environment variable,
either P4MERGE
or MERGE
.
Merge()
returns after the external merge program exits.
As in
Diff()
,
the external program is invoked using
ClientUser::RunCmd()
.
See also
Example
When the "merge" option is selected during an interactive resolve,
the file arguments to
Merge()
are as follows:
Argument |
Value |
---|---|
|
A temp file built from the depot revision that is the "base" of the resolve. |
|
A temp file built from the depot revision that is the "theirs" of the resolve. |
|
The local workspace file that is the "yours" of the resolve. |
|
A temp file in which to construct the new revision of "yours". |
These file arguments correspond exactly to the command-line arguments passed to the merge tool.
After you "accept" the merged file (with "ae
"),
the "result" temp file is copied into the "leg2
"
or "yours" workspace file, and this is the file that is submitted to
the depot.
To change the way that external merge programs are called during a
resolve, create a subclass of ClientUser
with an
alternate implementation of
Merge()
.
For example, suppose that one of your favorite merge tools,
"yourmerge
", requires the
"result
" file as the first argument. Rather than
wrapping the call to the merge tool in a script and requiring your
users to set P4MERGE
to point to the script, you might
want to provide support for this tool from within your application as
follows:
void MyClientUser::Merge( FileSys *base, FileSys *leg1, FileSys *leg2, FileSys *result, Error *e ) { char *merger; if ( !( merger = enviro->Get( "P4MERGE" ) ) && !( merger = getenv( "MERGE" ) ) ) { e->Set( ErrClient::NoMerger ); return; } if ( strcmp( merger, "yourmerge" ) == 0 ) { RunCmd( merger, result->Name(), base->Name(), leg1->Name(), leg2->Name(), 0, e ); } else { RunCmd( merger, base->Name(), leg1->Name(), leg2->Name(), result->Name(), 0, e ); } }
ClientUser::Message( Error * )
Output information or errors.
Virtual? |
Yes |
|
Class |
||
Arguments |
|
an |
Returns |
|
Notes
Message()
is used by 2002.1 and later servers to display information or errors
resulting from Perforce commands. Earlier versions of the Perforce
server call
OutputInfo()
to display information, and
HandleError()
to display errors.
The default implementation of
Message()
makes calls to
OutputInfo()
or
HandleError()
as appropriate. If you want your application to be compatible with
pre-2002.1 servers, use this default implementation of
Message()
- newer servers will call
Message()
,
and older servers will call
OutputInfo()
and
HandleError()
directly.
If you re-implement
Message()
to handle errors and information in a different way, be advised that
older servers will still call
OutputInfo()
and
HandleError()
rather than your
Message()
method.
Example
> p4 files //depot/proj/... //depot/proj/file.c#1 - add change 456 (text)
In this example, the server passes a single Error
object to the ClientUser
's
Message()
method, with a severity of E_INFO
and text
"//depot/proj/file.c#1 - add change 456
(text)
". The default
Message()
method detects that this was an "info" message, and passes the text
to
OutputInfo()
,
which by default sends the text to stdout
.
To handle messages differently, subclass
ClientUser
and re-implement the
Message()
method (see the preceding note on interoperability with old
servers if you do this).
For example, to take all server messages and load them into a
StrBuf
that is a member of your
ClientUser
class, use the following:
void MyClientUser::Message( Error *err ) { StrBuf buf; err->Fmt( buf, EF_PLAIN ); myBuf.Append( buf ); }
ClientUser::OutputBinary( const char *, int )
Output binary data.
Virtual? |
Yes |
|
Class |
||
Arguments |
|
a pointer to the first byte of data to output |
|
the number of bytes to output |
|
Returns |
|
Notes
The default implementation of
OutputBinary()
writes the contents of a binary file to stdout
. A
call to
OutputBinary()
is typically the result of running p4 print on a
binary file:
p4 print //depot/file.jpg > newfile.jpg
Example
To modify the way in which binary files are output with p4
print, create a subclass of ClientUser
with an alternate implementation of
OutputBinary()
.
For example, suppose that you want PDF files to be printed to
stdout
as plain text. Add the following code (that
checks to see if the file is PDF and, if so, calls a hypothetical
OutputPDF()
function to output PDFs to
stdout
) to the beginning of your implementation of
OutputBinary()
.
void MyClientUser::OutputBinary( const char *data, int length ) { static unsigned char pdfFlag[] = { '%', 'P', 'D', 'F', '-' }; if ( length >= 5 && memcmp( data, pdfFlag, sizeof( pdfFlag ) ) ) OutputPDF( data, length ); else ClientUser::OutputBinary( data, length ); }
ClientUser::OutputError( const char * )
Display a message as an error.
Virtual? |
Yes |
|
Class |
||
Arguments |
|
the error message |
Returns |
|
Notes
The default implementation sends its argument to
stderr
.
OutputError()
is called by functions like
HandleError()
.
Example
Because the default implementation of
HandleError()
calls it,
OutputError()
is responsible for printing every error message in Perforce. For
example:
p4 files //nonexistent/... nonexistent - no such file(s).
In this case, the argument to
OutputError()
is the array containing the error message
"nonexistent - no such file(s).
"
To change the way error messages are displayed, create a subclass of
ClientUser
and define an alternate implementation
of
OutputError()
.
For example, to print all error messages to stdout
rather than stderr
, and precede them with the
phrase "!!ERROR!!
", implement
OutputError()
as follows:
void MyClientUser::OutputError( const char *errBuf ) { printf( "!!ERROR!! " ); fwrite( errBuf, 1, strlen( errBuf ), stdout ); }
ClientUser::OutputInfo( char, const char * )
Output tabular data.
Virtual? |
Yes |
|
Class |
||
Arguments |
|
the indentation "level" of the output |
|
one line of output |
|
Returns |
|
Notes
OutputInfo()
is called by the server during most Perforce commands; its most
common use is to display listings of information about files. Any
output not printed with
OutputInfo()
is typically printed with
OutputText()
.
Running p4 -s
<command
> indicates
whether any given line of output is "info" or "text".
In the default implementation of
OutputInfo()
,
one "...
" string is printed per "level". Values
given as "levels" are either 0
,
1
, or 2
. The "data" passed is
generally one line, without a line break;
OutputInfo()
adds the newline when it prints the output.
To capture information directly from Perforce commands for parsing or
storing rather than output to stdout
, it is
usually necessary to use an alternate implementation of
OutputInfo()
.
2002.1 and newer servers do not call
OutputInfo()
to display information. Instead, they call
Message()
.
The default implementation of
Message()
calls
OutputInfo()
if its argument represents information instead of an error; older
code that uses
OutputInfo()
can be used with the newer API and newer servers, so long as the default implementation of
Message()
is retained.
Example
The p4 filelog command produces tabular output:
> p4 filelog final.c //depot/final.c ... #3 change 703 edit on 2001/08/24 by testuser@shire (text) 'fixed' ... ... copy into //depot/new.c#4 ... #2 change 698 edit on 2001/08/24 by testuser@shire (text) 'buggy' ... ... branch into //depot/middle.c#1 ... #1 change 697 branch on 2001/08/24 by testuser@shire (text) 'test' ... ... branch from //depot/old.c#1,#3
Each line of output corresponds to one call to
OutputInfo()
.
The first line of output has a level of '0', the line for each
revision has a level of '1', and the integration record lines have
levels of '2'. (The actual "data" text for these lines does not
include the "...
" strings.)
To alter the way in which "info" output from the server is handled,
create a subclass of ClientUser
and provide an
alternate implementation of
OutputInfo()
.
For example, to capture output in a set of StrBuf
variables rather than display it to stdout
, your
ClientUser
subclass must contain three
StrBuf
s, one for each level of info output, as
follows:
void MyClientUser::OutputInfo( char level, const char *data ) { switch( level ) { default: case '0': myInfo0.Append( data ); myInfo0.Append( "\n" ); break; case '1': myInfo1.Append( data ); myInfo1.Append( "\n" ); break; case '2': myInfo2.Append( data ); myInfo2.Append( "\n" ); break; } }
ClientUser::OutputStat( StrDict * )
Process tagged output.
Virtual? |
Yes |
|
Class |
||
Arguments |
|
a |
Returns |
|
Notes
Normally, the only Perforce command that sends output through
OutputStat()
is p4 fstat, which always returns tagged output.
Some other commands can be made to return tagged output by setting
the "tag" protocol variable, in which case the output is in the form
of a StrDict
suitable for passing to
OutputStat()
for processing.
It is generally easier to deal with tagged output than it is to parse
standard output. The default implementation of
OutputStat()
passes each variable/value pair in the StrDict
to
OutputInfo()
as a line of text with a level of "1", with the exception of the
"func" var, which it skips. Alternate implementations can use tagged
output to extract the pieces of information desired from a given
command.
Example
Consider the following output from p4 fstat:
> p4 fstat file.c ... depotFile //depot/file.c ... clientFile c:\depot\file.c ... isMapped ... headAction integrate ... headType text ... headTime 998644337 ... headRev 10 ... headChange 681 ... headModTime 998643970 ... haveRev 10
The StrDict
passed to
OutputStat()
consists of eight variable/value pairs, one for each line of output,
plus a "func" entry, which is discarded by the default implementation
of
OutputStat()
.
Other commands can be made to return tagged output through
OutputStat()
by using the -Ztag
global option at the
command line.
To process tagged output differently, create a subclass of
ClientUser
with an alternate implementation
of
OutputStat()
.
The following simple example demonstrates how the
"headRev
" and "haveRev
"
variables resulting from an "fstat
" command can be
easily extracted and manipulated.
Other commands provide StrDict
s with different
variable/value pairs that can be processed in similar ways; use
p4 -Ztag command
to get
an understanding for what sort of information to expect.
void MyClientUser::OutputStat( StrDict *varList ) { StrPtr *headrev; StrPtr *haverev; headrev = varList->GetVar( "headRev" ); haverev = varList->GetVar( "haveRev" ); printf( "By default, revision numbers are returned as strings:\n" ); printf( " Head revision number: %s\n", headrev->Text() ); printf( " Have revision number: %s\n", haverev->Text() ); printf( "but revision numbers can be converted to integers:\n" ); printf( " Head revision number: %d\n", headrev->Atoi() ); printf( " Have revision number: %d\n", haverev->Atoi() ); }
ClientUser::OutputText( const char *, int )
Output textual data.
Virtual? |
Yes |
|
Class |
||
Arguments |
|
the block of text to be printed |
|
the length of the data |
|
Returns |
|
Notes
The most common usage of
OutputText()
is in running p4 print on a text file.
Example
> p4 print -q file.txt This is a text file. It is called "file.txt"
The arguments to
OutputText()
in the preceding example are the pointer to the first character in
the file contents, and the length of the file in bytes.
To alter the way in which
OutputText()
handles text data, create a subclass of ClientUser
and provide an alternate implementation of
OutputText()
.
For example, suppose that your ClientUser
subclass
contains a StrBuf
called
myData
, and you want to store the data in this
StrBuf
rather than dump it to
stdout
.
void MyClientUser::OutputText( const char *data, int length ) { myData.Set( data, length ); }
ClientUser::ProgressIndicator()
Returns nonzero if progress is to be reported, otherwise returns 0.
Virtual? |
Yes |
|
Class |
||
Arguments |
None |
|
Returns |
|
returns non-zero if progress indicators are desired, 0 otherwise |
Notes
After you have created a
ClientProgress
object with
CreateProgress()
,
you must also implement
ProgressIndicator()
to return 0 or 1 depending on whether or not you want to report
progress.
See also
Example
The typical implementation of
ProgressIndicator()
returns 1, and you call it when you wish to enable progress
reporting:
MyUserProgress::ProgressIndicator() { return 1; }
ClientUser::Prompt( const StrPtr &, StrBuf &, int, Error * )
Prompt the user and get a response.
Virtual? |
Yes |
|
Class |
||
Arguments |
|
the message with which to prompt the user |
|
where to put the user's response |
|
|
specifies whether echo should be turned off at the console |
|
|
an |
|
Returns |
|
Notes
Prompt()
is used in the default implementation of
HandleError()
to prompt the user to correct the error.
Prompt()
is also used by the interactive resolve routine to prompt for
options.
Example
Consider the following user interaction with p4 resolve:
> p4 resolve file.c c:\depot\file.c - merging //depot/file.c#2,#10 Diff chunks: 0 yours + 1 theirs + 0 both + 0 conflicting Accept(a) Edit(e) Diff(d) Merge (m) Skip(s) Help(?) [at]: at
In the above example, the "msg" argument to
Prompt()
is the "Accept...[at]:
" string. The response,
"at", is placed into the "rsp" StrBuf
, which is
sent to the server and processed as "accept theirs".
To alter the behavior of
Prompt()
,
create a subclass of ClientUser
and provide an
alternate implementation of
Prompt()
.
For example, suppose that you are writing a GUI application and want
each option in the interactive resolve to appear in a dialog box. A
function called MyDialog()
to create a dialog box
containing the text of its argument and a text field, and return a
character array with the user's response, would look like this:
void MyClientUser::Prompt( const StrPtr &msg, StrBuf &buf, \ int noEcho, Error *e ) { buf.Set( MyDialog( msg.Text() ) ); }
ClientUser::RunCmd( const char *, const char *, [...], Error * )
Call an external program.
Virtual? |
No |
|
Class |
|
|
Arguments |
|
the executable to be called |
|
the first argument |
|
|
the second argument |
|
|
the third argument |
|
|
the fourth argument |
|
|
a pager, if any |
|
|
an |
|
Returns |
|
Notes
RunCmd()
is called when the client needs to call an external program, such as
a merge or diff utility.
RunCmd()
stores any resulting errors in the specified Error
object.
Example
If you select "d" for "Diff" during an interactive resolve, and both
P4DIFF
and P4PAGER
are set in your
environment,
RunCmd()
is called with the following arguments:
Argument |
Value |
---|---|
command
|
|
|
local file name |
|
temp file name (depot file) |
|
null |
|
null |
|
|
The P4DIFF
program is called with the two file names
as arguments, and the output is piped through the
P4PAGER
program.
See the examples for
Diff()
and
Merge()
for code illustrating the use of
RunCmd()
.
Error methods
Error::Clear()
Remove any error messages from an Error
object.
Virtual? |
No |
|
Class |
||
Arguments |
None |
|
Returns |
|
Notes
Clear()
can be
used if you need to clear an Error
after having
handled it in a way that does not automatically clear it.
Example
The following code attempts to establish a connection to a nonexistent server, displays the error's severity, clears the error, and shows that the error has been cleared:
ClientApi client; Error e; client.SetPort( "bogus:12345" ); client.Init( &e ); printf( "Error severity after Init() is is %d.\n", e.GetSeverity() ); e.Clear(); printf( "Error severity after Clear() is %d.\n", e.GetSeverity() );
Executing the preceding code produces the following output:
Error severity after Init() is 4. Error severity after Clear() is 0.
Error::Dump( const char * )
Display an Error
struct for debugging.
Virtual? |
No |
|
Class |
||
Arguments |
|
a string to appear next to the debugging output |
Returns |
|
Notes
Dump()
can be used to determine the exact nature of an
Error
that is being handled. Its primary use is in
debugging, as the nature of the output is more geared towards
informing the developer than helping an end user.
Example
The following code attempts to establish a connection to a nonexistent server, and dumps the resulting error:
ClientApi client; Error e; client.SetPort( "bogus:12345" ); client.Init( &e ); e.Dump( "example" );
Executing the preceding code produces the following output:
Error example 0012FF5C Severity 4 (error) Generic 38 Count 3 0: 1093012493 (sub 13 sys 3 gen 38 args 1 sev 4 code 3085) 0: %host%: host unknown. 1: 1093012492 (sub 12 sys 3 gen 38 args 1 sev 4 code 3084) 1: TCP connect to %host% failed. 2: 1076240385 (sub 1 sys 8 gen 38 args 0 sev 4 code 8193) 2: Connect to server failed; check $P4PORT. host = bogus host = bogus:12345
Error::Fmt( StrBuf * )
Format the text of an error into a StrBuf
.
Virtual? |
No |
|
Class |
||
Arguments |
|
a pointer to the |
Returns |
|
Notes
The result of
Fmt()
is suitable
for displaying to an end user; this formatted text is what the
command line client displays when an error occurs.
If an error has no severity (E_EMPTY
),
Fmt()
returns
with no change to the StrBuf
.
If the error has severity of info (E_INFO
), the
StrBuf
is formatted.
If the error has any higher severity, the StrBuf
argument passed to
Fmt()
is cleared and then replaced with the formatted error.
Example
The following example code displays an error's text:
if ( e.Test() ) { StrBuf msg; e.Fmt( &msg ); printf( "ERROR:\n%s", msg.Text() ); }
Error::Fmt( StrBuf *, int )
Format the text of an error into a StrBuf
,
after applying formatting.
Virtual? |
No |
|
Class |
||
Arguments |
|
a pointer to the |
|
formatting options |
|
Returns |
|
Notes
The result of
Fmt()
is suitable
for displaying to an end user; this formatted text is what the
command line client displays when an error occurs.
If an error has no severity (E_EMPTY
),
Fmt()
returns
with no change to the StrBuf
.
If the error has severity of info (E_INFO
), the
StrBuf
is formatted.
If the error has any higher severity, the StrBuf
argument passed to
Fmt()
is cleared and then replaced with the formatted error.
The opts
argument is a flag or combination of
flags defined by the ErrorFmtOpts
enum. The
default is EF_NEWLINE
, which puts a newline at the
end of the buffer.
Formatting options are as follows:
Argument |
Value |
Meaning |
---|---|---|
|
|
perform no additional formatting. |
|
|
indent each line with a tab ( |
|
|
default - terminate buffer with a newline
( |
|
|
ignore |
Example
The following example code displays an error's text, indented with a tab.
if ( e.Test() ) { StrBuf msg; e.Fmt( &msg, EF_INDENT ); printf( "ERROR:\n%s", msg.Text() ); }
Error::GetGeneric()
Returns generic error code of the most severe error.
Virtual? |
No |
|
Class |
||
Arguments |
None |
|
Returns |
|
the "generic" code of the most severe error |
Notes
For more sophisticated handling, use a "switch" statement based on the error number to handle different errors in different ways.
The generic error codes are not documented at this time.
Example
The following example attempts to establish a connection to a nonexistent server, and displays the resulting generic error code.
ClientApi client; Error e; client.SetPort( "bogus:12345" ); client.Init( &e ); if ( e.Test() ) printf( "Init() failed, error code %d.\n", e.GetGeneric() );
Executing the preceding code produces the following output:
Init() failed, error code 38.
Error::GetSeverity()
Returns severity of the most severe error.
Virtual? |
No |
|
Class |
||
Arguments |
None |
|
Returns |
|
the severity of the most severe error |
Notes
The severity can take the following values:
Severity |
Meaning |
---|---|
|
no error |
|
information, not necessarily an error |
|
a minor error occurred |
|
the command was used incorrectly |
|
fatal error, the command can't be processed |
Example
The following code attempts to establish a connection to a server, and beeps if the severity is a warning or worse:
ClientApi client; Error e; client.SetPort( "magic:1666" ); client.Init( &e ); if ( e.GetSeverity() > E_INFO ) printf( "Uh-oh!%c\n", 13 );
Error::IsFatal()
Tests whether there has been a fatal error.
Virtual? |
No |
|
Class |
||
Arguments |
None |
|
Returns |
|
nonzero if error is fatal |
Notes
This function returns nonzero if
GetSeverity()
== E_FATAL
.
Example
The following code attempts to establish a connection to a server, and beeps if the severity is fatal:
ClientApi client; Error e; client.SetPort( "magic:1666" ); client.Init( &e ); if ( e.IsFatal() ) printf( "Fatal error!%c\n", 13 );
Error::IsWarning()
Tests whether the error is a warning.
Virtual? |
No |
|
Class |
||
Arguments |
None |
|
Returns |
|
nonzero if the most severe error is a warning |
Notes
This function returns nonzero if
GetSeverity()
== E_WARN
.
Example
The following code attempts to establish a connection to a server, and beeps if the severity is a warning:
ClientApi client; Error e; client.SetPort( "magic:1666" ); client.Init( &e ); if ( e.IsWarning() ) printf( "Warning!%c\n", 13 );
Error::Net( const char *, const char * )
Add a network-related error to an Error
.
Virtual? |
No |
|
Class |
||
Arguments |
|
the network operation that was attempted |
|
relevant information about that operation |
|
Returns |
|
Notes
To use an Error
object to track network-related
errors, use
Net()
.
Note that network communication with the Perforce server and related
errors are already handled by lower levels of the client API.
Example
The following example adds an error message, related to a failure to
bind to a network interface, to an Error
object.
e.Net( "bind", service.Text() );
Error::operator << ( int )
Add data to the text of an error message.
Virtual? |
No |
|
Class |
||
Arguments |
|
text to be added to this |
Returns |
|
a reference to the modified |
Notes
The "<<
" operator can be used to add
text to an error as if the error is an output stream. This
operator is typically used in the implementation of other
Error
methods.
Note that an Error
consists of more than its
text, it's more useful to use
Set()
to establish a base Error
and then add text
into that, rather than merely adding text to an empty
Error
object.
Example
The following example creates an Error
using
Set()
and the <<
operator.
e.Set( E_WARN, "Warning, number " ) << myErrNum;
Error::operator << ( char * )
Add data to the text of an error message.
Virtual? |
No |
|
Class |
||
Arguments |
|
text to be added to this |
Returns |
|
a reference to the modified |
Notes
The "<<
" operator can be used to add
text to an error as if the error is an output stream. This
operator is typically used in the implementation of other
Error
methods.
Note that an Error
consists of more than its
text, it's more useful to use
Set()
to establish a base Error
and then add text
into that, rather than merely adding text to an empty
Error
object.
Example
The following example creates an Error
using
Set()
and the <<
operator.
e.Set( E_WARN, "Warning! " ) << "Something bad happened";
Error::operator << ( const StrPtr & )
Add data to the text of an error message.
Virtual? |
No |
|
Class |
||
Arguments |
|
text to be added to this |
Returns |
|
a reference to the modified |
Notes
See
Error::operator << (int)
for details.
Error::operator = ( Error & )
Copy an error.
Virtual? |
No |
|
Class |
||
Arguments |
|
the |
Returns |
|
Notes
The "=
" operator copies one
Error
into another.
Example
The following example sets Error
e1
to equal e2
.
Error e1, e2; e1 = e2;
Error::Set( enum ErrorSeverity, const char * )
Add an error message to an Error
.
Virtual? |
No |
|
Class |
||
Arguments |
|
|
|
|
|
Returns |
|
Notes
An Error
can hold multiple error messages;
Set()
adds the error message to the Error
, rather
than replacing the Error
's previous contents.
An ErrorSeverity
is an int
from 0-4 as described in the documentation on
GetSeverity()
.
Example
The following example adds a fatal error to an
Error
object.
Error e; e.Set( E_FATAL, "Fatal error!");
Error::Set( ErrorId & )
Add an error message to an Error
.
Virtual? |
No |
|
Class |
||
Arguments |
|
the severity and text of the error message |
Returns |
|
Notes
See
Error::Set( enum ErrSeverity, const char * )
for details.
An ErrorId
is a struct
containing an int
(s
) and
a const char *
(fmt
).
Error::Sys( const char *, const char * )
Add a system error to an Error
.
Virtual? |
No |
|
Class |
||
Arguments |
|
the system call that was attempted |
|
relevant information about that call |
|
Returns |
|
Notes
To use an Error
object to track errors generated
by system calls such as file operations, use
Sys()
.
Example
The following example adds an error message, related to a failure to
rename a file, to an Error
object.
e.Sys( "rename", targetFile->Name() );
Error::Test()
Test whether an Error
is non-empty.
Virtual? |
No |
|
Class |
||
Arguments |
None |
|
Returns |
|
nonzero if the error is non-empty |
Notes
Test()
returns nonzero if
GetSeverity()
!= E_EMPTY
.
Example
The following code attempts to establish a connection to a server, and beeps if an error occurs:
ClientApi client; Error e; client.SetPort( "magic:1666" ); client.Init( &e ); if ( e.Test() ) printf( "An error has occurred.%c\n", 13 );
ErrorLog methods
ErrorLog::Abort()
Abort with an error status if an error is detected.
Virtual? |
No |
|
Class |
||
Arguments |
None |
|
Returns |
|
Notes
If the error is empty (severity is E_EMPTY
),
Abort()
returns. Otherwise
Abort()
causes the program to exit with a status of -1.
Example
Abort()
is typically called after
Init()
or
Run()
to
abort the program with a non-zero status if there has been a
connection problem. The code in p4api.cc
is one
example:
ClientApi client; Error e; client.Init( &e ); ErrorLog::Abort();
If any errors are generated during
ClientApi::Init()
, the Error
object is non-empty, and
Abort()
reports the connection error before terminating the program.
ErrorLog::Report()
Print the text of an error to stderr
.
Virtual? |
No |
|
Class |
||
Arguments |
None |
|
Returns |
|
Notes
Report()
functions similarly to
Error::Fmt()
,
but displays the text on stderr
rather than
copying it into a StrBuf
.
Example
The following example displays the contents of an error.
ClientApi client; Error e; client.Init( &e ); ErrorLog::Report();
ErrorLog::SetLog( const char * )
Redirects this Error
's
Report()
output to a file.
Virtual? |
No |
|
Class |
||
Arguments |
|
the file to serve as an error log |
Returns |
|
Notes
After
SetLog()
is called on a given Error
object,
Report()
directs its output to the specified file rather than
stderr
. This setting applies only to the
specified Error
object.
Example
The following example redirects an Error
's output
to a log file, and then writes the Error
's text to
that log file.
ClientApi client; Error e; ErrorLog::SetLog( "C:\Perforce\errlog" ); client.Init( &e ); ErrorLog::Report();
ErrorLog::SetSyslog()
Redirects this Error
's
Report()
output to syslog on UNIX only.
Virtual? |
No |
|
Class |
||
Arguments |
None |
|
Returns |
|
Notes
This method is only valid on UNIX. After it is called, the output of
Report()
is redirected to syslog
, similar to
SetLog()
.
Example
The following example redirects an Error
's output
to syslog, and then outputs the
Error
's text to syslog.
ClientApi client; Error e; ErrorLog::SetSyslog(); client.Init( &e ); ErrorLog::Report();
ErrorLog::SetTag( const char * )
Changes the standard tag used by this Error
's
Report()
method.
Virtual? |
No |
|
Class |
||
Arguments |
|
the text of the new tag |
Returns |
|
Notes
The default tag is "Error
".
SetTag()
sets the new tag for the specified Error
object
only.
Example
The following example resets the tag on an Error
to be "NewError
".
ClientApi client; Error e; client.Init( &e ); ErrorLog::SetTag( "NewError" );
ErrorLog::UnsetSyslog()
Stop writing errors to syslog.
Virtual? |
No |
|
Class |
||
Arguments |
None |
|
Returns |
|
Notes
UnsetSyslog()
reverses the effect of
SetSyslog()
by resetting the Error
object to output to
stderr
.
Example
The following example prints an error message to
syslog and then resets the
Error
back to using stderr
for
output.
ClientApi client; Error e; client.Init( &e ); ErrorLog::SetSyslog(); ErrorLog::Report(); ErrorLog::UnsetSyslog();
FileSys methods
FileSys::Chmod( FilePerm, Error * )
Modify the file mode bits of the file specified by the
path
protected FileSys
member.
Virtual? |
Yes |
|
Class |
||
Arguments |
|
permissions to change the file, either
|
|
returned error status |
|
Returns |
|
Notes
This method is called to make a client file writable
(FPM_RW
) when it is opened for
edit
, or to change it to read-only
(FPM_RO
) after a submit
.
A FilePerm
is an enum
taking
one of the following values:
Argument |
Value |
Meaning |
---|---|---|
|
|
leave file read-only. |
|
|
allow read and write operations |
Example
To use
Chmod()
to
create a configuration file and set its permissions to read-only:
FileSys *f = FileSys::Create( FST_ATEXT ); Error e; f->Set( "c:\\configfile.txt" ); f->Chmod( FPM_RO, &e );
To reimplement
Chmod()
under
UNIX:
void FileSysDemo::Chmod( FilePerm perms, Error *e ) { int bits = IsExec() ? PERM_0777 : PERM_0666; if ( perms == FPM_RO ) bits &= ~PERM_0222; if ( chmod( Name(), bits & ~myumask ) < 0 ) e->Sys( "chmod", Name() ); if ( DEBUG ) printf( "Debug (Chmod): %s\n", Name() ); }
FileSys::Close( Error * )
Close the file specified by the path
protected
FileSys
member and release any OS resources
associated with the open file.
Virtual? |
Yes |
|
Class |
||
Arguments |
|
returned error status |
Returns |
|
Notes
The default implementation of
Close()
is
called every time a file that is currently
Open()
is no longer required. Typically, the handle that was returned for
the Open()
call is used to free up the resource.
Your implementation must correctly report any system errors that may occur during the close.
Example
To use
Close()
to
close an open file:
FileSys *f = FileSys::Create( FST_ATEXT ); Error e; f->Set( "c:\\configfile.txt" ); f->Open( FOM_WRITE, &e ); f->Close( &e );
To reimplement
Close()
to report errors using
Error::Sys()
and provide debugging output:
void FileSysDemo::Close( Error *e ) { if ( close( fd ) == -1 ) e->Sys( "close", Name() ); if ( DEBUG ) printf( "Debug (Close): %s\n", Name() ); }
FileSys::Create( FileSysType )
Create a new FileSys
object.
Virtual? |
Yes |
|
Class |
||
Arguments |
|
file type |
Returns |
|
a pointer to the new |
Notes
A FileSysType
is an enum
taking
one of the values defined in filesys.h
. The most
commonly used FileSysType
s are as follows:
Argument |
Value |
Meaning |
---|---|---|
|
|
file is text |
|
|
file is binary |
|
|
file is text, open only for append |
Example
To use
Create()
to
create a FileSys
object for a log file (text file,
append-only):
FileSys *f = FileSys::Create( FST_ATEXT );
FileSys::Open( FileOpenMode, Error * )
Open the file name specified by the path
protected
FileSys
member for reading or writing as specified
by the argument FileOpenMode
.
Virtual? |
Yes |
|
Class |
||
Arguments |
|
Mode to open the file, either |
|
returned error status |
|
Returns |
|
Notes
The default implementation of
Open()
is
called every time there is a need to create or access a file on the
client workspace.
Operating systems typically return a handle to the opened file, which is then used to allow future read/write calls to access the file.
Your implementation must correctly report any system errors that may occur during the open.
Example
To use
open()
to open
a log file for writing:
FileSys *f = FileSys::Create( FST_ATEXT ); Error e; StrBuf m; m.Append( "example: text to append to a log file\r\n" ); f->Set( "C:\\logfile.txt" ); f->Open( FOM_WRITE, &e ); f->Write( m.Text(), m.Length(), &e ); f->Close( &e );
To reimplement
Open()
to
report errors with
Error::Sys()
,
provide debugging output, and use the
FileSysDemo
member "fd
" to
hold the file handle returned from the open()
system call:
void FileSysDemo::Open( FileOpenMode mode, Error *e ) { this->mode = mode; int bits = ( mode == FOM_READ ) ? O_RDONLY : O_WRONLY|O_CREAT|O_APPEND; if ( ( fd = open( Name(), bits, PERM_0666 ) ) < 0 ) { e->Sys( mode == FOM_READ ? "open for read" : "open for write", Name() ); } if ( DEBUG ) { printf( "Debug (Open): '%s' opened for '%s'\n", Name(), mode == FOM_READ ? "read" : "write" ); } }
FileSys::Read( const char *, int, Error * )
Attempt to read len
bytes of data from the object
referenced by the file handle (returned by the
Open()
method)
to the buffer pointed to by buf
. Upon successful
completion,
Read()
returns
the number of bytes actually read and placed in the buffer.
Virtual? |
Yes |
|
Class |
||
Arguments |
|
pointer to buffer into which to read data |
|
length of data to read |
|
|
returned error status |
|
Returns |
|
number of bytes actually read |
Notes
The default implementation of
Read()
is
called every time there is a need to read data from the file
referenced by the
Open()
call.
Your implementation must correctly report any system errors that may occur during I/O.
Example
To use Read()
to read a line from a log file:
char line[80]; m.Set( msg ); FileSys *f = FileSys::Create( FST_ATEXT ); Error e; f->Set( "C:\\logfile.txt" ); f->Open( FOM_READ, &e ); f->Read( line, 80, &e ); f->Close( &e );
To reimplement
Read()
to
report errors with
Error::Sys()
,
provide debugging output, and use the FileSysDemo
member "fd
" to hold the file handle returned from
the read()
system call:
int FileSysDemo::Read( char *buf, int len, Error *e ) { int bytes; if ( ( bytes = read( fd, buf, len ) ) < 0 ) e->Sys( "read", Name() ); if ( DEBUG ) { printf( "debug (Read): %d bytes\n", bytes ); } return( bytes ); }
FileSys::Rename( FileSys *, Error * )
Rename the file specified by the path
protected
FileSys
member to the file specified by the target
FileSys
object.
Virtual? |
Yes |
|
Class |
||
Arguments |
|
name of target for rename |
|
returned error status |
|
Returns |
|
Notes
On some operating systems, an unlink might be required before calling
Rename()
.
Your implementation must correctly report any system errors that may occur during the rename.
Example
To use
Rename()
to
rename /usr/logs/log2
to
/usr/logs/log1
:
FileSys *f1 = FileSys::Create( FST_TEXT ); FileSys *f2 = FileSys::Create( FST_TEXT ); Error e; f1->Set( "/usr/logs/log1" ); f2->Set( "/usr/logs/log2" ); f1->Rename( f2, &e );
To reimplement
Rename()
to
report errors with
Error::Sys()
and
provide debugging output:
void FileSysDemo::Rename( FileSys *target, Error *e ) { if ( rename( Name(), target->Name() ) < 0 ) e->Sys( "rename", Name() ); if ( DEBUG ) printf( "Debug (Rename): %s to %s\n", Name(), target->Name() ); }
FileSys::Set( const StrPtr * )
Initializes the protected StrBuf
variable
path
to the supplied filename argument; this
path
is used by other FileSys
member functions when reading and writing to a physical file location.
Virtual? |
Yes |
|
Class |
||
Arguments |
|
filename for this |
Returns |
|
Notes
After creating a FileSys
object, call
Set()
to supply
it with a path
.
Example
To use Set()
to
set a filename:
FileSys *f = FileSys::Create( FST_BINARY ); f->Set( "/tmp/file.bin" );
To reimplement
Set()
to
provide debugging output:
void FileSysDemo::Set( const StrPtr &name ) { // Set must initialize the protected variable "path" // with the filename argument "name". path.Set( name ); if ( DEBUG ) printf( "debug (Set): %s\n", path.Text() ); }
FileSys::Stat()
Obtain information about the file specified by the
path
protected FileSys
member.
Virtual? |
Yes |
|
Class |
||
Arguments |
None |
|
Returns |
|
0 for failure, or status bits as defined below |
The status bits have the following meanings:
Status |
Meaning |
---|---|
|
failure |
|
file exists |
|
file is user-writable |
|
file is a directory |
|
file is symlink |
|
file is a special file (in the UNIX sense) |
|
file is executable |
|
file is empty |
|
file is invisible (hidden) |
Notes
The default implementation of
Stat()
is
called to obtain file status every time a file is opened for read.
Example
To use
Stat()
to
verify the existence of /usr/bin/p4
:
FileSys *f = FileSys::Create( FST_BINARY ); f->Set( "/usr/bin/p4" ); int state = f->Stat(); if ( state & FSF_EXISTS ) printf( "File found\n" );
To reimplement
Stat()
to
provide debugging output:
int FileSysDemo::Stat() { int flags = 0; struct stat st; if ( DEBUG ) printf( "Debug (Stat): %s\n", Name() ); if ( stat( Name(), &st ) < 0 ) return( flags ); // Set internal flags flags |= FSF_EXISTS; if ( st.st_mode & S_IWUSR ) flags |= FSF_WRITEABLE; if ( st.st_mode & S_IXUSR ) flags |= FSF_EXECUTABLE; if ( S_ISDIR( st.st_mode ) ) flags |= FSF_DIRECTORY; if ( !S_ISREG( st.st_mode ) ) flags |= FSF_SPECIAL; if ( !st.st_size ) flags |= FSF_EMPTY; return flags; }
FileSys::StatModTime()
Return the last modified time of the file specified by the
path
protected FileSys
member.
Virtual? |
Yes |
|
Class |
||
Arguments |
None |
|
Returns |
|
0 for failure, or last modified time in seconds since 00:00:00, January 1, 1970, GMT. |
Notes
The default implementation of
StatModTime()
is called every time a client file is submitted or synced.
Example
To use
StatModTime()
to obtain the modification time on a log file:
FileSys *f = FileSys::Create( FST_ATEXT ); f->Set( "/usr/logs/logfile.txt" ); int time = f->StatModTime(); if ( time ) printf( "%d", time );
To reimplement
StatModTime()
to provide debugging output:
int FileSysDemo::StatModTime() { struct stat st; if ( stat( Name(), &st ) < 0 ) return( 0 ); if ( DEBUG ) printf( "Debug (StatModTime): %s\n", Name() ); return (int)( st.st_mtime ); }
FileSys::Truncate()
Truncate the file specified by the path
protected
FileSys
member to zero length.
Virtual? |
Yes |
|
Class |
||
Arguments |
None |
|
Returns |
|
Notes
The default implementation of
Truncate()
is only called by the Perforce server.
FileSys::Unlink( Error * )
Remove the file specified by the path
protected
FileSys
member from the filesystem.
Virtual? |
Yes |
|
Class |
||
Arguments |
|
returned error status |
Returns |
|
Notes
The default implementation of
Unlink()
is
always called if the file created is temporary.
Your implementation must correctly report any system errors that may occur during removal.
Example
To use
Unlink()
to
delete an old log file:
FileSys *f = FileSys::Create( FST_TEXT ); Error e; f->Set( "/usr/logs/oldlog" ); f->Unlink( &e );
To reimplement
Unlink()
to
report errors with
Error::Sys()
and
provide debugging output:
void FileSysDemo::Unlink( Error *e ) { if ( unlink( Name() ) < 0 ) e->Sys( "unlink", Name() ); if ( DEBUG ) printf( "Debug (Unlink): %s\n", Name() ); }
FileSys::Write( const char *, int, Error * )
Attempt to write "len
" bytes of data to the object
referenced by the file handle (returned by the
Open()
method)
from the buffer pointed to by "buf
".
Virtual? |
Yes |
|
Class |
||
Arguments |
|
pointer to buffer containing data to be written |
|
length of data to write |
|
|
returned error status |
|
Returns |
|
Notes
The default implementation of
Write()
is
called every time there is a need to write data to the file created
by the Open()
call.
Your implementation must correctly report any system errors that may occur during I/O.
Example
To use
Write()
to
write an error to a log file:
StrBuf m; m.Set( "Unknown user\r\n" ); FileSys *f = FileSys::Create( FST_ATEXT ); Error e; f->Set( "C:\\logfile.txt" ); f->Open( FOM_WRITE, &e ); f->Write( m.Text(), m.Length(), &e ); f->Close( &e );
To reimplement
Write()
to
report errors with
Error::Sys()
and
provide debugging output:
void FileSysDemo::Write( const char *buf, int len, Error *e ) { int bytes; if ( ( bytes = write( fd, buf, len ) ) < 0 ) e->Sys( "write", Name() ); if ( DEBUG ) printf( "debug (Write): %d bytes\n", bytes ); }
Ignore methods
Ignore::Reject( const StrPtr &, const StrPtr & )
Tests whether the provided path will be rejected when it is opened for add because it matches an entry in the provided ignore file.
Virtual? |
No |
|
Class |
||
Arguments |
|
the path to check |
|
the full path to the ignore file |
|
Returns |
|
nonzero if path is ignored |
Notes
Calling
Reject()
provides a preview of what will happen when files are opened for add.
If the ignore file does not exist, or is not readable, no files are rejected.
Example
The following example demonstrates the usage of
Reject()
.
# include "clientapi.h" # include "ignore.h" int main() { ClientApi client; StrBuf clientPath; client.SetIgnoreFile( ".p4ignore" ); clientPath = "ignore.txt"; if ( client->GetIgnore()->Reject( *clientPath, client->GetIgnoreFile() ) ) { printf( "%s is to be ignored.\n", clientPath.Text() ); } }
Ignore::RejectCheck( const StrPtr & )
Tests whether the provided path will be rejected when it is opened for add because it matches an ignore file entry.
Virtual? |
No |
|
Class |
||
Arguments |
|
the path to check |
Returns |
|
nonzero if path is ignored |
Notes
Calling
RejectCheck()
.
provides a preview of what will happen the file is opened for add.
Use RejectCheck()
when you have to test multiple
paths that may be rejected. First call
Reject()
to parse the ignore file, and then call
RejectCheck()
for each additional path that needs
to be checked.
Example
The following example demonstrates the usage of
RejectCheck()
.
# include "clientapi.h" # include "ignore.h" int main() { ClientApi client; StrBuf clientPath; client.SetIgnoreFile( ".p4ignore" ); clientPath = "ignore.txt"; if ( client->GetIgnore()->Reject( *clientPath, client->GetIgnoreFile() ) ) { printf( "%s is to be ignored.\n", clientPath.Text() ); } clientPath = "ignore2.txt"; if ( client->GetIgnore()->Reject( *clientPath, client->GetIgnoreFile() ) ) { printf( "%s is to be ignored.\n", clientPath.Text() ); } }
KeepAlive methods
KeepAlive::IsAlive()
The only method of the
KeepAlive
class,
IsAlive()
is used in applications to request that the current command be
terminated by disconnecting.
Virtual? |
Yes |
|
Class |
||
Arguments |
None |
|
Returns |
|
0 to terminate connection, 1 to continue processing |
Notes
Use
ClientApi::SetBreak()
to establish a callback to be called every 0.5 seconds during command
execution.
See also
Example
The following example implements a custom
IsAlive()
that can be called three times before returning 0 and terminating the
connection. If the call to run the changes
command
takes less than 1.5 seconds to complete on the server side, the
program outputs the list of changes. If the call to run the
changes
command takes more than 1.5 seconds, the
connection is interrupted.
#include <clientapi.h> // subclass KeepAlive to implement a customized IsAlive function. class MyKeepAlive : public KeepAlive { public: int IsAlive(); }; // Set up the interrupt callback. After being called 3 times, // interrupt 3 times, interrupt the current server operation. int MyKeepAlive::IsAlive() { static int counter = 0; if ( ++counter > 3 ) { counter = 0; return( 0 ); } return( 1 ); } // Now test the callback ClientUser ui; ClientApi client; MyKeepAlive cb; Error e; client.Init( &e ); client.SetBreak( &cb ); // SetBreak must happen after the Init client.Run( "changes", &ui ); client.Final( &e );
MapApi methods
MapApi::Clear()
Empties a mapping.
Virtual? |
No |
|
Class |
||
Arguments |
None |
|
Returns |
|
Notes
After this method has been called on a MapApi
object, the object is indistinguishable from a freshly-constructed
object.
MapApi::Count()
Returns the number of entries currently in the mapping.
Virtual? |
No |
|
Class |
||
Arguments |
None |
|
Returns |
|
The number of entries currently in the mapping |
Notes
The number returned by
Count()
may be
different from the number of times that
Insert()
has been called. This is because MapApi
automatically disambiguates itself, adding new exclusions to
eliminate ambiguity between partially overlapping entries and
removing entries that are redundant.
Example
The following example demonstrates
Count()
,
GetType()
,
GetLeft()
,
and
GetRight()
being used to iterate over a MapApi
that contains
four entries after two calls to
Insert()
.
This code produces the following output:
//depot/... //client/... -//depot/d2/... //client/d2/... -//depot/d1/... //client/d1/... //depot/d1/... //client/d2/...
MapApi clientmap; clientmap.Insert( StrRef( "//depot/..." ), StrRef( "//client/..." ) ); clientmap.Insert( StrRef( "//depot/d1/..." ), StrRef( "//client/d2/..." ) ); char c = ' '; for ( int i = 0; i < clientmap.Count(); i++ ) { switch( clientmap.GetType( i ) ) { case MapInclude: c = ' '; break; case MapExclude: c = '-'; break; case MapOverlay: c = '+'; break; } printf( "%c%s %s\n", c, clientmap.GetLeft( i )->Text(), clientmap.GetRight( i )->Text() ); }
MapApi::GetLeft( int )
Returns the left side of the specified view entry.
Virtual? |
No |
|
Class |
||
Arguments |
|
the index of the desired entry |
Returns |
|
a string representing the left side of the entry |
Notes
The index should be between 0 and one less than the number of mapping entries.
See also
Example
See the example for MapApi::Count()
.
MapApi::GetRight( int )
Returns the right side of the specified view entry.
Virtual? |
No |
|
Class |
||
Arguments |
|
the index of the desired entry |
Returns |
|
a string representing the right side of the entry |
Notes
The index should be between 0 and one less than the number of mapping entries.
See also
Example
See the example for MapApi::Count()
.
MapApi::GetType( int )
Returns the type of the specified view entry.
Virtual? |
No |
|
Class |
||
Arguments |
|
the index of the desired entry |
Returns |
|
the entry type |
Notes
The entry type is one of MapInclude
,
MapExclude
, and MapOverlay
.
MapExclude
entries negate earlier
MapInclude
and MapOverlay
entries that map the same paths, and MapOverlay
entries are not disambiguated if they overlap with earlier
MapInclude
entries.
In human-readable Perforce view specifications,
MapExclude
lines are indicated with a
-
character, and MapOverlay
lines are indicated with a +
character.
See also
Example
See the example for MapApi::Count()
.
MapApi::Insert( const StrPtr &, MapType )
Adds a new entry to the mapping.
Virtual? |
No |
|
Class |
||
Arguments |
|
the path to which the entry applies |
|
the mapping type (by default, |
|
Returns |
|
Notes
This Insert()
overload is a convenience function that adds an entry with identical
left and right sides. It is meant to represent mappings whose sole
purpose is to include and exclude files, such as protection tables
and label views.
Example
The following example demonstrates the construction and use of a protection table mapping.
MapApi protect; protect.Insert( StrRef( "//..." ) ); protect.Insert( StrRef( "//private/..." ), MapExclude ); StrBuf to; StrBuf file1( "//depot/file.txt" ); StrBuf file2( "//private/file.txt" ); printf( "%s - access %d\n", file1.Text(), protect.Translate( file1, to ) ); printf( "%s - access %d\n", file2.Text(), protect.Translate( file2, to ) );
This produces the following output:
//depot/file.txt - access 1 //private/file.txt - access 0
MapApi::Insert( const StrPtr &, const StrPtr &, MapType )
Adds a new entry to the mapping.
Virtual? |
No |
|
Class |
||
Arguments |
|
the left side of the entry |
|
the right side of the entry |
|
|
the mapping type (by default,
|
|
Returns |
|
Notes
Insert()
adds
one new entry to a mapping at the "bottom" (highest precedence)
position in the map. The MapType
parameter
indicates whether the entry is a standard inclusion (the default), an
exclusion, or an overlay mapping (only useful when modeling a client
view).
Example
The following example demonstrates the construction and use of a branch view mapping.
MapApi branch; branch.Insert( StrRef( "//depot/main/..." ), StrRef( "//depot/rel1/..." ) ); StrBuf source( "//depot/main/file.c" ); StrBuf target; branch.Translate( source, target ); printf( "%s -> %s\n", source.Text(), target.Text() );
This produces the following output:
//depot/main/file.c -> //depot/rel1/file.c
MapApi::Join( MapApi *, MapApi * ) [static]
Joins two MapApi
s together to produce a
combined mapping.
Virtual? |
No |
|
Class |
||
Arguments |
|
the first mapping |
|
the second mapping |
|
Returns |
|
a new MapApi representing the joined maps |
Notes
This overload of
Join()
links
the right side of the first mapping to the left side of the second
mapping, as if the two mappings were laid out left to right and glued
together in the middle. The resulting MapApi
's
left side corresponds to the first mapping's left side, and its right
side corresponds to the second mapping's right side.
If the right side of the first mapping does not have anything in common with the left side of the second mapping, the resulting map is empty.
The other
Join()
overload
allows more control over which side of each mapping is joined to the
other, and the direction of the resulting mapping.
This function allocates a new MapApi
object on the
heap; the caller is responsible for deleting it.
Example
The following example demonstrates a join between a branch view and a client view.
MapApi branchmap; branchmap.Insert( StrRef( "//depot/main/..." ), StrRef( "//depot/rel1/...") ); MapApi clientmap; clientmap.Insert( StrRef( "//depot/..." ), StrRef( "//client/depot/..." ) ); MapApi *branch_to_client = MapApi::Join( &branchmap, &clientmap ); StrBuf source( "//depot/main/file.c" ); StrBuf target; branch_to_client->Translate( source, target ); printf( "%s -> %s\n", source.Text(), target.Text() ); delete branch_to_client;
This produces the following output:
//depot/main/file.c -> //client/depot/rel1/file.c
MapApi::Join( MapApi *, MapDir, MapApi *, MapDir ) [static]
Joins two MapApi
s together to produce a
combined mapping.
Virtual? |
No |
|
Class |
||
Arguments |
|
the first mapping |
|
the orientation of the first mapping |
|
|
the second mapping |
|
|
the orientation of the second mapping |
|
Returns |
|
a new MapApi representing the joined maps |
Notes
This overload of
Join()
works
exactly like the simpler two-argument overload, but allows the caller
to reverse either or both mappings before they are joined together.
Specifying MapLeftRight
as the direction for both
mappings will produce the same result as the two-argument
Join()
.
If the two mappings do not have anything in common at the join point, the result is an empty mapping.
This function allocates a new MapApi
object on the
heap; the caller is responsible for deleting it.
Example
The following example demonstrates a join between a branch view and a client view, with both mappings reversed so that the client path is on the left side of the result and the branch source is on the right side.
MapApi branchmap; branchmap.Insert( StrRef( "//depot/main/..." ), StrRef( "//depot/rel1/...") ); MapApi clientmap; clientmap.Insert( StrRef( "//depot/..." ), StrRef( "//client/depot/..." ) ); MapApi *client_to_branch = MapApi::Join ( &clientmap, MapRightLeft, &branchmap, MapRightLeft ); StrBuf clientFile( "//client/depot/rel1/file.c" ); StrBuf branchFile; client_to_branch->Translate( clientFile, branchFile ); printf( "%s -> %s\n", clientFile.Text(), branchFile.Text() ); delete client_to_branch;
Executing the preceding code produces the following output:
//client/depot/rel1/file.c -> //depot/main/file.c
MapApi::Translate( const StrPtr &, StrBuf&, MapDir )
Translates a file path from one side of a mapping to the other.
Virtual? |
No |
|
Class |
||
Arguments |
|
the input path |
|
the output path |
|
|
the direction in which to translate (by default,
|
|
Returns |
|
whether or not the translation succeeded |
Notes
The
Translate()
function is used to determine the effect of the mapping on any
particular file. In the case of a two-sided mapping (such as a client
view), it indicates where any given depot file maps in the client, or
vice versa. In the case of a one-sided mapping (such as a protection
table), it simply indicates whether a particular file is mapped at
all.
If the specified MapDir
is
MapLeftRight
, the input path is translated from
the left side of the mapping to the right side of the mapping. If the
MapDir
is MapRightLeft
, the
mapping is effectively inverted, so that the input path is translated
from the right side to the left.
If the input path does not match anything in the left side of the
mapping (or the right side in the MapRightLeft
case), the translation fails just as if the input path had been
excluded from the mapping.
Translate()
is designed to map single files. To model the effect of passing a
broader path through a mapping, create a new one-sided mapping that
represents that path and
Join()
it with
the other mapping.
Options methods
Options::GetValue( char opt, int subopt )
Returns the value of a flag previously stored by
Options::Parse()
.
Virtual? |
No |
|
Class |
||
Arguments |
|
The flag to check |
|
Return the argument associated with the
|
|
Returns |
|
The value of the flag. This is " |
Notes
You must call
Options::Parse()
before calling
GetValue()
.
If a flag does not occur on the command line,
GetValue()
returns NULL
.
If a flag is provided without a value,
GetValue
()
returns "true
".
If a flag appears only once on a command line, extract the value of
its arguments by calling
GetValue()
with a subopt
of zero, or use the
[]
operator.
If a flag occurs more than once on a command line, extract the value
supplied with each occurrence by calling
Options::GetValue()
once for each occurrence, using different subopt
values.
See also
Example
Executing the following code produces the following output:
$ getvalue -h -c1 -c2 -d3 opts.GetValue( h, 0 ) value is true opts.GetValue( c, 0 ) value is 1 opts.GetValue( c, 1 ) value is 2 opts.GetValue( d, 0 ) value is 3
#include <stdhdrs.h> #include <strbuf.h> #include <error.h> #include <options.h> int main( int argc, char **argv ) { // Parse options. Error *e = new Error(); ErrorId usage = { E_FAILED, "Usage: getvalue -h for usage." }; Options opts; // strip out the program name before parsing argc--; argv++; char *ParseOpts = "ha:b:c:d:e:f:"; opts.Parse( argc, argv, ParseOpts, OPT_ANY, usage, e ); if ( e->Test() ) { StrBuf msg; e->Fmt( &msg ); // See Error::Fmt() printf( "ERROR:\n%s", msg.Text() ); return 1; } char *iParseOpts = ParseOpts; int isubopt; StrPtr *s; // Print values for options. while( *iParseOpts != '\0' ) { if ( *iParseOpts != ':' ) { isubopt = 0; while( s = opts.GetValue( *iParseOpts, isubopt ) ) { printf( "opts.GetValue( %c, %d ) value is %s\n", *iParseOpts, isubopt, s->Text() ); isubopt++; } } iParseOpts++; } return 0; }
Options::operator[]( char opt )
Returns the value of a flag previously stored by
Options::Parse()
.
Virtual? |
No |
|
Class |
||
Arguments |
|
The flag to check |
Returns |
|
Notes
You must call
Options::Parse()
before using the []
operator.
If a flag does not occur on the command line, the
[]
operator returns NULL
.
If a flag is provided without a value, the []
operator returns "true
".
If a flag appears once on a command line, the []
operator returns its argument. This is equivalent to calling
Options::GetValue()
with a subopt
of zero.
The []
operator is sufficient for extracting the
value of any flag which does not have more than one value associated
with it. If a flag appears more than once on the same command line,
you must use
Options::GetValue()
,
specifying a different subopt
value for each
appearance.
See also
Example
The following code parses some of the standard Perforce global
options and stores them in a ClientApi
object.
If the -h
option is supplied, the program also
displays a brief message.
#include <iostream> #include <clientapi.h> #include <error.h> #include <errornum.h> #include <msgclient.h> #include <options.h> int main( int argc, char **argv ) { Error *e = new Error(); ErrorId usage = { E_FAILED, "Usage: myapp -h for usage." }; // Bypass argv[0] before parsing argc--; argv++; Options opts; opts.Parse( argc, argv, "hc:H:d:u:p:P:", OPT_ANY, usage, e ); if ( e->Test() ) { StrBuf msg; e->Fmt( &msg ); // See Error::Fmt() printf( "Error: %s", msg.Text() ); return 1; } ClientApi client; StrPtr *s; // Get command line overrides of client, host, cwd, user, port, pass if ( s = opts[ 'h' ] ) printf ( "User asked for help\n" ); if ( s = opts[ 'c' ] ) client.SetClient ( s ); if ( s = opts[ 'H' ] ) client.SetHost ( s ); if ( s = opts[ 'd' ] ) client.SetCwd ( s ); if ( s = opts[ 'u' ] ) client.SetUser ( s ); if ( s = opts[ 'p' ] ) client.SetPort ( s ); if ( s = opts[ 'P' ] ) client.SetPassword ( s ); // Perform desired operation(s) with your ClientApi here return 0; }
Options::Parse( int &, char ** &, const char *, int, const ErrorId &, Error * )
Manipulate argc
and argv
to
extract command line arguments and associated values.
Virtual? |
No |
|
Class |
||
Arguments |
|
Number of arguments |
|
An array of arguments to parse |
|
|
The list of valid options to extract |
|
|
A flag indicating how many arguments are expected to remain when parsing is complete |
|
|
An error message containing usage tips |
|
|
The |
|
Returns |
|
Notes
You must bypass argv[0]
(that is, the name of the
calling program) before calling
Options::Parse()
.
This is most easily done by decrementing argc
and
incrementing argv
.
An argument by be of the form
-a
value
or
-a
value
. Although
an argument of the form
-a
value
is passed
as two entries in argv
, the
Options::Parse()
method parses it as one logical argument.
As arguments are scanned from the caller's argv
,
the caller's argc
and argv
are
modified to reflect the arguments scanned. Scanning stops when the
next argument either:
-
does not begin with a
-
, or -
is a
-
only, or -
is not in the array of expected options.
Once scanning has stopped, argc
and
argv
are returned "as-is"; that is, they are
returned as they were when scanning stopped. There is no "shuffling"
of arguments.
The opts
argument is a format string indicating
which options are to be scanned, and whether these options are to
have associated values supplied by the user. Flags with associated
values must be followed by a colon (":
") or a
period (".
") in the format string. Using a colon
allows arguments to be specified in the form
-a
value
or
-a
value
; using a
period allows only the
-a
value
form.
If, based on the expectation set in the format string, the actual
option string in argv
does not provide a value
where one is expected, an error is generated.
For instance, the p4 Command Line Client's
-V
and -?
flags are
expected to be supplied without values, but the
-p
flag is expected to be accompanied with a
setting for P4PORT
. This is the format string used by
the p4 Command Line Client:
"?c:C:d:GRhH:p:P:l:L:su:v:Vx:z:Z:"
Characters followed by colons (c
,
C
, and so on) are command line flags that take values;
all characters not followed by colons (?
,
G
, R
, h
,
s
, and V
) represent command line
flags that require no values.
There is a limit of 20 options per command line, as defined in
options.h
by the constant
N_OPTS
.
The flag
argument should be one of the following
values (defined in options.h
):
Argument |
Value |
Meaning |
---|---|---|
|
|
Exactly one argument is expected to remain after parsing |
|
|
Exactly two arguments are expected to remain after parsing |
|
|
Exactly three arguments are expected to remain after parsing |
|
|
More than two arguments (three or more) are to remain after parsing |
|
|
Require that zero arguments remain after parsing; if arguments remain after parsing, set an error. |
|
|
If no arguments remain after parsing, create one that
points to |
|
|
|
|
|
|
|
|
|
|
|
|
See also
Example
The following code and examples illustrate how
Options::Parse()
works.
#include <stdhdrs.h> #include <strbuf.h> #include <error.h> #include <options.h> int main( int argc, char **argv ) { // Parse options. Error *e = new Error(); ErrorId usage = { E_FAILED, "Usage: parse optionstring flag args" }; Options opts; // strip out the program name before parsing argc--; argv++; // next argument is options to be parsed char *ParseOpts = argv[ 0 ]; argc--; argv++; // next argument is number of arguments remaining after parse int flag = strtol( argv[ 0 ], NULL, 0 ); argc--; argv++; // Echo pre-parse values int iargv; printf( "Prior to Options::Parse call:\n" ); printf( " ParseOpts is %s\n", ParseOpts ); printf( " flag is 0x%2.2X\n", flag ); printf( " argc is %d\n", argc ); for ( iargv = 0; iargv < argc; iargv++ ) { printf( " argv[ %d ] is %s\n", iargv, argv[ iargv ] ); } printf( "\n" ); opts.Parse( argc, argv, ParseOpts, flag, usage, e ); if ( e->Test() ) { // See example for Error::Fmt() StrBuf msg; e->Fmt( &msg ); printf( "ERROR:\n%s\n", msg.Text() ); } char *iParseOpts = ParseOpts; int isubopt; StrPtr *s; // Print values for options. while( *iParseOpts != '\0' ) { if ( *iParseOpts != ':' ) { isubopt = 0; while( s = opts.GetValue( *iParseOpts, isubopt ) ) { printf( "opts.GetValue( %c, %d ) value is %s\n", *iParseOpts, isubopt, s->Text() ); isubopt++; } } iParseOpts++; } // Echo post-parse values printf( "\n" ); printf( "After Options::Parse call:\n" ); printf( " argc is %d\n", argc ); for ( iargv = 0; iargv < argc; iargv++ ) { printf( " argv[ %d ] is %s\n", iargv, argv[ iargv ] ); } return 0; }
Invoke parsedemo
with a format string, a flag (as
defined in options.h
) to specify the number of
options expected, and a series of arguments.
For instance, to allow arguments -a
,
-b
and -c
, where
-a
and -b
take values,
but -c
does not take a value, and to use a
flag
of OPT_NONE
(0x10
) to require that no options remain unparsed
after the call to
Options::Parse()
,
invoke parsedemo
as follows.
$ parsedemo a:b:c 0x10 -a vala -b valb -c
Arguments of the form -c one
are passed as two
entries in argv
, but parsed as one logical
argument:
$ parsedemo ha:b:c:d:e: 0x10 -cone Prior to Options::Parse call: ParseOpts is ha:b:c:d:e: flag is 0x10 argc is 1 argv[ 0 ] is -cone opts.GetValue( c, 0 ) value is one After Options::Parse call: argc is 0 $ parsedemo ha:b:c:d:e: 0x10 -c one Prior to Options::Parse call: ParseOpts is ha:b:c:d:e: flag is 0x10 argc is 2 argv[ 0 ] is -c argv[ 1 ] is one opts.GetValue( c, 0 ) value is one After Options::Parse call: argc is 0
Use of a period in the options string disallows the -c
one
form for the c
option:
$ parsedemo ha:b:c.d:e: 0x10 -c one Prior to Options::Parse call: ParseOpts is ha:b:c.d:e: flag is 0x10 argc is 2 argv[ 0 ] is -c argv[ 1 ] is one ERROR: Usage: parse optionstring flag args Unexpected arguments. opts.GetValue( c, 0 ) value is After Options::Parse call: argc is 1 argv[ 0 ] is one
Arguments not in the format string are permitted or rejected with the
use of different flag values;
OPT_NONE
(0x10
) requires that
no arguments remain after the call to
Options::Parse()
,
while OPT_ONE
(0x01
) requires
that one argument remain.
$ parsedemo ha:b:c:d:e: 0x10 -c one two Prior to Options::Parse call: ParseOpts is ha:b:c:d:e: flag is 0x10 argc is 3 argv[ 0 ] is -c argv[ 1 ] is one argv[ 2 ] is two ERROR: Usage: parse optionstring flag args Unexpected arguments. opts.GetValue( c, 0 ) value is one $ parse ha:b:c:d:e: 0x01 -c one two Prior to Options::Parse call: ParseOpts is ha:b:c:d:e: flag is 0x01 argc is 3 argv[ 0 ] is -c argv[ 1 ] is one argv[ 2 ] is two opts.GetValue( c, 0 ) value is one After Options::Parse call: argc is 1 argv[ 0 ] is two
Options::Parse( int &, StrPtr * &, const char *, int, const ErrorId &, Error * )
Extract command line arguments and associated values.
Virtual? |
No |
|
Class |
||
Arguments |
|
Number of arguments |
|
An array of arguments to parse |
|
|
The list of valid options to extract |
|
|
A flag indicating how many arguments are expected to remain when parsing is complete |
|
|
An error message containing usage tips |
|
|
The |
|
Returns |
|
Notes
See the notes for the char ** &argv
version of
Options::Parse()
for details.
See also
Signaler methods
Signaler::Block()
Cause interrupt signals from the user to be ignored until a subsequent
call to
Signaler::Catch()
.
Virtual? |
No |
|
Class |
||
Arguments |
None |
|
Returns |
|
Notes
Block()
does
not actually block the signals, but causes the process to ignore
them.
For portability reasons,
Block()
and
Catch()
use the BSD/ANSI C signal(2)
function rather than
the POSIX sigaction()
.
See also
Example
#include <unistd.h> // for sleep() #include <stdhdrs.h> #include <strbuf.h> #include <signaler.h> int main( int argc, char **argv ) { // Block ^C printf( "For the next 5 seconds, ^C will be ignored\n" ); signaler.Block(); sleep( 5 ); printf( "Enabling ^C again\n" ); signaler.Catch(); for ( ; ; ) sleep( 60 ); exit( 0 ); }
Signaler::Catch()
Allow interrupt signals from the user to be delivered once more
following a previous call to
Signaler::Block()
.
Virtual? |
No |
|
Class |
||
Arguments |
None |
|
Returns |
|
Notes
Catch()
does
not replace your signal handler if you have already replaced the
Signaler
class' handler with one of your own using
the ANSI signal(2)
function.
For portability reasons,
Block()
and
Catch()
use the BSD/ANSI C signal(2)
function rather than
the POSIX sigaction()
.
See also
Example
int main( int argc, char **argv ) { // Block ^C printf( "For the next 5 seconds, ^C will be ignored\n" ); signaler.Block(); sleep( 5 ); printf( "Enabling ^C again\n" ); signaler.Catch(); for ( ; ; ) sleep( 60 ); exit( 0 ); }
Signaler::DeleteOnIntr( void * )
Removes a function previously registered using
OnIntr()
from the list.
Virtual? |
No |
|
Class |
||
Arguments |
|
Pointer to the data item with which the original function was registered |
Returns |
|
See also
Example
#include <unistd.h> // for sleep() #include <stdhdrs.h> #include <strbuf.h> #include <signaler.h> class MyClass { public: void Set( StrPtr *d ) { data = *d; } const StrPtr *Get() { return &data; } void Identify() { printf( "I'm %s\n", data.Text() ); } private: StrBuf data; }; static void InterruptHandler( void *p ) { MyClass *m = ( MyClass * )p; m->Identify(); } int main( int argc, char **argv ) { StrBuf data; MyClass *list[ 5 ]; for ( int i = 1; i <= 5; i++ ) { data.Set( "Object" ); data << i; MyClass *p = new MyClass; list[ i - 1 ] = p; p->Set( &data ); signaler.OnIntr( InterruptHandler, (void *)p ); } // Unregister Object 3 signaler.DeleteOnIntr( list[ 2 ] ); printf( "Hit ^C to fire the interrupt handler\n" ); for ( ; ; ) sleep( 60 ); exit( 0 ); }
Signaler::Intr()
Coordinate execution of all functions registered by
Signaler::OnIntr()
.
Virtual? |
No |
|
Class |
||
Arguments |
None |
|
Returns |
|
Notes
Intr()
is the
Signaler
class's main handler for interrupt
signals.
Most Perforce client applications do not need to call
Intr()
directly, because it is called directly from the internal handler
function that catches the interrupt signals.
This internal handler function also causes the process to exit,
returning an exit status of -1 to the operating system. (For
instance,
signaler.Intr()
; exit( -1 )
)
If you require more flexible or complex interrupt handling, replace
the default interrupt handler function with your own by using the
ANSI C signal(2)
function, and call
Intr()
to execute the registered functions.
Caveat
Intr()
does
not deregister functions after they have been called. When calling a
registered function twice might cause a failure, immediately
deregister it using
DeleteOnIntr()
after the function has been called.
See also
Example
#include <unistd.h> // for sleep() #include <signal.h> #include <stdhdrs.h> #include <strbuf.h> #include <signaler.h> class MyClass { public: void Set( StrPtr *d ) { data = *d; } const StrPtr *Get() { return &data; } void Identify() { printf( "I'm %s\n", data.Text() ); } private: StrBuf data; }; static int intrCount = 0; static const int maxIntr = 3; // Replacement handler for SIGINT signals. Overrides Signaler class's // default handler to avoid immediate exit. static void trap_interrupt( int sig ) { intrCount++; printf( "Received SIGINT. Calling registered functions...\n" ); signaler.Intr(); printf( "All functions done\n\n" ); if ( intrCount >= maxIntr ) { printf( "Interrupt limit hit. Exiting...\n" ); exit( 0 ); } } static void InterruptHandler( void *p ) { MyClass *m = ( MyClass * )p; m->Identify(); // Don't identify this object again signaler.DeleteOnIntr( p ); } int main( int argc, char **argv ) { signal( SIGINT, trap_interrupt ); signaler.Catch(); int objCount = 5; int nextId = 1; for ( ; ; ) { int i; for ( i = nextId; i < nextId + objCount; i++ ) { StrBuf data; data.Set( "Object" ); data << i; MyClass *p = new MyClass; p->Set( &data ); printf( "Registering %s\n", data.Text() ); signaler.OnIntr( InterruptHandler, ( void * )p ); } nextId = i; printf( "\n" ); printf( "Hit ^C to fire the interrupt handler [%d to go]\n", maxIntr - intrCount ); sleep( 10 ); } exit( 0 ); }
Signaler::OnIntr( SignalFunc, void * )
Register a function and argument to be called when an interrupt signal is received.
Virtual? |
No |
|
Class |
||
Arguments |
|
Pointer to a function to call on receipt of an interrupt signal.
The function must have the prototype
|
|
Pointer to a data item to pass to the callback function when invoking it. |
|
Returns |
|
Notes
Functions are called in the reverse order that they are registered.
See also
Example
#include <unistd.h> // for sleep() #include <stdhdrs.h> #include <strbuf.h> #include <signaler.h> class MyClass { public: void Set( StrPtr *d ) { data = *d; } const StrPtr *Get() { return &data; } void Identify() { printf( "I'm %s\n", data.Text() ); } private: StrBuf data; }; static void InterruptHandler( void *p ) { MyClass *m = ( MyClass * )p; m->Identify(); } int main( int argc, char **argv ) { for ( int i = 1; i <= 5; i++ ) { StrBuf data; data.Set( "Object" ); data << i; MyClass *p = new MyClass; p->Set( &data ); signaler.OnIntr( InterruptHandler, ( void * )p ); } printf( "Hit ^C to fire the interrupt handler\n" ); for ( ; ; ) sleep( 60 ); exit( 0 ); }
Signaler::Signaler() (constructor)
Constructs a new Signaler
object.
Virtual? |
No |
|
Class |
||
Arguments |
N/A |
|
Returns |
N/A |
Notes
There is rarely a need for API users to construct
Signaler
objects themselves. Use the global
Signaler
variable signaler
instead.
StrBuf methods
StrBuf::Alloc( int )
Allocate an additional specified number of bytes to a
StrBuf
. The string pointed to by the
StrBuf
's buffer
is logically
extended.
Virtual? |
No |
|
Class |
||
Arguments |
|
number of bytes to be allocated |
Returns |
|
pointer to the first additional byte allocated |
Notes
The length
of the StrBuf
is
incremented by the len
argument.
If the memory for the StrBuf
's
buffer
is not large enough, enough new memory is
allocated to contiguously contain the extended string. If new memory
is allocated, the old memory is freed. (All StrBuf
member functions with the potential to increase the length of a
StrBuf
manage memory this way.)
A call to
Alloc()
might
change the string pointed to by the StrBuf
's
buffer
; do not rely on pointer arithmetic to
determine the new pointer, because the call to
Alloc()
might have moved the buffer location.
Example
#include <iostream> #include <iomanip> #include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { StrBuf sb; char *p; sb.Set( "xyz" ); cout << "sb.Text() prior to sb.Alloc( 70 ) returns "; cout << "\"" << sb.Text() << "\"\n"; cout << "(int)sb.Text() prior to sb.Alloc( 70 ) returns 0x" << hex; cout << setw( 8 ) << setfill( '0' ) << (int)sb.Text() << dec << "\n"; cout << "sb.Length() prior to sb.Alloc( 70 ) returns "; cout << sb.Length() << "\n\n"; p = sb.Alloc( 70 ); // allocate in StrBuf cout << "sb.Text() after sb.Alloc( 70 ) returns (first three bytes) "; cout << "\"" << setw( 3 ) << sb.Text() << "\"\n"; cout << "(int)sb.Text() after sb.Alloc( 70 ) returns 0x" << hex; cout << setw( 8 ) << setfill( '0' ) << (int)sb.Text() << dec << "\n"; cout << "(int)sb.Alloc( 70 ) returned 0x" << hex; cout << setw( 8 ) << setfill( '0' ) << (int)p << dec << "\n"; cout << "sb.Length() after sb.Alloc( 70 ) returns "; cout << sb.Length() << "\n"; }
Executing the preceding code produces the following output:
sb.Text() prior to sb.Alloc( 70 ) returns "xyz" (int)sb.Text() prior to sb.Alloc( 70 ) returns 0x0804a9a0 sb.Length() prior to sb.Alloc( 70 ) returns 3 sb.Text() after sb.Alloc( 70 ) returns (first three bytes) "xyz" (int)sb.Text() after sb.Alloc( 70 ) returns 0x0804a9b0 (int)sb.Alloc( 70 ) returned 0x0804a9b3 sb.Length() after sb.Alloc( 70 ) returns 73
StrBuf::Append( const char * )
Append a null-terminated string to a StrBuf
. The
string is logically appended to the string pointed to by the
StrBuf
's buffer
.
Virtual? |
No |
|
Class |
||
Arguments |
|
pointer to the first byte of the null-terminated string |
Returns |
|
Notes
The StrBuf
's length
is
incremented by the number of bytes prior to the first null byte in
the string.
If the memory for the StrBuf
's
buffer
is not large enough, new memory to
contiguously contain the results of appending the null-terminated
string is allocated. If new memory is allocated, the old memory is
freed. Any memory allocated is separate from the memory for the
string.
Example
int main( int argc, char **argv ) { char chars[] = "zy"; StrBuf sb; sb.Set( "xyz" ); cout << "sb.Text() prior to sb.Append( chars ) returns "; cout << "\"" << sb.Text() << "\"\n"; cout << "sb.Length() prior to sb.Append( chars ) returns "; cout << sb.Length() << "\n\n"; sb.Append( chars ); // append char * to StrBuf cout << "sb.Text() after sb.Append( chars ) returns "; cout << "\"" << sb.Text() << "\"\n"; cout << "sb.Length() after sb.Append( chars ) returns "; cout << sb.Length() << "\n"; }
Executing the preceding code produces the following output:
sb.Text() prior to sb.Append( chars ) returns "xyz" sb.Length() prior to sb.Append( chars ) returns 3 sb.Text() after sb.Append( chars ) returns "xyzzy" sb.Length() after sb.Append( chars ) returns 5
StrBuf::Append( const char *, int )
Append a string of a specified length to a StrBuf
.
The string is logically appended to the string pointed to by the
StrBuf
's buffer
.
Virtual? |
No |
|
Class |
||
Arguments |
|
pointer to the first byte of the string |
|
length of the string |
|
Returns |
|
Notes
Exactly len
bytes are appended to the
StrBuf
from the string. The
length
of the StrBuf
is
incremented by the len
argument.
If the memory for the StrBuf
's
buffer
is not large enough, new memory to
contiguously contain the results of appending the string of specified
length is allocated. If new memory is allocated, the old memory is
freed. Any memory allocated is separate from the memory for the
string.
Example
#include <iostream> #include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { char chars[] = "zyx"; StrBuf sb; sb.Set( "xyz" ); cout << "sb.Text() prior to sb.Append( chars, 2 ) returns "; cout << "\"" << sb.Text() << "\"\n"; cout << "sb.Length() prior to sb.Append( chars, 2 ) returns "; cout << sb.Length() << "\n\n"; sb.Append( chars, 2 ); // append len bytes of char * to StrBuf cout << "sb.Text() after sb.Append( chars, 2 ) returns "; cout << "\"" << sb.Text() << "\"\n"; cout << "sb.Length() after sb.Append( chars, 2 ) returns "; cout << sb.Length() << "\n"; }
Executing the preceding code produces the following output:
sb.Text() prior to sb.Append( chars, 2 ) returns "xyz" sb.Length() prior to sb.Append( chars, 2 ) returns 3 sb.Text() after sb.Append( chars, 2 ) returns "xyzzy" sb.Length() after sb.Append( chars, 2 ) returns 5
StrBuf::Append( const StrPtr * )
Append a StrPtr
to a StrBuf
.
The argument is passed as a pointer to the
StrPtr
. The string pointed to by the
StrPtr
's buffer
is logically
appended to the string pointed to by the
StrBuf
's buffer
. Arguments
are commonly addresses of instances of classes derived from the
StrPtr
class, such as StrRef
and StrBuf
.
Virtual? |
No |
|
Class |
||
Arguments |
|
pointer to the |
Returns |
|
Notes
Initialize the StrBuf
and the
StrPtr
before calling
Append()
.
Exactly the number of bytes specified by the
length
of the StrPtr
are
appended to the StrBuf
from the
StrPtr
. The length
of the
StrBuf
is incremented by the
length
of the StrPtr
.
If the memory for the StrBuf
's
buffer
is not large enough, new memory to
contiguously contain the results of appending the
StrPtr
is allocated. If new memory is
allocated, the old memory is freed. Any memory allocated is
separate from the memory for the StrPtr
.
Example
#include <iostream> #include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { StrRef sr( "zy" ); StrPtr *sp = &sr; StrBuf sba; StrBuf sbb; sba.Set( "xyz" ); sbb.Set( "xyz" ); cout << "sba.Text() after sba.Set( \"xyz\" ) returns "; cout << "\"" << sba.Text() << "\"\n"; cout << "sba.Length() after sba.Set( \"xyz\" ) returns "; cout << sba.Length() << "\n"; cout << "sbb.Text() after sbb.Set( \"xyz\" ) returns "; cout << "\"" << sbb.Text() << "\"\n"; cout << "sbb.Length() after sbb.Set( \"xyz\" ) returns "; cout << sbb.Length() << "\n\n"; sba.Append( sp ); // append StrPtr * to StrBuf cout << "sba.Text() after sba.Append( sp ) returns "; cout << "\"" << sba.Text() << "\"\n"; cout << "sba.Length() after sba.Append( sp ) returns "; cout << sba.Length() << "\n\n"; sbb.Append( &sr ); // append &StrRef to StrBuf cout << "sbb.Text() after sbb.Append( &sr ) returns "; cout << "\"" << sbb.Text() << "\"\n"; cout << "sbb.Length() after sbb.Append( &sr ) returns "; cout << sbb.Length() << "\n\n"; sba.Append( &sbb ); // append &StrBuf to StrBuf cout << "sba.Text() after sba.Append( &sbb ) returns "; cout << "\"" << sba.Text() << "\"\n"; cout << "sba.Length() after sba.Append( &sbb ) returns "; cout << sba.Length() << "\n"; }
Executing the preceding code produces the following output:
sba.Text() after sba.Set( "xyz" ) returns "xyz" sba.Length() after sba.Set( "xyz" ) returns 3 sbb.Text() after sbb.Set( "xyz" ) returns "xyz" sbb.Length() after sbb.Set( "xyz" ) returns 3 sba.Text() after sba.Append( sp ) returns "xyzzy" sba.Length() after sba.Append( sp ) returns 5 sbb.Text() after sbb.Append( &sr ) returns "xyzzy" sbb.Length() after sbb.Append( &sr ) returns 5 sba.Text() after sba.Append( &sbb ) returns "xyzzyxyzzy" sba.Length() after sba.Append( &sbb ) returns 10
StrBuf::Clear()
Clear the length
member of a
StrBuf
.
Virtual? |
No |
|
Class |
||
Arguments |
None |
|
Returns |
|
Notes
Only the length
member of the
StrBuf
is zeroed.
To set the buffer
member to a zero-length string,
call
Terminate()
after calling
Clear()
.
See also
Example
#include <iostream> #include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { StrBuf sb; sb.Set( "xyz" ); cout << "Prior to sb.Clear() and sb.Terminate():\n"; cout << " sb.Length() returns " << sb.Length() << "\n"; cout << " sb.Text() returns \"" << sb.Text() << "\"\n\n"; sb.Clear(); // zero out the length cout << "After sb.Clear() but prior to sb.Terminate():\n"; cout << " sb.Length() returns " << sb.Length() << "\n"; cout << " sb.Text() returns \"" << sb.Text() << "\"\n\n"; sb.Terminate(); cout << "After sb.Clear() and sb.Terminate():\n"; cout << " sb.Length() returns " << sb.Length() << "\n"; cout << " sb.Text() returns \"" << sb.Text() << "\"\n"; }
Executing the preceding code produces the following output:
Prior to sb.Clear() and sb.Terminate(): sb.Length() returns 3 sb.Text() returns "xyz" After sb.Clear() but prior to sb.Terminate(): sb.Length() returns 0 sb.Text() returns "xyz" After sb.Clear() and sb.Terminate(): sb.Length() returns 0 sb.Text() returns ""
StrBuf::StrBuf() (Constructor)
Construct a StrBuf
.
Virtual? |
No |
|
Class |
||
Arguments |
None |
|
Returns |
N/A |
Notes
The StrBuf
constructor initializes the
StrBuf
to contain a zero-length null buffer.
Example
int main( int argc, char **argv ) { StrBuf sb; // constructor called cout << "sb.Text() returns \"" << sb.Text() << "\"\n"; cout << "sb.Length() returns " << sb.Length() << "\n"; }
Executing the preceding code produces the following output:
sb.Text() returns "" sb.Length() returns 0
StrBuf::StrBuf( const StrBuf & ) (Copy Constructor)
Construct a copy of a StrBuf
.
Virtual? |
No |
|
Class |
||
Arguments |
|
(implied) reference of the |
Returns |
N/A |
Notes
The StrBuf
copy constructor creates a copy of a
StrBuf
. The StrBuf
from which
copying occurs must be initialized before calling the copy
constructor.
The StrBuf
copy constructor initializes the new
StrBuf
to contain a zero-length null buffer, and
sets the contents of the new StrBuf
using the
contents of the original StrBuf
. Any memory
allocated for the buffer
of the copy is separate
from the memory for the buffer
of the original
StrBuf
.
Example
#include <iostream> #include <stdhdrs.h> #include <strbuf.h> void called( StrBuf csb ) { csb << "zy"; cout << "called() csb.Text() returns \"" << csb.Text() << "\"\n"; } int main( int argc, char **argv ) { StrBuf sb; sb.Set( "xyz" ); called( sb ); // copy constructor called cout << "main() sb.Text() returns \"" << sb.Text() << "\"\n"; }
Executing the preceding code produces the following output:
called() csb.Text() returns "xyzzy" main() sb.Text() returns "xyz"
StrBuf::~StrBuf() (Destructor)
Destroy a StrBuf
.
Virtual? |
No |
|
Class |
||
Arguments |
None |
|
Returns |
N/A |
Notes
The StrBuf
destructor destroys a
StrBuf
.
If the buffer
points to allocated memory other
than nullStrBuf
, the allocated memory is freed.
Example
#include <iostream> #include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { StrBuf *psb; psb = new StrBuf; psb->Set( "xyz" ); cout << "psb->Text() returns \"" << psb->Text() << "\"\n"; delete psb; // destructor called and allocated memory freed }
Executing the preceding code produces the following output:
psb->Text() returns "xyz"
StrBuf::Extend( char )
Extend a StrBuf
by one byte. The string pointed to
by the StrBuf
's buffer
is
logically extended.
Virtual? |
No |
|
Class |
||
Arguments |
|
the byte copied to the extended string |
Returns |
|
Notes
One byte is copied to the extended StrBuf
. The
length
of the StrBuf
is
incremented by one.
Extend()
does not null-terminate the extended string pointed to by the
StrBuf
's buffer
. To ensure that
the extended string is null-terminated, call
Terminate()
after calling
Extend()
.
If the memory for the StrBuf
's
buffer
is not large enough, enough new memory is
allocated to contiguously contain the extended string. If new memory
is allocated, the old memory is freed. Any memory allocated is
separate from the memory for the byte.
See also
Example
#include <iostream> #include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { StrBuf sb; sb.Set( "xy" ); cout << "sb.Text() prior to sb.Extend( 'z' ) returns "; cout << "\"" << sb.Text() << "\"\n"; cout << "sb.Length() prior to sb.Extend( 'z' ) returns "; cout << sb.Length() << "\n\n"; sb.Extend( 'z' ); // extend StrBuf from char sb.Terminate(); cout << "sb.Text() after sb.Extend( 'z' ) returns "; cout << "\"" << sb.Text() << "\"\n"; cout << "sb.Length() after sb.Extend( 'z' ) returns "; cout << sb.Length() << "\n"; }
Executing the preceding code produces the following output:
sb.Text() prior to sb.Extend( 'z' ) returns "xy" sb.Length() prior to sb.Extend( 'z' ) returns 2 sb.Text() after sb.Extend( 'z' ) returns "xyz" sb.Length() after sb.Extend( 'z' ) returns 3
StrBuf::Extend( const char *, int )
Extend a StrBuf
by a string of a specified
length. The string pointed to by the StrBuf
's
buffer
is logically extended.
Virtual? |
No |
|
Class |
||
Arguments |
|
pointer to the first byte of the string |
|
length of the string |
|
Returns |
|
Notes
Exactly len
bytes are copied from the string to
the extended StrBuf
. The length
of the StrBuf
is incremented by
len
bytes.
Extend()
does
not null-terminate the extended string pointed to by the
StrBuf
's buffer
. To ensure that
the extended string is null-terminated, call
Terminate()
after calling
Extend()
.
If the memory for the StrBuf
's
buffer
is not large enough, enough new memory is
allocated to contiguously contain the extended string. If new memory
is allocated, the old memory is freed. Any memory allocated is
separate from the memory for the string.
See also
Example
int main( int argc, char **argv ) { char chars[] = "zyx"; StrBuf sb; sb.Set( "xyz" ); cout << "sb.Text() prior to sb.Extend( chars, 2 ) returns "; cout << "\"" << sb.Text() << "\"\n"; cout << "sb.Length() prior to sb.Extend( chars, 2 ) returns "; cout << sb.Length() << "\n\n"; sb.Extend( chars, 2 ); // extend StrBuf from len bytes of char * sb.Terminate(); cout << "sb.Text() after sb.Extend( chars, 2 ) returns "; cout << "\"" << sb.Text() << "\"\n"; cout << "sb.Length() after sb.Extend( chars, 2 ) returns "; cout << sb.Length() << "\n"; }
Executing the preceding code produces the following output:
sb.Text() prior to sb.Extend( chars, 2 ) returns "xyz" sb.Length() prior to sb.Extend( chars, 2 ) returns 3 sb.Text() after sb.Extend( chars, 2 ) returns "xyzzy" sb.Length() after sb.Extend( chars, 2 ) returns 5
StrBuf::operator =( const char * )
Assign a StrBuf
from a null-terminated string.
Virtual? |
No |
|
Class |
||
Arguments |
|
(implied) pointer to the first byte of the null-terminated string |
Returns |
|
Notes
Initialize the StrBuf
before the assignment.
The length
is set to the number of bytes prior to
the first null byte in the string.
Any memory allocated for the StrBuf
's
buffer
is separate from the memory for the string.
Example
#include <iostream> #include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { char chars[] = "xyz"; StrBuf sb; sb = chars; // assign StrBuf from char * cout << "chars[] = \"" << chars << "\"\n"; cout << "sb.Text() returns \"" << sb.Text() << "\"\n"; }
Executing the preceding code produces the following output:
chars[] = "xyz" sb.Text() returns "xyz"
StrBuf::operator =( const StrBuf & )
Assign a StrBuf
from another
StrBuf
.
Virtual? |
No |
|
Class |
||
Arguments |
|
(implied) reference of the |
Returns |
|
Notes
Initialize both StrBuf
s before the assignment.
Any memory allocated for the assigned StrBuf
's
buffer
is separate from the memory for the
StrBuf
's buffer
from which
assignment occurs.
Do not assign a StrBuf
to itself.
Example
#include <iostream> #include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { StrBuf sba; StrBuf sbb; sba.Set( "xyz" ); sbb = sba; // assign StrBuf to StrBuf cout << "sba.Text() returns \"" << sba.Text() << "\"\n"; cout << "sbb.Text() returns \"" << sbb.Text() << "\"\n"; }
Executing the preceding code produces the following output:
sba.Text() returns "xyz" sbb.Text() returns "xyz"
StrBuf::operator =( const StrPtr & )
Assign a StrBuf
from a
StrPtr
.
Virtual? |
No |
|
Class |
||
Arguments |
|
(implied) reference of the |
Returns |
|
Notes
Initialize the StrBuf
and the
StrPtr
before assignment.
Any memory allocated for the StrBuf
's
buffer
is separate from the memory for the
StrPtr
's buffer
.
Example
#include <iostream> #include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { StrRef sr( "xyz" ); StrPtr *sp = &sr; StrBuf sb; sb = *sp; // assign StrBuf from StrPtr cout << "sp->Text() returns \"" << sp->Text() << "\"\n"; cout << "sb.Text() returns \"" << sb.Text() << "\"\n"; }
Executing the preceding code produces the following output:
sp->Text() returns "xyz" sb.Text() returns "xyz"
StrBuf::operator =( const StrRef & )
Assign a StrBuf
from a
StrRef
.
Virtual? |
No |
|
Class |
||
Arguments |
|
(implied) reference of the |
Returns |
|
Notes
Initialize the StrBuf
and
StrRef
before assignment.
Any memory allocated for the StrBuf
's
buffer
is separate from that of the
StrRef
's buffer
.
Example
#include <iostream> #include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { StrRef sr( "xyz" ); StrBuf sb; sb = sr; // assign StrBuf from StrRef cout << "sr.Text() returns \"" << sr.Text() << "\"\n"; cout << "sb.Text() returns \"" << sb.Text() << "\"\n"; }
Executing the preceding code produces the following output:
sr.Text() returns "xyz" sb.Text() returns "xyz"
StrBuf::operator <<( const char * )
Append a null-terminated string to a StrBuf
.
The string is logically appended to the string pointed to by the
StrBuf
's buffer
.
Virtual? |
No |
|
Class |
||
Arguments |
|
(implied) pointer to the first byte of the null-terminated string |
Returns |
|
reference of the |
Notes
The StrBuf
's length
is
incremented by the number of bytes prior to the first null byte in
the string.
If the memory for the StrBuf
's
buffer
is not large enough, new contiguous memory
is allocated to contain the results of appending the null-terminated
string. If new memory is allocated, the old memory is freed. Any
memory allocated is separate from the memory for the string.
Example
#include <iostream> #include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { char chars[] = "zy"; StrBuf sb; sb.Set( "xyz" ); cout << "sb.Text() prior to sb << chars returns "; cout << "\"" << sb.Text() << "\"\n"; cout << "sb.Length() prior to sb << chars returns "; cout << sb.Length() << "\n\n"; sb << chars; // append char * to StrBuf cout << "sb.Text() after sb << chars returns "; cout << "\"" << sb.Text() << "\"\n"; cout << "sb.Length() after sb << chars returns "; cout << sb.Length() << "\n"; }
Executing the preceding code produces the following output:
sb.Text() prior to sb << chars returns "xyz" sb.Length() prior to sb << chars returns 3 sb.Text() after sb << chars returns "xyzzy" sb.Length() after sb << chars returns 5
StrBuf::operator <<( int )
Append a formatted integer to a StrBuf
. The
formatted integer is logically appended to the string pointed to
by the StrBuf
's buffer
.
Virtual? |
No |
|
Class |
||
Arguments |
|
(implied) integer |
Returns |
|
reference of the |
Notes
The integer is formatted with the logical equivalent of
sprintf( buf, "%d", v )
.
The length
is incremented by the number of bytes
of the formatted integer.
If the memory for the StrBuf
's
buffer
is not large enough, new contiguous memory
is allocated to contain the results of appending the formatted
integer. If new memory is allocated, the old memory is freed. Any
memory allocated is separate from the memory for the formatted
integer.
Example
#include <iostream> #include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { StrBuf sb; int i; sb.Set( "xyz" ); i = 73; cout << "sb.Text() prior to sb << i returns "; cout << "\"" << sb.Text() << "\"\n"; cout << "sb.Length() prior to sb << i returns "; cout << sb.Length() << "\n\n"; sb << i; // append (formatted) int to StrBuf cout << "sb.Text() after sb << i returns "; cout << "\"" << sb.Text() << "\"\n"; cout << "sb.Length() after sb << i returns "; cout << sb.Length() << "\n"; }
Executing the preceding code produces the following output:
sb.Text() prior to sb << i returns "xyz" sb.Length() prior to sb << i returns 3 sb.Text() after sb << i returns "xyz73" sb.Length() after sb << i returns 5
StrBuf::operator <<( const StrPtr * )
Append a StrPtr
to a StrBuf
.
The string pointed to by the StrPtr
's
buffer
is logically appended to the string
pointed to by the StrBuf
's
buffer
.
Virtual? |
No |
|
Class |
||
Arguments |
|
(implied) pointer to the |
Returns |
|
reference of the |
Notes
Exactly the number of bytes specified by the
StrPtr
's length
are appended to
the StrBuf
. The StrBuf
's
length
is incremented by the
StrPtr
's length
.
If the memory for the StrBuf
's
buffer
is not large enough, new contiguous memory
is allocated to contain the results of appending the
StrPtr
. If new memory is allocated, the old memory
is freed. Any memory allocated is separate from the memory for the
StrPtr
.
Example
#include <iostream> #include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { StrRef sr( "zy" ); StrPtr *sp = &sr; StrBuf sb; sb.Set( "xyz" ); cout << "sb.Text() prior to sb << sp returns "; cout << "\"" << sb.Text() << "\"\n"; cout << "sb.Length() prior to sb << sp returns "; cout << sb.Length() << "\n\n"; sb << sp; // append StrPtr * to StrBuf cout << "sb.Text() after sb << sp returns "; cout << "\"" << sb.Text() << "\"\n"; cout << "sb.Length() after sb << sp returns "; cout << sb.Length() << "\n"; }
Executing the preceding code produces the following output:
sb.Text() prior to sb << sp returns "xyz" sb.Length() prior to sb << sp returns 3 sb.Text() after sb << sp returns "xyzzy" sb.Length() after sb << sp returns 5
StrBuf::operator <<( const StrPtr & )
Append a StrPtr
to a StrBuf
.
The argument is passed as a reference of the
StrPtr
. The string pointed to by the
StrPtr
's buffer
is logically
appended to the string pointed to by the
StrBuf
's buffer
.
Virtual? |
No |
|
Class |
||
Arguments |
|
(implied) reference of the |
Returns |
|
reference of the |
Notes
Arguments are typically instances of classes derived from the
StrPtr
class, such as StrRef
and StrBuf
.
Exactly the number of bytes specified by the
length
of the StrPtr
are
appended to the StrBuf
from the
StrPtr
. The length
of the
StrBuf
is incremented by the
length
of the StrPtr
.
If the memory for the StrBuf
's
buffer
is not large enough, new contiguous memory
is allocated to contain the results of appending the
StrPtr
. If new memory is allocated, the old memory
is freed. Any memory allocated is separate from the memory for the
StrPtr
.
Example
#include <iostream> #include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { StrRef sr( "zy" ); StrPtr *sp = &sr; StrBuf sba; StrBuf sbb; sba.Set( "xyzzy" ); sbb.Set( "xyz" ); cout << "sba.Text() after sba.Set( \"xyzzy\" ) returns "; cout << "\"" << sba.Text() << "\"\n"; cout << "sba.Length() after sba.Set( \"xyzzy\" ) returns "; cout << sba.Length() << "\n"; cout << "sbb.Text() after sbb.Set( \"xyz\" ) returns "; cout << "\"" << sbb.Text() << "\"\n"; cout << "sbb.Length() after sbb.Set( \"xyz\" ) returns "; cout << sbb.Length() << "\n"; sbb << sr; // append StrRef to StrBuf cout << "sbb.Text() after sbb << sr returns "; cout << "\"" << sbb.Text() << "\"\n"; cout << "sbb.Length() after sbb << sr returns "; cout << sbb.Length() << "\n"; sba << sbb; // append StrBuf to StrBuf cout << "sba.Text() after sba << sbb returns "; cout << "\"" << sba.Text() << "\"\n"; cout << "sba.Length() after sba << sbb returns "; cout << sba.Length() << "\n"; }
Executing the preceding code produces the following output:
sba.Text() after sba.Set( "xyzzy" ) returns "xyzzy" sba.Length() after sba.Set( "xyzzy" ) returns 5 sbb.Text() after sbb.Set( "xyz" ) returns "xyz" sbb.Length() after sbb.Set( "xyz" ) returns 3 sbb.Text() after sbb << sr returns "xyzzy" sbb.Length() after sbb << sr returns 5 sba.Text() after sba << sbb returns "xyzzyxyzzy" sba.Length() after sba << sbb returns 10
StrBuf::Set( const char * )
Set a StrBuf
from a null-terminated string.
Virtual? |
No |
|
Class |
||
Arguments |
|
pointer to the first byte of the null-terminated string |
Returns |
|
Notes
Initialize the StrBuf
before calling
Set()
.
The length
of the StrBuf
is set
to the number of bytes prior to the first null byte in the string.
Any memory allocated for the StrBuf
's
buffer
is separate from the memory for the string.
Example
#include <iostream> #include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { char chars[] = "string"; StrBuf sb; sb.Set( chars ); // set StrBuf from char * cout << "chars[] = \"" << chars << "\"\n"; cout << "sb.Text() returns \"" << sb.Text() << "\"\n"; }
Executing the preceding code produces the following output:
chars[] = "string" sb.Text() returns "string"
StrBuf::Set( const char *, int )
Set a StrBuf
from a string of a specified
length.
Virtual? |
No |
|
Class |
||
Arguments |
|
pointer to the first byte of the string |
|
length of the string |
|
Returns |
|
Notes
Initialize the StrBuf
before calling
Set()
.
Exactly len
bytes are copied from the string to
the StrBuf
. The length
of the
StrBuf
is set to the len
argument.
Any memory allocated for the StrBuf
's
buffer
is separate from the memory for the string.
Example
#include <iostream> #include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { char chars[] = "xyzzy"; StrBuf sb; sb.Set( chars, 3 ); // set StrBuf from len bytes of char * cout << "chars[] = \"" << chars << "\"\n"; cout << "sb.Text() returns \"" << sb.Text() << "\"\n"; }
Executing the preceding code produces the following output:
chars[] = "xyzzy" sb.Text() returns "xyz"
StrBuf::Set( const StrPtr * )
Set a StrBuf
from a pointer to a
StrPtr
.
Virtual? |
No |
|
Class |
||
Arguments |
|
pointer to the |
Returns |
|
Notes
Initialize the StrBuf
and the
StrPtr
before calling
Set()
.
Any memory allocated for the StrBuf
's
buffer
is separate from the memory for the
StrPtr
's buffer
.
Example
#include <iostream> #include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { StrRef sr( "xyz" ); StrPtr *sp = &sr; StrBuf sb; sb.Set( sp ); // set StrBuf from StrPtr * cout << "sp->Text() returns \"" << sp->Text() << "\"\n"; cout << "sb.Text() returns \"" << sb.Text() << "\"\n"; }
Executing the preceding code produces the following output:
sp->Text() returns "xyz" sb.Text() returns "xyz"
StrBuf::Set( const StrPtr & )
Set a StrBuf
from a reference of a
StrPtr
. Arguments are commonly instances of
classes derived from the StrPtr
class, such as
StrRef
and StrBuf
.
Virtual? |
No |
|
Class |
||
Arguments |
|
reference of the |
Returns |
|
Notes
Initialize the StrBuf
and the
StrPtr
before calling
Set()
.
Any memory allocated for the StrBuf
's
buffer
is separate from the memory for the
StrPtr
's buffer
.
Example
#include <iostream> #include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { StrRef sr; StrBuf sbs; StrBuf sbt; sr.Set( "xyz" ); sbt.Set( sr ); // set StrBuf from StrRef cout << "sr.Text() returns \"" << sr.Text() << "\"\n"; cout << "sbt.Text() returns \"" << sbt.Text() << "\"\n\n"; sbs.Set( "abc" ); sbt.Set( sbs ); // set StrBuf from StrBuf cout << "sbs.Text() returns \"" << sbs.Text() << "\"\n"; cout << "sbt.Text() returns \"" << sbt.Text() << "\"\n"; }
Executing the preceding code produces the following output:
sr.Text() returns "xyz" sbt.Text() returns "xyz" sbs.Text() returns "abc" sbt.Text() returns "abc"
StrBuf::StringInit()
Initialize a StrBuf
.
Virtual? |
No |
|
Class |
||
Arguments |
None |
|
Returns |
|
Notes
StringInit()
initializes the StrBuf
to contain a zero-length
null buffer.
Normally when a StrBuf
is created, it is
initialized using the StrBuf
constructor.
However, there may be specialized cases where memory has already been
allocated for a StrBuf
instance, but the memory
was not allocated through the normal mechanisms that would result in
the StrBuf
constructor initializing the instance.
For these specialized cases,
StringInit()
is appropriate for initializing a StrBuf
instance.
After a StrBuf
has been used, calling
StringInit()
for the instance can result in a memory leak. Specifically, once the
buffer
member has been pointed to memory other
than nullStrBuf
, calling
StringInit()
for the instance will abandon the memory.
In most cases, it is preferable to use an alternative such as one of the following:
sb1 = StrRef::Null(); sb2.Clear(); sb2.Terminate(); sb3.Set( "" ); sb4 = "";
See also
Example
#include <iostream> #include <errno.h> #include <stdhdrs.h> #include <strbuf.h> #define NSTRBUFS 5 #define CHUNKSIZE 1024 #define STRBUFSIZE sizeof( StrBuf ) int main( int argc, char **argv ) { char chunk[ CHUNKSIZE ]; int chunkFree = CHUNKSIZE; char *pchunkStart = &chunk[ 0 ]; char *pchunk; int iStrBuf; // Initialize the StrBufs in the chunk. ` for ( iStrBuf = 0, pchunk = pchunkStart; iStrBuf < NSTRBUFS; iStrBuf++, pchunk += STRBUFSIZE ) { // Ensure that there's enough free left in the chunk for a StrBuf. if ( (chunkFree -= STRBUFSIZE) < 0) { cout << "Not enough free left in the chunk!\n"; return ENOMEM; } // Initialize and set the value of the StrBuf. ((StrBuf *)pchunk)->StringInit(); *(StrBuf *)pchunk << iStrBuf + 73; } // Print the StrBufs. Do this in a separate loop so as to provide // some evidence that the above loop didn't corrupt adjacent StrBufs. for ( iStrBuf = 0, pchunk = pchunkStart; iStrBuf < NSTRBUFS; iStrBuf++, pchunk += STRBUFSIZE ) { cout << "StrBuf " << iStrBuf + 1 << " contains \""; cout << ((StrBuf *)pchunk)->Text() << "\"\n"; } }
Executing the preceding code produces the following output:
StrBuf 1 contains "73" StrBuf 2 contains "74" StrBuf 3 contains "75" StrBuf 4 contains "76" StrBuf 5 contains "77"
StrBuf::Terminate()
Null-terminate the string pointed to by the buffer
member of a StrBuf
. The null byte is placed in the
buffer at the location indicated by the length
member.
Virtual? |
No |
|
Class |
||
Arguments |
None |
|
Returns |
|
Notes
Initialize the StrBuf
before calling
Terminate()
.
The length
member of the StrBuf
is effectively unchanged by
Terminate()
.
Example
Terminate()
is defined in strbuf.h
as follows:
void Terminate() { Extend( 0 ); --length; }
Terminate()
null-terminates the string by calling Extend( 0 )
,
which also increments the length
member; the
length
is then decremented within
Terminate()
,
leaving it unchanged.
See also
Example
#include <iostream> #include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { StrBuf sb; sb.Set( "xyzzy" ); cout << "Prior to sb.SetLength( 3 ) and sb.Terminate():\n"; cout << " sb.Length() returns " << sb.Length() << "\n"; cout << " sb.Text() returns \"" << sb.Text() << "\"\n\n"; sb.SetLength( 3 ); cout << "After sb.SetLength( 3 ) but prior to sb.Terminate():\n"; cout << " sb.Length() returns " << sb.Length() << "\n"; cout << " sb.Text() returns \"" << sb.Text() << "\"\n\n"; sb.Terminate(); // null-terminate the string at length cout << "After sb.SetLength( 3 ) and sb.Terminate():\n"; cout << " sb.Length() returns " << sb.Length() << "\n"; cout << " sb.Text() returns \"" << sb.Text() << "\"\n"; }
Executing the preceding code produces the following output:
Prior to sb.SetLength( 3 ) and sb.Terminate(): sb.Length() returns 5 sb.Text() returns "xyzzy" After sb.SetLength( 3 ) but prior to sb.Terminate(): sb.Length() returns 3 sb.Text() returns "xyzzy" After sb.SetLength( 3 ) and sb.Terminate(): sb.Length() returns 3 sb.Text() returns "xyz"
StrDict methods
StrDict::GetVar( const StrPtr & )
Return the value of the specified variable, or NULL
if
not defined.
Virtual? |
No |
|
Class |
||
Arguments |
|
the name of the variable to look up |
Returns |
|
the value, or |
Notes
For the most part, all of the following methods are equivalent:
-
StrDict::GetVar( const StrPtr & )
-
StrDict::GetVar( const char * )
-
StrDict::GetVar( const char *, Error * )
-
StrDict::GetVar( const StrPtr &, int )
-
StrDict::GetVar( const StrPtr &, int, int )
-
StrDict::GetVar( int, StrPtr &, StrPtr & )
The var
argument must specify the name of a
variable in the StrDict
that you're trying to look
up. In some instances, variables in a StrDict
are
named according to the convention
FOO
or
x
FOO
- one example is the tagged output of p4 filelog.
Calling
x
,y
GetVar()
with these numbers as arguments saves you the work of manually
constructing the variable name by using itoa()
and
Append()
.
The version of
GetVar()
that returns an int
is useful for iterating
through a StrDict
; the int
argument is an index into the StrDict
, and
the two StrPtr
arguments are set to contain
the variable and value found at that index, if any. This method
returns zero if there was no variable at the specified index.
Example
The implementation of
ClientUser::OutputStat()
in clientuser.cc
provides a good source example:
void ClientUser::OutputStat( StrDict *varList ) { int i; StrBuf msg; StrRef var, val; // Dump out the variables, using the GetVar( x ) interface. // Don't display the function, which is only relevant to rpc. for ( i = 0; varList->GetVar( i, var, val ); i++ ) { if ( var == "func" ) continue; // otherAction and otherOpen go at level 2, as per 99.1 + earlier msg.Clear(); msg << var << " " << val; char level = strncmp( var.Text(), "other", 5 ) ? '1' : '2'; OutputInfo( level, msg.Text() ); } // blank line OutputInfo( '0', "" ); }
An example of output:
% p4 -Ztag filelog file.c ... depotFile //depot/depot/source/file.c ... rev0 3 ... change0 1949 ... action0 integrate ... type0 text ... time0 1017363022 ... user0 testuser ... client0 testuser-luey ... desc0 <enter description here> ... how0,0 ignored ... file0,0 //depot/depot/source/old.c ... srev0,0 #1 ... erev0,0 #2 ... how0,1 ignored ...
StrDict::GetVar( const char * )
Return the value of the specified variable, or NULL
if
not defined.
Virtual? |
No |
|
Class |
||
Arguments |
|
the name of the variable to look up |
Returns |
|
the value, or |
Notes
For the most part, all of the
GetVar()
methods are equivalent.
For details, see
StrDict::GetVar( const StrPtr & )
StrDict::GetVar( const char *, Error * )
Return the value of the specified variable, or NULL
if not defined.
Virtual? |
No |
|
Class |
||
Arguments |
|
the name of the variable to look up |
|
an error message indicating that the required parameter
|
|
Returns |
|
the value, or |
Notes
For the most part, all of the
GetVar()
methods are equivalent.
For details, see
StrDict::GetVar( const StrPtr & )
StrDict::GetVar( const StrPtr &, int )
Return the value of the specified variable, or NULL
if not defined.
Virtual? |
No |
|
Class |
||
Arguments |
|
the name of the variable to look up |
|
appended to the variable's name |
|
Returns |
|
the value, or |
Notes
For the most part, all of the
GetVar()
methods are equivalent.
For details, see
StrDict::GetVar( const StrPtr & )
StrDict::GetVar( const StrPtr &, int, int )
Return the value of the specified variable, or NULL
if not defined.
Virtual? |
No |
|
Class |
||
Arguments |
|
the name of the variable to look up |
|
appended to the variable's name |
|
|
appended to the variable's name |
|
Returns |
|
the value, or |
Notes
For the most part, all of the
GetVar()
methods are equivalent.
For details, see
StrDict::GetVar( const StrPtr & )
StrDict::GetVar( int, StrPtr &, StrPtr & )
Return the value of the specified variable, or NULL
if not defined.
Virtual? |
No |
|
Class |
||
Arguments |
|
the index of a variable in the
|
|
the name of the variable at that index, if any |
|
|
the value found at that index, if any |
|
Returns |
|
the value, or zero if no variable found |
Notes
This method is typically used when iterating through a
StrDict
.
For the most part, all of the
GetVar()
methods are equivalent.
For details, see
StrDict::GetVar( const StrPtr & )
StrDict::Load( FILE * )
Unmarshals the StrDict
from a file.
Virtual? |
No |
|
Class |
||
Arguments |
|
the file to load from |
Returns |
|
always equals 1 |
Example
The following example "loads" a StrDict
by reading
it from stdin
.
MyStrDict sd; ClientUser ui; sd.Load( stdin ); ui.OutputStat( &sd );
Given a marshaled StrDict
on
stdin
, the code produces the following
output:
> cat marshaled.strdict depotFile=//depot/file.c clientFile=c:\test\depot\file.c headAction=edit headType=text headTime=1020067607 headRev=4 headChange=2042 headModTime 1020067484 func=client-FstatInfo > a.out < marshaled.strdict ... depotFile //depot/file.c ... clientFile clientFile=c:\test\depot\file.c ... headAction edit ... headType text ... headTime 1020067607 ... headRev 4 ... headChange 2042 ... headModTime 1020067484
StrDict::Save( FILE * )
Marshals the StrDict
into a text file.
Virtual? |
No |
|
Class |
||
Arguments |
|
the file to save to |
Returns |
|
always equals 1 |
Notes
Save()
stores
the StrDict
in a marshalled form to a text file,
which can be recovered by using
Load()
.
Example
The following example "saves" a StrDict
by writing
it to stdout
.
void MyClientUser::OutputStat( StrDict *varList ) { varList->Save( stdout ); }
Executing the preceding code produces the following output:
> a.out fstat //depot/file.c depotFile=//depot/file.c clientFile=c:\test\depot\file.c headAction=edit headType=text headTime=1020067607 headRev=4 headChange=2042 headModTime=1020067484 func=client-FstatInfo
StrDict::SetArgv( int, char *const * )
Set a list of values, such as the arguments to a Perforce command.
Virtual? |
No |
|
Class |
||
Arguments |
|
the number of variables (arguments) |
|
the variables (arguments) themselves |
|
Returns |
|
Notes
SetArgv()
is typically used when setting command arguments in
ClientApi
.
Example
p4api.cc
provides an example of using
SetArgv()
to set arguments.
int main( int argc, char **argv ) { ClientUser ui; ClientApi client; Error e; // Any special protocol mods // client.SetProtocol( "tag", "" ); // Connect to server client.Init( &e ); // Run the command "argv[1] argv[2...]" client.SetArgv( argc - 2, argv + 2 ); client.Run( argv[1], &ui ); // Close connection client.Final( &e ); return 0; }
StrNum methods
StrNum::StrNum( int ) (constructor)
Create a StrNum
, either unset or with a value.
Virtual? |
No |
|
Class |
||
Arguments |
|
the number to store (optional) |
Returns |
|
Notes
A StrNum
always stores numbers using base ten.
To create a StrNum
without a value, call
StrNum()
without an argument.
Example
The following example creates a StrNum
and
displays it:
#include <iostream> #include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { StrNum sn = StrNum( 1666 ); cout << "sn.Text() returns \"" << sn.Text() << "\"\n"; }
Executing the preceding code produces the following output:
sn.Text() returns "1666"
StrNum::Set( int )
Set a StrNum
's value.
Virtual? |
No |
|
Class |
||
Arguments |
|
the number to store |
Returns |
|
Notes
A StrNum
always stores numbers using base ten.
Example
#include <iostream> #include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { StrNum sn; sn.Set ( 1666 ); cout << "sn.Text() returns \"" << sn.Text() << "\"\n"; }
Executing the preceding code produces the following output:
sn.Text() returns "1666"
StrOps methods
StrOps::Caps( StrBuf & )
Convert the first character in a string (in place) to uppercase.
Virtual? |
No |
|
Class |
||
Arguments |
|
the string to capitalize |
Returns |
|
Example
#include <stdhdrs.h> #include <strbuf.h> #include <strops.h> int main( int argc, char **argv ) { StrBuf sb; sb.Set( "xyzzy" ); printf( "Before: %s\n", sb.Text() ); StrOps::Caps( sb ); printf( "After: %s\n", sb.Text() ); return 0; }
Executing the preceding code produces the following output:
Before: xyzzy After: Xyzzy
StrOps::Dump( const StrPtr & )
Pretty-print a string to stdout
Virtual? |
No |
|
Class |
||
Arguments |
|
the string to dump |
Returns |
|
Notes
Unprintable characters are displayed as hexadecimal ASCII values, surrounded by greater-than/less-than characters.
Example
#include <stdhdrs.h> #include <strbuf.h> #include <strops.h> int main( int argc, char **argv ) { StrBuf sb; sb.Set( "\tXyzzy" ); StrOps::Dump( sb ); return 0; }
Executing the preceding code produces the following output:
<09>Xyzzy
StrOps::Expand( StrBuf &, StrPtr &, StrDict & )
Expand "%
" strings
into corresponding "var
%
"
strings from a val
StrDict
.
Virtual? |
No |
|
Class |
||
Arguments |
|
the output string |
|
the input string |
|
|
the var/value pairs to look up |
|
Returns |
|
Notes
This function provides a way to quickly expand variables from a
StrDict
into a StrBuf
.
Example
This small program demonstrates the
Expand()
method in an
OutputStat()
implementation:
void MyClientUser::OutputStat( StrDict *varList ) { StrBuf s = StrBuf(); s.Set( "File: %depotFile% Rev: %rev%" ); StrBuf o = StrBuf(); StrOps::Expand( o, s, *varList ); StrOps::Dump( o ); } int main( int argc, char **argv ) { ClientApi client; MyClientUser ui; Error e; client.SetProtocol( "tag", "" ); client.Init( &e ); client.SetArgv( 1, ++argv ); client.Run( "files", &ui ); return client.Final( &e ); }
Executing the preceding code produces the following output:
% a.out * File: //depot/src/file1.c Rev: 4 File: //depot/src/file2.c Rev: 2
StrOps::Expand2( StrBuf &, StrPtr &, StrDict & )
Expand
"[%
"
strings into corresponding
"var
%|alt
]
" strings from a
val
StrDict
, or
"
" if
"alt
" is undefined.
var
Virtual? |
No |
|
Class |
||
Arguments |
|
the output string |
|
the input string |
|
|
the var/value pairs to look up |
|
Returns |
|
Notes
Like
Expand()
,
this function provides a way to quickly expand variables from a
StrDict
into a StrBuf
, with the
additional feature of providing alternate text if the value is not
defined.
The exact syntax of the expression to be expanded is:
[
text1
%var
%
text2
|
alt
]
If variable "
" has
value "val" in the var
StrDict d
, the expression
expands to:
text1
val
text2
otherwise, it expands to:
alt
See the example for details.
Example
This small program demonstrates the
Expand2()
method in an
OutputStat()
implementation:
void MyClientUser::OutputStat( StrDict *varList ) { StrBuf s = StrBuf(); s.Set( "stat: [File: %depotFile%|No file]!" ); StrBuf o = StrBuf(); StrOps::Expand2( o, s, *varList ); StrOps::Dump( o ); } int main( int argc, char **argv ) { ClientApi client; MyClientUser ui; Error e; client.SetProtocol( "tag", "" ); client.Init( &e ); client.SetArgv( argc - 2, argv + 2 ); client.Run( argv[1], &ui ); return client.Final( &e ); }
Executing the preceding code produces the following output:
% a.out files * stat: File: //depot/src/file1.c! stat: File: //depot/src/file2.c! % a.out labels stat: No file! stat: No file! stat: No file! stat: No file! stat: No file!
StrOps::Indent( StrBuf &, const StrPtr & )
Make a copy of a string, with each line indented.
Virtual? |
No |
|
Class |
||
Arguments |
|
the output string |
|
the input string |
|
Returns |
|
Notes
This function reads the input string s
and copies
it to the output string o
, with each line indented
with a single tab.
Example
StrBuf s = StrBuf(); s.Set( "abc\ndef\nghi\n" ); StrBuf o = StrBuf(); StrOps::Indent( o, s ); printf( "Before:\n%s", s.Text() ); printf( "After:\n%s", o.Text() );
Executing the preceding code produces the following output:
Before: abc def ghi After: abc def ghi
StrOps::Lines( StrBuf &, char *[], int )
Break a string apart at line breaks.
Virtual? |
No |
|
Class |
||
Arguments |
|
the input string |
|
the output array |
|
|
the maximum number of lines to handle |
|
Returns |
|
the actual number of lines handled |
Notes
This function handles all types of line breaks:
"\r
", "\n
", and
"\r\n
".
Example
StrBuf o = StrBuf(); o.Set( "abc\ndef\nghi\n" ); printf( "Input StrBuf:\n%s\n", o.Text() ); char *vec[4]; int l = StrOps::Lines( o, vec, 4 ); for ( ; l ; l-- ) { printf( "Line %d: %s\n", l, vec[l-1] ); }
Executing the preceding code produces the following output:
Input StrBuf: abc def ghi Line 3: abc Line 2: def Line 1: ghi
StrOps::Lower( StrBuf & )
Convert each character in a string (in place) to lowercase
Virtual? |
No |
|
Class |
||
Arguments |
|
the string to convert to lowercase |
Returns |
|
Notes
This function modifies an original string in place by converting all uppercase characters to lowercase.
Example
StrBuf o = StrBuf(); o.Set( "xYzZy" ); printf( "Before: %s\n", o ); StrOps::Lower( o ); printf( "After: %s\n", o ); return 0;
Executing the preceding code produces the following output:
% a.out Before: xYzZy After: xyzzy
StrOps::OtoX( const unsigned char *, int, StrBuf & )
Convert an octet stream into hex.
Virtual? |
No |
|
Class |
||
Arguments |
|
the input stream |
|
length of the input in bytes |
|
|
the output string |
|
Returns |
|
Notes
This function converts the input stream into a string of hexadecimal numbers, with each byte from the input being represented as exactly two hex digits.
Example
const unsigned char stream[3] = { 'f', 'o', 'o' }; StrBuf hex; StrOps::OtoX( stream, 3, hex ); StrOps::Dump( hex ); return 0;
Executing the preceding code produces the following output:
% a.out 666F6F
StrOps::Replace( StrBuf &, const StrPtr &, const StrPtr &, const StrPtr & )
Replace substrings in a StrPtr
and store the result
to a StrBuf
.
Virtual? |
No |
|
Class |
||
Arguments |
|
the output string |
|
the input string |
|
|
the substring to match |
|
|
the substring to replace |
|
Returns |
|
Notes
This function reads the input string i
and copies
it to the output string o
, after replacing each
occurrence of the string s
with string
r
.
Example
StrBuf i = StrBuf(); i.Set( "PerForce is PerForce, of course, of course!" ); StrBuf wrong, right; wrong.Set( "PerForce" ); right.Set( "Perforce" ); StrBuf o = StrBuf(); StrOps::Replace( o, i, wrong, right ); StrOps::Dump( o );
Executing the preceding code produces the following output:
% a.out Perforce is Perforce, of course, of course!
StrOps::Sub( StrPtr &, char, char )
Substitute instances of one character for another.
Virtual? |
No |
|
Class |
||
Arguments |
|
the string on which to operate |
|
the target character |
|
|
the character with which to replace
|
|
Returns |
|
Notes
This function substitutes the replace
character
for every instance of the target
character in the
input string
. The substitution is performed in
place.
Example
#include <stdhdrs.h> #include <strbuf.h> #include <strops.h> int main( int argc, char **argv ) { StrBuf sb; sb.Set( "\tPassword" ); StrOps::Sub( sb, 'o', '0' ); StrOps::Sub( sb, 'a', '4' ); StrOps::Dump( sb ); return 0; }
Executing the preceding code produces the following output:
P4ssw0rd
StrOps::Upper( StrBuf & )
Convert each character in a string (in place) to uppercase
Virtual? |
No |
|
Class |
||
Arguments |
|
the string to convert to uppercase |
Returns |
|
Notes
This function modifies an original string in place by converting all lowercase characters to uppercase.
Example
StrBuf o = StrBuf(); o.Set( "xYzZy" ); printf( "Before: %s\n", o ); StrOps::Upper( o ); printf( "After: %s\n", o ); return 0;
Executing the preceding code produces the following output:
% a.out Before: xYzZy After: XYZZY
StrOps::Words( StrBuf &, const char *[], char *[], int )
Break a string apart at whitespace.
Virtual? |
No |
|
Class |
||
Arguments |
|
a temporary string |
|
the input string |
|
|
the output array |
|
|
the maximum number of words to handle |
|
Returns |
|
the actual number of words handled |
Notes
This function uses the isAspace()
function to
define whitespace.
Example
StrBuf o = StrBuf(); StrBuf tmp = StrBuf(); o.Set( "abc\tdef ghi\nxyz xyzzy plugh" ); printf( "Input StrBuf:\n%s\n", o.Text() ); char *vec[5]; int w = StrOps::Words( tmp, o, vec, 5 ); for ( ; w ; w-- ) { printf( "Word %d: %s\n", w, vec[w-1] ); } return 0;
Executing the preceding code produces the following output:
Input StrBuf: abc def ghi xyz xyzzy plugh Word 5: xyzzy Word 4: xyz Word 3: ghi Word 2: def Word 1: abc
StrOps::XtoO( char *, unsigned char *, int )
Convert a hex string into an octet stream.
Virtual? |
No |
|
Class |
||
Arguments |
|
the input hex string |
|
the output stream |
|
|
the length of the output, in bytes |
|
Returns |
|
Notes
This function converts the input hexadecimal string into the stream of bytes that it represents.
Example
char *hex = "666F6F"; unsigned char oct[4]; StrOps::XtoO( hex, oct, 3 ); oct[3] = '\0'; printf( "%s", oct ); return 0;
Executing the preceding code produces the following output:
% a.out foo
StrPtr methods
StrPtr::Atoi()
Return the numeric value, if any, represented by this
StrPtr
's buffer.
Virtual? |
No |
|
Class |
||
Arguments |
None |
 |
Returns |
|
integer value of the string |
Notes
StrPtr::Atoi()
is equivalent to calling
atoi(
StrPtr::Text()
)
.
Non-numeric strings typically return a value of zero.
Example
#include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { StrBuf str1; StrBuf str2; str1.Set( "123" ); str2.Set( "234" ); printf( "%s + %s = %d\n", str1.Text(), str2.Text(), str1.Atoi() + str2.Atoi() ); }
Executing the preceding code produces the following output:
123 + 234 = 357
StrPtr::CCompare( const StrPtr & )
Case insensitive comparison of two StrPtr
s.
Virtual? |
No |
|
Class |
||
Arguments |
|
the |
Returns |
|
zero if identical, nonzero if different |
Notes
StrPtr::CCompare()
is a wrapper for stricmp()
or
strcasecmp()
. Its return value, if nonzero,
indicates which of the two strings is "greater" in the ASCII sense.
See also
Example
#include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { StrBuf str1, str2, str3; str1.Set( "abc" ); str2.Set( "Abc" ); str3.Set( "xyz" ); if ( str1.CCompare( str2 ) == 0 ) printf( "%s == %s\n", str1.Text(), str2.Text() ); else printf( "%s != %s\n", str1.Text(), str2.Text() ); if ( str1.CCompare( str3) == 0 ) printf( "%s == %s\n", str1.Text(), str3.Text() ); else printf( "%s != %s\n", str1.Text(), str3.Text() ); return 0; }
Executing the preceding code produces the following output:
abc == Abc abc != xyz
StrPtr::Compare( const StrPtr & )
Comparison of two StrPtr
s, with case sensitivity
based on client platform.
Virtual? |
No |
|
Class |
||
Arguments |
|
the |
Returns |
|
zero if identical, nonzero if different |
Notes
StrPtr::Compare()
is a wrapper for zstrcmp()
. Its return value, if
nonzero, indicates which of the two strings is "greater" in the ASCII
sense.
See also
Example
#include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { StrBuf str1, str2, str3; str1.Set( "abc" ); str2.Set( "Abc" ); str3.Set( "xyz" ); if ( str1.Compare( str2 ) == 0 ) printf( "%s == %s\n", str1.Text(), str2.Text() ); else printf( "%s != %s\n", str1.Text(), str2.Text() ); if ( str1.Compare( str3 ) == 0 ) printf( "%s == %s\n", str1.Text(), str3.Text() ); else printf( "%s != %s\n", str1.Text(), str3.Text() ); return 0; }
Executing the preceding code produces the following output on Windows:
abc == Abc abc != xyz
and on Unix::
abc != Abc abc != xyz
StrPtr::Contains( const StrPtr & )
Look for a substring and, if found, return it.
Virtual? |
No |
|
Class |
||
Arguments |
|
the substring to look for |
Returns |
|
the start of the substring if found, otherwise
|
Notes
StrPtr::Contains()
returns a pointer to the StrPtr
's buffer, rather
than allocating a new buffer for the substring. If it cannot find the
substring,
Contains()
returns NULL
.
Example
#include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { StrBuf str1, str2; str1.Set( "the quick brown fox jumps over the lazy dog" ); str2.Set( "brown fox" ); printf( "%s\n", str1.Contains( str2 ) ); return 0; }
Executing the preceding code produces the following output:
brown fox jumps over the lazy dog
StrPtr::Length()
Return the length of this StrPtr
.
Virtual? |
No |
|
Class |
||
Arguments |
None |
|
Returns |
|
the length of this |
Example
#include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { StrBuf str1; str1.Set( "This string" ); printf( "%s is %d bytes long\n", str1, str1.Length() ); return 0; }
Executing the preceding code produces the following output:
This string is 11 bytes long
StrPtr::operator []( int )
Return the character at the specified index.
Virtual? |
No |
|
Class |
||
Arguments |
|
the index to look in |
Returns |
|
the character at that index |
Notes
This operator does no bounds checking, and can therefore return data from beyond the end of the string.
Example
#include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { StrBuf str1; str1.Set( "the quick brown fox jumps over the lazy dog" ); printf( "%c%c%c%c%c\n", str1[1], str1[2], str1[35], str1[35], str1[12] ); return 0; }
Executing the preceding code produces the following output:
hello
StrPtr::operators ==, !=, >, <, <=, >= ( const char * )
Case-sensitive comparison operators between
StrPtr
and char *
.
Virtual? |
No |
|
Class |
||
Arguments |
|
the string to compare with |
Returns |
|
zero if the comparison is false, nonzero if true. |
Notes
These operators are typically used in simple comparisons between
StrPtr
s, such as to see whether two
StrPtr
s contain the same string, or whether one is
greater than the other, ASCII-wise. The comparison is always
case-sensitive.
Example
#include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { StrBuf str1; str1.Set( "This string" ); printf( "%s", str1.Text()); if ( str1 == "that string" ) printf( " == " ); if ( str1 > "that string" ) printf( " > " ); if ( str1 < "that string" ) printf( " < " ); printf( "that string" ); return 0; }
Executing the preceding code produces the following output:
This string < that string
(Note that "t
" > "T
" in ASCII.)
StrPtr::operators ==, !=, >, <, <=, >= ( const StrPtr & )
Case-sensitive comparison operators between
StrPtr
and StrPtr
.
Virtual? |
No |
|
Class |
||
Arguments |
|
the string to compare with |
Returns |
|
zero if the comparison is false, nonzero if true. |
Notes
These operators are typically used in simple comparisons between
StrPtr
s, such as to see whether two
StrPtr
s contain the same string, or whether one is
greater than the other, ASCII-wise. The comparison is always
case-sensitive.
Example
#include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { StrBuf str1, str2; str1.Set( "This string" ); str2.Set( "that string" ); printf( "%s", str1.Text()); if ( str1 == str2 ) printf( " == " ); if ( str1 > str2 ) printf( " > " ); if ( str1 < str2 ) printf( " < " ); printf( "%s\n", str2.Text() ); return 0; }
Executing the preceding code produces the following output:
This string < that string
(Note that "t
" > "T
" in ASCII.)
StrPtr::Text()
Return the char *
containing this
StrPtr
's text.
Virtual? |
No |
|
Class |
||
Arguments |
None |
|
Returns |
|
This |
Notes
StrPtr::Text()
and
StrPtr::Value()
are exactly equivalent. Their most typical use is converting a
StrPtr
to a char *
for functions
outside of the client API to use.
Example
#include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { StrBuf str1; str1.Set( "the quick brown fox jumps over the lazy dog" ); printf( "%s\n", str1.Text() ); return 0; }
Executing the preceding code produces the following output:
the quick brown fox jumps over the lazy dog
StrPtr::Value()
Return the char *
containing this
StrPtr
's text.
Virtual? |
No |
|
Class |
||
Arguments |
None |
|
Returns |
|
This |
Notes
StrPtr::Value()
is the deprecated form of
StrPtr::Text()
.
The two functions are equivalent. Their most typical use is
converting a StrPtr
to a char *
for functions outside of the client API to use.
Example
#include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { StrBuf str1; str1.Set( "the quick brown fox jumps over the lazy dog" ); printf( "%s\n", str1.Value() ); return 0; }
Executing the preceding code produces the following output:
the quick brown fox jumps over the lazy dog
StrPtr::XCompare( const StrPtr & )
Case sensitive comparison of two StrPtr
s.
Virtual? |
No |
|
Class |
||
Arguments |
|
the |
Returns |
|
zero if identical, nonzero if different |
Notes
StrPtr::XCompare()
is a wrapper for strcmp()
. Its return value, if
nonzero, indicates which of the two strings is "greater" in the ASCII
sense.
See also
Example
#include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { StrBuf str1, str2, str3; str1.Set( "abc" ); str2.Set( "Abc" ); str3.Set( "xyz" ); if ( str1.XCompare( str2 ) == 0 ) printf( "%s == %s\n", str1.Text(), str2.Text() ); else printf( "%s != %s\n", str1.Text(), str2.Text() ); if ( str1.XCompare( str3 ) == 0 ) printf( "%s == %s\n", str1.Text(), str3.Text() ); else printf( "%s != %s\n", str1.Text(), str3.Text() ); return 0; }
Executing the preceding code produces the following output:
abc != Abc abc != xyz
StrRef methods
StrRef::StrRef() (constructor)
Construct a StrRef
, and leave it unset.
Virtual? |
No |
|
Class |
||
Arguments |
None |
|
Returns |
|
Notes
If arguments are provided, the constructor calls
Set()
with them.
StrRef::StrRef( const StrPtr & ) (constructor)
Construct a StrRef
, referencing an existing
string.
Virtual? |
No |
|
Class |
||
Arguments |
|
a |
Returns |
|
Notes
If arguments are provided, the constructor calls
Set()
with them.
Example
#include <iostream> #include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { StrBuf str1; str1.Set( "abc" ); StrRef sr = StrRef( str1 ); cout << "str1 = \"" << str1.Text() << "\"\n"; cout << "sr.Text() returns \"" << sr.Text() << "\"\n"; }
Executing the preceding code produces the following output:
str1 = "abc" sr.Text() returns "abc"
StrRef::StrRef( const char * ) (constructor)
Construct a StrRef
, referencing an existing
string.
Virtual? |
No |
|
Class |
||
Arguments |
|
a null-terminated string to reference |
Returns |
|
Notes
If arguments are provided, the constructor calls
Set()
with them.
Example
#include <iostream> #include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { char chars[] = "abc"; StrRef sr = StrRef( chars ); cout << "chars[] = \"" << chars << "\"\n"; cout << "sr.Text() returns \"" << sr.Text() << "\"\n"; }
Executing the preceding code produces the following output:
chars[] = "abc" sr.Text() returns "abc"
StrRef::StrRef( const char * , int ) (constructor)
Construct a StrRef
, referencing an existing
string.
Virtual? |
No |
|
Class |
||
Arguments |
|
a null-terminated string to reference |
|
the string length |
|
Returns |
|
Notes
If arguments are provided, the constructor calls
Set()
with them.
StrRef::Set()
does not copy the target string; it simply creates a pointer to it.
Be sure that the StrRef
pointing to the target
string does not outlive the target string.
Example
#include <iostream> #include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { char chars[] = "xyzzy"; StrRef sr = StrRef( chars, 3 ); StrBuf sb; sb.Set( sr ); printf( "chars[] = \"%s\"\n", chars ); printf( "sr.Text() returns \"%s\"\n", sr.Text() ); printf( "sb.Text() returns \"%s\"\n", sb.Text() ); return 0; }
Executing the preceding code produces the following output:
chars[] = "xyzzy" sr.Text() returns "xyzzy" sb.Text() returns "xyz"
StrRef::Null()
Return a null StrPtr
.
Virtual? |
No |
|
Class |
||
Arguments |
None |
|
Returns |
|
an empty |
Notes
StrRef::Null()
is a static function.
Example
#include <iostream> #include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { StrBuf str1; str1.Set( "abc" ); StrRef sr = StrRef( str1 ); if ( sr == StrRef::Null() ) cout << "str1 was null\n"; else cout << "str1 was not null\n"; }
Executing the preceding code produces the following output:
str1 was not null
StrRef::operator =( StrPtr & )
Set a StrPtr
to reference an existing
StrPtr
or null-terminated string.
Virtual? |
No |
|
Class |
||
Arguments |
|
the |
Returns |
|
Notes
The =
operator is equivalent to calling
Set()
.
Example
#include <iostream> #include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { StrBuf str1; str1.Set( "xyz" ); StrRef sr = str1; cout << "str1 = \"" << str1.Text() << "\"\n"; cout << "sr.Text() returns \"" << sr.Text() << "\"\n"; }
Executing the preceding code produces the following output:
str1 = "xyz" sr.Text() returns "xyz"
StrRef::operator =( char * )
Set a StrPtr
to reference an existing
StrPtr
or null-terminated string.
Virtual? |
No |
|
Class |
||
Arguments |
|
the null-terminated string to reference. |
Returns |
|
Notes
The =
operator is equivalent to calling
Set()
.
Example
#include <iostream> #include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { char chars[] = "xyz"; StrRef sr; sr = chars; cout << "chars[] = \"" << chars << "\"\n"; cout << "sr.Text() returns \"" << sr.Text() << "\"\n"; }
Executing the preceding code produces the following output:
chars[] = "xyz" sr.Text() returns "xyz"
StrRef::operator +=( int )
Increase a StrRef's
pointer and decrease its
length.
Virtual? |
No |
|
Class |
||
Arguments |
|
the amount by which to move the pointer |
Returns |
|
Notes
This method has the effect of removing len
characters from the beginning of the StrRef
. It
does not, however, free the memory allocated to those characters.
Example
#include <iostream> #include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { char chars[] = "xyzzy"; StrRef sr = StrRef( chars ); sr += 3; cout << "chars[] = \"" << chars << "\"\n"; cout << "sr.Text() returns \"" << sr.Text() << "\"\n"; }
Executing the preceding code produces the following output:
chars[] = "xyzzy" sr.Text() returns "zy"
StrRef::Set( char * )
Set a StrRef
to reference an existing
null-terminated string.
Virtual? |
No |
|
Class |
||
Arguments |
|
the null-terminated string to reference |
Returns |
|
Notes
StrRef::Set()
does not copy the target string; it simply establishes a pointer to
it. Be sure that the StrRef
pointing to the target
string does not outlive the target string.
Example
#include <iostream> #include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { char chars[] = "xyz"; StrRef sr; sr.Set( chars ); cout << "chars[] = \"" << chars << "\"\n"; cout << "sr.Text() returns \"" << sr.Text() << "'\"n"; }
Executing the preceding code produces the following output:
chars[] = "xyz" sr.Text() returns "xyz"
StrRef::Set( char * , int )
Set a StrRef
to reference an existing
null-terminated string.
Virtual? |
No |
|
Class |
||
Arguments |
|
the null-terminated string to reference |
|
the length of the string |
|
Returns |
|
Notes
StrRef::Set()
does not copy the target string; it simply establishes a pointer to
it. Be sure that the StrRef
pointing to the target
string does not outlive the target string.
Example
#include <iostream> #include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { char chars[] = "xyzzy"; StrBuf sb; StrRef sr; sb.Set( chars ); sr.Set( chars, 3 ); printf( "chars[] = \"%s\"\n", chars ); printf( "sr.Text() returns \"%s\"\n", sr.Text() ); printf( "sb.Text() returns \"%s\"\n", sb.Text() ); return 0; }
Executing the preceding code produces the following output:
chars[] = "xyzzy" sr.Text() returns "xyzzy" sb.Text() returns "xyz"
StrRef::Set( const StrPtr * )
Set a StrRef
to reference an existing
StrPtr
.
Virtual? |
No |
|
Class |
||
Arguments |
|
the value to set |
Returns |
|
Notes
StrRef::Set()
does not copy the target string; it simply establishes a pointer to
it. Be sure that the StrRef
pointing to the target
string does not outlive the target string.
Example
#include <iostream> #include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { StrRef sr; sr.Set( "xyz" ); cout << "sr.Text() returns \"" << sr.Text() << "'\"n"; }
Executing the preceding code produces the following output:
sr.Text() returns "xyz"
StrRef::Set( const StrPtr & )
Set a StrRef
to reference an existing
StrPtr
.
Virtual? |
No |
|
Class |
||
Arguments |
|
the |
Returns |
|
Notes
StrRef::Set()
does not copy the target string; it simply establishes a pointer to
it. Be sure that the StrRef
pointing to the target
string does not outlive the target string.
Example
#include <iostream> #include <stdhdrs.h> #include <strbuf.h> int main( int argc, char **argv ) { StrBuf str1; StrRef sr; str1.Set ( "xyz" ); sr.Set( str1 ); cout << "str1 = \"" << str1.Text() << "\"\n"; cout << "sr.Text() returns \"" << sr.Text() << "'\"n"; }
Executing the preceding code produces the following output:
str1 = "xyz" sr.Text() returns "xyz"