| LLVM Programmer's Manual |
Written by Chris Lattner, Dinakar Dhurjati, and Joel Stanley
| Introduction |
This document should get you oriented so that you can find your way in the continuously growing source code that makes up the LLVM infrastructure. Note that this manual is not intended to serve as a replacement for reading the source code, so if you think there should be a method in one of these classes to do something, but it's not listed, check the source. Links to the doxygen sources are provided to make this as easy as possible.
The first section of this document describes general information that is useful to know when working in the LLVM infrastructure, and the second describes the Core LLVM classes. In the future this manual will be extended with information describing how to use extension libraries, such as dominator information, CFG traversal routines, and useful utilities like the InstVisitor template.
| General Information |
| The C++ Standard Template Library |
Here are some useful links:
You are also encouraged to take a look at the LLVM Coding Standards guide which focuses on how to write maintainable code more than where to put your curly braces.
| Important and useful LLVM APIs |
| The isa<>, cast<> and dyn_cast<> templates |
static bool isLoopInvariant(const Value *V, const Loop *L) { if (isa<Constant>(V) || isa<Argument>(V) || isa<GlobalValue>(V)) return true; // Otherwise, it must be an instruction... return !L->contains(cast<Instruction>(V)->getParent());
Note that you should not use an isa<> test followed by a cast<>, for that use the dyn_cast<> operator.
if (AllocationInst *AI = dyn_cast<AllocationInst>(Val)) { ... }
This form of the if statement effectively combines together a call to isa<> and a call to cast<> into one statement, which is very convenient.
Another common example is:
// Loop over all of the phi nodes in a basic block BasicBlock::iterator BBI = BB->begin(); for (; PHINode *PN = dyn_cast<PHINode>(BBI); ++BBI) cerr << *PN;
Note that the dyn_cast<> operator, like C++'s dynamic_cast or Java's instanceof operator, can be abused. In particular you should not use big chained if/then/else blocks to check for lots of different variants of classes. If you find yourself wanting to do this, it is much cleaner and more efficient to use the InstVisitor class to dispatch over the instruction type directly.
| The DEBUG() macro & -debug option |
Naturally, because of this, you don't want to delete the debug printouts, but you don't want them to always be noisy. A standard compromise is to comment them out, allowing you to enable them if you need them in the future.
The "Support/Debug.h" file provides a macro named DEBUG() that is a much nicer solution to this problem. Basically, you can put arbitrary code into the argument of the DEBUG macro, and it is only executed if 'opt' (or any other tool) is run with the '-debug' command line argument:
... DEBUG(std::cerr << "I am here!\n"); ...
Then you can run your pass like this:
$ opt < a.bc > /dev/null -mypass <no output> $ opt < a.bc > /dev/null -mypass -debug I am here! $
Using the DEBUG() macro instead of a home-brewed solution allows you to now have to create "yet another" command line option for the debug output for your pass. Note that DEBUG() macros are disabled for optimized builds, so they do not cause a performance impact at all (for the same reason, they should also not contain side-effects!).
One additional nice thing about the DEBUG() macro is that you can enable or disable it directly in gdb. Just use "set DebugFlag=0" or "set DebugFlag=1" from the gdb if the program is running. If the program hasn't been started yet, you can always just run it with -debug.
... DEBUG(std::cerr << "No debug type\n"); #undef DEBUG_TYPE #define DEBUG_TYPE "foo" DEBUG(std::cerr << "'foo' debug type\n"); #undef DEBUG_TYPE #define DEBUG_TYPE "bar" DEBUG(std::cerr << "'bar' debug type\n"); #undef DEBUG_TYPE #define DEBUG_TYPE "" DEBUG(std::cerr << "No debug type (2)\n"); ...
 Also, you should use names more meaningful that "foo" and "bar", because there is no system in place to ensure that names do not conflict: if two different modules use the same string, they will all be turned on when the name is specified. This allows all, say, instruction scheduling, debug information to be enabled with -debug-type=InstrSched, even if the source lives in multiple files.
| The Statistic template & -stats option |
Often you may run your pass on some big program, and you're interested to see how many times it makes a certain transformation. Although you can do this with hand inspection, or some ad-hoc method, this is a real pain and not very useful for big programs. Using the Statistic template makes it very easy to keep track of this information, and the calculated information is presented in a uniform manner with the rest of the passes being executed.
There are many examples of Statistic users, but this basics of using it are as follows:
static Statistic<> NumXForms("mypassname", "The # of times I did stuff");
The Statistic template can emulate just about any data-type, but if you do not specify a template argument, it defaults to acting like an unsigned int counter (this is usually what you want).
++NumXForms; // I did stuff
That's all you have to do. To get 'opt' to print out the statistics gathered, use the '-stats' option:
$ opt -stats -mypassname < program.bc > /dev/null ... statistic output ...
When running gccas on a C file from the SPEC benchmark suite, it gives a report that looks like this:
7646 bytecodewriter - Number of normal instructions 725 bytecodewriter - Number of oversized instructions 129996 bytecodewriter - Number of bytecode bytes written 2817 raise - Number of insts DCEd or constprop'd 3213 raise - Number of cast-of-self removed 5046 raise - Number of expression trees converted 75 raise - Number of other getelementptr's formed 138 raise - Number of load/store peepholes 42 deadtypeelim - Number of unused typenames removed from symtab 392 funcresolve - Number of varargs functions resolved 27 globaldce - Number of global variables removed 2 adce - Number of basic blocks removed 134 cee - Number of branches revectored 49 cee - Number of setcc instruction eliminated 532 gcse - Number of loads removed 2919 gcse - Number of instructions removed 86 indvars - Number of canonical indvars added 87 indvars - Number of aux indvars removed 25 instcombine - Number of dead inst eliminate 434 instcombine - Number of insts combined 248 licm - Number of load insts hoisted 1298 licm - Number of insts hoisted to a loop pre-header 3 licm - Number of insts hoisted to multiple loop preds (bad, no loop pre-header) 75 mem2reg - Number of alloca's promoted 1444 cfgsimplify - Number of blocks simplified
Obviously, with so many optimizations, having a unified framework for this stuff is very nice. Making your pass fit well into the framework makes it more maintainable and useful.
| Helpful Hints for Common Operations |
Because this is a "how-to" section, you should also read about the main classes that you will be working with. The Core LLVM Class Hierarchy Reference contains details and descriptions of the main classes that you should know about.
| Basic Inspection and Traversal Routines |
Because the pattern for iteration is common across many different aspects of the program representation, the standard template library algorithms may be used on them, and it is easier to remember how to iterate. First we show a few common examples of the data structures that need to be traversed. Other data structures are traversed in very similar ways.
// func is a pointer to a Function instance for (Function::iterator i = func->begin(), e = func->end(); i != e; ++i) { // print out the name of the basic block if it has one, and then the // number of instructions that it contains cerr << "Basic block (name=" << i->getName() << ") has " << i->size() << " instructions.\n"; }Note that i can be used as if it were a pointer for the purposes of invoking member functions of the Instruction class. This is because the indirection operator is overloaded for the iterator classes. In the above code, the expression i->size() is exactly equivalent to (*i).size() just like you'd expect.
// blk is a pointer to a BasicBlock instance for (BasicBlock::iterator i = blk->begin(), e = blk->end(); i != e; ++i) // the next statement works since operator<<(ostream&,...) // is overloaded for Instruction& cerr << *i << "\n";However, this isn't really the best way to print out the contents of a BasicBlock!
Note that currently operator<< is implemented for Value*, so it will print out the contents of the pointer, instead of the pointer value you might expect. This is a deprecated interface that will be removed in the future, so it's best not to depend on it. To print out the pointer value for now, you must cast to void*.
#include "llvm/Support/InstIterator.h" ... // Suppose F is a ptr to a function for (inst_iterator i = inst_begin(F), e = inst_end(F); i != e; ++i) cerr << **i << "\n";Easy, isn't it? You can also use InstIterators to fill a worklist with its initial contents. For example, if you wanted to initialize a worklist to contain all instructions in a Function F, all you would need to do is something like:
std::set<Instruction*> worklist; worklist.insert(inst_begin(F), inst_end(F));The STL set worklist would now contain all instructions in the Function pointed to by F.
Instruction& inst = *i; // grab reference to instruction reference Instruction* pinst = &*i; // grab pointer to instruction reference const Instruction& inst = *j;However, the iterators you'll be working with in the LLVM framework are special: they will automatically convert to a ptr-to-instance type whenever they need to. Instead of dereferencing the iterator and then taking the address of the result, you can simply assign the iterator to the proper pointer type and you get the dereference and address-of operation as a result of the assignment (behind the scenes, this is a result of overloading casting mechanisms). Thus the last line of the last example,
Instruction* pinst = &*i;is semantically equivalent to
Instruction* pinst = i;It's also possible to turn a class pointer into the corresponding iterator. Usually, this conversion is quite inexpensive. The following code snippet illustrates use of the conversion constructors provided by LLVM iterators. By using these, you can explicitly grab the iterator of something without actually obtaining it via iteration over some structure:
void printNextInstruction(Instruction* inst) { BasicBlock::iterator it(inst); ++it; // after this line, it refers to the instruction after *inst. if (it != inst->getParent()->end()) cerr << *it << "\n"; }Of course, this example is strictly pedagogical, because it'd be much better to explicitly grab the next instruction directly from inst.
initialize callCounter to zero for each Function f in the Module for each BasicBlock b in f for each Instruction i in b if (i is a CallInst and calls the given function) increment callCounterAnd the actual code is (remember, since we're writing a FunctionPass, our FunctionPass-derived class simply has to override the runOnFunction method...):
Function* targetFunc = ...; class OurFunctionPass : public FunctionPass { public: OurFunctionPass(): callCounter(0) { } virtual runOnFunction(Function& F) { for (Function::iterator b = F.begin(), be = F.end(); b != be; ++b) { for (BasicBlock::iterator i = b->begin(); ie = b->end(); i != ie; ++i) { if (CallInst* callInst = dyn_cast<CallInst>(&*i)) { // we know we've encountered a call instruction, so we // need to determine if it's a call to the // function pointed to by m_func or not. if (callInst->getCalledFunction() == targetFunc) ++callCounter; } } } private: unsigned callCounter; };
Function* F = ...; for (Value::use_iterator i = F->use_begin(), e = F->use_end(); i != e; ++i) { if (Instruction *Inst = dyn_cast<Instruction>(*i)) { cerr << "F is used in instruction:\n"; cerr << *Inst << "\n"; } }Alternately, it's common to have an instance of the User Class and need to know what Values are used by it. The list of all Values used by a User is known as a use-def chain. Instances of class Instruction are common Users, so we might want to iterate over all of the values that a particular instruction uses (that is, the operands of the particular Instruction):
Instruction* pi = ...; for (User::op_iterator i = pi->op_begin(), e = pi->op_end(); i != e; ++i) { Value* v = *i; ... }
| Making simple changes |
Creation of Instructions is straightforward: simply call the constructor for the kind of instruction to instantiate and provide the necessary parameters. For example, an AllocaInst only requires a (const-ptr-to) Type. Thus:
AllocaInst* ai = new AllocaInst(Type::IntTy);will create an AllocaInst instance that represents the allocation of one integer in the current stack frame, at runtime. Each Instruction subclass is likely to have varying default parameters which change the semantics of the instruction, so refer to the doxygen documentation for the subclass of Instruction that you're interested in instantiating.
Naming values
It is very useful to name the values of instructions when you're able to, as this facilitates the debugging of your transformations. If you end up looking at generated LLVM machine code, you definitely want to have logical names associated with the results of instructions! By supplying a value for the Name (default) parameter of the Instruction constructor, you associate a logical name with the result of the instruction's execution at runtime. For example, say that I'm writing a transformation that dynamically allocates space for an integer on the stack, and that integer is going to be used as some kind of index by some other code. To accomplish this, I place an AllocaInst at the first point in the first BasicBlock of some Function, and I'm intending to use it within the same Function. I might do:
AllocaInst* pa = new AllocaInst(Type::IntTy, 0, "indexLoc");where indexLoc is now the logical name of the instruction's execution value, which is a pointer to an integer on the runtime stack.
Inserting instructions
There are essentially two ways to insert an Instruction into an existing sequence of instructions that form a BasicBlock:
Given a BasicBlock* pb, an Instruction* pi within that BasicBlock, and a newly-created instruction we wish to insert before *pi, we do the following:
BasicBlock *pb = ...; Instruction *pi = ...; Instruction *newInst = new Instruction(...); pb->getInstList().insert(pi, newInst); // inserts newInst before pi in pb
Instruction instances that are already in BasicBlocks are implicitly associated with an existing instruction list: the instruction list of the enclosing basic block. Thus, we could have accomplished the same thing as the above code without being given a BasicBlock by doing:
Instruction *pi = ...; Instruction *newInst = new Instruction(...); pi->getParent()->getInstList().insert(pi, newInst);In fact, this sequence of steps occurs so frequently that the Instruction class and Instruction-derived classes provide constructors which take (as a default parameter) a pointer to an Instruction which the newly-created Instruction should precede. That is, Instruction constructors are capable of inserting the newly-created instance into the BasicBlock of a provided instruction, immediately before that instruction. Using an Instruction constructor with a insertBefore (default) parameter, the above code becomes:
Instruction* pi = ...; Instruction* newInst = new Instruction(..., pi);which is much cleaner, especially if you're creating a lot of instructions and adding them to BasicBlocks.
For example:
Instruction *I = .. ; BasicBlock *BB = I->getParent(); BB->getInstList().erase(I);
Replacing individual instructions
Including "llvm/Transforms/Utils/BasicBlockUtils.h" permits use of two very useful replace functions: ReplaceInstWithValue and ReplaceInstWithInst.
This function replaces all uses (within a basic block) of a given instruction with a value, and then removes the original instruction. The following example illustrates the replacement of the result of a particular AllocaInst that allocates memory for a single integer with an null pointer to an integer.
AllocaInst* instToReplace = ...; BasicBlock::iterator ii(instToReplace); ReplaceInstWithValue(instToReplace->getParent()->getInstList(), ii, Constant::getNullValue(PointerType::get(Type::IntTy)));
This function replaces a particular instruction with another instruction. The following example illustrates the replacement of one AllocaInst with another.
AllocaInst* instToReplace = ...; BasicBlock::iterator ii(instToReplace); ReplaceInstWithInst(instToReplace->getParent()->getInstList(), ii, new AllocaInst(Type::IntTy, 0, "ptrToReplacedInt"));
Replacing multiple uses of Users and Values
You can use Value::replaceAllUsesWith and User::replaceUsesOfWith to change more than one use at a time. See the doxygen documentation for the Value Class and User Class, respectively, for more information.| The Core LLVM Class Hierarchy Reference |
| The Value class |
The Value class is the most important class in LLVM Source base. It represents a typed value that may be used (among other things) as an operand to an instruction. There are many different types of Values, such as Constants, Arguments, and even Instructions and Functions are Values.
A particular Value may be used many times in the LLVM representation for a program. For example, an incoming argument to a function (represented with an instance of the Argument class) is "used" by every instruction in the function that references the argument. To keep track of this relationship, the Value class keeps a list of all of the Users that is using it (the User class is a base class for all nodes in the LLVM graph that can refer to Values). This use list is how LLVM represents def-use information in the program, and is accessible through the use_* methods, shown below.
Because LLVM is a typed representation, every LLVM Value is typed, and
this Type is available through the getType()
method. In addition, all LLVM values can be named. The
"name" of the Value is symbolic string printed in the LLVM code:
One important aspect of LLVM is that there is no distinction between an SSA
variable and the operation that produces it. Because of this, any reference to
the value produced by an instruction (or the value available as an incoming
argument, for example) is represented as a direct pointer to the class that
represents this value. Although this may take some getting used to, it
simplifies the representation and makes it easier to manipulate.
%foo = add int 1, 2
The name of this instruction is "foo". NOTE that the name of any value
may be missing (an empty string), so names should ONLY be used for
debugging (making the source code easier to read, debugging printouts), they
should not be used to keep track of values or map between them. For this
purpose, use a std::map of pointers to the Value itself
instead.
These methods are the interface to access the def-use information in LLVM. As with all other iterators in LLVM, the naming conventions follow the conventions defined by the STL.
This method returns the Type of the Value.
This family of methods is used to access and assign a name to a Value, be aware of the precaution above.
This method traverses the use list of a Value changing all Users of the current value to refer to "V" instead. For example, if you detect that an instruction always produces a constant value (for example through constant folding), you can replace all uses of the instruction with the constant like this:
Inst->replaceAllUsesWith(ConstVal);
| The User class |
The User class is the common base class of all LLVM nodes that may refer to Values. It exposes a list of "Operands" that are all of the Values that the User is referring to. The User class itself is a subclass of Value.
The operands of a User point directly to the LLVM Value that it refers to. Because LLVM uses Static Single Assignment (SSA) form, there can only be one definition referred to, allowing this direct connection. This connection provides the use-def information in LLVM.
These two methods expose the operands of the User in a convenient form for direct access.
Together, these methods make up the iterator based interface to the operands of a User.
| The Instruction class |
The Instruction class is the common base class for all LLVM instructions. It provides only a few methods, but is a very commonly used class. The primary data tracked by the Instruction class itself is the opcode (instruction type) and the parent BasicBlock the Instruction is embedded into. To represent a specific type of instruction, one of many subclasses of Instruction are used.
Because the Instruction class subclasses the User class, its operands can be accessed in the same way as for other Users (with the getOperand()/getNumOperands() and op_begin()/op_end() methods).
An important file for the Instruction class is the llvm/Instruction.def file. This file contains some meta-data about the various different types of instructions in LLVM. It describes the enum values that are used as opcodes (for example Instruction::Add and Instruction::SetLE), as well as the concrete sub-classes of Instruction that implement the instruction (for example BinaryOperator and SetCondInst). Unfortunately, the use of macros in this file confused doxygen, so these enum values don't show up correctly in the doxygen output.
Returns the BasicBlock that this Instruction is embedded into.
Returns true if the instruction writes to memory, i.e. it is a call, free, invoke, or store.
Returns the opcode for the Instruction.
Returns another instance of the specified instruction, identical in all ways to the original except that the instruction has no parent (ie it's not embedded into a BasicBlock), and it has no name.
| The BasicBlock class |
This class represents a single entry multiple exit section of the code, commonly known as a basic block by the compiler community. The BasicBlock class maintains a list of Instructions, which form the body of the block. Matching the language definition, the last element of this list of instructions is always a terminator instruction (a subclass of the TerminatorInst class).
In addition to tracking the list of instructions that make up the block, the BasicBlock class also keeps track of the Function that it is embedded into.
Note that BasicBlocks themselves are Values, because they are referenced by instructions like branches and can go in the switch tables. BasicBlocks have type label.
The BasicBlock constructor is used to create new basic blocks for insertion into a function. The constructor simply takes a name for the new block, and optionally a Function to insert it into. If the Parent parameter is specified, the new BasicBlock is automatically inserted at the end of the specified Function, if not specified, the BasicBlock must be manually inserted into the Function.
These methods and typedefs are forwarding functions that have the same semantics as the standard library methods of the same names. These methods expose the underlying instruction list of a basic block in a way that is easy to manipulate. To get the full complement of container operations (including operations to update the list), you must use the getInstList() method.
This method is used to get access to the underlying container that actually holds the Instructions. This method must be used when there isn't a forwarding function in the BasicBlock class for the operation that you would like to perform. Because there are no forwarding functions for "updating" operations, you need to use this if you want to update the contents of a BasicBlock.
Returns a pointer to Function the block is embedded into, or a null pointer if it is homeless.
Returns a pointer to the terminator instruction that appears at the end of the BasicBlock. If there is no terminator instruction, or if the last instruction in the block is not a terminator, then a null pointer is returned.
| The GlobalValue class |
Global values (GlobalVariables or Functions) are the only LLVM values that are visible in the bodies of all Functions. Because they are visible at global scope, they are also subject to linking with other globals defined in different translation units. To control the linking process, GlobalValues know their linkage rules. Specifically, GlobalValues know whether they have internal or external linkage.
If a GlobalValue has internal linkage (equivalent to being static in C), it is not visible to code outside the current translation unit, and does not participate in linking. If it has external linkage, it is visible to external code, and does participate in linking. In addition to linkage information, GlobalValues keep track of which Module they are currently part of.
Because GlobalValues are memory objects, they are always referred to by their address. As such, the Type of a global is always a pointer to its contents. This is explained in the LLVM Language Reference Manual.
These methods manipulate the linkage characteristics of the GlobalValue.
This returns the Module that the GlobalValue is currently embedded into.
| The Function class |
The Function class represents a single procedure in LLVM. It is actually one of the more complex classes in the LLVM heirarchy because it must keep track of a large amount of data. The Function class keeps track of a list of BasicBlocks, a list of formal Arguments, and a SymbolTable.
The list of BasicBlocks is the most commonly used part of Function objects. The list imposes an implicit ordering of the blocks in the function, which indicate how the code will be layed out by the backend. Additionally, the first BasicBlock is the implicit entry node for the Function. It is not legal in LLVM explicitly branch to this initial block. There are no implicit exit nodes, and in fact there may be multiple exit nodes from a single Function. If the BasicBlock list is empty, this indicates that the Function is actually a function declaration: the actual body of the function hasn't been linked in yet.
In addition to a list of BasicBlocks, the Function class also keeps track of the list of formal Arguments that the function receives. This container manages the lifetime of the Argument nodes, just like the BasicBlock list does for the BasicBlocks.
The SymbolTable is a very rarely used LLVM feature that is only used when you have to look up a value by name. Aside from that, the SymbolTable is used internally to make sure that there are not conflicts between the names of Instructions, BasicBlocks, or Arguments in the function body.
Constructor used when you need to create new Functions to add the the program. The constructor must specify the type of the function to create and whether or not it should start out with internal or external linkage.
Return whether or not the Function has a body defined. If the function is "external", it does not have a body, and thus must be resolved by linking with a function defined in a different translation unit.
These are forwarding methods that make it easy to access the contents of a Function object's BasicBlock list.
Returns the list of BasicBlocks. This is necessary to use when you need to update the list or perform a complex action that doesn't have a forwarding method.
These are forwarding methods that make it easy to access the contents of a Function object's Argument list.
Returns the list of Arguments. This is necessary to use when you need to update the list or perform a complex action that doesn't have a forwarding method.
Returns the entry BasicBlock for the function. Because the entry block for the function is always the first block, this returns the first block of the Function.
This traverses the Type of the Function and returns the return type of the function, or the FunctionType of the actual function.
Return a pointer to the SymbolTable for this Function.
| The GlobalVariable class |
Global variables are represented with the (suprise suprise) GlobalVariable class. Like functions, GlobalVariables are also subclasses of GlobalValue, and as such are always referenced by their address (global values must live in memory, so their "name" refers to their address). Global variables may have an initial value (which must be a Constant), and if they have an initializer, they may be marked as "constant" themselves (indicating that their contents never change at runtime).
Create a new global variable of the specified type. If isConstant is true then the global variable will be marked as unchanging for the program, and if isInternal is true the resultant global variable will have internal linkage. Optionally an initializer and name may be specified for the global variable as well.
Returns true if this is a global variable is known not to be modified at runtime.
Returns true if this GlobalVariable has an intializer.
Returns the intial value for a GlobalVariable. It is not legal to call this method if there is no initializer.
| The Module class |
The Module class represents the top level structure present in LLVM programs. An LLVM module is effectively either a translation unit of the original program or a combination of several translation units merged by the linker. The Module class keeps track of a list of Functions, a list of GlobalVariables, and a SymbolTable. Additionally, it contains a few helpful member functions that try to make common operations easy.
These are forwarding methods that make it easy to access the contents of a Module object's Function list.
Returns the list of Functions. This is necessary to use when you need to update the list or perform a complex action that doesn't have a forwarding method.
These are forwarding methods that make it easy to access the contents of a Module object's GlobalVariable list.
Returns the list of GlobalVariables. This is necessary to use when you need to update the list or perform a complex action that doesn't have a forwarding method.
Return a reference to the SymbolTable for this Module.
Look up the specified function in the Module SymbolTable. If it does not exist, return null.
Look up the specified function in the Module SymbolTable. If it does not exist, add an external declaration for the function and return it.
If there is at least one entry in the SymbolTable for the specified Type, return it. Otherwise return the empty string.
Insert an entry in the SymbolTable mapping Name to Ty. If there is already an entry for this name, true is returned and the SymbolTable is not modified.
| The Constant class and subclasses |
| The Type class and Derived Types |
| The Argument class |


| kfmfe04 wrote: |
|---|
| you are breaking class level encapsulation (by using friend) in order to provide for library-level encapsulation (users of the library cannot instantiate an iterator) |
Sounds to me like you're splitting hairs. Though I guess it depends on how you define your terms.
One could argue that std::list<T>::iterator is part of the std::list<T> class (which it is, depending on how you define "part of") and therefore it does not violate class level encapsulation. It's just two different parts of the same class talking to each other.
I won't make that argument though, because I don't care enough about it.
From my viewpoint, encapsulation is about separating interface from implementation. STL container classes, with their use of friendship, do exactly that. Whether you define that separation on a class level or on a broader level is completely arbitrary and irrelevant.
The bottom line (again, from my viewpoint) is that:
- with friendship, std::list<T> and std::list<T>::iterator can be properly encapsulated from the user's standpoint
- without friendship, they can't be
Going from that, friendship does not hinder encapsulation in any sense of the word.
So if you want to draw the line and say that "encapsulation means it must be contained within a single class", then you're either left with compromising that with friendship, or violating it completely to expose internals to the end user.
But again drawing that line at a class boundary is arbitrary. It's just the most convenient place to draw the line in
most situations.
| which makes life harder for the maintainer, but easier for the user, |
That's kind of the point. In fact, you're more or less describing OOP as a whole with that statement.
Compare std::string (OOP) verses strcpy, etc functions (procedural).
- string is a lot harder to write and maintain
- string is a lot easier and safer to use
While maintaining string might be more difficult, maintaining programs that use string is easier.
When working on larger projects, maintaining individual classes might be more difficult, but maintaining the project as a whole is a lot easier.
| however, notice that FAQ actually advocates making each class a mutual friend of the other as the safest way to implement something?!? |
I'm less interested in defending the FAQ author than I am in defending the merits of friendship.
I don't really agree with his example, but I do agree with his overall message.


We wanted to follow simple enumeration pattern without overriding "this" as other frameworks do it. Purpose of this is to create good compatibility with people coming from different platforms.
Returns true, if there is an item to consume in the given list. Just like Java, C#, you have to call next method in a while loop to check availability of next item in enumeration.
Returns current item.
Returns current index in enumeration.
We have created DOM Child enumerator, which allows you to enumerate child of dom element in fastest way. This method does not create any array, instead it simply uses nextSibling to nagivate, which is pretty fast. ChildEnumerator class expects parent element as an argument to constructor.


Hello Lead Observer! This email is to remind you that you are signed up to observe in 2 weeks.
Some reminders:
Thanks for all the hard work you do as Lead Observer! Please let us know if you have any questions/concerns/comments.
Clear Skies,
Claire Poppett,
on behalf of the DESI Observing Operations Team
We are honored to be permitted to conduct scientific research on l’oligam Du’ag (Manzanita Bush Mountain), a place with particular significance to the Tohono O’odham Nation. You can find an introduction to the Tohono O’odham history and culture at: https://noirlab.edu/intra/videos/tohono-oodham-history-and-culture
Warning: this email was sent automatically. Please contact Claire if you think it was sent in error.


Michael
Your account
Create a group
Fairness calculators
Log out
Loading
Loading...
Loading...
Loading...


Handling events with React elements is very similar to handling events on DOM elements. There are some syntax differences:
For example, the HTML:
is slightly different in React:
<button onClick={activateLasers}>
Activate Lasers
</button>
Another difference is that you cannot return false
to prevent default behavior in React. You must call preventDefault
explicitly. For example, with plain HTML, to prevent the default link behavior of opening a new page, you can write:
In React, this could instead be:
function ActionLink() {
function handleClick(e) {
e.preventDefault();
console.log('The link was clicked.');
}
return (
<a href="#" onClick={handleClick}>
Click me
</a>
);
}
Here, e
is a synthetic event. React defines these synthetic events according to the W3C spec, so you don't need to worry about cross-browser
compatibility. React events do not work exactly the same as native events. See the SyntheticEvent
reference guide to learn more.
When using React, you generally don't need to call addEventListener
to add listeners to a DOM element
after it is created. Instead, just provide a listener when the element is initially rendered.
When you define a component using an ES6 class, a common pattern is for an event handler to be a method on the class. For example, this Toggle
component renders a button that lets the user toggle between "ON" and "OFF" states:
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// This binding is necessary to make `this` work in the callback
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(state => ({
isToggleOn: !state.isToggleOn
}));
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
ReactDOM.render(
<Toggle />,
document.getElementById('root')
);
You have to be careful about the meaning of this
in JSX callbacks. In JavaScript, class methods are not bound by default. If you forget to bind this.handleClick
and pass it to onClick
, this
will be undefined
when the function is actually called.
This is not React-specific behavior; it is a part of how functions work in JavaScript. Generally, if you refer to a method without ()
after it, such as onClick={this.handleClick}
, you should bind that method.
If calling bind
annoys you, there are two ways you can get around this. If you are using the experimental public class fields syntax, you can use class fields to correctly bind callbacks:
class LoggingButton extends React.Component {
// This syntax ensures `this` is bound within handleClick.
// Warning: this is *experimental* syntax.
handleClick = () => {
console.log('this is:', this);
}
render() {
return (
<button onClick={this.handleClick}>
Click me
</button>
);
}
}
This syntax is enabled by default in Create React App.
If you aren't using class fields syntax, you can use an arrow function in the callback:
class LoggingButton extends React.Component {
handleClick() {
console.log('this is:', this);
}
render() {
// This syntax ensures `this` is bound within handleClick
return (
<button onClick={() => this.handleClick()}>
Click me
</button>
);
}
}
The problem with this syntax is that a different callback is created each time the LoggingButton
renders. In most cases, this is fine. However, if this callback is passed as a prop to lower components, those components might do an extra re-rendering. We generally recommend binding in the constructor or using the class fields syntax, to avoid this sort of performance problem.
Inside a loop, it is common to want to pass an extra parameter to an event handler. For example, if id
is the row ID, either of the following would work:
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
The above two lines are equivalent, and use arrow functions and Function.prototype.bind
respectively.
In both cases, the e
argument representing the React event will be passed as a second argument after the ID. With an arrow function, we have to pass it explicitly, but with bind
any further arguments are automatically forwarded.


the and {background was cases margin {border-style COVID- px;} state #ffffff;} would after end number The for May new respectively. Brazilian Sao daily June, before rate July, Rio are confirmed months two August, March from mathematical our peak public px; this with {font-family Brazil Health Janeiro city critical font-size until Paulo any disease double; face have model one pandemic preventive quarantine quarantine, started .%, Brazil, COVID-. Ceara Daily June Quarantine Total border-color border-width care drop first important intensive last lockdown masks measures prorogated social solid; starting that were {font-style {font-weight ∼,, (R) Isolation Microbes Pernambuco around bold capital case cities courier; drop. em; most outbreak persist pt;} reach results several since space spreading state). states units weeks


{% extends "_post.html" %}
{% hyde
title: "On Leading"
snip: "Some of my thoughts on leading after five years of doing it."
created: 2008-08-01 15:28:33
flattr: true
%}
{% block article %}
For those of you that don't know, one of the things I do with my free time is
dancing. I've been swing dancing (Lindy Hop) for about five years, blues
dancing for a year or so, and recently started learning tango. All of these
dances are improvised partner dances and so rely heavily on leading and
following. People do make routines but at least 95% of it is unrehearsed
social dancing with partners you might have never met.
As a male I'm usually in the role of leader, though I do try to follow when I
get the chance. I've learned a lot over the years so I'm going to write a few
posts about leading, and this is the first. I'm going to use the traditional
pronouns to make things easier to read, but everything applies to both genders
in both roles.
Beginning
-----
When a guy is first taught how to swing dance (or blues, or tango; everything
I'm saying applies to all three) he's usually taught that his main job is to
lead. This sounds obvious, but it's a lot for a beginner to take in. He has to
learn the footwork and ingrain it into his memory so it becomes automatic,
which takes some time. The next step is learning individual moves: not only
how to do them himself but also how to lead a follower to do them at the same
time. It takes coordination and most of all practice.
Leading at this point involves clearly showing the follower where she should
go and what she should do. "Placing the follower's weight" is a concept that's
a bit tricky but very useful. If a leader isn't clear in his leading the
follower won't be able to follow him unless she "cheats" and just does what
she knows he wants her to do (because she's danced with him before and so
knows what he's trying to do). This falls apart when the leader dances with a
new partner. Without leading and following swing dancing just doesn't work, so
leading clearly is the main role of a beginner guy.
Moving On
-----
Let me take a second to explain something I see happen very often with leaders
that take classes and progress nicely in their skill. Once the leader gets the
basics down pat and starts learning more moves, there seems to be a tendency
to learn things that let him show off. The followers get to really shine in
Lindy Hop quite a bit, so it's only natural for the guys to want to measure up
and look cool themselves. Unfortunately I think this gets in the way of my
next idea.
I think once a leader reaches a point where he's comfortable with the
structure of the dance and has a repertoire of moves and vocabulary of
movements, his role changes. His job is no longer "lead." His role becomes
*"lead the follower you are dancing with right now."*
Every follower is different. Every single one has a different level of
experience, a different style, and a different personality (as it relates to
dancing). If the leader simply leads every dance the same way, those dances
are not as good as they could be. An "advanced" leader leading a beginner
follower in a lot of complicated movements she's not capable of following yet
turns into a complete mess. He goes away from the dance feeling bored or
frustrated (or worse, arrogant) and she goes away feeling confused,
discouraged or angry. This is not a good thing.
Paying attention to the follow's level is critical. I'm not saying "only do
moves that the follower has learned and can easily follow." Pushing the
follower slightly beyond her comfortable, "automatic" level is wonderful and
helps her immensely; but going totally over her head and confusing the hell
out of her just so he can show off (to her or others) is obnoxious. This also
works in reverse: followers, please challenge your leaders but be mindful of
their skill.
Experience isn't the only difference between followers.
Adjusting his style to mesh better with hers makes the connection between
partners so much better, which makes the dance that much more fun. This also
works both ways. Followers are generally better at "listening" to their
partner because it's their main job; if a lead makes an effort to really
listen to the follow and change his leading to incorporate her ideas,
personality, style and level it makes an enormous difference.
The point I'm trying to make is that "leading" a follower is not just leading.
It's paying attention to the follower and leading *her*.
{% endblock %}


KeyEventArgs Class
Definition
Line 29 of System.Screen/Events.cm
Constructors & Destructor
Member Functions
| public nothrow bool |
Handled() const |
| public nothrow uchar |
Key() const |
| public nothrow void |
SetHandled() |
Member Variables
| private bool |
handled |
| private uchar |
key |
Constructor& Destructor Details
KeyEventArgs Constructor
public nothrow KeyEventArgs(uchar key_)
Definition
Line 31 of System.Screen/Events.cm
Member Function Details
Handled Member Function
public nothrow bool Handled()
Definition
Line 38 of System.Screen/Events.cm
Key Member Function
public nothrow uchar Key()
Definition
Line 34 of System.Screen/Events.cm
SetHandled Member Function
public nothrow void SetHandled()
Definition
Line 42 of System.Screen/Events.cm


| Hydrogeological Toolbox |
Well test often requires to treat the data prior to their interpretation. One of the strength of hytool is to make full benefit of the matlab environment to preprocess the data. Functions that are specially helpful are the import capabilities (load, xlsread, cvsread), interpolation functions (interp1), ploting functions (plot) and the signal processing tools.
In addition, in order to facilitate some operations that are very frequent, hytool provides a set of simple utilies that are listed below.
| ldf | Load Data File: reads a two column ASCII file |
| igmeread | Read the time, head, and flow rate from the IGME standard csv file |
| hyclean | Clean the data sets by selecting values that are finite and have strictly positive time |
| hyselect | Selecting a part of a dataset between xstart and xend |
| hyfilter | Filtering a signal in order to reduce the noise |
| hysampling | Sampling a signal at regular intervals |
| hyplot | Plotting selected/filtered/sampled data |
| simplify_rate | Group time periods having the same flow rate |
| Hytool |
© 1998-2017 Philppe Renard and Co. Terms of Use Acknowledgments


import math
from itertools import combinations
from fa2l import force_atlas2_layout
import networkx as nx
def _get_distance(pos1, pos2):
""" Returns distance between two points
Params :
pos1 : tuple in (x,y) format
pos2 : tuple in (x,y) format
"""
return math.sqrt((pos2[0]-pos1[0])**2 + (pos2[1]-pos1[1])**2)
def _get_pairwise_distance_between_largest_nodes(G, pos, node_sizes, k=20):
"""
Boolean. Returns the distances between top k largest nodes
Parameters
----------
G : A graph object
pos : dict containing the position of the nodes
k : number of nodes to consider
Returns
-------
Returns the dictionary containing the distance between the top k largest nodes.
"""
top_k_nodes = [n[0] for n in sorted(
node_sizes.items(), key=lambda x:x[1], reverse=True)[0:k]]
distances = {}
for n1, n2 in combinations(top_k_nodes, 2):
distances[(n1, n2)] = _get_distance(pos[n1], pos[n2])
return distances
[docs]def get_auto_scale(G, pos, node_sizes, k=20):
""" Returns the ratio of the ideal vs current top node distance.
The scale is being set with a heuristic that we consider k largest nodes to prevent overlap,
take the distances of all these nodes, find the current minimum top node distance. We also
find the ideal minimum top node distance that will prevent overlap and return their ratio to scale
the layout by that scale.

Number of nodes to consider when setting the scale automatically.
"""
result = _get_pairwise_distance_between_largest_nodes(
G, pos, node_sizes, k=20)
current_minimum_top_node_distance = min(result.values())
nodes = min(result, key=result.get)
ideal_minimum_top_node_distance = node_sizes[nodes[0]
] + node_sizes[nodes[1]] + 50
return ideal_minimum_top_node_distance/current_minimum_top_node_distance
[docs]def scale_layout(pos, scale):
""" Scales layout
Parameters
----------
pos: dict
A dictionary containing the positions of the nodes.
scale : int or float.
Number to scale the positions by.
Returns
-------
dict
Returns Dictionary containing Positions for the nodes scaled by the scale.
"""
return {k: (v[0]*scale, v[1]*scale) for k, v in pos.items()}


RouteComposer
RouteComposer
is the protocol oriented, Cocoa UI abstractions based library that helps to handle view controllers composition, navigation
and deep linking tasks in the iOS application.
Can be used as the universal replacement for the Coordinator pattern.
Table of contents
- Navigation concerns
- Installation
- Example
- Requirements
- Testimonials
- Sponsor this project
- Usage
- SwiftUI
- Advanced Configuration
- Contributing
- License
- Articles
- Author
Navigation concerns
There are 2 ways of implementing the navigation available in the iOS application:
- Built-in mechanism provided by Apple using storyboards and segues
- Programmatic navigation directly in the code
The downsides of these two solutions:
- Built-in mechanism: navigation in the storyboards is relatively static and often requires the extra navigation code in the
UIViewController
s and can lead to a lot of boilerplate code - Programmatic navigation: forces
UIViewController
s coupling or can be complex depending on the chosen design pattern (Router, Coordinator)
RouteComposer helps
- Facilitate the cutting of an application into small logical steps of navigation
- Provide the navigation configuration in a declarative way and address the majority of the navigation cases
- Remove navigation code from
UIViewController
s - Allow the composition of the
UIViewController
s in different ways according to the application state - Make every
UIViewController
deep-linkable out of the box - Simplify the creation of the User facing A/B tests with the different navigation and layout patterns
- Able to work side-by-side with any other navigation mechanism that exist in the IOs application: Builtin or custom
Installation
CocoaPods
RouteComposer is available through CocoaPods. To install it, simply add the following line to your Podfile:
pod 'RouteComposer'
For Xcode 10.1 / Swift 4.2 Support
pod 'RouteComposer', '~> 1.4'
And then run pod install
.
Once successfully integrated, just add the following statement to any Swift file where you want to use RouteComposer:
import RouteComposer
Check out the Example app included, as it covers most of the general use cases.
Swift Package Manager
The Swift Package Manager is a tool for automating the distribution of Swift code and is integrated into the swift
compiler.
Once you have your Swift package set up, adding RouteComposer as a dependency is as easy as adding it to the dependencies
value of your Package.swift
.
dependencies: [
.package(url: "https://github.com/ekazaev/RouteComposer", .upToNextMajor(from: "2.10.4"))
]
Example
To run the example project, clone the repo, and run pod install
from the Example directory first.
Requirements
There are no actual requirements to use this library. But if you are going to implement your custom containers and actions you should be familiar with the library concepts and UIKit’s view controller navigation stack intricacies.
API documentation
Detailed API documentation can be found here. Test coverage - here
Testimonials
Viz.ai
At Viz.ai, the leading synchronised stroke care service, we went into replacing our entire navigation system, and we knew we needed to address complex and dynamic navigation scenarios. Coordinators and other flow-control libraries just didn’t answer our needs, and lead to mixing application logic and navigation, or creating massive coordinator classes. RouteComposer was an amazing fit for us, and actually, as the creator of this library states, it is the drop in replacement for any coordinator code you currently use.
The separation of concerns on this library is absolutely beautiful, and as with anything genius, it all works like magic. It does have a small learning curve, but one that pays off far more than coordinators and flow controllers, and will save you a ton of coding once you implement it.
It makes navigation in the app as simple as saying “go to x with y” and not worrying about the current state or stack. I wholeheartedly recommend it.
Elazar Yifrach, Sr iOS Developer @ Viz.ai
Hudson’s Bay Company
In our iOS app we wanted to provide a seamless experience for our users to guarantee that whenever they click on a push notification or a link in an email, they will land on the required view in the app seamlessly no matter of the state of the app.
We tried a programmatic navigational approach in the code and also tried to rely on a few other libraries. However, none of them seemed to do the trick. RouteComposer was not our first choice as originally it looked too complex. Thankfully, it turned out to be a fantastic and elegant solution. We started to use it not only to handle external deeplinking but also to handle our internal navigation within the app.It also turned out to be a great tool for UI A/B tests when you have different navigation patterns for different users. It saved us a load of time, and we really like the logic behind it.
The creator of the library is super responsive and helped with all questions that we had. I would thoroughly recommend it!
Alexandra Mikhailouskaya, Senior lead engineer @ Hudson’s Bay Company
B.W.A., 130 year old retail bank.
We recently performed our fifth and largest app update which involved restructuring the user navigation from scratch. We started with a simple migration of our existing (six-file long) coordinator before one of our senior devs suggested we trial RouteComposer. The proof of concept was challenging, but Eugene Kazaev put himself at my disposal to work through retrofitting the RouteComposer into our existing enterprise-grade codebase and when the pieces all fell into place, the result was simplicity itself.
Our other devs have embraced the RouteComposer in lieu of segues, unwind segues, manual pushes, pops, and modal drops and the resulting navigtion around our app is delightful.
Great thanks to Eugene for all his help. skooter Martin, Senior Specialist Mobile Engineer @ B.W.A.
Sponsor this project
If you like this library and especially if you are using it in production please consider sponsoring this
project here. I work on RouteComposer
in my spare time. Sponsorship
will help me to work on this project and continue to contribute to the Open Source community.
Usage
RouteComposer uses 3 main entities (Factory
, Finder
, Action
) that should be defined by a host application to support it.
It also provides 3 helping entities (RoutingInterceptor
, ContextTask
, PostRoutingTask
) that you may implement to handle some
default actions during the routing process. There are 2 associatedtype
in the description of each entity below:
ViewController
- Type of view controller. UINavigationController, CustomViewController, etc.Context
- Type of context object that is passed to the router from the hosting application that router will pass to the view controllers it is going to build. String, UUID, Any, etc. Can be optional.
NB
Context
represents a payload that you need to pass to your UIViewController
and something that distinguishes it from others.
It is not a View Model or some kind of Presenter. It is the missing piece of information. If your view controller requires a
productID
to display its content, and the productID
is a UUID
, then the type of Context
is the UUID
. The internal logic
belongs to the view controller. Context
answers the questions What to I need to present a ProductViewController and Am I
already presenting a ProductViewController for this product.
Implementation
1. Factory
Factory is responsible for building view controllers, that the router has to navigate to upon request.
Every Factory instance must implement the Factory
protocol:
public protocol Factory {
associatedtype ViewController: UIViewController
associatedtype Context
func build(with context: Context) throws -> ViewController
}
The most important function here is build
which should actually create the view controller. For detailed information
see the documentation.
The prepare
function provides you with a way of doing something before the routing actually takes place.
For example, you could throw
from inside this function in order to inform the router that you do not have the data required to
display the view correctly. It may be useful if you are implementing Universal Links in your application and the routing can’t be
handled, in which case the application might open the provided URL in Safari instead.
Example: Basic implementation of the factory for some custom ProductViewController
view controller might look like:
class ProductViewControllerFactory: Factory {
func build(with productID: UUID) throws -> ProductViewController {
let productViewController = ProductViewController(nibName: "ProductViewController", bundle: nil)
productViewController.productID = productID // Parameter initialisation can be handled by a ContextAction, see below:
return productViewController
}
}
Important note: Automatic associatedtype
resolution is broken in Xcode 10.2, you must set associated types manually using typealias
keyword.
Swift compiler bug reported.
2. Finder
Finder helps router to find out if a particular view controller is already present in view controller graph. All the finder instances
should conform to Finder
protocol.
public protocol Finder {
associatedtype ViewController: UIViewController
associatedtype Context
func findViewController(with context: Context) throws -> ViewController?
}
In some cases, you may use default finders provided by the library. In other cases, when you can have more than one view controller of
the same type in the graph, you may implement your own finder. There is an implementation of this protocol included called StackIteratingFinder
that helps to solve iterations in view controller graph and handles it. You just have to implement the function isTarget
to determine if it’s the
view controller that you are looking for or not.
Example of ProductViewControllerFinder
that can help the router find a ProductViewController
that presents a particular
product in your view controller stack:
class ProductViewControllerFinder: StackIteratingFinder {
let iterator: StackIterator = DefaultStackIterator()
func isTarget(_ productViewController: ProductViewController, with productID: UUID) -> Bool {
return productViewController.productID == productID
}
}
SearchOptions
is an enum that informs StackIteratingFinder
how to iterate through the graph when searching. See documentation.
3. Action
The Action
instance explains to the router how the view controller is created by a Factory
should be integrated into a view controller stack.
Most likely, you will not need to implement your own actions because the library provides actions for most of the default actions that can be done in
UIKit
like (GeneralAction.presentModally
, UITabBarController.add
, UINavigationController.push
etc.). You may need to implement your own actions if you are
doing something unusual.
Check example app to see a custom action implementation.
Example: As you most likely will not need to implement your own actions, let’s look at the implementation of PresentModally
provided
by the library:
class PresentModally: Action {
func perform(viewController: UIViewController, on existingController: UIViewController, animated: Bool, completion: @escaping (_: RoutingResult) -> Void) {
existingController.present(viewController, animated: animated, completion: {
completion(.success)
})
}
}
4. Routing Interceptor
Routing interceptor will be used by the router before it will start routing to the target view controller. For example, to navigate to
some particular view controller, the user might need to be logged in. You may create a class that implements the RoutingInterceptor
protocol
and if the user is not logged in, it will present a login view controller where the user can log in. If this process finishes successfully,
the interceptor should inform the router and it will continue routing or otherwise stop routing. See example app for details.
Example: If the user is logged in, router can continue routing. If the user is not logged in, the router should not continue
class LoginInterceptor<C>: RoutingInterceptor {
func perform(with context: C, completion: @escaping (_: RoutingResult) -> Void) {
guard !LoginManager.sharedInstance.isUserLoggedIn else {
completion(.failure("User has not been logged in."))
return
// Or present the LoginViewController. See Example app for more information.
}
completion(.success)
}
}
5. Context Task
If you are using one default Factory
and Finder
implementation provided by the library, you still need to set data in
context to your view controller. You have to do this even if it already exists in the stack, if it’s just going to be created by a Factory
or do any other
actions at the moment when router found/created a view controller. Just implement ContextTask
protocol.
Example: Even if ProductViewController
is present on the screen or it is going to be created you have to set productID to
present a product.
class ProductViewControllerContextTask: ContextTask {
func perform(on productViewController: ProductViewController, with productID: UUID) {
productViewController.productID = productID
}
}
See example app for the details.
Or use ContextSettingTask
provided with the library to avoid extra code.
6. Post Routing Task
A post-routing task will be called by the router after it successfully finishes navigating to the target view controller.
You should implement PostRoutingTask
protocol and create all necessary actions there.
Example: You need to log an event in your analytics every time the user lands on a product view controller:
class ProductViewControllerPostTask: PostRoutingTask {
let analyticsManager: AnalyticsManager
init(analyticsManager: AnalyticsManager) {
self.analyticsManager = analyticsManager
}
func perform(on productViewController: ProductViewController, with productID: UUID, routingStack: [UIViewController]) {
analyticsManager.trackProductView(productID: productViewController.productID)
}
}
Configuring Step
Everything that the router does is configured using a DestinationStep
instance. There is no need to create your own implementation of this protocol.
Use StepAssembly
provided by the library to configure any step that the router should execute during the routing.
Example: A ProductViewController
configuration that explains to the router that it should be boxed in UINavigationController
which should be presented modally from any currently visible view controller.
let productScreen = StepAssembly(finder: ProductViewControllerFinder(), factory: ProductViewControllerFactory())
.add(LoginInterceptor<UUID>()) // Have to specify the context type till https://bugs.swift.org/browse/SR-8719, https://bugs.swift.org/browse/SR-8705 are fixed
.add(ProductViewControllerContextTask())
.add(ProductViewControllerPostTask(analyticsManager: AnalyticsManager.sharedInstance))
.using(UINavigationController.push())
.from(NavigationControllerStep())
.using(GeneralActions.presentModally())
.from(GeneralStep.current())
.assemble()
This configuration means:
- Use
ProductViewControllerFinder
to potentially find an existing product view controller in the stack, or create it usingProductViewControllerFactory
if it has not been found. - If it was created push it into a navigation stack
- Navigation stack should be provided from another step
NavigationControllerStep
, that will create aUINavigationController
instance - The
UINavigationController
instance should be presented modally from any currently visible view controller. - Before routing run
LoginInterceptor
- After view controller been created or found, run
ProductViewControllerContextTask
- After successful routing run
ProductViewControllerPostTask
See example app to find out different ways to provide and store routing step configurations.
See advanced ProductViewController
configuration here.
Navigation
After you have implemented all necessary classes and configured a routing step, you can start to use the Router
to navigate. The library provides
a DefaultRouter
which is an implementation of the Router
protocol to handle routing based on the configuration explained above.
Example: The user taps on a cell in a UITableView
. It then asks the router to navigate the user to ProductViewController
. The user
should be logged into see the product details.
struct Configuration {
static let productScreen = StepAssembly(finder: ProductViewControllerFinder(), factory: ProductViewControllerFactory())
.add(LoginInterceptor<UUID>())
.add(ProductViewControllerContextTask())
.add(ProductViewControllerPostTask(analyticsManager: AnalyticsManager.sharedInstance))
.using(UINavigationController.push())
.from(NavigationControllerStep())
.using(GeneralActions.presentModally())
.from(GeneralStep.current())
.assemble()
}
class ProductArrayViewController: UITableViewController {
let products: [UUID]?
let router = DefaultRouter()
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
guard let productID = products[indexPath.row] else {
return
}
try? router.navigate(to: Configuration.productScreen, with: productID)
}
}
Example below shows the same process without the use of RouteComposer
class ProductArrayViewController: UITableViewController {
let products: [UUID]?
let analyticsManager = AnalyticsManager.sharedInstance
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
guard let productID = products[indexPath.row] else {
return
}
// Handled by LoginInterceptor
guard !LoginManager.sharedInstance.isUserLoggedIn else {
return
}
// Handled by a ProductViewControllerFactory
let productViewController = ProductViewController(nibName: "ProductViewController", bundle: nil)
// Handled by ProductViewControllerContextTask
productViewController.productID = productID
// Handled by NavigationControllerStep and UINavigationController.push
let navigationController = UINavigationController(rootViewController: productViewController)
// handled by DefaultActions.PresentModally
present(navigationController, animated: true) { [weak self] in
// Handled by ProductViewControllerPostTask
self?.analyticsManager.trackProductView(productID: productID)
}
}
}
In the example without RouteComposer
the code may seem simpler, however, everything is hardcoded in the actual function implementation.
RouteComposer
allows you to split everything into small reusable pieces and store navigation configuration separately from
your view logic. Also, the above implementation will grow dramatically when you try to add Universal Link support to your app.
Especially if you will have to choose from opening ProductViewController
from a universal link if it is already present on the
screen or not and so on. With the library, each of your view controllers is deep linkable by nature.
As you can see from the examples above the Router
does not do anything that tweaks UIKit
basis. It just allows you to break the
navigation process into small reusable pieces. The router will call them in a proper order based on the configuration provided.
The library does not break the rules of VIPER or MVVM architectural patterns and can be used in parallel with them.
See example app for other examples of defining routing configurations and instantiating router.
Container View Controllers
There are view controllers like UINavigationController
, UITabBarController
, UISplitController
and so on, that can contain
other view controllers inside them. RouteComposer
calls one such view controller, ContainerViewController
s. As each container
view controller has its own unique methods of interacting with the contained view controllers, RouteComposer
uses special
entities called ContainerAdapters. The RouteComposer
contains built-in adapters for the main container view controllers that come with UIKit
. You can create your own ContainerAdapter
s
if you are using your own custom container view controllers or ones that come from another library. If you want RouteComposer
to work
correctly with such containers, switch their tabs or make another view controller visible within them e.t.c.
Please check the Example app for the reference.
Deep-linking
With RouteComposer
every view controller becomes deep-linkable out of the box. You can also provide different configuration in case
the screen is being opened using universal link. See Example app for more information.
let router = DefaultRouter()
func application(_ application: UIApplication,
open url: URL,
sourceApplication: String?,
annotation: Any) -> Bool {
guard let productID = extractProductId(from: url) else {
return false
}
try? router.navigate(to: Configuration.productScreen, with: productID)
return true
}
Troubleshooting
If for some reason you are unsatisfied with the result and you think that it is the Routers issue, or you found that your particular case is not covered, you can always temporarily replace the router with your custom implementation and implement simple routing yourself. Please, create a new issue and we will try to fix the issue as soon as possible.
Example:
func goToProduct(with productId: UUID) {
// If view controller with this product id is present on the screen - do nothing
guard ProductViewControllerFinder(options: .currentVisibleOnly).getViewController(with: productId) == nil else {
return
}
/// Otherwise, find visible `UINavigationController`, build `ProductViewController`
guard let navigationController = ClassFinder<UINavigationController, Any?>(options: .currentVisibleOnly).getViewController(),
let productController = try? ProductViewControllerFactory().execute(with: productId) else {
return
}
/// Apply context task if necessary
try? ProductViewControllerContextTask().execute(on: productController, with: productId)
/// Push `ProductViewController` into `UINavigationController`
navigationController.pushViewController(productController, animated: true)
}
SwiftUI:
RouteComposer
is compatible with SwiftUI. See example app for the details.
Advanced Configuration:
You can find more configuration examples here.
Contributing
RouteComposer is in active development, and we welcome your contributions.
If you’d like to contribute to this repo, please read the contribution guidelines.
License
RouteComposer is distributed under the MIT license.
RouteComposer is provided for your use, free-of-charge, on an as-is basis. We make no guarantees, promises or apologies. Caveat developer.
Articles
English:
- Composition of UIViewControllers and navigation between them
- Going deeper into the RouteComposer configuration
- Coordinator Pattern’s Issues & What is RouteComposer
Russian:
- Композиция UIViewController-ов и навигация между ними
- Примеры конфигурации UIViewController-ов используя RouteComposer
- Проблемы паттерна Координатор и при чем тут RouteComposer
Author
Evgeny Kazaev<EMAIL_ADDRESS>Twitter ekazaev
I am happy to answer any questions you may have. Just create a new issue.


{# Copyright 2015-2016 Capstone Team G Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. #} {% extends "_wrapper.html" %} {% block headtitle %}Lintable | Status {% if job %}for job {{ job.job_id }}{% endif %}{% endblock %} {% block pagetitle %} Status {% if job %} for job {{ job.job_id }} {% endif %} {% endblock %} {% block content %} {% if not job %}
You currently have these jobs active.
| Job ID | Status | Duration | Repo |
|---|---|---|---|
| {% if job.finished() %} {% else %} {% endif %} {{ job.job_id }} | {{ job.status }} | {{ job.duration() }} | {{ job.repo.url }} |
This job is {% if job.finished() %} finished. It took {{ job.duration() }}. {% else %} currently running. It's been running for {{ job.duration() }}. {% endif %}
| File | Errors |
|---|---|
| {{ summary.file_name }} | {{ summary.error_count }} |


“Maybe love is like looking for a place
That doesn’t even
exist”
Profile
Lee Ji-eun (Korean: 이지은; born May 16, 1993), known professionally as IU (Korean: 아이유), is a South Korean singer-songwriter and actress. She signed with Kakao M (formerly LOEN Entertainment) in 2007 as a trainee and debuted as a singer at the age of fifteen with her album Lost and Found. Although her follow-up albums, Growing Up and IU...IM, brought mainstream success, it was after the release of "Good Day" (Korean: 좋은 날), the lead single from her 2010 album Real, that she achieved national stardom. "Good Day" went on to spend five consecutive weeks at the top position of South Korea's Gaon Digital Chart, and in 2019 it was ranked number one on Billboard magazine's 100 Greatest K-Pop Songs of the 2010s.
With the success of her 2011 albums, Real+ and Last Fantasy, IU established herself as a formidable force on the music charts of her native country and further cemented her girl next door image as Korea's "little sister". 2011 also saw her first foray into songwriting with "Hold My Hand", which was written for the television series The Greatest Love. IU's third full-length album release, Modern Times (2013), showcased a more mature style that marked a departure from her earlier girlish image, with several tracks reaching the top 10 positions on Gaon Digital Chart. While her subsequent releases, including albums A Flower Bookmark, Chat-Shire, and Palette, continued to deviate from the mainstream K-pop style, IU retained her dominance on music charts. Chat-Shire marked the first time she is credited as the sole lyricist and composer of her own album. IU has released a total of four studio albums and nine extended plays in her career, scoring three number-one albums and twenty-four number-one singles on the Gaon Music Charts.


Showmax launches R49 mobile plan in South Africa
by Jamie McKaneMultiChoice has launched a new Showmax mobile-only plan in South Africa.
At its Media Showcase event in Sandton, Johannesburg, the company said this new plan would be priced at R49 per month and would limit viewing to a single mobile device.
Showmax has also partnered with Vodacom to offer a promotional monthly package for Vodacom customers.
The promotion is priced at R99 per month and includes a mobile-only Showmax subscription with 2GB of mobile data every month.
The Vodacom promotional plan will be billed through Vodacom and includes a Showmax Mobile monthly subscription and 2GB of Showmax mobile data per month.
“This is all about an African service developing a solution that meets the needs of African consumers. Customer feedback consistently points to local content and sport as some of the things that people value most from Showmax,” said MultiChoice Connected Video CEO Niclas Ekdahl.
“That’s of course on top of the international series, movies, and kids’ shows that are our bread and butter.”
“With all of that content now available in a product designed specifically for mobile usage, we’re doing something no other service can offer,” Ekdahl said.
Mobile-only plan
Showmax’s mobile-only plan is now available for order from its website, along with the promotional Vodacom package.
Mobile-only subscribers are able to watch on a smartphone or a tablet and can view one simultaneous stream across their account.
Unlike standard subscribers, mobile-only users do not have access to Showmax’s HD streaming.
The packages can be cancelled at any time and offer a 14-day free trial with recurring payment. Both the standard and mobile plans include live sport, sport magazine shows, and sport documentaries.
The full comparison between Showmax’s standard and mobile-only offerings is below:
| Showmax | Mobile Only | Standard |
|---|---|---|
| Watch on smartphone or tablet | Yes | Yes |
| Watch on Smart TV and computer | No | Yes |
| HD streaming | No | Yes |
| TV series, movies, kids’ shows | Yes | Yes |
| Simultaneous streams | 1 | 2 |
| Chromecast and Airplay | No | Yes |
| Registered devices | 1 | 5 |
| Sports | Yes | Yes |
| Price | R49 per month | R99 per month |
Showmax’s mobile plan is currently available in Nigeria, Kenya, and South Africa.
Customers can sign up for the new mobile plan and the Vodacom promotion on the Showmax website.


You can add content to the bottom of an element with the .append method!
You can add content to the top of an element with the .prepend method!
This time we will target the paragraph and insert the content before it.
You can add after an element with the .after method!
This time we will replace the div html content (paragraph) with the new content using the .html method.
You can replace me with the .html method!
This time we will replace the paragraph text with the new content using the .text method.
(Notice that we'll need to remove the html tags from our content variable
You can replace me with the .text method!


January
Get release candidate out
Update release page
February
First bug pass on release candidate
Check this, pal


Rails, iOS, Swift, JS, Android, Express, Python, Linux,
React, TDD/BDD (rspec, mocha), Reactive programming (RxSwift, RxJS) ,Go, Docker, Ansible, Elixir,advanced software design patterns, data mining (pandas), neutron GUI framework
functional programming (haskell, lisp), Vim, Machine learning & A.I stuff,
I've made web applications using Rails, Sinatra, Express.js, MEAN stack, Flask.
I've comprehensive expreince in building RESTful API's in MEAN stack and Flask.
I've worked with MongoDB, RealmDB, MariaDB, Redis & Postgres.
Native mobile application for iOS & Android as well as hybrid applications using ionic framework.
I've worked with several popular libraries like Alamofire, SwiftyJSON, Volley etc.
I'm very fluent with sketchapp for making high fidelity mokups.
I've used bootstrap, foundation in several projects.
I have a thing for clean and minimal UI design.


--- layout: page title: "About" description: "This is what I do." header-img: "img/about-bg.jpg" ---
Fourth-year undergrad student at UC Berkeley, majoring in Computer Science. I love designing, developing, and creating awesome experiences for users. Most of my experience is with desktop and mobile web applications, but right now I'm learning iOS development.
Besides tech, I am really into teaching, mentoring, entrepreneurship, and learning and practicing leadership and public speaking skills. I'm quite a curious person. I want to understand how things work — my friends know me as the person who always asks "why?"
After graduation, I will be joining Google as a software engineering in August. Summer, I'll be traveling the world.  Come join me!


{% extends "sections/base.html" %} {% block title %}Board of directors - {{ block.super }}{% endblock title %} {% block section %}
Executive Vice President, Viavi Solutions
Susan (Sue) Spradley brings to US Ignite more than 20 years of experience in the wireless telecommunications industry in which she has held senior executive positions in sales, product line management, operations, services and customer support. Most recently she was Head of the North American Region at Nokia Siemens Networks and also a member of the company’s Executive Board.
Prior to joining Nokia Siemens Networks, Ms. Spradley held prominent leadership roles at Nortel Networks including President of Global Services and Operations, President of Global Product Line Management and North American Sales, and Vice-President of Customer Service and Operations. She also served as Vice-President of Marketing and Product Development for North America at Siemens Communications.
In addition, she previously was a member of the National Security Telecommunications Advisory Committee reporting to the President of the United States.
Susan Spradley holds a bachelor’s degree in Computer Science from the University of Kansas and completed the Advanced Management Program at Harvard Business School. Susan is a member of the Executive Board of the Perot Museum of Nature and Science in Dallas, and a board member at Tango Networks and EXFO.
Lev is co-founder of OneCommunity and became CEO July 1, 2013.
In 2011 Government Technology awarded Lev one of their “Top 25 Doers, Dreamers & Drivers in Public-Sector Innovation.” In the same year Crain’s Business Cleveland named Gonick one its “10 Difference Makers” in Northeast Ohio and Broadband Properties honored him with their Cornerstone Award for “using fiber to build an inclusive society and empower individuals.” In 2010 he received recognition as “Visionary of the Year” from NATOA. Lev has been recognized by ComputerWorld as a Premier 100 IT leader and honored by CIO magazine with a CIO 100 Award. Northeast Ohio’s Inside Business has recognized Lev as one of their Power 100.
Lev was CIO at Case Western Reserve University from 2001-2013. He and his colleagues were internationally recognized for technology innovations in community engagement, learning spaces, next generation network projects, and organizational development. Lev’s innovations, including the Case Connection Zone catalyzed national projects, including US Ignite and Gig.U
A frequent international speaker and consultant, Lev currently serves on the Boards of Monarch Teaching Technologies (educational software developers for persons with autism), DecisionDesk, EGenio, Groundworks Dance Theater, and Cleveland Independents (Restaurants).
Shareholder, Chambliss, Bahner & Stophel, P.C
Rick Hitchcock advises and represents clients in environmental matters, business planning, technology issues, transactions, and trial and appellate litigation. He also counsels businesses and utilities concerning environmental compliance matters.
Mr. Hitchcock has represented clients in significant environmental matters before administrative agencies, regional EPA offices, and several state and federal courts. He has successfully handled a number of appellate cases, including a leading case on the lender exception to liability under the federal Superfund law. He has served as special counsel to local governments on contract, franchise, and constitutional issues and represents electric and telecommunications utilities in strategic business planning. As counsel to the charter study commission of the City of Chattanooga, he served as a principal drafter of a charter framework that was implemented in 1990.
Mr. Hitchcock is involved in a variety of community activities. He helped lead successful voter initiatives to combine local schools and to provide financial resources to support public education. He has been actively involved in the revitalization of downtown Chattanooga.
President and CEO, Internet2
In partnership with the Board of Trustees and the Executive Leadership Team, Lambert is responsible for leading and implementing the organization’s strategic vision and ensuring its priorities are aligned with the technical and thought leadership of its membership.
Lambert is leading Internet2 to focus on several key areas: advanced network services and leadership, national and regional collaboration, global reach and leadership, industry and research partnership development and engagement, CIO engagement, NET+ Services “above the network,” and the U.S. Unified Community Anchor Network (U.S. UCAN).
Prior to joining Internet2, Lambert was the first Vice President for Information Services and Chief Information Officer at Georgetown University, where he held the position of VP/CIO since early 1998. He was recruited to Georgetown University from Cornell University, where he served as Vice President for Information Technology from 1994 through 1997 and as Director of Network Services from 1989 through 1993.
Prior to joining Cornell in 1989, Lambert held several technical and leadership positions at Indiana University, Bloomington, where he was responsible for the deployment of the first university-wide multi-service IP network.
Mr. Lambert's academic background includes a B.A. in Political Science from West Virginia University and doctoral studies in Political Science at Indiana University, Bloomington.
He and his family live in Bethesda, Maryland.
Senior Vice President, Strategy & Marketing, Platform Systems Division, Juniper Networks, Inc.
Mike Marcellin maintains responsibility for business strategy and marketing of Juniper’s industry-leading portfolio of high performance routing, switching, and data center fabric products, as well as the company’s groundbreaking Junos operating system and best-in-industry silicon portfolio. Marcellin’s team is responsible for business strategy and product marketing, go-to-market planning, sales and customer education and information experience, as well as competitive analysis worldwide.
Previously, Marcellin served as Vice President of Global Managed Solutions for Verizon, responsible for product development and marketing of its portfolio of managed IP networking, hosting, security and IT solutions for businesses around the world. During his tenure, Marcellin managed this $4 billion portfolio, along with $75 million in product development capital, to deliver best-in-industry security solutions, an innovative cloud computing offering for enterprises and a first-of-its-kind managed mobility solution.
Prior to that, Marcellin served as Vice President of Global Product Marketing for Verizon Business. Under his direction, Marcellin’s team received numerous industry awards and recognition, including the 2008 Frost & Sullivan North American Product Line Strategy awards for hosted IP telephony and VoIP access and the Metro Ethernet Forum 2008 Ethernet Service Provider of the Year awards for North America and Europe.
A Rodman Scholar at the University of Virginia, Marcellin received a Bachelor of Science degree with Distinction in Systems Engineering. Marcellin is based in Sunnyvale, California.
Professor of Innovation and Murchison Fellow of Free Enterprise in the University of Texas at Austin's Cockrell School Of Engineering
Bob Metcalfe was an Internet pioneer at MIT starting in 1970 and in 1973 received his PhD from Harvard for “Packet Communication.” He invented Ethernet in 1973 and founded 3Com Corporation (now part of HP) in 1979. He was a publisher-pundit in the 1990s with International Data Group and a venture capitalist in the 2000s with Polaris Venture Partners.
Dr. Metcalfe has received awards including the ACM Grace Hopper Award in 1980, the IEEE Alexander Graham Bell Medal in 1988, the IEEE Medal of Honor in 1996, the National Medal of Technology in 2005, induction into to the National Inventors Hall of Fame in 2007, the Fellow Award from the Computer History Museum in 2008, and the Japan NEC C&C (Computing and Communication) Prize in 2011. He is a life trustee of MIT and a member of the National Academy of Engineering.
Executive Director, US Ignite
William Wallace brings to US Ignite more than 25 years of experience in the telecommunications industry, most recently as co-founder and Executive Vice President of DigitalBridge Communications (DBC), a venture-backed startup dedicated to bringing 4G broadband wireless services to underserved portions of the U.S.
Prior to DBC, Mr. Wallace was co-founder and CEO of OnePoint Communications, which was purchased by Verizon Communications in 2000. OnePoint and its successor company, Verizon Avenue, provide bundled communications services to concentrated communities nationwide, including apartment communities, military bases, and rural areas.
Previously, he served as head of the Telecommunications practice and Chief Operating Officer for Gemini Consulting, a wholly-owned subsidiary of the Cap Gemini Sogeti group. In that role, he led teams that developed strategies and improved operations for many of the world’s largest carriers.
Mr. Wallace received an AB degree in Government and Economics from Harvard College and an MBA from Harvard Business School.
Founder and CTO, US Ignite
Glenn Ricart brings forty years of innovation in computer networking and related fields to US Ignite. Glenn is an Internet pioneer who implemented the first Inter-net interconnection point (the FIX in College Park, Maryland) and was recognized for this achievement by being inducted into the Internet Hall of Fame in August 2013. In one of his previous roles where he was academic CIO at the University of Maryland, his campus implemented the first institution-wide TCP/IP (Internet) network in 1983 using low-cost PDP-11 routers (“Fuzballs”) with software devised at the University of Maryland. Glenn was principal investigator of SURAnet, the first regional TCP/IP (Internet) network of academic and commercial institutions.
Dr. Ricart has also held other senior management positions including Executive Vice President and CTO for Novell in the 1990s, Managing Director of PricewaterhouseCoopers, and CEO and President of National LambdaRail. Dr. Ricart is also the founder or co-founder of five startups; the one previous to US Ignite, CenterBeam, was sold to Earthlink in 2013 after 14 years of independent operation.
Glenn’s formal education includes degrees from Case Institute of Technology and Case Western Reserve University, and his Ph.D. in Computer Science is from the University of Maryland, College Park. His inventions have resulted in more than a dozen patents. Dr. Ricart has served on the boards of three public companies, CACI, the SCO Organization, and First USA Financial Services, in addition to numerous non-profits.


|
| void | clearBuffer () |
| |
| void | menu (Company *c) |
| |
| int | showMenu () |
| |
| void | fileManager (Company *c) |
| |
| void | companyMenu (Company *c) |
| |
| int | showCompanyInformationOptions (Company *c) |
| |
| void | bakeryMenu (Company *c) |
| |
| int | showBakeryOptions (Company *c) |
| |
| void | chooseBakery (Company *c) |
| |
| void | addBakery (Company *c) |
| |
| void | chooseBakeryMenu (Company *c, Bakery *b) |
| |
| int | showChooseBakeryOptions (Bakery *b) |
| |
| void | changeBakeryAddress (Company *c, Bakery *b) |
| |
| void | addEmployee (Company *c, Bakery *b) |
| |
| void | removeEmployee (Company *c, Bakery *b) |
| |
| void | addBakery (Company *c, string address) |
| |
| void | changeBakeryAddress (Company *c, string oldAddress, string newAddress) |
| |
| void | addEmployee (Company *c, string address, string name, int nif, int salary) |
| |
| void | removeEmployee (Company *c, string address, int nif) |
| |
| void | clientMenu (Company *c) |
| |
| int | showClientOptions (Company *c) |
| |
| void | chooseClient (Company *c) |
| |
| void | addClient (Company *c) |
| |
| void | chooseClientMenu (Company *c, Client *cli) |
| |
| int | showChooseClientOptions (Company *c, Client *cli) |
| |
| void | togglePremiumClient (Company *c, Client *cli) |
| |
| void | makeOrder (Company *c, Client *cli) |
| |
| void | goToBakery (Company *c, Client *cli) |
| |
| void | addClient (Company *c, int nif, string name, string premium) |
| |
| void | togglePremiumClient (Company *c, int nif) |
| |
| void | makeOrder (Company *c, int nifClient, string address, string productName1, int quantity1, string productName2="", int quantity2=0, string productName3="", int quantity3=0) |
| |
| void | goToBakery (Company *c, int nifClient, string address) |
| |
| void | orderMenu (Company *c) |
| |
| int | showOrderOptions (Company *c) |
| |
| void | chooseOrder (Company *c) |
| |
| void | employeesMenu (Company *c) |
| |
| int | showEmployeeOptions (Company *c) |
| |
| void | chooseEmployee (Company *c) |
| |
| void | addEmployee (Company *c) |
| |
| void | chooseEmployeeMenu (Company *c, Employee *e) |
| |
| int | showChooseEmployeeOptions (Company *c, Employee *e) |
| |
| void | changeSalary (Company *c, Employee *e) |
| |
| int | getSalary (vector< Employee * > employees) |
| |
| void | changeSalary (Company *c, int salary, int nifEmployee) |
| |
| void | addEmployee (Company *c, int nif, string name, int salary, string address) |
| |
| void | productsMenu (Company *c) |
| |
| int | showProductOptions (Company *c) |
| |
| void | addProduct (Company *c) |
| |
| void | addProduct (Company *c, string type, string name, double price, int sizeBeverage, string sizeBread) |
| |


{% extends "base.html" %} {% import "_macros.html" as macros %} {% import "bootstrap/wtf.html" as wtf %} {% block page_content %} {% block title %}Pic{% endblock %}


a cornucopia of delights, including Dobson in the Biblical Land of Nod, railings and pewter, Spem in Alium by Thomas Tallis, bees, chewed things, Richard Nixon, Emily Dickinson and Ah-Fang Van Der Houygendorp, paper crumpling, and Tex-Mex Jiffy Bag Sprites!


class Subdef extends AbstractRepository
Methods
| __construct(EntityManager $em) | from AbstractRepository | |
| ArrayCollection |
findByRecord(integer $databoxId, integer $recordId, integer $devices = array(), integer $mimes = array())
Find all subdefs that belong to the provided record |
|
| Subdef |
findByRecordAndName(integer $databoxId, integer $recordId, string $name)
Find a subdefs by its name that belong to the provided record |
Details
in AbstractRepository at line 30
public
__construct(EntityManager $em)
at line 31
public ArrayCollection
findByRecord(integer $databoxId, integer $recordId, integer $devices = array(), integer $mimes = array())
Find all subdefs that belong to the provided record
at line 71
public Subdef
findByRecordAndName(integer $databoxId, integer $recordId, string $name)
Find a subdefs by its name that belong to the provided record


Online piracy has an effect on all industries with digital content - software, music, media, art can all be pirated illegally. This section contains resources that discuss the effects, advantages and disadvantages of online piracy.
The first resource chosen is a peer-reviewed journal article titled "Why the music industry may gain from free downloading — The role of sampling", written by Martin Peitz and Patrick Waelbroeck, and published in 2005. This article discusses the potential advantages of digital sharing of music for the music industry.
The second resource chosen is a book titled “Piracy of Digital Content”, written by Piotr Stryszowski and Danny Scorpecci, and published by the Organisation for Economic Co-operation and Development in 2009. This book discusses how piracy exists, the disadvantages and dangers of pirating content, and why it causes issues for the industry.
Title: Why the music industry may gain from free downloading — The role of sampling
Authors: Martin Peitz, Patrick Waelbroeck
Published: 2005
Category: Peer-reviewed Journal Article
This journal article provides the argument of how downloading music for free can be beneficial for the music industry. The article argues that consumers are willing to pay more if they find the music aligns with their taste in music, and so consumers should be able to download and listen to music for free to sample the music and decide if they enjoy it before they buy the music.
However, there is a drawback for the music industry as some users may have less incentive to pay for the music because they can already access it for free. Consumers have the option to keep the downloaded music and listen to it without paying. The article shows that even with this drawback, online file sharing of music is still advantageous, it can lead to lower prices, higher unit sales and higher profits.
The article illustrates this with a simple model of users, music firms and songs that the users might enjoy. Basically the users do not know what songs they would enjoy. If they are unable to download music, they do not know what they will enjoy and must buy at random. Consumers that have downloaded music, learn exactly which products they enjoy by trying each song. As they already know the song is suited to their musical taste, they are willing to pay more to purchase the songs they enjoy. In this model, profits increase because consumers can make more informed purchasing decisions because of sampling and are willing to spend for the original although they could consume the download for free.
Read this article to get a more in depth explanation on why consumers should be able to download music for free.
Title: Piracy of Digital Content
Authors: Piotr Stryszowski, Danny Scorpecci
Published: 2009
Category: Book
This book discusses the unique market of digital piracy and the challenges it has imposed on those trying to combat piracy.
The unique market of digital piracy is due to how suppliers are willing to provide content for free. This has serious consequences for copyright owners and policy makers. It has become extremely difficult and costly for copyright owners and law enforcers to detect and respond to digital piracy due to the large number of suppliers.
Another issue discussed is that users that engage in digital piracy leave themselves vulnerable to potential security risks when exchanging files online. This could leave them exposed to malicious software that is designed to infiltrate or damage a computer system.
The book reveals that peer-to-peer networks (used for sending files between users) generate 39% of the total Internet traffic in North America.
Some of these P2P networks are reported to distribute various types of potentially harmful malicious software such as trojans, viruses, etc. This is a major disadvantage of piracy as users are susceptible of being tricked by malicious content and can have their computers destroyed or their privacy breached. According to a survey presented in the book on page 60, a large volume of users are not aware of the potential security risks or consider them to be insignificant. In fact, it is shown that only 35% of respondents reduced their music piracy after the effects of viruses on their computer.
Read this book to learn how piracy exists, the disadvantages and dangers of pirating content, and why it causes issues for the industry.


{% overextends "index.html" %} {% load i18n %} {% block index_banner %} {% endblock %} {% block example_search_terms %} {% blocktrans %}Try the following:{% endblocktrans %} Helsinki {% trans "or" %} Länsimetro {% endblock %} {% block index_sub_left %}
{% blocktrans %}Every citizen has the right under the Freedom of Information Laws to ask for and receive access to information from Public Bodies concerning public affairs.{% endblocktrans %}
{% blocktrans %}Read more about the Freedom of Information!{% endblocktrans %}


{% extends "base.html" %} {% load static %} {% block content %}
| Name | Type | Address | Comments | Updated on | by |
|---|---|---|---|---|---|
| {{ location.name }} | {{ location.type|get_location_type }} | {{ location.get_address }} | {{ location.comment }} | {{ location.updated_on }} | {{ location.updated_by.username }} |
No locations have been created yet.
{% endif %}